lnwallet: integrate obfuscated state hints into funding workflow

This commit finalizes the implementation of #58 by integrating passing
around the obfuscate state hints into the funding workflow of the
wallet, and also the daemon’s funding manager.

In order to amend the tests, the functions to set and receive the state
hints are now publicly exported.
This commit is contained in:
Olaoluwa Osuntokun committed 2016-11-16 12:54:39 -08:00
1 parent 3010412bbc
commit 22074eb737
6 files changed
+147 -34

No files matched your search

+70 -2
View File
@@ -6,6 +6,7 @@ import (
"sync"
"sync/atomic"
"github.com/btcsuite/fastsha256"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/channeldb"
@@ -197,10 +198,14 @@ type addSingleFunderSigsMsg struct {
// construct for them.
revokeKey *btcec.PublicKey
// This should be 1/2 of the signatures needed to succesfully spend our
// version of the commitment transaction.
// theirCommitmentSig are the 1/2 of the signatures needed to
// succesfully spend our version of the commitment transaction.
theirCommitmentSig []byte
// obsfucator is the bytes to be used to obsfucate the state hints on
// the commitment transaction.
obsfucator [StateHintSize]byte
// NOTE: In order to avoid deadlocks, this channel MUST be buffered.
err chan error
}
@@ -782,6 +787,24 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
return
}
// With both commitment transactions constructed, generate the state
// obsfucator then use it to encode the current state number withi both
// commitment transactions.
// TODO(roasbeef): define obsfucator scheme for dual funder
var stateObsfucator [StateHintSize]byte
if pendingReservation.partialState.IsInitiator {
stateObsfucator, err = deriveStateHintObsfucator(elkremSender)
if err != nil {
req.err <- err
return
}
}
err = initStateHints(ourCommitTx, theirCommitTx, stateObsfucator)
if err != nil {
req.err <- err
return
}
// Sort both transactions according to the agreed upon cannonical
// ordering. This lets us skip sending the entire transaction over,
// instead we'll just send signatures.
@@ -801,6 +824,7 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
pendingReservation.partialState.TheirCommitKey = theirCommitKey
pendingReservation.partialState.TheirMultiSigKey = theirContribution.MultiSigKey
pendingReservation.partialState.OurCommitTx = ourCommitTx
pendingReservation.partialState.StateHintObsfucator = stateObsfucator
pendingReservation.ourContribution.RevocationKey = ourRevokeKey
// Generate a signature for their version of the initial commitment
@@ -1047,6 +1071,7 @@ func (l *LightningWallet) handleSingleFunderSigs(req *addSingleFunderSigsMsg) {
pendingReservation.partialState.FundingOutpoint = req.fundingOutpoint
pendingReservation.partialState.TheirCurrentRevocation = req.revokeKey
pendingReservation.partialState.ChanID = req.fundingOutpoint
pendingReservation.partialState.StateHintObsfucator = req.obsfucator
fundingTxIn := wire.NewTxIn(req.fundingOutpoint, nil, nil)
// Now that we have the funding outpoint, we can generate both versions
@@ -1071,6 +1096,15 @@ func (l *LightningWallet) handleSingleFunderSigs(req *addSingleFunderSigsMsg) {
return
}
// With both commitment transactions constructed, generate the state
// obsfucator then use it to encode the current state number within
// both commitment transactions.
err = initStateHints(ourCommitTx, theirCommitTx, req.obsfucator)
if err != nil {
req.err <- err
return
}
// Sort both transactions according to the agreed upon cannonical
// ordering. This ensures that both parties sign the same sighash
// without further synchronization.
@@ -1291,6 +1325,40 @@ func (l *LightningWallet) deriveMasterElkremRoot() (*btcec.PrivateKey, error) {
return masterElkremRoot.ECPrivKey()
}
// deriveStateHintObsfucator derives the bytes to be used for obsfucatating the
// state hints from the elkerem root to be used for a new channel. The
// obsfucator is generated by performing an additional sha256 hash of the first
// child derived from the elkrem root. The leading 4 bytes are used for the
// obsfucator.
func deriveStateHintObsfucator(elkremRoot *elkrem.ElkremSender) ([StateHintSize]byte, error) {
var obsfucator [StateHintSize]byte
firstChild, err := elkremRoot.AtIndex(0)
if err != nil {
return obsfucator, err
}
grandChild := fastsha256.Sum256(firstChild[:])
copy(obsfucator[:], grandChild[:])
return obsfucator, nil
}
// initStateHints properly sets the obsfucated state ints ob both commitment
// transactions using the passed obsfucator.
func initStateHints(commit1, commit2 *wire.MsgTx,
obsfucator [StateHintSize]byte) error {
if err := SetStateNumHint(commit1, 0, obsfucator); err != nil {
return err
}
if err := SetStateNumHint(commit2, 0, obsfucator); err != nil {
return err
}
return nil
}
// selectInputs selects a slice of inputs necessary to meet the specified
// selection amount. If input selection is unable to suceed to to insuffcient
// funds, a non-nil error is returned. Additionally, the total amount of the