github.com/decred/dcrlnd@v0.7.6/lnwallet/revocation_producer_itest.go (about)

     1  //go:build rpctest
     2  // +build rpctest
     3  
     4  package lnwallet
     5  
     6  import (
     7  	"github.com/decred/dcrd/chaincfg/chainhash"
     8  	"github.com/decred/dcrlnd/keychain"
     9  	"github.com/decred/dcrlnd/shachain"
    10  )
    11  
    12  // nextRevocationProducer creates a new revocation producer, deriving the
    13  // revocation root by applying ECDH to a new key from our revocation root family
    14  // and the multisig key we use for the channel.
    15  func (l *LightningWallet) nextRevocationProducer(res *ChannelReservation,
    16  	keyRing keychain.KeyRing) (shachain.Producer, error) {
    17  
    18  	// Derive the next key in the revocation root family.
    19  	nextRevocationKeyDesc, err := keyRing.DeriveNextKey(
    20  		keychain.KeyFamilyRevocationRoot,
    21  	)
    22  	if err != nil {
    23  		return nil, err
    24  	}
    25  
    26  	// Within our itests, we want to make sure we can still restore channel
    27  	// backups created with the old revocation root derivation method. To
    28  	// create a channel in the legacy format during the test, we signal this
    29  	// by setting an explicit pending channel ID. The ID is the hex
    30  	// representation of the string "legacy-revocation".
    31  	itestLegacyFormatChanID := [32]byte{
    32  		0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x2d, 0x72, 0x65, 0x76,
    33  		0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
    34  	}
    35  	if res.pendingChanID == itestLegacyFormatChanID {
    36  		revocationRoot, err := l.DerivePrivKey(nextRevocationKeyDesc)
    37  		if err != nil {
    38  			return nil, err
    39  		}
    40  
    41  		// Once we have the root, we can then generate our shachain
    42  		// producer and from that generate the per-commitment point.
    43  		revRoot, err := chainhash.NewHash(revocationRoot.Serialize())
    44  		if err != nil {
    45  			return nil, err
    46  		}
    47  
    48  		return shachain.NewRevocationProducer(shachain.ShaHash(*revRoot)), nil
    49  	}
    50  
    51  	// If the DeriveNextKey call returns the first key with Index 0, we need
    52  	// to re-derive the key as the keychain/btcwallet.go DerivePrivKey call
    53  	// special-cases Index 0.
    54  	if nextRevocationKeyDesc.Index == 0 {
    55  		nextRevocationKeyDesc, err = keyRing.DeriveNextKey(
    56  			keychain.KeyFamilyRevocationRoot,
    57  		)
    58  		if err != nil {
    59  			return nil, err
    60  		}
    61  	}
    62  
    63  	res.nextRevocationKeyLoc = nextRevocationKeyDesc.KeyLocator
    64  
    65  	// Perform an ECDH operation between the private key described in
    66  	// nextRevocationKeyDesc and our public multisig key. The result will be
    67  	// used to seed the revocation producer.
    68  	revRoot, err := l.ECDH(
    69  		nextRevocationKeyDesc, res.ourContribution.MultiSigKey.PubKey,
    70  	)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  
    75  	// Once we have the root, we can then generate our shachain producer
    76  	// and from that generate the per-commitment point.
    77  	return shachain.NewRevocationProducer(revRoot), nil
    78  }