revocation_producer_itest.go 2.9 KB

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