Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor the lnwallet package to directly use the WalletController interface #17

Merged
merged 15 commits into from
Sep 8, 2016

Conversation

Roasbeef
Copy link
Member

@Roasbeef Roasbeef commented Aug 12, 2016

This PR implements a major refactor of the lnwallet package in order to provide a more streamlined path of the integration of new internal/external wallets into lnd. Previously the LightningWallet struct directly interacted with an instance of btcwallet.Wallet to handle duties such as signing, coin selection, address derivation, funding channels, etc. With this PR, rather than directly referencing a concrete wallet implementation, the WalletController interface is now used throughout the codebase. This will allow future wallets to drop in easily into the daemon, de-coupling the daemon from the underlying wallet implementation.

Along the way, two new interfaces have been introduced: BlockChainIO, and Signer.

The BlockChainIO interface currently serves as read-only access to the most current blockchain state. In a future PR, this new interface may be merged with the ChainNotifier interface as the abstractions are similar, and may be implemented by the same object behind the scenes.

The Signer interface abstracts away all signing related functionality within the wallet. Rather than holding private keys directly in memory, we now defer all signing to the Signer interface. The interface is capable of generating both raw signatures, and full input scripts (including nested p2sh spends). This interface further decouples signing within the daemon and paves the way for more secure methods such as hardware wallet integration, HSM's, hardware tokens, etc. Currently the BtcWallet implementation of the WalletController interface is used by default throughout the codebase, however new signers can easily be dropped.

The following is an overview of the changes within this PR:

  • Private keys are no longer stored within channeldb. This practice has been obviated by the usage of the Signer interface throughout the daemon. As a result, we no longer need the EncryptorDecryptor interface, so it's been scrapped.
  • The glide build files have been updated to include a modification required to my fork of `btcwallet.
  • Coin selection within the wallet has been revamped. Rather than using the btcutil.coinset package, we now perform manual coin selection. This change allows our soin selection to more accurately estimate the size of the resulting transaction, thereby accounting for fees defined to a certain fee rate (in sat/byte).
  • The previous lnwallet/wallet_test.go file has been renamed to lnwallet/interface_test.go. This new file tests against all registered WalletController interfaces rather than directly against a concrete implementation.
  • In order to achieve this, the concept of a WalletDriver has been introduced, whcih is essentially a "factory" struct capable of creating a concrete WalletController interface from a variable set of parameters.
  • Drivers are to be registered within the init() method of all create concrete implementations.
  • Along the way a few functions required to maintain the black-box testing methodology have been publicly exported.
  • A new concrete implementation of the WalletController, BtcWallet has been created. To go along with it a driver has been created and will be registered upon import of the new sub-package .
  • The prior LightningWallet reservation workflow has been *significantly refactored to directly use the WalletController rather than btcwallet. This has had the major benefiting of allowing the removal of several hundred lines of code, simplifying the reservation workflow code.
  • Rather than asking the wallet for an identity key, and using the private key for the channels' multi-sig to derive secrets, we now obtain a "root" key from the wallet, and use that to seed an HD chain. This HD chain is then used to derive all LN specific secrets such as elkrem roots, onion private keys, and identity keys.

@Roasbeef
Copy link
Member Author

Roasbeef commented Sep 2, 2016

The final diff count on this PR is a bit off due to this commit e07d1fa. I renamed lnwallet/wallet_test.go to lnwallet/interface_test.go then refactored the tests a bit, but that was shown as a full deletion of the file, with a new one being (interface_test.go) created. I'll insert a commit which adds the intermediate renaming.

@Roasbeef Roasbeef force-pushed the wallet-interface-refactor branch 4 times, most recently from c4417bc to 5d90321 Compare September 3, 2016 02:26
@Roasbeef
Copy link
Member Author

Roasbeef commented Sep 3, 2016

I've modified the stream of commits. The final diff now accurately reflects the changes to the master branch by this PR.

@josephpoon
Copy link
Member

LGTM!

waifu

@Roasbeef Roasbeef force-pushed the wallet-interface-refactor branch from 3b545bf to bbbd6e4 Compare September 8, 2016 19:09
This commit removes the EncryptorDecryptor interface, and all related
usage within channeldb. This interface is no longer needed as wallet
specific secrets such as private keys are no longer stored within the
database.
This commit removes the storage+encryption of private keys within
channeldb. We no longer need to encrypt these secrets before storing as
the base wallet is now expected to retain full control of these secrets
rather than the database.

As a result, we now only store public keys within the database.
This commit removes the wrapper functions used to rely on the coinset
package for coin selection. In a future commit the prior behavior will
be replaced by a custom coin selection implementation which estimates
the size of the funding transaction.
This commit revamps the previous WalletController interface, edging it
closer to a more complete version.

Additionally, this commit also introduces two new interfaces:
BlockchainIO, and Singer along with a new factor driver struct, the
WalletDriver.

This BlockChainIO abstracts read-only access to the blockchain, while
the Singer interface abstracts the signing of inputs from the base
wallet paving the way to hardware wallets, air-gapped signing, etc.

Finally, in order to provide an easy method for selecting a particular
concrete implementation of a WalletController interface, the concept of
registering “WalletDriver”s has been introduced. A wallet driver is
essentially the encapsulation of a factory function capable of create a
new instance of a Wallet Controller.
This commit adds the first concrete implementation of the
WalletController interface: BtcWallet. This implementation is simply a
series of wrapper functions are the base btcwallet struct.

Additionally, for ease of use both the BlockChain IO and Signer
interface are also implemented by BtcWallet. Finally a new WalletDriver
implementation has been implemented, and will be register by the init()
method within this new package.
This file is no longer needed as each implementation of the
WalletController is expected to handle its own set up via an instance
of the WalletDriver factory struct.
This commit modifies the elkrem root derivation for each newly created
channel. First a master elkrem root is derived from the rood HD seed
generated from private wallet data. Next, a HKDF is used with the
secret being the master elkrem root.
…ntroller.

This commit performs a major refactor of the current wallet,
reservation, and channel code in order to call into a WalletController
implementation rather than directly into btcwallet.

The current set of wallets tests have been modified in order to test
against *all* registered WalletController implementations rather than
only btcwallet. As a result, all future WalletControllers primary need
to ensure that their implementation passes the current set of tests
(which will be expanded into the future), providing an easy path of
integration assurance.

Rather than directly holding the private keys throughout funding and
channel creation, the burden of securing keys has been shifted to the
specified WalletController and Signer interfaces. All signing is done
via the Signer interface rather than directly, increasing flexibility
dramatically.

During channel funding, rather than creating a txscript.Engine to
verify commitment signatures, regular ECDSA sig verification is now
used instead. This is faster and more efficient.

Finally certain fields/methods within ChannelReservation and
LightningChannel have been exposed publicly in order to restrict the
amount of modifications the prior tests needed to undergo in order to
support testing directly agains the WalletController interface.
@Roasbeef Roasbeef force-pushed the wallet-interface-refactor branch from bbbd6e4 to bccb1b9 Compare September 8, 2016 19:28
@Roasbeef Roasbeef merged commit dfe37cd into master Sep 8, 2016
@Roasbeef Roasbeef deleted the wallet-interface-refactor branch December 14, 2016 00:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants