From 349eee3263f82e0d080b84f555468eab05425a63 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 11 Jul 2023 18:56:15 -0700 Subject: [PATCH] input: ensure sessionOpts is properly threaded through --- channeldb/channel.go | 61 +++++++++++++++++++++++++++ input/musig2_session_manager.go | 2 +- lnwallet/channel.go | 27 ++---------- lnwallet/musig_session.go | 41 ------------------ lnwallet/revocation_producer.go | 3 +- lnwallet/revocation_producer_itest.go | 9 +++- 6 files changed, 74 insertions(+), 69 deletions(-) diff --git a/channeldb/channel.go b/channeldb/channel.go index d69765645..277b855dc 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -2,6 +2,7 @@ package channeldb import ( "bytes" + "crypto/hmac" "crypto/sha256" "encoding/binary" "errors" @@ -13,6 +14,7 @@ import ( "sync" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" @@ -1381,6 +1383,65 @@ func (c *OpenChannel) SecondCommitmentPoint() (*btcec.PublicKey, error) { return input.ComputeCommitmentPoint(revocation[:]), nil } +var ( + // taprootRevRootKey is the key used to derive the revocation root for + // the taproot nonces. This is done via HMAC of the existing revocation + // root. + taprootRevRootKey = []byte("taproot-rev-root") +) + +// DeriveMusig2Shachain derives a shachain producer for the taproot channel +// from normal shachain revocation root. +func DeriveMusig2Shachain(revRoot shachain.Producer) (shachain.Producer, error) { //nolint:lll + // In order to obtain the revocation root hash to create the taproot + // revocation, we'll encode the producer into a buffer, then use that + // to derive the shachain root needed. + var rootHashBuf bytes.Buffer + if err := revRoot.Encode(&rootHashBuf); err != nil { + return nil, fmt.Errorf("unable to encode producer: %w", err) + } + + revRootHash := chainhash.HashH(rootHashBuf.Bytes()) + + // For taproot channel types, we'll also generate a distinct shachain + // root using the same seed information. We'll use this to generate + // verification nonces for the channel. We'll bind with this a simple + // hmac. + taprootRevHmac := hmac.New(sha256.New, taprootRevRootKey) + if _, err := taprootRevHmac.Write(revRootHash[:]); err != nil { + return nil, err + } + + taprootRevRoot := taprootRevHmac.Sum(nil) + + // Once we have the root, we can then generate our shachain producer + // and from that generate the per-commitment point. + return shachain.NewRevocationProducerFromBytes( + taprootRevRoot, + ) +} + +// NewMusigVerificationNonce generates the local or verification nonce for +// another musig2 session. In order to permit our implementation to not have to +// write any secret nonce state to disk, we'll use the _next_ shachain +// pre-image as our primary randomness source. When used to generate the nonce +// again to broadcast our commitment hte current height will be used. +func NewMusigVerificationNonce(pubKey *btcec.PublicKey, targetHeight uint64, + shaGen shachain.Producer) (*musig2.Nonces, error) { + + // Now that we know what height we need, we'll grab the shachain + // pre-image at the target destination. + nextPreimage, err := shaGen.AtIndex(targetHeight) + if err != nil { + return nil, err + } + + shaChainRand := musig2.WithCustomRand(bytes.NewBuffer(nextPreimage[:])) + pubKeyOpt := musig2.WithPublicKey(pubKey) + + return musig2.GenNonces(pubKeyOpt, shaChainRand) +} + // ChanSyncMsg returns the ChannelReestablish message that should be sent upon // reconnection with the remote peer that we're maintaining this channel with. // The information contained within this message is necessary to re-sync our diff --git a/input/musig2_session_manager.go b/input/musig2_session_manager.go index 3bf26004a..4b1d412d1 100644 --- a/input/musig2_session_manager.go +++ b/input/musig2_session_manager.go @@ -78,7 +78,7 @@ func (m *MusigSessionManager) MuSig2CreateSession(bipVersion MuSig2Version, // Create a signing context and session with the given private key and // list of all known signer public keys. musigContext, musigSession, err := MuSig2CreateContext( - bipVersion, privKey, allSignerPubKeys, tweaks, + bipVersion, privKey, allSignerPubKeys, tweaks, sessionOpts..., ) if err != nil { return nil, fmt.Errorf("error creating signing context: %w", diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 58400079f..e6508a711 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -1396,7 +1396,7 @@ func NewLightningChannel(signer input.Signer, logPrefix := fmt.Sprintf("ChannelPoint(%v):", state.FundingOutpoint) - taprootNonceProducer, err := deriveMusig2Shachain( + taprootNonceProducer, err := channeldb.DeriveMusig2Shachain( state.RevocationProducer, ) if err != nil { @@ -6103,7 +6103,7 @@ func (lc *LightningChannel) getSignedCommitTx() (*wire.MsgTx, error) { // the remote party to create this musig session. We pass in // the same height here as we're generating the nonce needed // for the _current_ state. - localNonce, err := NewMusigVerificationNonce( + localNonce, err := channeldb.NewMusigVerificationNonce( ourKey.PubKey, lc.currentHeight, lc.taprootNonceProducer, ) @@ -8163,7 +8163,7 @@ func (lc *LightningChannel) GenMusigNonces() (*musig2.Nonces, error) { // We pass in the current height+1 as this'll be the set of // verification nonces we'll send to the party to create our _next_ // state. - lc.pendingVerificationNonce, err = NewMusigVerificationNonce( + lc.pendingVerificationNonce, err = channeldb.NewMusigVerificationNonce( lc.channelState.LocalChanCfg.MultiSigKey.PubKey, lc.currentHeight+1, lc.taprootNonceProducer, ) @@ -8174,27 +8174,6 @@ func (lc *LightningChannel) GenMusigNonces() (*musig2.Nonces, error) { return lc.pendingVerificationNonce, nil } -// NewMusigVerificationNonce generates the local or verification nonce for -// another musig2 session. In order to permit our implementation to not have to -// write any secret nonce state to disk, we'll use the _next_ shachain -// pre-image as our primary randomness source. When used to generate the nonce -// again to broadcast our commitment hte current height will be used. -func NewMusigVerificationNonce(pubKey *btcec.PublicKey, targetHeight uint64, - shaGen shachain.Producer) (*musig2.Nonces, error) { - - // Now that we know what height we need, we'll grab the shachain - // pre-image at the target destination. - nextPreimage, err := shaGen.AtIndex(targetHeight) - if err != nil { - return nil, err - } - - shaChainRand := musig2.WithCustomRand(bytes.NewBuffer(nextPreimage[:])) - pubKeyOpt := musig2.WithPublicKey(pubKey) - - return musig2.GenNonces(pubKeyOpt, shaChainRand) -} - // HasRemoteNonces returns true if the channel has a remote nonce pair. func (lc *LightningChannel) HasRemoteNonces() bool { return lc.musigSessions != nil diff --git a/lnwallet/musig_session.go b/lnwallet/musig_session.go index 30d28e414..89cc36a96 100644 --- a/lnwallet/musig_session.go +++ b/lnwallet/musig_session.go @@ -2,15 +2,12 @@ package lnwallet import ( "bytes" - "crypto/hmac" - "crypto/sha256" "fmt" "io" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2" - "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/input" @@ -575,41 +572,3 @@ func NewMusigPairSession(cfg *MusigSessionCfg) *MusigPairSession { signer: cfg.Signer, } } - -var ( - // taprootRevRootKey is the key used to derive the revocation root for - // the taproot nonces. This is done via HMAC of the existing revocation - // root. - taprootRevRootKey = []byte("taproot-rev-root") -) - -// deriveMusig2Shachain derives a shachain producer for the taproot channel -// from normal shachain revocation root. -func deriveMusig2Shachain(revRoot shachain.Producer) (shachain.Producer, error) { - // In order to obtain the revocation root hash to create the taproot - // revocation, we'll encode the producer into a buffer, then use that - // to derive the shachain root needed. - var rootHashBuf bytes.Buffer - if err := revRoot.Encode(&rootHashBuf); err != nil { - return nil, fmt.Errorf("unable to encode producer: %v", err) - } - - revRootHash := chainhash.HashH(rootHashBuf.Bytes()) - - // For taproot channel types, we'll also generate a distinct shachain - // root using the same seed information. We'll use this to generate - // verification nonces for the channel. We'll bind with this a simple - // hmac. - taprootRevHmac := hmac.New(sha256.New, taprootRevRootKey) - if _, err := taprootRevHmac.Write(revRootHash[:]); err != nil { - return nil, err - } - - taprootRevRoot := taprootRevHmac.Sum(nil) - - // Once we have the root, we can then generate our shachain producer - // and from that generate the per-commitment point. - return shachain.NewRevocationProducerFromBytes( - taprootRevRoot, - ) -} diff --git a/lnwallet/revocation_producer.go b/lnwallet/revocation_producer.go index 7b8349950..0bf490d2f 100644 --- a/lnwallet/revocation_producer.go +++ b/lnwallet/revocation_producer.go @@ -3,6 +3,7 @@ package lnwallet import ( + "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/shachain" ) @@ -50,7 +51,7 @@ func (l *LightningWallet) nextRevocationProducer(res *ChannelReservation, // Once we have the root, we can then generate our shachain producer // and from that generate the per-commitment point. shaChainRoot := shachain.NewRevocationProducer(revRoot) - taprootShaChainRoot, err := deriveMusig2Shachain(shaChainRoot) + taprootShaChainRoot, err := channeldb.DeriveMusig2Shachain(shaChainRoot) if err != nil { return nil, nil, err } diff --git a/lnwallet/revocation_producer_itest.go b/lnwallet/revocation_producer_itest.go index 824597176..a1b6a0551 100644 --- a/lnwallet/revocation_producer_itest.go +++ b/lnwallet/revocation_producer_itest.go @@ -4,6 +4,7 @@ package lnwallet import ( "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/shachain" ) @@ -46,7 +47,9 @@ func (l *LightningWallet) nextRevocationProducer(res *ChannelReservation, } shaChainRoot := shachain.NewRevocationProducer(*revRoot) - taprootShaChainRoot, err := deriveMusig2Shachain(*revRoot) + taprootShaChainRoot, err := channeldb.DeriveMusig2Shachain( + shaChainRoot, + ) if err != nil { return nil, nil, err } @@ -81,7 +84,9 @@ func (l *LightningWallet) nextRevocationProducer(res *ChannelReservation, // Once we have the root, we can then generate our shachain producer // and from that generate the per-commitment point. shaChainRoot := shachain.NewRevocationProducer(revRoot) - taprootShaChainRoot, err := deriveMusig2Shachain(revRoot) + taprootShaChainRoot, err := channeldb.DeriveMusig2Shachain( + shaChainRoot, + ) if err != nil { return nil, nil, err }