mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-29 03:01:52 +01:00
channeldb: prep waiting proof store for taproot proofs
With a migration to migrate existing entries in the waiting proof store to use a type byte prefix.
This commit is contained in:
parent
2a4f36397d
commit
c0b66d76df
@ -26,6 +26,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/channeldb/migration29"
|
||||
"github.com/lightningnetwork/lnd/channeldb/migration30"
|
||||
"github.com/lightningnetwork/lnd/channeldb/migration31"
|
||||
"github.com/lightningnetwork/lnd/channeldb/migration32"
|
||||
"github.com/lightningnetwork/lnd/channeldb/migration_01_to_11"
|
||||
"github.com/lightningnetwork/lnd/clock"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
@ -286,6 +287,10 @@ var (
|
||||
number: 31,
|
||||
migration: migration31.DeleteLastPublishedTxTLB,
|
||||
},
|
||||
{
|
||||
number: 32,
|
||||
migration: migration32.MigrateWaitingProofStore,
|
||||
},
|
||||
}
|
||||
|
||||
// optionalVersions stores all optional migrations that are applied
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/channeldb/migration24"
|
||||
"github.com/lightningnetwork/lnd/channeldb/migration30"
|
||||
"github.com/lightningnetwork/lnd/channeldb/migration31"
|
||||
"github.com/lightningnetwork/lnd/channeldb/migration32"
|
||||
"github.com/lightningnetwork/lnd/channeldb/migration_01_to_11"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
)
|
||||
@ -42,5 +43,6 @@ func UseLogger(logger btclog.Logger) {
|
||||
migration24.UseLogger(logger)
|
||||
migration30.UseLogger(logger)
|
||||
migration31.UseLogger(logger)
|
||||
migration32.UseLogger(logger)
|
||||
kvdb.UseLogger(logger)
|
||||
}
|
||||
|
14
channeldb/migration32/log.go
Normal file
14
channeldb/migration32/log.go
Normal file
@ -0,0 +1,14 @@
|
||||
package migration32
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btclog"
|
||||
)
|
||||
|
||||
// log is a logger that is initialized as disabled. This means the package will
|
||||
// not perform any logging by default until a logger is set.
|
||||
var log = btclog.Disabled
|
||||
|
||||
// UseLogger uses a specified Logger to output package logging info.
|
||||
func UseLogger(logger btclog.Logger) {
|
||||
log = logger
|
||||
}
|
55
channeldb/migration32/migration.go
Normal file
55
channeldb/migration32/migration.go
Normal file
@ -0,0 +1,55 @@
|
||||
package migration32
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
)
|
||||
|
||||
// waitingProofsBucketKey byte string name of the waiting proofs store.
|
||||
var waitingProofsBucketKey = []byte("waitingproofs")
|
||||
|
||||
// MigrateWaitingProofStore migrates the waiting proof store so that all entries
|
||||
// are prefixed with a type byte.
|
||||
func MigrateWaitingProofStore(tx kvdb.RwTx) error {
|
||||
log.Infof("Migrating waiting proof store")
|
||||
|
||||
bucket := tx.ReadWriteBucket(waitingProofsBucketKey)
|
||||
|
||||
// If the bucket does not exist yet, then there are no entries to
|
||||
// migrate.
|
||||
if bucket == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return bucket.ForEach(func(k, v []byte) error {
|
||||
// Skip buckets fields.
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read in the waiting proof using the legacy decoding method.
|
||||
var proof WaitingProof
|
||||
if err := proof.LegacyDecode(bytes.NewReader(v)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Do sanity check to ensure that the proof key is the same as
|
||||
// the key used to store the proof.
|
||||
key := proof.Key()
|
||||
if !bytes.Equal(key[:], k) {
|
||||
return fmt.Errorf("proof key (%x) does not match "+
|
||||
"the key used to store the proof: %x", key, k)
|
||||
}
|
||||
|
||||
// Re-encode the proof using the new, type-prefixed encoding.
|
||||
var b bytes.Buffer
|
||||
err := proof.UpdatedEncode(&b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return bucket.Put(k, b.Bytes())
|
||||
})
|
||||
}
|
100
channeldb/migration32/migration_test.go
Normal file
100
channeldb/migration32/migration_test.go
Normal file
@ -0,0 +1,100 @@
|
||||
package migration32
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
||||
lnwire "github.com/lightningnetwork/lnd/channeldb/migration/lnwire21"
|
||||
"github.com/lightningnetwork/lnd/channeldb/migtest"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
testRBytes, _ = hex.DecodeString("8ce2bc69281ce27da07e6683571" +
|
||||
"319d18e949ddfa2965fb6caa1bf0314f882d7")
|
||||
testSBytes, _ = hex.DecodeString("299105481d63e0f4bc2a" +
|
||||
"88121167221b6700d72a0ead154c03be696a292d24ae")
|
||||
testRScalar = new(btcec.ModNScalar)
|
||||
testSScalar = new(btcec.ModNScalar)
|
||||
_ = testRScalar.SetByteSlice(testRBytes)
|
||||
_ = testSScalar.SetByteSlice(testSBytes)
|
||||
testSig = ecdsa.NewSignature(testRScalar, testSScalar)
|
||||
|
||||
sig, _ = lnwire.NewSigFromSignature(testSig)
|
||||
|
||||
wp1 = &WaitingProof{
|
||||
AnnounceSignatures: &lnwire.AnnounceSignatures{
|
||||
ChannelID: lnwire.ChannelID{1},
|
||||
ShortChannelID: lnwire.NewShortChanIDFromInt(1),
|
||||
NodeSignature: sig,
|
||||
BitcoinSignature: sig,
|
||||
ExtraOpaqueData: []byte{1, 2, 3, 4},
|
||||
},
|
||||
isRemote: false,
|
||||
}
|
||||
|
||||
wp2 = &WaitingProof{
|
||||
AnnounceSignatures: &lnwire.AnnounceSignatures{
|
||||
ChannelID: lnwire.ChannelID{2},
|
||||
ShortChannelID: lnwire.NewShortChanIDFromInt(2),
|
||||
NodeSignature: sig,
|
||||
BitcoinSignature: sig,
|
||||
},
|
||||
isRemote: true,
|
||||
}
|
||||
)
|
||||
|
||||
// TestMigrationWaitingProofStore tests that the MigrateWaitingProofStore
|
||||
// function works as expected.
|
||||
func TestMigrateWaitingProofStore(t *testing.T) {
|
||||
var (
|
||||
key1 = wp1.Key()
|
||||
key2 = wp2.Key()
|
||||
wp1BytesBefore bytes.Buffer
|
||||
wp2BytesBefore bytes.Buffer
|
||||
wp1BytesAfter bytes.Buffer
|
||||
wp2BytesAfter bytes.Buffer
|
||||
)
|
||||
|
||||
err := wp1.LegacyEncode(&wp1BytesBefore)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = wp2.LegacyEncode(&wp2BytesBefore)
|
||||
require.NoError(t, err)
|
||||
|
||||
wpStoreBefore := map[string]interface{}{
|
||||
string(key1[:]): wp1BytesBefore.String(),
|
||||
string(key2[:]): wp2BytesBefore.String(),
|
||||
}
|
||||
|
||||
err = wp1.UpdatedEncode(&wp1BytesAfter)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = wp2.UpdatedEncode(&wp2BytesAfter)
|
||||
require.NoError(t, err)
|
||||
|
||||
wpStoreAfter := map[string]interface{}{
|
||||
string(key1[:]): wp1BytesAfter.String(),
|
||||
string(key2[:]): wp2BytesAfter.String(),
|
||||
}
|
||||
|
||||
before := func(tx kvdb.RwTx) error {
|
||||
return migtest.RestoreDB(
|
||||
tx, waitingProofsBucketKey, wpStoreBefore,
|
||||
)
|
||||
}
|
||||
|
||||
after := func(tx kvdb.RwTx) error {
|
||||
return migtest.VerifyDB(
|
||||
tx, waitingProofsBucketKey, wpStoreAfter,
|
||||
)
|
||||
}
|
||||
|
||||
migtest.ApplyMigration(
|
||||
t, before, after, MigrateWaitingProofStore, false,
|
||||
)
|
||||
}
|
100
channeldb/migration32/waitingproof.go
Normal file
100
channeldb/migration32/waitingproof.go
Normal file
@ -0,0 +1,100 @@
|
||||
package migration32
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
lnwire "github.com/lightningnetwork/lnd/channeldb/migration/lnwire21"
|
||||
)
|
||||
|
||||
var byteOrder = binary.BigEndian
|
||||
|
||||
// WaitingProofType represents the type of the encoded waiting proof.
|
||||
type WaitingProofType uint8
|
||||
|
||||
const (
|
||||
// WaitingProofTypeLegacy represents a waiting proof for legacy P2WSH
|
||||
// channels.
|
||||
WaitingProofTypeLegacy WaitingProofType = 0
|
||||
)
|
||||
|
||||
// WaitingProofKey is the proof key which uniquely identifies the waiting
|
||||
// proof object. The goal of this key is distinguish the local and remote
|
||||
// proof for the same channel id.
|
||||
type WaitingProofKey [9]byte
|
||||
|
||||
// WaitingProof is the storable object, which encapsulate the half proof and
|
||||
// the information about from which side this proof came. This structure is
|
||||
// needed to make channel proof exchange persistent, so that after client
|
||||
// restart we may receive remote/local half proof and process it.
|
||||
type WaitingProof struct {
|
||||
*lnwire.AnnounceSignatures
|
||||
isRemote bool
|
||||
}
|
||||
|
||||
// Key returns the key which uniquely identifies waiting proof.
|
||||
func (p *WaitingProof) Key() WaitingProofKey {
|
||||
var key [9]byte
|
||||
binary.BigEndian.PutUint64(key[:8], p.ShortChannelID.ToUint64())
|
||||
|
||||
if p.isRemote {
|
||||
key[8] = 1
|
||||
}
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
// UpdatedEncode writes the internal representation of waiting proof in byte
|
||||
// stream using the new format that is prefixed with a type byte.
|
||||
func (p *WaitingProof) UpdatedEncode(w io.Writer) error {
|
||||
// Write the type byte.
|
||||
err := binary.Write(w, byteOrder, WaitingProofTypeLegacy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Write(w, byteOrder, p.isRemote); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf, ok := w.(*bytes.Buffer)
|
||||
if !ok {
|
||||
return fmt.Errorf("expect io.Writer to be *bytes.Buffer")
|
||||
}
|
||||
|
||||
return p.AnnounceSignatures.Encode(buf, 0)
|
||||
}
|
||||
|
||||
// LegacyEncode writes the internal representation of waiting proof in byte
|
||||
// stream using the legacy format.
|
||||
func (p *WaitingProof) LegacyEncode(w io.Writer) error {
|
||||
if err := binary.Write(w, byteOrder, p.isRemote); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf, ok := w.(*bytes.Buffer)
|
||||
if !ok {
|
||||
return fmt.Errorf("expect io.Writer to be *bytes.Buffer")
|
||||
}
|
||||
|
||||
return p.AnnounceSignatures.Encode(buf, 0)
|
||||
}
|
||||
|
||||
// LegacyDecode reads the data from the byte stream and initializes the
|
||||
// waiting proof object with it.
|
||||
func (p *WaitingProof) LegacyDecode(r io.Reader) error {
|
||||
if err := binary.Read(r, byteOrder, &p.isRemote); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msg := &lnwire.AnnounceSignatures{}
|
||||
if err := msg.Decode(r, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.AnnounceSignatures = msg
|
||||
|
||||
return nil
|
||||
}
|
@ -7,6 +7,7 @@ import (
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
@ -20,11 +21,6 @@ var (
|
||||
// found by db.
|
||||
ErrWaitingProofNotFound = errors.New("waiting proofs haven't been " +
|
||||
"found")
|
||||
|
||||
// ErrWaitingProofAlreadyExist is returned if waiting proofs haven't been
|
||||
// found by db.
|
||||
ErrWaitingProofAlreadyExist = errors.New("waiting proof with such " +
|
||||
"key already exist")
|
||||
)
|
||||
|
||||
// WaitingProofStore is the bold db map-like storage for half announcement
|
||||
@ -186,29 +182,191 @@ func (s *WaitingProofStore) Get(key WaitingProofKey) (*WaitingProof, error) {
|
||||
// proof for the same channel id.
|
||||
type WaitingProofKey [9]byte
|
||||
|
||||
// WaitingProofType represents the type of the encoded waiting proof.
|
||||
type WaitingProofType uint8
|
||||
|
||||
const (
|
||||
// WaitingProofTypeLegacy represents a waiting proof for legacy P2WSH
|
||||
// channels.
|
||||
WaitingProofTypeLegacy WaitingProofType = 0
|
||||
|
||||
// WaitingProofTypeTaproot represents a waiting proof for taproot
|
||||
// channels.
|
||||
WaitingProofTypeTaproot WaitingProofType = 1
|
||||
)
|
||||
|
||||
// typeToWaitingProofType is a map from WaitingProofType to an empty
|
||||
// instantiation of the associated type.
|
||||
func typeToWaitingProof(pt WaitingProofType) (WaitingProofInterface, bool) {
|
||||
switch pt {
|
||||
case WaitingProofTypeLegacy:
|
||||
return &LegacyWaitingProof{}, true
|
||||
case WaitingProofTypeTaproot:
|
||||
return &TaprootWaitingProof{}, true
|
||||
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
// WaitingProofInterface is an interface that must be implemented by any waiting
|
||||
// proof to be stored in the waiting proof DB.
|
||||
type WaitingProofInterface interface {
|
||||
// SCID returns the short channel ID of the channel that the waiting
|
||||
// proof is for.
|
||||
SCID() lnwire.ShortChannelID
|
||||
|
||||
// Encode encodes the waiting proof to the given buffer.
|
||||
Encode(w *bytes.Buffer, pver uint32) error
|
||||
|
||||
// Decode parses the bytes from the given reader to reconstruct the
|
||||
// waiting proof.
|
||||
Decode(r io.Reader, pver uint32) error
|
||||
|
||||
// Type returns the waiting proof type.
|
||||
Type() WaitingProofType
|
||||
}
|
||||
|
||||
// LegacyWaitingProof is an implementation of the WaitingProofInterface to be
|
||||
// used for legacy, P2WSH channels.
|
||||
type LegacyWaitingProof struct {
|
||||
lnwire.AnnounceSignatures1
|
||||
}
|
||||
|
||||
// SCID returns the short channel ID of the channel that the waiting
|
||||
// proof is for.
|
||||
//
|
||||
// NOTE: this is part of the WaitingProofInterface.
|
||||
func (l *LegacyWaitingProof) SCID() lnwire.ShortChannelID {
|
||||
return l.ShortChannelID
|
||||
}
|
||||
|
||||
// Type returns the waiting proof type.
|
||||
//
|
||||
// NOTE: this is part of the WaitingProofInterface.
|
||||
func (l *LegacyWaitingProof) Type() WaitingProofType {
|
||||
return WaitingProofTypeLegacy
|
||||
}
|
||||
|
||||
var _ WaitingProofInterface = (*LegacyWaitingProof)(nil)
|
||||
|
||||
// TaprootWaitingProof is an implementation of the WaitingProofInterface to be
|
||||
// used for taproot channels.
|
||||
type TaprootWaitingProof struct {
|
||||
lnwire.AnnounceSignatures2
|
||||
|
||||
// AggNonce is the aggregate nonce used to construct the partial
|
||||
// signatures. It will be used as the R value in the final signature.
|
||||
AggNonce *btcec.PublicKey
|
||||
}
|
||||
|
||||
// SCID returns the short channel ID of the channel that the waiting
|
||||
// proof is for.
|
||||
//
|
||||
// NOTE: this is part of the WaitingProofInterface.
|
||||
func (t *TaprootWaitingProof) SCID() lnwire.ShortChannelID {
|
||||
return t.ShortChannelID
|
||||
}
|
||||
|
||||
// Decode parses the bytes from the given reader to reconstruct the
|
||||
// waiting proof.
|
||||
//
|
||||
// NOTE: this is part of the WaitingProofInterface.
|
||||
func (t *TaprootWaitingProof) Decode(r io.Reader, pver uint32) error {
|
||||
// Read byte to see if agg nonce is present.
|
||||
var aggNoncePresent bool
|
||||
if err := binary.Read(r, byteOrder, &aggNoncePresent); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If agg nonce is present, read it in.
|
||||
if aggNoncePresent {
|
||||
var nonceBytes [btcec.PubKeyBytesLenCompressed]byte
|
||||
if err := binary.Read(r, byteOrder, &nonceBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nonce, err := btcec.ParsePubKey(nonceBytes[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.AggNonce = nonce
|
||||
}
|
||||
|
||||
return t.AnnounceSignatures2.Decode(r, pver)
|
||||
}
|
||||
|
||||
// Encode encodes the waiting proof to the given buffer.
|
||||
//
|
||||
// NOTE: this is part of the WaitingProofInterface.
|
||||
func (t *TaprootWaitingProof) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
// If agg nonce is present, write a signaling byte for that.
|
||||
aggNoncePresent := t.AggNonce != nil
|
||||
if err := binary.Write(w, byteOrder, aggNoncePresent); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Now follow with the actual nonce if present.
|
||||
if aggNoncePresent {
|
||||
err := binary.Write(
|
||||
w, byteOrder, t.AggNonce.SerializeCompressed(),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return t.AnnounceSignatures2.Encode(w, pver)
|
||||
}
|
||||
|
||||
// Type returns the waiting proof type.
|
||||
//
|
||||
// NOTE: this is part of the WaitingProofInterface.
|
||||
func (t *TaprootWaitingProof) Type() WaitingProofType {
|
||||
return WaitingProofTypeTaproot
|
||||
}
|
||||
|
||||
var _ WaitingProofInterface = (*TaprootWaitingProof)(nil)
|
||||
|
||||
// WaitingProof is the storable object, which encapsulate the half proof and
|
||||
// the information about from which side this proof came. This structure is
|
||||
// needed to make channel proof exchange persistent, so that after client
|
||||
// restart we may receive remote/local half proof and process it.
|
||||
type WaitingProof struct {
|
||||
*lnwire.AnnounceSignatures1
|
||||
WaitingProofInterface
|
||||
isRemote bool
|
||||
}
|
||||
|
||||
// NewWaitingProof constructs a new waiting prof instance.
|
||||
func NewWaitingProof(isRemote bool,
|
||||
// NewLegacyWaitingProof constructs a new waiting prof instance for a legacy,
|
||||
// P2WSH channel.
|
||||
func NewLegacyWaitingProof(isRemote bool,
|
||||
proof *lnwire.AnnounceSignatures1) *WaitingProof {
|
||||
|
||||
return &WaitingProof{
|
||||
AnnounceSignatures1: proof,
|
||||
isRemote: isRemote,
|
||||
WaitingProofInterface: &LegacyWaitingProof{*proof},
|
||||
isRemote: isRemote,
|
||||
}
|
||||
}
|
||||
|
||||
// NewTaprootWaitingProof constructs a new waiting prof instance for a taproot
|
||||
// channel.
|
||||
func NewTaprootWaitingProof(isRemote bool, proof *lnwire.AnnounceSignatures2,
|
||||
aggNonce *btcec.PublicKey) *WaitingProof {
|
||||
|
||||
return &WaitingProof{
|
||||
WaitingProofInterface: &TaprootWaitingProof{
|
||||
AnnounceSignatures2: *proof,
|
||||
AggNonce: aggNonce,
|
||||
},
|
||||
isRemote: isRemote,
|
||||
}
|
||||
}
|
||||
|
||||
// OppositeKey returns the key which uniquely identifies opposite waiting proof.
|
||||
func (p *WaitingProof) OppositeKey() WaitingProofKey {
|
||||
var key [9]byte
|
||||
binary.BigEndian.PutUint64(key[:8], p.ShortChannelID.ToUint64())
|
||||
binary.BigEndian.PutUint64(key[:8], p.SCID().ToUint64())
|
||||
|
||||
if !p.isRemote {
|
||||
key[8] = 1
|
||||
@ -219,7 +377,7 @@ func (p *WaitingProof) OppositeKey() WaitingProofKey {
|
||||
// Key returns the key which uniquely identifies waiting proof.
|
||||
func (p *WaitingProof) Key() WaitingProofKey {
|
||||
var key [9]byte
|
||||
binary.BigEndian.PutUint64(key[:8], p.ShortChannelID.ToUint64())
|
||||
binary.BigEndian.PutUint64(key[:8], p.SCID().ToUint64())
|
||||
|
||||
if p.isRemote {
|
||||
key[8] = 1
|
||||
@ -229,6 +387,11 @@ func (p *WaitingProof) Key() WaitingProofKey {
|
||||
|
||||
// Encode writes the internal representation of waiting proof in byte stream.
|
||||
func (p *WaitingProof) Encode(w io.Writer) error {
|
||||
// Write the type byte.
|
||||
if err := binary.Write(w, byteOrder, p.Type()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Write(w, byteOrder, p.isRemote); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -240,26 +403,31 @@ func (p *WaitingProof) Encode(w io.Writer) error {
|
||||
return fmt.Errorf("expect io.Writer to be *bytes.Buffer")
|
||||
}
|
||||
|
||||
if err := p.AnnounceSignatures1.Encode(buf, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return p.WaitingProofInterface.Encode(buf, 0)
|
||||
}
|
||||
|
||||
// Decode reads the data from the byte stream and initializes the
|
||||
// waiting proof object with it.
|
||||
func (p *WaitingProof) Decode(r io.Reader) error {
|
||||
var proofType WaitingProofType
|
||||
if err := binary.Read(r, byteOrder, &proofType); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Read(r, byteOrder, &p.isRemote); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msg := &lnwire.AnnounceSignatures1{}
|
||||
if err := msg.Decode(r, 0); err != nil {
|
||||
proof, ok := typeToWaitingProof(proofType)
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown proof type")
|
||||
}
|
||||
|
||||
if err := proof.Decode(r, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.AnnounceSignatures1 = msg
|
||||
p.WaitingProofInterface = proof
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
package channeldb
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -18,35 +18,54 @@ func TestWaitingProofStore(t *testing.T) {
|
||||
db, err := MakeTestDB(t)
|
||||
require.NoError(t, err, "failed to make test database")
|
||||
|
||||
proof1 := NewWaitingProof(true, &lnwire.AnnounceSignatures1{
|
||||
proof1 := NewLegacyWaitingProof(true, &lnwire.AnnounceSignatures1{
|
||||
NodeSignature: wireSig,
|
||||
BitcoinSignature: wireSig,
|
||||
ExtraOpaqueData: make([]byte, 0),
|
||||
})
|
||||
|
||||
// No agg nonce.
|
||||
proof2 := NewTaprootWaitingProof(true, &lnwire.AnnounceSignatures2{
|
||||
ShortChannelID: lnwire.ShortChannelID{
|
||||
BlockHeight: 2000,
|
||||
},
|
||||
PartialSignature: *randPartialSig(t),
|
||||
ExtraOpaqueData: make([]byte, 0),
|
||||
}, nil)
|
||||
|
||||
// With agg nonce.
|
||||
priv, err := btcec.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
proof3 := NewTaprootWaitingProof(true, &lnwire.AnnounceSignatures2{
|
||||
ShortChannelID: lnwire.ShortChannelID{
|
||||
BlockHeight: 2000,
|
||||
},
|
||||
PartialSignature: *randPartialSig(t),
|
||||
ExtraOpaqueData: make([]byte, 0),
|
||||
}, priv.PubKey())
|
||||
|
||||
proofs := []*WaitingProof{
|
||||
proof1,
|
||||
proof2,
|
||||
proof3,
|
||||
}
|
||||
|
||||
store, err := NewWaitingProofStore(db)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create the waiting proofs storage: %v",
|
||||
err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
if err := store.Add(proof1); err != nil {
|
||||
t.Fatalf("unable add proof to storage: %v", err)
|
||||
}
|
||||
for _, proof := range proofs {
|
||||
require.NoError(t, store.Add(proof))
|
||||
|
||||
proof2, err := store.Get(proof1.Key())
|
||||
require.NoError(t, err, "unable retrieve proof from storage")
|
||||
if !reflect.DeepEqual(proof1, proof2) {
|
||||
t.Fatalf("wrong proof retrieved: expected %v, got %v",
|
||||
spew.Sdump(proof1), spew.Sdump(proof2))
|
||||
}
|
||||
p2, err := store.Get(proof.Key())
|
||||
require.NoError(t, err, "unable retrieve proof from storage")
|
||||
require.Equal(t, proof, p2)
|
||||
|
||||
if _, err := store.Get(proof1.OppositeKey()); err != ErrWaitingProofNotFound {
|
||||
t.Fatalf("proof shouldn't be found: %v", err)
|
||||
}
|
||||
_, err = store.Get(proof.OppositeKey())
|
||||
require.ErrorIs(t, err, ErrWaitingProofNotFound)
|
||||
|
||||
if err := store.Remove(proof1.Key()); err != nil {
|
||||
t.Fatalf("unable remove proof from storage: %v", err)
|
||||
err = store.Remove(proof.Key())
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
if err := store.ForAll(func(proof *WaitingProof) error {
|
||||
@ -55,3 +74,16 @@ func TestWaitingProofStore(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func randPartialSig(t *testing.T) *lnwire.PartialSig {
|
||||
var sigBytes [32]byte
|
||||
_, err := rand.Read(sigBytes[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
var s btcec.ModNScalar
|
||||
s.SetByteSlice(sigBytes[:])
|
||||
|
||||
return &lnwire.PartialSig{
|
||||
Sig: s,
|
||||
}
|
||||
}
|
||||
|
@ -3347,7 +3347,7 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
|
||||
return nil, false
|
||||
}
|
||||
|
||||
proof := channeldb.NewWaitingProof(nMsg.isRemote, ann)
|
||||
proof := channeldb.NewLegacyWaitingProof(nMsg.isRemote, ann)
|
||||
err := d.cfg.WaitingProofStore.Add(proof)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("unable to store the proof for "+
|
||||
@ -3459,8 +3459,8 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
|
||||
// announcement. If we didn't receive the opposite half of the proof
|
||||
// then we should store this one, and wait for the opposite to be
|
||||
// received.
|
||||
proof := channeldb.NewWaitingProof(nMsg.isRemote, ann)
|
||||
oppProof, err := d.cfg.WaitingProofStore.Get(proof.OppositeKey())
|
||||
proof := channeldb.NewLegacyWaitingProof(nMsg.isRemote, ann)
|
||||
oppositeProof, err := d.cfg.WaitingProofStore.Get(proof.OppositeKey())
|
||||
if err != nil && err != channeldb.ErrWaitingProofNotFound {
|
||||
err := fmt.Errorf("unable to get the opposite proof for "+
|
||||
"short_chan_id=%v: %v", shortChanID, err)
|
||||
@ -3487,6 +3487,14 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
|
||||
return nil, false
|
||||
}
|
||||
|
||||
oppProof, ok := oppositeProof.
|
||||
WaitingProofInterface.(*channeldb.LegacyWaitingProof)
|
||||
if !ok {
|
||||
nMsg.err <- fmt.Errorf("got wrong waiting proof type")
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// We now have both halves of the channel announcement proof, then
|
||||
// we'll reconstruct the initial announcement so we can validate it
|
||||
// shortly below.
|
||||
|
Loading…
x
Reference in New Issue
Block a user