Merge pull request #706 from Roasbeef/gc-fixes-reject-cache
multi: memoize pubkey+signature decoding to reduce GC bursts, add reject cache to stop zombie churn
This commit is contained in:
commit
7bbcbc6fea
@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/roasbeef/btcd/btcec"
|
"github.com/roasbeef/btcd/btcec"
|
||||||
"github.com/roasbeef/btcd/wire"
|
"github.com/roasbeef/btcd/wire"
|
||||||
"github.com/roasbeef/btcutil"
|
"github.com/roasbeef/btcutil"
|
||||||
|
@ -63,7 +63,8 @@ var _ Node = (*dbNode)(nil)
|
|||||||
//
|
//
|
||||||
// NOTE: Part of the autopilot.Node interface.
|
// NOTE: Part of the autopilot.Node interface.
|
||||||
func (d dbNode) PubKey() *btcec.PublicKey {
|
func (d dbNode) PubKey() *btcec.PublicKey {
|
||||||
return d.node.PubKey
|
pubKey, _ := d.node.PubKey()
|
||||||
|
return pubKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// Addrs returns a slice of publicly reachable public TCP addresses that the
|
// Addrs returns a slice of publicly reachable public TCP addresses that the
|
||||||
@ -84,12 +85,13 @@ func (d dbNode) ForEachChannel(cb func(ChannelEdge) error) error {
|
|||||||
return d.node.ForEachChannel(d.tx, func(tx *bolt.Tx,
|
return d.node.ForEachChannel(d.tx, func(tx *bolt.Tx,
|
||||||
ei *channeldb.ChannelEdgeInfo, ep, _ *channeldb.ChannelEdgePolicy) error {
|
ei *channeldb.ChannelEdgeInfo, ep, _ *channeldb.ChannelEdgePolicy) error {
|
||||||
|
|
||||||
|
pubkey, _ := ep.Node.PubKey()
|
||||||
edge := ChannelEdge{
|
edge := ChannelEdge{
|
||||||
Channel: Channel{
|
Channel: Channel{
|
||||||
ChanID: lnwire.NewShortChanIDFromInt(ep.ChannelID),
|
ChanID: lnwire.NewShortChanIDFromInt(ep.ChannelID),
|
||||||
Capacity: ei.Capacity,
|
Capacity: ei.Capacity,
|
||||||
FundedAmt: ei.Capacity,
|
FundedAmt: ei.Capacity,
|
||||||
Node: NewNodeID(ep.Node.PubKey),
|
Node: NewNodeID(pubkey),
|
||||||
},
|
},
|
||||||
Peer: dbNode{
|
Peer: dbNode{
|
||||||
tx: tx,
|
tx: tx,
|
||||||
@ -138,7 +140,6 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey,
|
|||||||
fallthrough
|
fallthrough
|
||||||
case err == channeldb.ErrGraphNotFound:
|
case err == channeldb.ErrGraphNotFound:
|
||||||
graphNode := &channeldb.LightningNode{
|
graphNode := &channeldb.LightningNode{
|
||||||
PubKey: pub,
|
|
||||||
HaveNodeAnnouncement: true,
|
HaveNodeAnnouncement: true,
|
||||||
Addresses: []net.Addr{
|
Addresses: []net.Addr{
|
||||||
&net.TCPAddr{
|
&net.TCPAddr{
|
||||||
@ -147,8 +148,9 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey,
|
|||||||
},
|
},
|
||||||
Features: lnwire.NewFeatureVector(nil,
|
Features: lnwire.NewFeatureVector(nil,
|
||||||
lnwire.GlobalFeatures),
|
lnwire.GlobalFeatures),
|
||||||
AuthSig: testSig,
|
AuthSigBytes: testSig.Serialize(),
|
||||||
}
|
}
|
||||||
|
graphNode.AddPubKey(pub)
|
||||||
if err := d.db.AddLightningNode(graphNode); err != nil {
|
if err := d.db.AddLightningNode(graphNode); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -164,7 +166,6 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dbNode := &channeldb.LightningNode{
|
dbNode := &channeldb.LightningNode{
|
||||||
PubKey: nodeKey,
|
|
||||||
HaveNodeAnnouncement: true,
|
HaveNodeAnnouncement: true,
|
||||||
Addresses: []net.Addr{
|
Addresses: []net.Addr{
|
||||||
&net.TCPAddr{
|
&net.TCPAddr{
|
||||||
@ -172,8 +173,9 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey,
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Features: lnwire.NewFeatureVector(nil, lnwire.GlobalFeatures),
|
Features: lnwire.NewFeatureVector(nil, lnwire.GlobalFeatures),
|
||||||
AuthSig: testSig,
|
AuthSigBytes: testSig.Serialize(),
|
||||||
}
|
}
|
||||||
|
dbNode.AddPubKey(nodeKey)
|
||||||
if err := d.db.AddLightningNode(dbNode); err != nil {
|
if err := d.db.AddLightningNode(dbNode); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -192,30 +194,25 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey,
|
|||||||
}
|
}
|
||||||
|
|
||||||
var lnNode1, lnNode2 *btcec.PublicKey
|
var lnNode1, lnNode2 *btcec.PublicKey
|
||||||
node1Bytes := vertex1.PubKey.SerializeCompressed()
|
if bytes.Compare(vertex1.PubKeyBytes[:], vertex2.PubKeyBytes[:]) == -1 {
|
||||||
node2Bytes := vertex2.PubKey.SerializeCompressed()
|
lnNode1, _ = vertex1.PubKey()
|
||||||
if bytes.Compare(node1Bytes, node2Bytes) == -1 {
|
lnNode2, _ = vertex2.PubKey()
|
||||||
lnNode1 = vertex1.PubKey
|
|
||||||
lnNode2 = vertex2.PubKey
|
|
||||||
} else {
|
} else {
|
||||||
lnNode1 = vertex2.PubKey
|
lnNode1, _ = vertex2.PubKey()
|
||||||
lnNode2 = vertex1.PubKey
|
lnNode2, _ = vertex1.PubKey()
|
||||||
}
|
}
|
||||||
|
|
||||||
chanID := randChanID()
|
chanID := randChanID()
|
||||||
edge := &channeldb.ChannelEdgeInfo{
|
edge := &channeldb.ChannelEdgeInfo{
|
||||||
ChannelID: chanID.ToUint64(),
|
ChannelID: chanID.ToUint64(),
|
||||||
NodeKey1: lnNode1,
|
|
||||||
NodeKey2: lnNode2,
|
|
||||||
BitcoinKey1: vertex1.PubKey,
|
|
||||||
BitcoinKey2: vertex2.PubKey,
|
|
||||||
Capacity: capacity,
|
Capacity: capacity,
|
||||||
}
|
}
|
||||||
|
edge.AddNodeKeys(lnNode1, lnNode2, lnNode1, lnNode2)
|
||||||
if err := d.db.AddChannelEdge(edge); err != nil {
|
if err := d.db.AddChannelEdge(edge); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
edgePolicy := &channeldb.ChannelEdgePolicy{
|
edgePolicy := &channeldb.ChannelEdgePolicy{
|
||||||
Signature: testSig,
|
SigBytes: testSig.Serialize(),
|
||||||
ChannelID: chanID.ToUint64(),
|
ChannelID: chanID.ToUint64(),
|
||||||
LastUpdate: time.Now(),
|
LastUpdate: time.Now(),
|
||||||
TimeLockDelta: 10,
|
TimeLockDelta: 10,
|
||||||
@ -229,7 +226,7 @@ func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey,
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
edgePolicy = &channeldb.ChannelEdgePolicy{
|
edgePolicy = &channeldb.ChannelEdgePolicy{
|
||||||
Signature: testSig,
|
SigBytes: testSig.Serialize(),
|
||||||
ChannelID: chanID.ToUint64(),
|
ChannelID: chanID.ToUint64(),
|
||||||
LastUpdate: time.Now(),
|
LastUpdate: time.Now(),
|
||||||
TimeLockDelta: 10,
|
TimeLockDelta: 10,
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/roasbeef/btcd/btcec"
|
|
||||||
"github.com/roasbeef/btcd/txscript"
|
"github.com/roasbeef/btcd/txscript"
|
||||||
"github.com/roasbeef/btcd/wire"
|
"github.com/roasbeef/btcd/wire"
|
||||||
"github.com/roasbeef/btcutil"
|
"github.com/roasbeef/btcutil"
|
||||||
@ -410,12 +409,12 @@ func (c *channelCloser) ProcessCloseMsg(msg lnwire.Message) ([]lnwire.Message, b
|
|||||||
// transaction! We'll craft the final closing transaction so
|
// transaction! We'll craft the final closing transaction so
|
||||||
// we can broadcast it to the network.
|
// we can broadcast it to the network.
|
||||||
matchingSig := c.priorFeeOffers[remoteProposedFee].Signature
|
matchingSig := c.priorFeeOffers[remoteProposedFee].Signature
|
||||||
localSig := append(
|
localSigBytes := matchingSig.ToSignatureBytes()
|
||||||
matchingSig.Serialize(), byte(txscript.SigHashAll),
|
localSig := append(localSigBytes, byte(txscript.SigHashAll))
|
||||||
)
|
|
||||||
remoteSig := append(
|
remoteSigBytes := closeSignedMsg.Signature.ToSignatureBytes()
|
||||||
closeSignedMsg.Signature.Serialize(), byte(txscript.SigHashAll),
|
remoteSig := append(remoteSigBytes, byte(txscript.SigHashAll))
|
||||||
)
|
|
||||||
closeTx, finalLocalBalance, err := c.cfg.channel.CompleteCooperativeClose(
|
closeTx, finalLocalBalance, err := c.cfg.channel.CompleteCooperativeClose(
|
||||||
localSig, remoteSig, c.localDeliveryScript,
|
localSig, remoteSig, c.localDeliveryScript,
|
||||||
c.remoteDeliveryScript, remoteProposedFee,
|
c.remoteDeliveryScript, remoteProposedFee,
|
||||||
@ -512,7 +511,7 @@ func (c *channelCloser) proposeCloseSigned(fee btcutil.Amount) (*lnwire.ClosingS
|
|||||||
// party responds we'll be able to decide if we've agreed on fees or
|
// party responds we'll be able to decide if we've agreed on fees or
|
||||||
// not.
|
// not.
|
||||||
c.lastFeeProposal = fee
|
c.lastFeeProposal = fee
|
||||||
parsedSig, err := btcec.ParseSignature(rawSig, btcec.S256())
|
parsedSig, err := lnwire.NewSigFromRawSignature(rawSig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,8 @@ var (
|
|||||||
Index: 0,
|
Index: 0,
|
||||||
}
|
}
|
||||||
privKey, pubKey = btcec.PrivKeyFromBytes(btcec.S256(), key[:])
|
privKey, pubKey = btcec.PrivKeyFromBytes(btcec.S256(), key[:])
|
||||||
|
|
||||||
|
wireSig, _ = lnwire.NewSigFromSignature(testSig)
|
||||||
)
|
)
|
||||||
|
|
||||||
// makeTestDB creates a new instance of the ChannelDB for testing purposes. A
|
// makeTestDB creates a new instance of the ChannelDB for testing purposes. A
|
||||||
@ -428,10 +430,10 @@ func TestChannelStateTransition(t *testing.T) {
|
|||||||
Commitment: remoteCommit,
|
Commitment: remoteCommit,
|
||||||
CommitSig: &lnwire.CommitSig{
|
CommitSig: &lnwire.CommitSig{
|
||||||
ChanID: lnwire.ChannelID(key),
|
ChanID: lnwire.ChannelID(key),
|
||||||
CommitSig: testSig,
|
CommitSig: wireSig,
|
||||||
HtlcSigs: []*btcec.Signature{
|
HtlcSigs: []lnwire.Sig{
|
||||||
testSig,
|
wireSig,
|
||||||
testSig,
|
wireSig,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
LogUpdates: []LogUpdate{
|
LogUpdates: []LogUpdate{
|
||||||
|
@ -309,7 +309,8 @@ func (c *ChannelGraph) SourceNode() (*LightningNode, error) {
|
|||||||
// node is to be used as the center of a star-graph within path finding
|
// node is to be used as the center of a star-graph within path finding
|
||||||
// algorithms.
|
// algorithms.
|
||||||
func (c *ChannelGraph) SetSourceNode(node *LightningNode) error {
|
func (c *ChannelGraph) SetSourceNode(node *LightningNode) error {
|
||||||
nodePub := node.PubKey.SerializeCompressed()
|
nodePubBytes := node.PubKeyBytes[:]
|
||||||
|
|
||||||
return c.db.Update(func(tx *bolt.Tx) error {
|
return c.db.Update(func(tx *bolt.Tx) error {
|
||||||
// First grab the nodes bucket which stores the mapping from
|
// First grab the nodes bucket which stores the mapping from
|
||||||
// pubKey to node information.
|
// pubKey to node information.
|
||||||
@ -320,7 +321,7 @@ func (c *ChannelGraph) SetSourceNode(node *LightningNode) error {
|
|||||||
|
|
||||||
// Next we create the mapping from source to the targeted
|
// Next we create the mapping from source to the targeted
|
||||||
// public key.
|
// public key.
|
||||||
if err := nodes.Put(sourceKey, nodePub); err != nil {
|
if err := nodes.Put(sourceKey, nodePubBytes); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -976,13 +977,13 @@ func (c *ChannelGraph) UpdateEdgePolicy(edge *ChannelEdgePolicy) error {
|
|||||||
// from it. As the graph is directed, a node will also have an incoming edge
|
// from it. As the graph is directed, a node will also have an incoming edge
|
||||||
// attached to it for each outgoing edge.
|
// attached to it for each outgoing edge.
|
||||||
type LightningNode struct {
|
type LightningNode struct {
|
||||||
// PubKey is the node's long-term identity public key. This key will be
|
// PubKeyBytes is the raw bytes of the public key of the target node.
|
||||||
// used to authenticated any advertisements/updates sent by the node.
|
PubKeyBytes [33]byte
|
||||||
PubKey *btcec.PublicKey
|
pubKey *btcec.PublicKey
|
||||||
|
|
||||||
// HaveNodeAnnouncement indicates whether we received a node announcement
|
// HaveNodeAnnouncement indicates whether we received a node
|
||||||
// for this particular node. If true, the remaining fields will be set,
|
// announcement for this particular node. If true, the remaining fields
|
||||||
// if false only the PubKey is known for this node.
|
// will be set, if false only the PubKey is known for this node.
|
||||||
HaveNodeAnnouncement bool
|
HaveNodeAnnouncement bool
|
||||||
|
|
||||||
// LastUpdate is the last time the vertex information for this node has
|
// LastUpdate is the last time the vertex information for this node has
|
||||||
@ -999,11 +1000,9 @@ type LightningNode struct {
|
|||||||
// a node's identity or to serve as a short ID for an address book.
|
// a node's identity or to serve as a short ID for an address book.
|
||||||
Alias string
|
Alias string
|
||||||
|
|
||||||
// AuthSig is a signature under the advertised public key which serves
|
// AuthSigBytes is the raw signature under the advertised public key
|
||||||
// to authenticate the attributes announced by this node.
|
// which serves to authenticate the attributes announced by this node.
|
||||||
//
|
AuthSigBytes []byte
|
||||||
// TODO(roasbeef): hook into serialization once full verification is in
|
|
||||||
AuthSig *btcec.Signature
|
|
||||||
|
|
||||||
// Features is the list of protocol features supported by this node.
|
// Features is the list of protocol features supported by this node.
|
||||||
Features *lnwire.FeatureVector
|
Features *lnwire.FeatureVector
|
||||||
@ -1016,6 +1015,42 @@ type LightningNode struct {
|
|||||||
// TODO(roasbeef): add update method and fetch?
|
// TODO(roasbeef): add update method and fetch?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PubKey is the node's long-term identity public key. This key will be used to
|
||||||
|
// authenticated any advertisements/updates sent by the node.
|
||||||
|
//
|
||||||
|
// NOTE: By having this method to access an attribute, we ensure we only need
|
||||||
|
// to fully deserialize the pubkey if absolutely necessary.
|
||||||
|
func (l *LightningNode) PubKey() (*btcec.PublicKey, error) {
|
||||||
|
if l.pubKey != nil {
|
||||||
|
return l.pubKey, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := btcec.ParsePubKey(l.PubKeyBytes[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
l.pubKey = key
|
||||||
|
l.pubKey.Curve = nil
|
||||||
|
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuthSig is a signature under the advertised public key which serves to
|
||||||
|
// authenticate the attributes announced by this node.
|
||||||
|
//
|
||||||
|
// NOTE: By having this method to access an attribute, we ensure we only need
|
||||||
|
// to fully deserialize the signature if absolutely necessary.
|
||||||
|
func (l *LightningNode) AuthSig() (*btcec.Signature, error) {
|
||||||
|
return btcec.ParseSignature(l.AuthSigBytes, btcec.S256())
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddPubKey is a setter-link method that can be used to swap out the public
|
||||||
|
// key for a node.
|
||||||
|
func (l *LightningNode) AddPubKey(key *btcec.PublicKey) {
|
||||||
|
l.pubKey = key
|
||||||
|
copy(l.PubKeyBytes[:], key.SerializeCompressed())
|
||||||
|
}
|
||||||
|
|
||||||
// FetchLightningNode attempts to look up a target node by its identity public
|
// FetchLightningNode attempts to look up a target node by its identity public
|
||||||
// key. If the node isn't found in the database, then ErrGraphNodeNotFound is
|
// key. If the node isn't found in the database, then ErrGraphNodeNotFound is
|
||||||
// returned.
|
// returned.
|
||||||
@ -1062,13 +1097,12 @@ func (c *ChannelGraph) FetchLightningNode(pub *btcec.PublicKey) (*LightningNode,
|
|||||||
// timestamp of when the data for the node was lasted updated is returned along
|
// timestamp of when the data for the node was lasted updated is returned along
|
||||||
// with a true boolean. Otherwise, an empty time.Time is returned with a false
|
// with a true boolean. Otherwise, an empty time.Time is returned with a false
|
||||||
// boolean.
|
// boolean.
|
||||||
func (c *ChannelGraph) HasLightningNode(pub *btcec.PublicKey) (time.Time, bool, error) {
|
func (c *ChannelGraph) HasLightningNode(nodePub [33]byte) (time.Time, bool, error) {
|
||||||
var (
|
var (
|
||||||
updateTime time.Time
|
updateTime time.Time
|
||||||
exists bool
|
exists bool
|
||||||
)
|
)
|
||||||
|
|
||||||
nodePub := pub.SerializeCompressed()
|
|
||||||
err := c.db.View(func(tx *bolt.Tx) error {
|
err := c.db.View(func(tx *bolt.Tx) error {
|
||||||
// First grab the nodes bucket which stores the mapping from
|
// First grab the nodes bucket which stores the mapping from
|
||||||
// pubKey to node information.
|
// pubKey to node information.
|
||||||
@ -1079,7 +1113,7 @@ func (c *ChannelGraph) HasLightningNode(pub *btcec.PublicKey) (time.Time, bool,
|
|||||||
|
|
||||||
// If a key for this serialized public key isn't found, we can
|
// If a key for this serialized public key isn't found, we can
|
||||||
// exit early.
|
// exit early.
|
||||||
nodeBytes := nodes.Get(nodePub)
|
nodeBytes := nodes.Get(nodePub[:])
|
||||||
if nodeBytes == nil {
|
if nodeBytes == nil {
|
||||||
exists = false
|
exists = false
|
||||||
return nil
|
return nil
|
||||||
@ -1119,7 +1153,11 @@ func (c *ChannelGraph) HasLightningNode(pub *btcec.PublicKey) (time.Time, bool,
|
|||||||
func (l *LightningNode) ForEachChannel(tx *bolt.Tx,
|
func (l *LightningNode) ForEachChannel(tx *bolt.Tx,
|
||||||
cb func(*bolt.Tx, *ChannelEdgeInfo, *ChannelEdgePolicy, *ChannelEdgePolicy) error) error {
|
cb func(*bolt.Tx, *ChannelEdgeInfo, *ChannelEdgePolicy, *ChannelEdgePolicy) error) error {
|
||||||
|
|
||||||
nodePub := l.PubKey.SerializeCompressed()
|
pub, err := l.PubKey()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
nodePub := pub.SerializeCompressed()
|
||||||
|
|
||||||
traversal := func(tx *bolt.Tx) error {
|
traversal := func(tx *bolt.Tx) error {
|
||||||
nodes := tx.Bucket(nodeBucket)
|
nodes := tx.Bucket(nodeBucket)
|
||||||
@ -1172,7 +1210,12 @@ func (l *LightningNode) ForEachChannel(tx *bolt.Tx,
|
|||||||
|
|
||||||
// We'll also fetch the incoming edge so this
|
// We'll also fetch the incoming edge so this
|
||||||
// information can be available to the caller.
|
// information can be available to the caller.
|
||||||
incomingNode := toEdgePolicy.Node.PubKey.SerializeCompressed()
|
incomingNodeKey, err := toEdgePolicy.Node.PubKey()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
incomingNode := incomingNodeKey.SerializeCompressed()
|
||||||
|
|
||||||
fromEdgePolicy, err := fetchChanEdgePolicy(
|
fromEdgePolicy, err := fetchChanEdgePolicy(
|
||||||
edges, chanID, incomingNode, nodes,
|
edges, chanID, incomingNode, nodes,
|
||||||
)
|
)
|
||||||
@ -1227,29 +1270,21 @@ type ChannelEdgeInfo struct {
|
|||||||
// * must add chain hash to prefix as well
|
// * must add chain hash to prefix as well
|
||||||
ChainHash chainhash.Hash
|
ChainHash chainhash.Hash
|
||||||
|
|
||||||
// NodeKey1 is the identity public key of the "first" node that was
|
// NodeKey1Bytes is the raw public key of the first node.
|
||||||
// involved in the creation of this channel. A node is considered
|
NodeKey1Bytes [33]byte
|
||||||
// "first" if the lexicographical ordering the its serialized public
|
nodeKey1 *btcec.PublicKey
|
||||||
// key is "smaller" than that of the other node involved in channel
|
|
||||||
// creation.
|
|
||||||
NodeKey1 *btcec.PublicKey
|
|
||||||
|
|
||||||
// NodeKey2 is the identity public key of the "second" node that was
|
// NodeKey2Bytes is the raw public key of the first node.
|
||||||
// involved in the creation of this channel. A node is considered
|
NodeKey2Bytes [33]byte
|
||||||
// "second" if the lexicographical ordering the its serialized public
|
nodeKey2 *btcec.PublicKey
|
||||||
// key is "larger" than that of the other node involved in channel
|
|
||||||
// creation.
|
|
||||||
NodeKey2 *btcec.PublicKey
|
|
||||||
|
|
||||||
// BitcoinKey1 is the Bitcoin multi-sig key belonging to the first
|
// BitcoinKey1Bytes is the raw public key of the first node.
|
||||||
// node, that was involved in the funding transaction that originally
|
BitcoinKey1Bytes [33]byte
|
||||||
// created the channel that this struct represents.
|
bitcoinKey1 *btcec.PublicKey
|
||||||
BitcoinKey1 *btcec.PublicKey
|
|
||||||
|
|
||||||
// BitcoinKey2 is the Bitcoin multi-sig key belonging to the second
|
// BitcoinKey2Bytes is the raw public key of the first node.
|
||||||
// node, that was involved in the funding transaction that originally
|
BitcoinKey2Bytes [33]byte
|
||||||
// created the channel that this struct represents.
|
bitcoinKey2 *btcec.PublicKey
|
||||||
BitcoinKey2 *btcec.PublicKey
|
|
||||||
|
|
||||||
// Features is an opaque byte slice that encodes the set of channel
|
// Features is an opaque byte slice that encodes the set of channel
|
||||||
// specific features that this channel edge supports.
|
// specific features that this channel edge supports.
|
||||||
@ -1269,6 +1304,107 @@ type ChannelEdgeInfo struct {
|
|||||||
Capacity btcutil.Amount
|
Capacity btcutil.Amount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddNodeKeys is a setter-like method that can be used to replace the set of
|
||||||
|
// keys for the target ChannelEdgeInfo.
|
||||||
|
func (c *ChannelEdgeInfo) AddNodeKeys(nodeKey1, nodeKey2, bitcoinKey1,
|
||||||
|
bitcoinKey2 *btcec.PublicKey) {
|
||||||
|
|
||||||
|
c.nodeKey1 = nodeKey1
|
||||||
|
copy(c.NodeKey1Bytes[:], c.nodeKey1.SerializeCompressed())
|
||||||
|
|
||||||
|
c.nodeKey2 = nodeKey2
|
||||||
|
copy(c.NodeKey2Bytes[:], nodeKey2.SerializeCompressed())
|
||||||
|
|
||||||
|
c.bitcoinKey1 = bitcoinKey1
|
||||||
|
copy(c.BitcoinKey1Bytes[:], c.bitcoinKey1.SerializeCompressed())
|
||||||
|
|
||||||
|
c.bitcoinKey2 = bitcoinKey2
|
||||||
|
copy(c.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed())
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodeKey1 is the identity public key of the "first" node that was involved in
|
||||||
|
// the creation of this channel. A node is considered "first" if the
|
||||||
|
// lexicographical ordering the its serialized public key is "smaller" than
|
||||||
|
// that of the other node involved in channel creation.
|
||||||
|
//
|
||||||
|
// NOTE: By having this method to access an attribute, we ensure we only need
|
||||||
|
// to fully deserialize the pubkey if absolutely necessary.
|
||||||
|
func (c *ChannelEdgeInfo) NodeKey1() (*btcec.PublicKey, error) {
|
||||||
|
if c.nodeKey1 != nil {
|
||||||
|
return c.nodeKey1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := btcec.ParsePubKey(c.NodeKey1Bytes[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.nodeKey1 = key
|
||||||
|
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodeKey2 is the identity public key of the "second" node that was
|
||||||
|
// involved in the creation of this channel. A node is considered
|
||||||
|
// "second" if the lexicographical ordering the its serialized public
|
||||||
|
// key is "larger" than that of the other node involved in channel
|
||||||
|
// creation.
|
||||||
|
//
|
||||||
|
// NOTE: By having this method to access an attribute, we ensure we only need
|
||||||
|
// to fully deserialize the pubkey if absolutely necessary.
|
||||||
|
func (c *ChannelEdgeInfo) NodeKey2() (*btcec.PublicKey, error) {
|
||||||
|
if c.nodeKey2 != nil {
|
||||||
|
return c.nodeKey2, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := btcec.ParsePubKey(c.NodeKey2Bytes[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.nodeKey2 = key
|
||||||
|
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BitcoinKey1 is the Bitcoin multi-sig key belonging to the first
|
||||||
|
// node, that was involved in the funding transaction that originally
|
||||||
|
// created the channel that this struct represents.
|
||||||
|
//
|
||||||
|
// NOTE: By having this method to access an attribute, we ensure we only need
|
||||||
|
// to fully deserialize the pubkey if absolutely necessary.
|
||||||
|
func (c *ChannelEdgeInfo) BitcoinKey1() (*btcec.PublicKey, error) {
|
||||||
|
if c.bitcoinKey1 != nil {
|
||||||
|
return c.bitcoinKey1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := btcec.ParsePubKey(c.BitcoinKey1Bytes[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.bitcoinKey1 = key
|
||||||
|
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BitcoinKey2 is the Bitcoin multi-sig key belonging to the second
|
||||||
|
// node, that was involved in the funding transaction that originally
|
||||||
|
// created the channel that this struct represents.
|
||||||
|
//
|
||||||
|
// NOTE: By having this method to access an attribute, we ensure we only need
|
||||||
|
// to fully deserialize the pubkey if absolutely necessary.
|
||||||
|
func (c *ChannelEdgeInfo) BitcoinKey2() (*btcec.PublicKey, error) {
|
||||||
|
if c.bitcoinKey2 != nil {
|
||||||
|
return c.bitcoinKey2, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := btcec.ParsePubKey(c.BitcoinKey2Bytes[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.bitcoinKey2 = key
|
||||||
|
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ChannelAuthProof is the authentication proof (the signature portion) for a
|
// ChannelAuthProof is the authentication proof (the signature portion) for a
|
||||||
// channel. Using the four signatures contained in the struct, and some
|
// channel. Using the four signatures contained in the struct, and some
|
||||||
// auxillary knowledge (the funding script, node identities, and outpoint) nodes
|
// auxillary knowledge (the funding script, node identities, and outpoint) nodes
|
||||||
@ -1277,32 +1413,124 @@ type ChannelEdgeInfo struct {
|
|||||||
// nodeID1 || nodeID2 || bitcoinKey1|| bitcoinKey2 || 2-byte-feature-len ||
|
// nodeID1 || nodeID2 || bitcoinKey1|| bitcoinKey2 || 2-byte-feature-len ||
|
||||||
// features.
|
// features.
|
||||||
type ChannelAuthProof struct {
|
type ChannelAuthProof struct {
|
||||||
// NodeSig1 is the signature using the identity key of the node that is
|
// nodeSig1 is a cached instance of the first node signature.
|
||||||
// first in a lexicographical ordering of the serialized public keys of
|
nodeSig1 *btcec.Signature
|
||||||
// the two nodes that created the channel.
|
|
||||||
NodeSig1 *btcec.Signature
|
|
||||||
|
|
||||||
// NodeSig2 is the signature using the identity key of the node that is
|
// NodeSig1Bytes are the raw bytes of the first node signature encoded
|
||||||
// second in a lexicographical ordering of the serialized public keys
|
// in DER format.
|
||||||
// of the two nodes that created the channel.
|
NodeSig1Bytes []byte
|
||||||
NodeSig2 *btcec.Signature
|
|
||||||
|
|
||||||
// BitcoinSig1 is the signature using the public key of the first node
|
// nodeSig2 is a cached instance of the second node signature.
|
||||||
// that was used in the channel's multi-sig output.
|
nodeSig2 *btcec.Signature
|
||||||
BitcoinSig1 *btcec.Signature
|
|
||||||
|
|
||||||
// BitcoinSig2 is the signature using the public key of the second node
|
// NodeSig2Bytes are the raw bytes of the second node signature
|
||||||
// that was used in the channel's multi-sig output.
|
// encoded in DER format.
|
||||||
BitcoinSig2 *btcec.Signature
|
NodeSig2Bytes []byte
|
||||||
|
|
||||||
|
// bitcoinSig1 is a cached instance of the first bitcoin signature.
|
||||||
|
bitcoinSig1 *btcec.Signature
|
||||||
|
|
||||||
|
// BitcoinSig1Bytes are the raw bytes of the first bitcoin signature
|
||||||
|
// encoded in DER format.
|
||||||
|
BitcoinSig1Bytes []byte
|
||||||
|
|
||||||
|
// bitcoinSig2 is a cached instance of the second bitcoin signature.
|
||||||
|
bitcoinSig2 *btcec.Signature
|
||||||
|
|
||||||
|
// BitcoinSig2Bytes are the raw bytes of the second bitcoin signature
|
||||||
|
// encoded in DER format.
|
||||||
|
BitcoinSig2Bytes []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node1Sig is the signature using the identity key of the node that is first
|
||||||
|
// in a lexicographical ordering of the serialized public keys of the two nodes
|
||||||
|
// that created the channel.
|
||||||
|
//
|
||||||
|
// NOTE: By having this method to access an attribute, we ensure we only need
|
||||||
|
// to fully deserialize the signature if absolutely necessary.
|
||||||
|
func (c *ChannelAuthProof) Node1Sig() (*btcec.Signature, error) {
|
||||||
|
if c.nodeSig1 != nil {
|
||||||
|
return c.nodeSig1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sig, err := btcec.ParseSignature(c.NodeSig1Bytes, btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.nodeSig1 = sig
|
||||||
|
|
||||||
|
return sig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node2Sig is the signature using the identity key of the node that is second
|
||||||
|
// in a lexicographical ordering of the serialized public keys of the two nodes
|
||||||
|
// that created the channel.
|
||||||
|
//
|
||||||
|
// NOTE: By having this method to access an attribute, we ensure we only need
|
||||||
|
// to fully deserialize the signature if absolutely necessary.
|
||||||
|
func (c *ChannelAuthProof) Node2Sig() (*btcec.Signature, error) {
|
||||||
|
if c.nodeSig2 != nil {
|
||||||
|
return c.nodeSig2, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sig, err := btcec.ParseSignature(c.NodeSig2Bytes, btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.nodeSig2 = sig
|
||||||
|
|
||||||
|
return sig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BitcoinSig1 is the signature using the public key of the first node that was
|
||||||
|
// used in the channel's multi-sig output.
|
||||||
|
//
|
||||||
|
// NOTE: By having this method to access an attribute, we ensure we only need
|
||||||
|
// to fully deserialize the signature if absolutely necessary.
|
||||||
|
func (c *ChannelAuthProof) BitcoinSig1() (*btcec.Signature, error) {
|
||||||
|
if c.bitcoinSig1 != nil {
|
||||||
|
return c.bitcoinSig1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sig, err := btcec.ParseSignature(c.BitcoinSig1Bytes, btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.bitcoinSig1 = sig
|
||||||
|
|
||||||
|
return sig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BitcoinSig2 is the signature using the public key of the second node that
|
||||||
|
// was used in the channel's multi-sig output.
|
||||||
|
//
|
||||||
|
// NOTE: By having this method to access an attribute, we ensure we only need
|
||||||
|
// to fully deserialize the signature if absolutely necessary.
|
||||||
|
func (c *ChannelAuthProof) BitcoinSig2() (*btcec.Signature, error) {
|
||||||
|
if c.bitcoinSig2 != nil {
|
||||||
|
return c.bitcoinSig2, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sig, err := btcec.ParseSignature(c.BitcoinSig2Bytes, btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.bitcoinSig2 = sig
|
||||||
|
|
||||||
|
return sig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEmpty check is the authentication proof is empty Proof is empty if at
|
// IsEmpty check is the authentication proof is empty Proof is empty if at
|
||||||
// least one of the signatures are equal to nil.
|
// least one of the signatures are equal to nil.
|
||||||
func (p *ChannelAuthProof) IsEmpty() bool {
|
func (c *ChannelAuthProof) IsEmpty() bool {
|
||||||
return p.NodeSig1 == nil ||
|
return len(c.NodeSig1Bytes) == 0 ||
|
||||||
p.NodeSig2 == nil ||
|
len(c.NodeSig2Bytes) == 0 ||
|
||||||
p.BitcoinSig1 == nil ||
|
len(c.BitcoinSig1Bytes) == 0 ||
|
||||||
p.BitcoinSig2 == nil
|
len(c.BitcoinSig2Bytes) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChannelEdgePolicy represents a *directed* edge within the channel graph. For
|
// ChannelEdgePolicy represents a *directed* edge within the channel graph. For
|
||||||
@ -1311,9 +1539,13 @@ func (p *ChannelAuthProof) IsEmpty() bool {
|
|||||||
// information concerning fees, and minimum time-lock information which is
|
// information concerning fees, and minimum time-lock information which is
|
||||||
// utilized during path finding.
|
// utilized during path finding.
|
||||||
type ChannelEdgePolicy struct {
|
type ChannelEdgePolicy struct {
|
||||||
// Signature is a channel announcement signature, which is needed for
|
// SigBytes is the raw bytes of the signature of the channel edge
|
||||||
// proper edge policy announcement.
|
// policy. We'll only parse these if the caller needs to access the
|
||||||
Signature *btcec.Signature
|
// signature for validation purposes.
|
||||||
|
SigBytes []byte
|
||||||
|
|
||||||
|
// sig is a cached fully parsed signature.
|
||||||
|
sig *btcec.Signature
|
||||||
|
|
||||||
// ChannelID is the unique channel ID for the channel. The first 3
|
// ChannelID is the unique channel ID for the channel. The first 3
|
||||||
// bytes are the block height, the next 3 the index within the block,
|
// bytes are the block height, the next 3 the index within the block,
|
||||||
@ -1352,6 +1584,26 @@ type ChannelEdgePolicy struct {
|
|||||||
db *DB
|
db *DB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Signature is a channel announcement signature, which is needed for proper
|
||||||
|
// edge policy announcement.
|
||||||
|
//
|
||||||
|
// NOTE: By having this method to access an attribute, we ensure we only need
|
||||||
|
// to fully deserialize the signature if absolutely necessary.
|
||||||
|
func (c *ChannelEdgePolicy) Signature() (*btcec.Signature, error) {
|
||||||
|
if c.sig != nil {
|
||||||
|
return c.sig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sig, err := btcec.ParseSignature(c.SigBytes, btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.sig = sig
|
||||||
|
|
||||||
|
return sig, nil
|
||||||
|
}
|
||||||
|
|
||||||
// FetchChannelEdgesByOutpoint attempts to lookup the two directed edges for
|
// FetchChannelEdgesByOutpoint attempts to lookup the two directed edges for
|
||||||
// the channel identified by the funding outpoint. If the channel can't be
|
// the channel identified by the funding outpoint. If the channel can't be
|
||||||
// found, then ErrEdgeNotFound is returned. A struct which houses the general
|
// found, then ErrEdgeNotFound is returned. A struct which houses the general
|
||||||
@ -1539,7 +1791,11 @@ func putLightningNode(nodeBucket *bolt.Bucket, aliasBucket *bolt.Bucket, node *L
|
|||||||
b bytes.Buffer
|
b bytes.Buffer
|
||||||
)
|
)
|
||||||
|
|
||||||
nodePub := node.PubKey.SerializeCompressed()
|
pub, err := node.PubKey()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
nodePub := pub.SerializeCompressed()
|
||||||
|
|
||||||
// If the node has the update time set, write it, else write 0.
|
// If the node has the update time set, write it, else write 0.
|
||||||
updateUnix := uint64(0)
|
updateUnix := uint64(0)
|
||||||
@ -1604,7 +1860,7 @@ func putLightningNode(nodeBucket *bolt.Bucket, aliasBucket *bolt.Bucket, node *L
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := wire.WriteVarBytes(&b, 0, node.AuthSig.Serialize())
|
err = wire.WriteVarBytes(&b, 0, node.AuthSigBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1630,8 +1886,12 @@ func fetchLightningNode(nodeBucket *bolt.Bucket,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func deserializeLightningNode(r io.Reader) (*LightningNode, error) {
|
func deserializeLightningNode(r io.Reader) (*LightningNode, error) {
|
||||||
|
var (
|
||||||
|
scratch [8]byte
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
node := &LightningNode{}
|
node := &LightningNode{}
|
||||||
var scratch [8]byte
|
|
||||||
|
|
||||||
if _, err := r.Read(scratch[:]); err != nil {
|
if _, err := r.Read(scratch[:]); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -1640,13 +1900,7 @@ func deserializeLightningNode(r io.Reader) (*LightningNode, error) {
|
|||||||
unix := int64(byteOrder.Uint64(scratch[:]))
|
unix := int64(byteOrder.Uint64(scratch[:]))
|
||||||
node.LastUpdate = time.Unix(unix, 0)
|
node.LastUpdate = time.Unix(unix, 0)
|
||||||
|
|
||||||
var pub [33]byte
|
if _, err := io.ReadFull(r, node.PubKeyBytes[:]); err != nil {
|
||||||
if _, err := r.Read(pub[:]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
node.PubKey, err = btcec.ParsePubKey(pub[:], btcec.S256())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1706,12 +1960,7 @@ func deserializeLightningNode(r io.Reader) (*LightningNode, error) {
|
|||||||
}
|
}
|
||||||
node.Addresses = addresses
|
node.Addresses = addresses
|
||||||
|
|
||||||
sigBytes, err := wire.ReadVarBytes(r, 0, 80, "sig")
|
node.AuthSigBytes, err = wire.ReadVarBytes(r, 0, 80, "sig")
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
node.AuthSig, err = btcec.ParseSignature(sigBytes, btcec.S256())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -1722,16 +1971,16 @@ func deserializeLightningNode(r io.Reader) (*LightningNode, error) {
|
|||||||
func putChanEdgeInfo(edgeIndex *bolt.Bucket, edgeInfo *ChannelEdgeInfo, chanID [8]byte) error {
|
func putChanEdgeInfo(edgeIndex *bolt.Bucket, edgeInfo *ChannelEdgeInfo, chanID [8]byte) error {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
|
|
||||||
if _, err := b.Write(edgeInfo.NodeKey1.SerializeCompressed()); err != nil {
|
if _, err := b.Write(edgeInfo.NodeKey1Bytes[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := b.Write(edgeInfo.NodeKey2.SerializeCompressed()); err != nil {
|
if _, err := b.Write(edgeInfo.NodeKey2Bytes[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := b.Write(edgeInfo.BitcoinKey1.SerializeCompressed()); err != nil {
|
if _, err := b.Write(edgeInfo.BitcoinKey1Bytes[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := b.Write(edgeInfo.BitcoinKey2.SerializeCompressed()); err != nil {
|
if _, err := b.Write(edgeInfo.BitcoinKey2Bytes[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1742,10 +1991,10 @@ func putChanEdgeInfo(edgeIndex *bolt.Bucket, edgeInfo *ChannelEdgeInfo, chanID [
|
|||||||
authProof := edgeInfo.AuthProof
|
authProof := edgeInfo.AuthProof
|
||||||
var nodeSig1, nodeSig2, bitcoinSig1, bitcoinSig2 []byte
|
var nodeSig1, nodeSig2, bitcoinSig1, bitcoinSig2 []byte
|
||||||
if authProof != nil {
|
if authProof != nil {
|
||||||
nodeSig1 = authProof.NodeSig1.Serialize()
|
nodeSig1 = authProof.NodeSig1Bytes
|
||||||
nodeSig2 = authProof.NodeSig2.Serialize()
|
nodeSig2 = authProof.NodeSig2Bytes
|
||||||
bitcoinSig1 = authProof.BitcoinSig1.Serialize()
|
bitcoinSig1 = authProof.BitcoinSig1Bytes
|
||||||
bitcoinSig2 = authProof.BitcoinSig2.Serialize()
|
bitcoinSig2 = authProof.BitcoinSig2Bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := wire.WriteVarBytes(&b, 0, nodeSig1); err != nil {
|
if err := wire.WriteVarBytes(&b, 0, nodeSig1); err != nil {
|
||||||
@ -1792,32 +2041,19 @@ func fetchChanEdgeInfo(edgeIndex *bolt.Bucket,
|
|||||||
func deserializeChanEdgeInfo(r io.Reader) (*ChannelEdgeInfo, error) {
|
func deserializeChanEdgeInfo(r io.Reader) (*ChannelEdgeInfo, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
pubKeyBytes [33]byte
|
|
||||||
edgeInfo = &ChannelEdgeInfo{}
|
edgeInfo = &ChannelEdgeInfo{}
|
||||||
)
|
)
|
||||||
|
|
||||||
readKey := func() (*btcec.PublicKey, error) {
|
if _, err := io.ReadFull(r, edgeInfo.NodeKey1Bytes[:]); err != nil {
|
||||||
if _, err := io.ReadFull(r, pubKeyBytes[:]); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if _, err := io.ReadFull(r, edgeInfo.NodeKey2Bytes[:]); err != nil {
|
||||||
return btcec.ParsePubKey(pubKeyBytes[:], btcec.S256())
|
|
||||||
}
|
|
||||||
|
|
||||||
edgeInfo.NodeKey1, err = readKey()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
edgeInfo.NodeKey2, err = readKey()
|
if _, err := io.ReadFull(r, edgeInfo.BitcoinKey1Bytes[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
edgeInfo.BitcoinKey1, err = readKey()
|
if _, err := io.ReadFull(r, edgeInfo.BitcoinKey2Bytes[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
edgeInfo.BitcoinKey2, err = readKey()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1828,32 +2064,23 @@ func deserializeChanEdgeInfo(r io.Reader) (*ChannelEdgeInfo, error) {
|
|||||||
|
|
||||||
proof := &ChannelAuthProof{}
|
proof := &ChannelAuthProof{}
|
||||||
|
|
||||||
readSig := func() (*btcec.Signature, error) {
|
readSig := func() ([]byte, error) {
|
||||||
sigBytes, err := wire.ReadVarBytes(r, 0, 80, "sigs")
|
return wire.ReadVarBytes(r, 0, 80, "sigs")
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(sigBytes) != 0 {
|
proof.NodeSig1Bytes, err = readSig()
|
||||||
return btcec.ParseSignature(sigBytes, btcec.S256())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
proof.NodeSig1, err = readSig()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
proof.NodeSig2, err = readSig()
|
proof.NodeSig2Bytes, err = readSig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
proof.BitcoinSig1, err = readSig()
|
proof.BitcoinSig1Bytes, err = readSig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
proof.BitcoinSig2, err = readSig()
|
proof.BitcoinSig2Bytes, err = readSig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -1887,7 +2114,7 @@ func putChanEdgePolicy(edges *bolt.Bucket, edge *ChannelEdgePolicy, from, to []b
|
|||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
|
|
||||||
err := wire.WriteVarBytes(&b, 0, edge.Signature.Serialize())
|
err := wire.WriteVarBytes(&b, 0, edge.SigBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1993,11 +2220,7 @@ func deserializeChanEdgePolicy(r io.Reader,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
edge.SigBytes = sigBytes
|
||||||
edge.Signature, err = btcec.ParseSignature(sigBytes, btcec.S256())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := binary.Read(r, byteOrder, &edge.ChannelID); err != nil {
|
if err := binary.Read(r, byteOrder, &edge.ChannelID); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -50,17 +50,19 @@ func createTestVertex(db *DB) (*LightningNode, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub := priv.PubKey().SerializeCompressed()
|
pub := priv.PubKey().SerializeCompressed()
|
||||||
return &LightningNode{
|
n := &LightningNode{
|
||||||
HaveNodeAnnouncement: true,
|
HaveNodeAnnouncement: true,
|
||||||
AuthSig: testSig,
|
AuthSigBytes: testSig.Serialize(),
|
||||||
LastUpdate: time.Unix(updateTime, 0),
|
LastUpdate: time.Unix(updateTime, 0),
|
||||||
PubKey: priv.PubKey(),
|
|
||||||
Color: color.RGBA{1, 2, 3, 0},
|
Color: color.RGBA{1, 2, 3, 0},
|
||||||
Alias: "kek" + string(pub[:]),
|
Alias: "kek" + string(pub[:]),
|
||||||
Features: testFeatures,
|
Features: testFeatures,
|
||||||
Addresses: testAddrs,
|
Addresses: testAddrs,
|
||||||
db: db,
|
db: db,
|
||||||
}, nil
|
}
|
||||||
|
copy(n.PubKeyBytes[:], priv.PubKey().SerializeCompressed())
|
||||||
|
|
||||||
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNodeInsertionAndDeletion(t *testing.T) {
|
func TestNodeInsertionAndDeletion(t *testing.T) {
|
||||||
@ -79,15 +81,15 @@ func TestNodeInsertionAndDeletion(t *testing.T) {
|
|||||||
_, testPub := btcec.PrivKeyFromBytes(btcec.S256(), key[:])
|
_, testPub := btcec.PrivKeyFromBytes(btcec.S256(), key[:])
|
||||||
node := &LightningNode{
|
node := &LightningNode{
|
||||||
HaveNodeAnnouncement: true,
|
HaveNodeAnnouncement: true,
|
||||||
AuthSig: testSig,
|
AuthSigBytes: testSig.Serialize(),
|
||||||
LastUpdate: time.Unix(1232342, 0),
|
LastUpdate: time.Unix(1232342, 0),
|
||||||
PubKey: testPub,
|
|
||||||
Color: color.RGBA{1, 2, 3, 0},
|
Color: color.RGBA{1, 2, 3, 0},
|
||||||
Alias: "kek",
|
Alias: "kek",
|
||||||
Features: testFeatures,
|
Features: testFeatures,
|
||||||
Addresses: testAddrs,
|
Addresses: testAddrs,
|
||||||
db: db,
|
db: db,
|
||||||
}
|
}
|
||||||
|
copy(node.PubKeyBytes[:], testPub.SerializeCompressed())
|
||||||
|
|
||||||
// First, insert the node into the graph DB. This should succeed
|
// First, insert the node into the graph DB. This should succeed
|
||||||
// without any errors.
|
// without any errors.
|
||||||
@ -102,7 +104,7 @@ func TestNodeInsertionAndDeletion(t *testing.T) {
|
|||||||
t.Fatalf("unable to locate node: %v", err)
|
t.Fatalf("unable to locate node: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, exists, err := graph.HasLightningNode(testPub); err != nil {
|
if _, exists, err := graph.HasLightningNode(dbNode.PubKeyBytes); err != nil {
|
||||||
t.Fatalf("unable to query for node: %v", err)
|
t.Fatalf("unable to query for node: %v", err)
|
||||||
} else if !exists {
|
} else if !exists {
|
||||||
t.Fatalf("node should be found but wasn't")
|
t.Fatalf("node should be found but wasn't")
|
||||||
@ -144,9 +146,9 @@ func TestPartialNode(t *testing.T) {
|
|||||||
// PubKey set.
|
// PubKey set.
|
||||||
_, testPub := btcec.PrivKeyFromBytes(btcec.S256(), key[:])
|
_, testPub := btcec.PrivKeyFromBytes(btcec.S256(), key[:])
|
||||||
node := &LightningNode{
|
node := &LightningNode{
|
||||||
PubKey: testPub,
|
|
||||||
HaveNodeAnnouncement: false,
|
HaveNodeAnnouncement: false,
|
||||||
}
|
}
|
||||||
|
copy(node.PubKeyBytes[:], testPub.SerializeCompressed())
|
||||||
|
|
||||||
if err := graph.AddLightningNode(node); err != nil {
|
if err := graph.AddLightningNode(node); err != nil {
|
||||||
t.Fatalf("unable to add node: %v", err)
|
t.Fatalf("unable to add node: %v", err)
|
||||||
@ -159,7 +161,7 @@ func TestPartialNode(t *testing.T) {
|
|||||||
t.Fatalf("unable to locate node: %v", err)
|
t.Fatalf("unable to locate node: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, exists, err := graph.HasLightningNode(testPub); err != nil {
|
if _, exists, err := graph.HasLightningNode(dbNode.PubKeyBytes); err != nil {
|
||||||
t.Fatalf("unable to query for node: %v", err)
|
t.Fatalf("unable to query for node: %v", err)
|
||||||
} else if !exists {
|
} else if !exists {
|
||||||
t.Fatalf("node should be found but wasn't")
|
t.Fatalf("node should be found but wasn't")
|
||||||
@ -168,11 +170,11 @@ func TestPartialNode(t *testing.T) {
|
|||||||
// The two nodes should match exactly! (with default values for
|
// The two nodes should match exactly! (with default values for
|
||||||
// LastUpdate and db set to satisfy compareNodes())
|
// LastUpdate and db set to satisfy compareNodes())
|
||||||
node = &LightningNode{
|
node = &LightningNode{
|
||||||
PubKey: testPub,
|
|
||||||
HaveNodeAnnouncement: false,
|
HaveNodeAnnouncement: false,
|
||||||
LastUpdate: time.Unix(0, 0),
|
LastUpdate: time.Unix(0, 0),
|
||||||
db: db,
|
db: db,
|
||||||
}
|
}
|
||||||
|
copy(node.PubKeyBytes[:], testPub.SerializeCompressed())
|
||||||
|
|
||||||
if err := compareNodes(node, dbNode); err != nil {
|
if err := compareNodes(node, dbNode); err != nil {
|
||||||
t.Fatalf("nodes don't match: %v", err)
|
t.Fatalf("nodes don't match: %v", err)
|
||||||
@ -181,7 +183,7 @@ func TestPartialNode(t *testing.T) {
|
|||||||
// Next, delete the node from the graph, this should purge all data
|
// Next, delete the node from the graph, this should purge all data
|
||||||
// related to the node.
|
// related to the node.
|
||||||
if err := graph.DeleteLightningNode(testPub); err != nil {
|
if err := graph.DeleteLightningNode(testPub); err != nil {
|
||||||
t.Fatalf("unable to delete node; %v", err)
|
t.Fatalf("unable to delete node: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, attempt to fetch the node again. This should fail as the
|
// Finally, attempt to fetch the node again. This should fail as the
|
||||||
@ -218,7 +220,11 @@ func TestAliasLookup(t *testing.T) {
|
|||||||
|
|
||||||
// Next, attempt to lookup the alias. The alias should exactly match
|
// Next, attempt to lookup the alias. The alias should exactly match
|
||||||
// the one which the test node was assigned.
|
// the one which the test node was assigned.
|
||||||
dbAlias, err := graph.LookupAlias(testNode.PubKey)
|
nodePub, err := testNode.PubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate pubkey: %v", err)
|
||||||
|
}
|
||||||
|
dbAlias, err := graph.LookupAlias(nodePub)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to find alias: %v", err)
|
t.Fatalf("unable to find alias: %v", err)
|
||||||
}
|
}
|
||||||
@ -232,7 +238,11 @@ func TestAliasLookup(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test node: %v", err)
|
t.Fatalf("unable to create test node: %v", err)
|
||||||
}
|
}
|
||||||
_, err = graph.LookupAlias(node.PubKey)
|
nodePub, err = node.PubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate pubkey: %v", err)
|
||||||
|
}
|
||||||
|
_, err = graph.LookupAlias(nodePub)
|
||||||
if err != ErrNodeAliasNotFound {
|
if err != ErrNodeAliasNotFound {
|
||||||
t.Fatalf("alias lookup should fail for non-existent pubkey")
|
t.Fatalf("alias lookup should fail for non-existent pubkey")
|
||||||
}
|
}
|
||||||
@ -311,22 +321,30 @@ func TestEdgeInsertionDeletion(t *testing.T) {
|
|||||||
|
|
||||||
// Add the new edge to the database, this should proceed without any
|
// Add the new edge to the database, this should proceed without any
|
||||||
// errors.
|
// errors.
|
||||||
|
node1Pub, err := node1.PubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate node key: %v", err)
|
||||||
|
}
|
||||||
|
node2Pub, err := node2.PubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate node key: %v", err)
|
||||||
|
}
|
||||||
edgeInfo := ChannelEdgeInfo{
|
edgeInfo := ChannelEdgeInfo{
|
||||||
ChannelID: chanID,
|
ChannelID: chanID,
|
||||||
ChainHash: key,
|
ChainHash: key,
|
||||||
NodeKey1: node1.PubKey,
|
|
||||||
NodeKey2: node2.PubKey,
|
|
||||||
BitcoinKey1: node1.PubKey,
|
|
||||||
BitcoinKey2: node2.PubKey,
|
|
||||||
AuthProof: &ChannelAuthProof{
|
AuthProof: &ChannelAuthProof{
|
||||||
NodeSig1: testSig,
|
NodeSig1Bytes: testSig.Serialize(),
|
||||||
NodeSig2: testSig,
|
NodeSig2Bytes: testSig.Serialize(),
|
||||||
BitcoinSig1: testSig,
|
BitcoinSig1Bytes: testSig.Serialize(),
|
||||||
BitcoinSig2: testSig,
|
BitcoinSig2Bytes: testSig.Serialize(),
|
||||||
},
|
},
|
||||||
ChannelPoint: outpoint,
|
ChannelPoint: outpoint,
|
||||||
Capacity: 9000,
|
Capacity: 9000,
|
||||||
}
|
}
|
||||||
|
copy(edgeInfo.NodeKey1Bytes[:], node1Pub.SerializeCompressed())
|
||||||
|
copy(edgeInfo.NodeKey2Bytes[:], node2Pub.SerializeCompressed())
|
||||||
|
copy(edgeInfo.BitcoinKey1Bytes[:], node1Pub.SerializeCompressed())
|
||||||
|
copy(edgeInfo.BitcoinKey2Bytes[:], node2Pub.SerializeCompressed())
|
||||||
|
|
||||||
if err := graph.AddChannelEdge(&edgeInfo); err != nil {
|
if err := graph.AddChannelEdge(&edgeInfo); err != nil {
|
||||||
t.Fatalf("unable to create channel edge: %v", err)
|
t.Fatalf("unable to create channel edge: %v", err)
|
||||||
@ -413,22 +431,26 @@ func TestDisconnectBlockAtHeight(t *testing.T) {
|
|||||||
Index: outPointIndex,
|
Index: outPointIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node1Pub, _ := node1.PubKey()
|
||||||
|
node2Pub, _ := node2.PubKey()
|
||||||
edgeInfo := ChannelEdgeInfo{
|
edgeInfo := ChannelEdgeInfo{
|
||||||
ChannelID: shortChanID.ToUint64(),
|
ChannelID: shortChanID.ToUint64(),
|
||||||
ChainHash: key,
|
ChainHash: key,
|
||||||
NodeKey1: node1.PubKey,
|
|
||||||
NodeKey2: node2.PubKey,
|
|
||||||
BitcoinKey1: node1.PubKey,
|
|
||||||
BitcoinKey2: node2.PubKey,
|
|
||||||
AuthProof: &ChannelAuthProof{
|
AuthProof: &ChannelAuthProof{
|
||||||
NodeSig1: testSig,
|
NodeSig1Bytes: testSig.Serialize(),
|
||||||
NodeSig2: testSig,
|
NodeSig2Bytes: testSig.Serialize(),
|
||||||
BitcoinSig1: testSig,
|
BitcoinSig1Bytes: testSig.Serialize(),
|
||||||
BitcoinSig2: testSig,
|
BitcoinSig2Bytes: testSig.Serialize(),
|
||||||
},
|
},
|
||||||
ChannelPoint: outpoint,
|
ChannelPoint: outpoint,
|
||||||
Capacity: 9000,
|
Capacity: 9000,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
copy(edgeInfo.NodeKey1Bytes[:], node1Pub.SerializeCompressed())
|
||||||
|
copy(edgeInfo.NodeKey2Bytes[:], node2Pub.SerializeCompressed())
|
||||||
|
copy(edgeInfo.BitcoinKey1Bytes[:], node1Pub.SerializeCompressed())
|
||||||
|
copy(edgeInfo.BitcoinKey2Bytes[:], node2Pub.SerializeCompressed())
|
||||||
|
|
||||||
return edgeInfo
|
return edgeInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,16 +552,16 @@ func assertEdgeInfoEqual(t *testing.T, e1 *ChannelEdgeInfo,
|
|||||||
e2.ChainHash)
|
e2.ChainHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !e1.NodeKey1.IsEqual(e2.NodeKey1) {
|
if !bytes.Equal(e1.NodeKey1Bytes[:], e2.NodeKey1Bytes[:]) {
|
||||||
t.Fatalf("nodekey1 doesn't match")
|
t.Fatalf("nodekey1 doesn't match")
|
||||||
}
|
}
|
||||||
if !e1.NodeKey2.IsEqual(e2.NodeKey2) {
|
if !bytes.Equal(e1.NodeKey2Bytes[:], e2.NodeKey2Bytes[:]) {
|
||||||
t.Fatalf("nodekey2 doesn't match")
|
t.Fatalf("nodekey2 doesn't match")
|
||||||
}
|
}
|
||||||
if !e1.BitcoinKey1.IsEqual(e2.BitcoinKey1) {
|
if !bytes.Equal(e1.BitcoinKey1Bytes[:], e2.BitcoinKey1Bytes[:]) {
|
||||||
t.Fatalf("bitcoinkey1 doesn't match")
|
t.Fatalf("bitcoinkey1 doesn't match")
|
||||||
}
|
}
|
||||||
if !e1.BitcoinKey2.IsEqual(e2.BitcoinKey2) {
|
if !bytes.Equal(e1.BitcoinKey2Bytes[:], e2.BitcoinKey2Bytes[:]) {
|
||||||
t.Fatalf("bitcoinkey2 doesn't match")
|
t.Fatalf("bitcoinkey2 doesn't match")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,18 +570,18 @@ func assertEdgeInfoEqual(t *testing.T, e1 *ChannelEdgeInfo,
|
|||||||
e2.Features)
|
e2.Features)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !e1.AuthProof.NodeSig1.IsEqual(e2.AuthProof.NodeSig1) {
|
if !bytes.Equal(e1.AuthProof.NodeSig1Bytes, e2.AuthProof.NodeSig1Bytes) {
|
||||||
t.Fatalf("nodesig1 doesn't match: %v vs %v",
|
t.Fatalf("nodesig1 doesn't match: %v vs %v",
|
||||||
spew.Sdump(e1.AuthProof.NodeSig1),
|
spew.Sdump(e1.AuthProof.NodeSig1Bytes),
|
||||||
spew.Sdump(e2.AuthProof.NodeSig1))
|
spew.Sdump(e2.AuthProof.NodeSig1Bytes))
|
||||||
}
|
}
|
||||||
if !e1.AuthProof.NodeSig2.IsEqual(e2.AuthProof.NodeSig2) {
|
if !bytes.Equal(e1.AuthProof.NodeSig2Bytes, e2.AuthProof.NodeSig2Bytes) {
|
||||||
t.Fatalf("nodesig2 doesn't match")
|
t.Fatalf("nodesig2 doesn't match")
|
||||||
}
|
}
|
||||||
if !e1.AuthProof.BitcoinSig1.IsEqual(e2.AuthProof.BitcoinSig1) {
|
if !bytes.Equal(e1.AuthProof.BitcoinSig1Bytes, e2.AuthProof.BitcoinSig1Bytes) {
|
||||||
t.Fatalf("bitcoinsig1 doesn't match")
|
t.Fatalf("bitcoinsig1 doesn't match")
|
||||||
}
|
}
|
||||||
if !e1.AuthProof.BitcoinSig2.IsEqual(e2.AuthProof.BitcoinSig2) {
|
if !bytes.Equal(e1.AuthProof.BitcoinSig2Bytes, e2.AuthProof.BitcoinSig2Bytes) {
|
||||||
t.Fatalf("bitcoinsig2 doesn't match")
|
t.Fatalf("bitcoinsig2 doesn't match")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,9 +628,7 @@ func TestEdgeInfoUpdates(t *testing.T) {
|
|||||||
firstNode *LightningNode
|
firstNode *LightningNode
|
||||||
secondNode *LightningNode
|
secondNode *LightningNode
|
||||||
)
|
)
|
||||||
node1Bytes := node1.PubKey.SerializeCompressed()
|
if bytes.Compare(node1.PubKeyBytes[:], node2.PubKeyBytes[:]) == -1 {
|
||||||
node2Bytes := node2.PubKey.SerializeCompressed()
|
|
||||||
if bytes.Compare(node1Bytes, node2Bytes) == -1 {
|
|
||||||
firstNode = node1
|
firstNode = node1
|
||||||
secondNode = node2
|
secondNode = node2
|
||||||
} else {
|
} else {
|
||||||
@ -629,19 +649,19 @@ func TestEdgeInfoUpdates(t *testing.T) {
|
|||||||
edgeInfo := &ChannelEdgeInfo{
|
edgeInfo := &ChannelEdgeInfo{
|
||||||
ChannelID: chanID,
|
ChannelID: chanID,
|
||||||
ChainHash: key,
|
ChainHash: key,
|
||||||
NodeKey1: firstNode.PubKey,
|
|
||||||
NodeKey2: secondNode.PubKey,
|
|
||||||
BitcoinKey1: firstNode.PubKey,
|
|
||||||
BitcoinKey2: secondNode.PubKey,
|
|
||||||
AuthProof: &ChannelAuthProof{
|
AuthProof: &ChannelAuthProof{
|
||||||
NodeSig1: testSig,
|
NodeSig1Bytes: testSig.Serialize(),
|
||||||
NodeSig2: testSig,
|
NodeSig2Bytes: testSig.Serialize(),
|
||||||
BitcoinSig1: testSig,
|
BitcoinSig1Bytes: testSig.Serialize(),
|
||||||
BitcoinSig2: testSig,
|
BitcoinSig2Bytes: testSig.Serialize(),
|
||||||
},
|
},
|
||||||
ChannelPoint: outpoint,
|
ChannelPoint: outpoint,
|
||||||
Capacity: 1000,
|
Capacity: 1000,
|
||||||
}
|
}
|
||||||
|
copy(edgeInfo.NodeKey1Bytes[:], firstNode.PubKeyBytes[:])
|
||||||
|
copy(edgeInfo.NodeKey2Bytes[:], secondNode.PubKeyBytes[:])
|
||||||
|
copy(edgeInfo.BitcoinKey1Bytes[:], firstNode.PubKeyBytes[:])
|
||||||
|
copy(edgeInfo.BitcoinKey2Bytes[:], secondNode.PubKeyBytes[:])
|
||||||
if err := graph.AddChannelEdge(edgeInfo); err != nil {
|
if err := graph.AddChannelEdge(edgeInfo); err != nil {
|
||||||
t.Fatalf("unable to create channel edge: %v", err)
|
t.Fatalf("unable to create channel edge: %v", err)
|
||||||
}
|
}
|
||||||
@ -649,7 +669,7 @@ func TestEdgeInfoUpdates(t *testing.T) {
|
|||||||
// With the edge added, we can now create some fake edge information to
|
// With the edge added, we can now create some fake edge information to
|
||||||
// update for both edges.
|
// update for both edges.
|
||||||
edge1 := &ChannelEdgePolicy{
|
edge1 := &ChannelEdgePolicy{
|
||||||
Signature: testSig,
|
SigBytes: testSig.Serialize(),
|
||||||
ChannelID: chanID,
|
ChannelID: chanID,
|
||||||
LastUpdate: time.Unix(433453, 0),
|
LastUpdate: time.Unix(433453, 0),
|
||||||
Flags: 0,
|
Flags: 0,
|
||||||
@ -661,7 +681,7 @@ func TestEdgeInfoUpdates(t *testing.T) {
|
|||||||
db: db,
|
db: db,
|
||||||
}
|
}
|
||||||
edge2 := &ChannelEdgePolicy{
|
edge2 := &ChannelEdgePolicy{
|
||||||
Signature: testSig,
|
SigBytes: testSig.Serialize(),
|
||||||
ChannelID: chanID,
|
ChannelID: chanID,
|
||||||
LastUpdate: time.Unix(124234, 0),
|
LastUpdate: time.Unix(124234, 0),
|
||||||
Flags: 1,
|
Flags: 1,
|
||||||
@ -796,9 +816,7 @@ func TestGraphTraversal(t *testing.T) {
|
|||||||
// Determine which node is "smaller", we'll need this in order to
|
// Determine which node is "smaller", we'll need this in order to
|
||||||
// properly create the edges for the graph.
|
// properly create the edges for the graph.
|
||||||
var firstNode, secondNode *LightningNode
|
var firstNode, secondNode *LightningNode
|
||||||
node1Bytes := nodes[0].PubKey.SerializeCompressed()
|
if bytes.Compare(nodes[0].PubKeyBytes[:], nodes[1].PubKeyBytes[:]) == -1 {
|
||||||
node2Bytes := nodes[1].PubKey.SerializeCompressed()
|
|
||||||
if bytes.Compare(node1Bytes, node2Bytes) == -1 {
|
|
||||||
firstNode = nodes[0]
|
firstNode = nodes[0]
|
||||||
secondNode = nodes[1]
|
secondNode = nodes[1]
|
||||||
} else {
|
} else {
|
||||||
@ -820,19 +838,19 @@ func TestGraphTraversal(t *testing.T) {
|
|||||||
edgeInfo := ChannelEdgeInfo{
|
edgeInfo := ChannelEdgeInfo{
|
||||||
ChannelID: chanID,
|
ChannelID: chanID,
|
||||||
ChainHash: key,
|
ChainHash: key,
|
||||||
NodeKey1: nodes[0].PubKey,
|
|
||||||
NodeKey2: nodes[1].PubKey,
|
|
||||||
BitcoinKey1: nodes[0].PubKey,
|
|
||||||
BitcoinKey2: nodes[1].PubKey,
|
|
||||||
AuthProof: &ChannelAuthProof{
|
AuthProof: &ChannelAuthProof{
|
||||||
NodeSig1: testSig,
|
NodeSig1Bytes: testSig.Serialize(),
|
||||||
NodeSig2: testSig,
|
NodeSig2Bytes: testSig.Serialize(),
|
||||||
BitcoinSig1: testSig,
|
BitcoinSig1Bytes: testSig.Serialize(),
|
||||||
BitcoinSig2: testSig,
|
BitcoinSig2Bytes: testSig.Serialize(),
|
||||||
},
|
},
|
||||||
ChannelPoint: op,
|
ChannelPoint: op,
|
||||||
Capacity: 1000,
|
Capacity: 1000,
|
||||||
}
|
}
|
||||||
|
copy(edgeInfo.NodeKey1Bytes[:], nodes[0].PubKeyBytes[:])
|
||||||
|
copy(edgeInfo.NodeKey2Bytes[:], nodes[1].PubKeyBytes[:])
|
||||||
|
copy(edgeInfo.BitcoinKey1Bytes[:], nodes[0].PubKeyBytes[:])
|
||||||
|
copy(edgeInfo.BitcoinKey2Bytes[:], nodes[1].PubKeyBytes[:])
|
||||||
err := graph.AddChannelEdge(&edgeInfo)
|
err := graph.AddChannelEdge(&edgeInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to add node: %v", err)
|
t.Fatalf("unable to add node: %v", err)
|
||||||
@ -843,7 +861,7 @@ func TestGraphTraversal(t *testing.T) {
|
|||||||
edge := randEdgePolicy(chanID, op, db)
|
edge := randEdgePolicy(chanID, op, db)
|
||||||
edge.Flags = 0
|
edge.Flags = 0
|
||||||
edge.Node = secondNode
|
edge.Node = secondNode
|
||||||
edge.Signature = testSig
|
edge.SigBytes = testSig.Serialize()
|
||||||
if err := graph.UpdateEdgePolicy(edge); err != nil {
|
if err := graph.UpdateEdgePolicy(edge); err != nil {
|
||||||
t.Fatalf("unable to update edge: %v", err)
|
t.Fatalf("unable to update edge: %v", err)
|
||||||
}
|
}
|
||||||
@ -853,7 +871,7 @@ func TestGraphTraversal(t *testing.T) {
|
|||||||
edge = randEdgePolicy(chanID, op, db)
|
edge = randEdgePolicy(chanID, op, db)
|
||||||
edge.Flags = 1
|
edge.Flags = 1
|
||||||
edge.Node = firstNode
|
edge.Node = firstNode
|
||||||
edge.Signature = testSig
|
edge.SigBytes = testSig.Serialize()
|
||||||
if err := graph.UpdateEdgePolicy(edge); err != nil {
|
if err := graph.UpdateEdgePolicy(edge); err != nil {
|
||||||
t.Fatalf("unable to update edge: %v", err)
|
t.Fatalf("unable to update edge: %v", err)
|
||||||
}
|
}
|
||||||
@ -885,13 +903,13 @@ func TestGraphTraversal(t *testing.T) {
|
|||||||
|
|
||||||
// Each each should indicate that it's outgoing (pointed
|
// Each each should indicate that it's outgoing (pointed
|
||||||
// towards the second node).
|
// towards the second node).
|
||||||
if !outEdge.Node.PubKey.IsEqual(secondNode.PubKey) {
|
if !bytes.Equal(outEdge.Node.PubKeyBytes[:], secondNode.PubKeyBytes[:]) {
|
||||||
return fmt.Errorf("wrong outgoing edge")
|
return fmt.Errorf("wrong outgoing edge")
|
||||||
}
|
}
|
||||||
|
|
||||||
// The incoming edge should also indicate that it's pointing to
|
// The incoming edge should also indicate that it's pointing to
|
||||||
// the origin node.
|
// the origin node.
|
||||||
if !inEdge.Node.PubKey.IsEqual(firstNode.PubKey) {
|
if !bytes.Equal(inEdge.Node.PubKeyBytes[:], firstNode.PubKeyBytes[:]) {
|
||||||
return fmt.Errorf("wrong outgoing edge")
|
return fmt.Errorf("wrong outgoing edge")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1010,20 +1028,19 @@ func TestGraphPruning(t *testing.T) {
|
|||||||
edgeInfo := ChannelEdgeInfo{
|
edgeInfo := ChannelEdgeInfo{
|
||||||
ChannelID: chanID,
|
ChannelID: chanID,
|
||||||
ChainHash: key,
|
ChainHash: key,
|
||||||
NodeKey1: graphNodes[i].PubKey,
|
|
||||||
NodeKey2: graphNodes[i+1].PubKey,
|
|
||||||
BitcoinKey1: graphNodes[i].PubKey,
|
|
||||||
BitcoinKey2: graphNodes[i+1].PubKey,
|
|
||||||
AuthProof: &ChannelAuthProof{
|
AuthProof: &ChannelAuthProof{
|
||||||
NodeSig1: testSig,
|
NodeSig1Bytes: testSig.Serialize(),
|
||||||
NodeSig2: testSig,
|
NodeSig2Bytes: testSig.Serialize(),
|
||||||
BitcoinSig1: testSig,
|
BitcoinSig1Bytes: testSig.Serialize(),
|
||||||
BitcoinSig2: testSig,
|
BitcoinSig2Bytes: testSig.Serialize(),
|
||||||
},
|
},
|
||||||
ChannelPoint: op,
|
ChannelPoint: op,
|
||||||
Capacity: 1000,
|
Capacity: 1000,
|
||||||
}
|
}
|
||||||
|
copy(edgeInfo.NodeKey1Bytes[:], graphNodes[i].PubKeyBytes[:])
|
||||||
|
copy(edgeInfo.NodeKey2Bytes[:], graphNodes[i+1].PubKeyBytes[:])
|
||||||
|
copy(edgeInfo.BitcoinKey1Bytes[:], graphNodes[i].PubKeyBytes[:])
|
||||||
|
copy(edgeInfo.BitcoinKey2Bytes[:], graphNodes[i+1].PubKeyBytes[:])
|
||||||
if err := graph.AddChannelEdge(&edgeInfo); err != nil {
|
if err := graph.AddChannelEdge(&edgeInfo); err != nil {
|
||||||
t.Fatalf("unable to add node: %v", err)
|
t.Fatalf("unable to add node: %v", err)
|
||||||
}
|
}
|
||||||
@ -1033,7 +1050,7 @@ func TestGraphPruning(t *testing.T) {
|
|||||||
edge := randEdgePolicy(chanID, op, db)
|
edge := randEdgePolicy(chanID, op, db)
|
||||||
edge.Flags = 0
|
edge.Flags = 0
|
||||||
edge.Node = graphNodes[i]
|
edge.Node = graphNodes[i]
|
||||||
edge.Signature = testSig
|
edge.SigBytes = testSig.Serialize()
|
||||||
if err := graph.UpdateEdgePolicy(edge); err != nil {
|
if err := graph.UpdateEdgePolicy(edge); err != nil {
|
||||||
t.Fatalf("unable to update edge: %v", err)
|
t.Fatalf("unable to update edge: %v", err)
|
||||||
}
|
}
|
||||||
@ -1043,7 +1060,7 @@ func TestGraphPruning(t *testing.T) {
|
|||||||
edge = randEdgePolicy(chanID, op, db)
|
edge = randEdgePolicy(chanID, op, db)
|
||||||
edge.Flags = 1
|
edge.Flags = 1
|
||||||
edge.Node = graphNodes[i]
|
edge.Node = graphNodes[i]
|
||||||
edge.Signature = testSig
|
edge.SigBytes = testSig.Serialize()
|
||||||
if err := graph.UpdateEdgePolicy(edge); err != nil {
|
if err := graph.UpdateEdgePolicy(edge); err != nil {
|
||||||
t.Fatalf("unable to update edge: %v", err)
|
t.Fatalf("unable to update edge: %v", err)
|
||||||
}
|
}
|
||||||
@ -1159,9 +1176,9 @@ func compareNodes(a, b *LightningNode) error {
|
|||||||
return fmt.Errorf("Addresses doesn't match: expected %#v, \n "+
|
return fmt.Errorf("Addresses doesn't match: expected %#v, \n "+
|
||||||
"got %#v", a.Addresses, b.Addresses)
|
"got %#v", a.Addresses, b.Addresses)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(a.PubKey, b.PubKey) {
|
if !reflect.DeepEqual(a.PubKeyBytes, b.PubKeyBytes) {
|
||||||
return fmt.Errorf("PubKey doesn't match: expected %#v, \n "+
|
return fmt.Errorf("PubKey doesn't match: expected %#v, \n "+
|
||||||
"got %#v", a.PubKey, b.PubKey)
|
"got %#v", a.PubKeyBytes, b.PubKeyBytes)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(a.Color, b.Color) {
|
if !reflect.DeepEqual(a.Color, b.Color) {
|
||||||
return fmt.Errorf("Color doesn't match: expected %#v, \n "+
|
return fmt.Errorf("Color doesn't match: expected %#v, \n "+
|
||||||
|
@ -21,8 +21,8 @@ func TestWaitingProofStore(t *testing.T) {
|
|||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
proof1 := NewWaitingProof(true, &lnwire.AnnounceSignatures{
|
proof1 := NewWaitingProof(true, &lnwire.AnnounceSignatures{
|
||||||
NodeSignature: testSig,
|
NodeSignature: wireSig,
|
||||||
BitcoinSignature: testSig,
|
BitcoinSignature: wireSig,
|
||||||
})
|
})
|
||||||
|
|
||||||
store, err := NewWaitingProofStore(db)
|
store, err := NewWaitingProofStore(db)
|
||||||
|
@ -26,23 +26,56 @@ func ValidateChannelAnn(a *lnwire.ChannelAnnouncement) error {
|
|||||||
|
|
||||||
// First we'll verify that the passed bitcoin key signature is indeed a
|
// First we'll verify that the passed bitcoin key signature is indeed a
|
||||||
// signature over the computed hash digest.
|
// signature over the computed hash digest.
|
||||||
if !a.BitcoinSig1.Verify(dataHash, copyPubKey(a.BitcoinKey1)) {
|
bitcoinSig1, err := a.BitcoinSig1.ToSignature()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
bitcoinKey1, err := btcec.ParsePubKey(a.BitcoinKey1[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !bitcoinSig1.Verify(dataHash, bitcoinKey1) {
|
||||||
return errors.New("can't verify first bitcoin signature")
|
return errors.New("can't verify first bitcoin signature")
|
||||||
}
|
}
|
||||||
|
|
||||||
// If that checks out, then we'll verify that the second bitcoin
|
// If that checks out, then we'll verify that the second bitcoin
|
||||||
// signature is a valid signature of the bitcoin public key over hash
|
// signature is a valid signature of the bitcoin public key over hash
|
||||||
// digest as well.
|
// digest as well.
|
||||||
if !a.BitcoinSig2.Verify(dataHash, copyPubKey(a.BitcoinKey2)) {
|
bitcoinSig2, err := a.BitcoinSig2.ToSignature()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
bitcoinKey2, err := btcec.ParsePubKey(a.BitcoinKey2[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !bitcoinSig2.Verify(dataHash, bitcoinKey2) {
|
||||||
return errors.New("can't verify second bitcoin signature")
|
return errors.New("can't verify second bitcoin signature")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Both node signatures attached should indeed be a valid signature
|
// Both node signatures attached should indeed be a valid signature
|
||||||
// over the selected digest of the channel announcement signature.
|
// over the selected digest of the channel announcement signature.
|
||||||
if !a.NodeSig1.Verify(dataHash, copyPubKey(a.NodeID1)) {
|
nodeSig1, err := a.NodeSig1.ToSignature()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
nodeKey1, err := btcec.ParsePubKey(a.NodeID1[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !nodeSig1.Verify(dataHash, nodeKey1) {
|
||||||
return errors.New("can't verify data in first node signature")
|
return errors.New("can't verify data in first node signature")
|
||||||
}
|
}
|
||||||
if !a.NodeSig2.Verify(dataHash, copyPubKey(a.NodeID2)) {
|
|
||||||
|
nodeSig2, err := a.NodeSig2.ToSignature()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
nodeKey2, err := btcec.ParsePubKey(a.NodeID2[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !nodeSig2.Verify(dataHash, nodeKey2) {
|
||||||
return errors.New("can't verify data in second node signature")
|
return errors.New("can't verify data in second node signature")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,17 +94,26 @@ func ValidateNodeAnn(a *lnwire.NodeAnnouncement) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nodeSig, err := a.Signature.ToSignature()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
nodeKey, err := btcec.ParsePubKey(a.NodeID[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Finally ensure that the passed signature is valid, if not we'll
|
// Finally ensure that the passed signature is valid, if not we'll
|
||||||
// return an error so this node announcement can be rejected.
|
// return an error so this node announcement can be rejected.
|
||||||
dataHash := chainhash.DoubleHashB(data)
|
dataHash := chainhash.DoubleHashB(data)
|
||||||
if !a.Signature.Verify(dataHash, copyPubKey(a.NodeID)) {
|
if !nodeSig.Verify(dataHash, nodeKey) {
|
||||||
var msgBuf bytes.Buffer
|
var msgBuf bytes.Buffer
|
||||||
if _, err := lnwire.WriteMessage(&msgBuf, a, 0); err != nil {
|
if _, err := lnwire.WriteMessage(&msgBuf, a, 0); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.Errorf("signature on NodeAnnouncement(%x) is "+
|
return errors.Errorf("signature on NodeAnnouncement(%x) is "+
|
||||||
"invalid: %x", a.NodeID.SerializeCompressed(),
|
"invalid: %x", nodeKey.SerializeCompressed(),
|
||||||
msgBuf.Bytes())
|
msgBuf.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +132,12 @@ func ValidateChannelUpdateAnn(pubKey *btcec.PublicKey,
|
|||||||
}
|
}
|
||||||
dataHash := chainhash.DoubleHashB(data)
|
dataHash := chainhash.DoubleHashB(data)
|
||||||
|
|
||||||
if !a.Signature.Verify(dataHash, copyPubKey(pubKey)) {
|
nodeSig, err := a.Signature.ToSignature()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !nodeSig.Verify(dataHash, pubKey) {
|
||||||
return errors.Errorf("invalid signature for channel "+
|
return errors.Errorf("invalid signature for channel "+
|
||||||
"update %v", spew.Sdump(a))
|
"update %v", spew.Sdump(a))
|
||||||
}
|
}
|
||||||
|
@ -157,17 +157,17 @@ type AuthenticatedGossiper struct {
|
|||||||
// TODO(roasbeef): limit premature networkMsgs to N
|
// TODO(roasbeef): limit premature networkMsgs to N
|
||||||
prematureAnnouncements map[uint32][]*networkMsg
|
prematureAnnouncements map[uint32][]*networkMsg
|
||||||
|
|
||||||
// prematureChannelUpdates is a map of ChannelUpdates we have
|
// prematureChannelUpdates is a map of ChannelUpdates we have received
|
||||||
// received that wasn't associated with any channel we know about.
|
// that wasn't associated with any channel we know about. We store
|
||||||
// We store them temporarily, such that we can reprocess them when
|
// them temporarily, such that we can reprocess them when a
|
||||||
// a ChannelAnnouncement for the channel is received.
|
// ChannelAnnouncement for the channel is received.
|
||||||
prematureChannelUpdates map[uint64][]*networkMsg
|
prematureChannelUpdates map[uint64][]*networkMsg
|
||||||
pChanUpdMtx sync.Mutex
|
pChanUpdMtx sync.Mutex
|
||||||
|
|
||||||
// waitingProofs is a persistent storage of partial channel proof
|
// waitingProofs is a persistent storage of partial channel proof
|
||||||
// announcement messages. We use it to buffer half of the material
|
// announcement messages. We use it to buffer half of the material
|
||||||
// needed to reconstruct a full authenticated channel announcement. Once
|
// needed to reconstruct a full authenticated channel announcement.
|
||||||
// we receive the other half the channel proof, we'll be able to
|
// Once we receive the other half the channel proof, we'll be able to
|
||||||
// properly validate it an re-broadcast it out to the network.
|
// properly validate it an re-broadcast it out to the network.
|
||||||
waitingProofs *channeldb.WaitingProofStore
|
waitingProofs *channeldb.WaitingProofStore
|
||||||
|
|
||||||
@ -176,8 +176,8 @@ type AuthenticatedGossiper struct {
|
|||||||
// networkHandler.
|
// networkHandler.
|
||||||
networkMsgs chan *networkMsg
|
networkMsgs chan *networkMsg
|
||||||
|
|
||||||
// chanPolicyUpdates is a channel that requests to update the forwarding
|
// chanPolicyUpdates is a channel that requests to update the
|
||||||
// policy of a set of channels is sent over.
|
// forwarding policy of a set of channels is sent over.
|
||||||
chanPolicyUpdates chan *chanPolicyUpdateRequest
|
chanPolicyUpdates chan *chanPolicyUpdateRequest
|
||||||
|
|
||||||
// bestHeight is the height of the block at the tip of the main chain
|
// bestHeight is the height of the block at the tip of the main chain
|
||||||
@ -193,6 +193,9 @@ type AuthenticatedGossiper struct {
|
|||||||
// consistent between when the DB is first read until it's written.
|
// consistent between when the DB is first read until it's written.
|
||||||
channelMtx *multimutex.Mutex
|
channelMtx *multimutex.Mutex
|
||||||
|
|
||||||
|
rejectMtx sync.RWMutex
|
||||||
|
recentRejects map[uint64]struct{}
|
||||||
|
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,6 +217,7 @@ func New(cfg Config, selfKey *btcec.PublicKey) (*AuthenticatedGossiper, error) {
|
|||||||
prematureChannelUpdates: make(map[uint64][]*networkMsg),
|
prematureChannelUpdates: make(map[uint64][]*networkMsg),
|
||||||
waitingProofs: storage,
|
waitingProofs: storage,
|
||||||
channelMtx: multimutex.NewMutex(),
|
channelMtx: multimutex.NewMutex(),
|
||||||
|
recentRejects: make(map[uint64]struct{}),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,17 +236,22 @@ func (d *AuthenticatedGossiper) SynchronizeNode(pub *btcec.PublicKey) error {
|
|||||||
// containing all the messages to be sent to the target peer.
|
// containing all the messages to be sent to the target peer.
|
||||||
var announceMessages []lnwire.Message
|
var announceMessages []lnwire.Message
|
||||||
|
|
||||||
makeNodeAnn := func(n *channeldb.LightningNode) *lnwire.NodeAnnouncement {
|
makeNodeAnn := func(n *channeldb.LightningNode) (*lnwire.NodeAnnouncement, error) {
|
||||||
alias, _ := lnwire.NewNodeAlias(n.Alias)
|
alias, _ := lnwire.NewNodeAlias(n.Alias)
|
||||||
|
|
||||||
|
wireSig, err := lnwire.NewSigFromRawSignature(n.AuthSigBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &lnwire.NodeAnnouncement{
|
return &lnwire.NodeAnnouncement{
|
||||||
Signature: n.AuthSig,
|
Signature: wireSig,
|
||||||
Timestamp: uint32(n.LastUpdate.Unix()),
|
Timestamp: uint32(n.LastUpdate.Unix()),
|
||||||
Addresses: n.Addresses,
|
Addresses: n.Addresses,
|
||||||
NodeID: n.PubKey,
|
NodeID: n.PubKeyBytes,
|
||||||
Features: n.Features.RawFeatureVector,
|
Features: n.Features.RawFeatureVector,
|
||||||
RGBColor: n.Color,
|
RGBColor: n.Color,
|
||||||
Alias: alias,
|
Alias: alias,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// As peers are expecting channel announcements before node
|
// As peers are expecting channel announcements before node
|
||||||
@ -262,8 +271,12 @@ func (d *AuthenticatedGossiper) SynchronizeNode(pub *btcec.PublicKey) error {
|
|||||||
// also has known validated nodes, then we'll send that as
|
// also has known validated nodes, then we'll send that as
|
||||||
// well.
|
// well.
|
||||||
if chanInfo.AuthProof != nil {
|
if chanInfo.AuthProof != nil {
|
||||||
chanAnn, e1Ann, e2Ann := createChanAnnouncement(
|
chanAnn, e1Ann, e2Ann, err := createChanAnnouncement(
|
||||||
chanInfo.AuthProof, chanInfo, e1, e2)
|
chanInfo.AuthProof, chanInfo, e1, e2,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
announceMessages = append(announceMessages, chanAnn)
|
announceMessages = append(announceMessages, chanAnn)
|
||||||
if e1Ann != nil {
|
if e1Ann != nil {
|
||||||
@ -272,7 +285,10 @@ func (d *AuthenticatedGossiper) SynchronizeNode(pub *btcec.PublicKey) error {
|
|||||||
// If this edge has a validated node
|
// If this edge has a validated node
|
||||||
// announcement, then we'll send that as well.
|
// announcement, then we'll send that as well.
|
||||||
if e1.Node.HaveNodeAnnouncement {
|
if e1.Node.HaveNodeAnnouncement {
|
||||||
nodeAnn := makeNodeAnn(e1.Node)
|
nodeAnn, err := makeNodeAnn(e1.Node)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
announceMessages = append(
|
announceMessages = append(
|
||||||
announceMessages, nodeAnn,
|
announceMessages, nodeAnn,
|
||||||
)
|
)
|
||||||
@ -285,7 +301,10 @@ func (d *AuthenticatedGossiper) SynchronizeNode(pub *btcec.PublicKey) error {
|
|||||||
// If this edge has a validated node
|
// If this edge has a validated node
|
||||||
// announcement, then we'll send that as well.
|
// announcement, then we'll send that as well.
|
||||||
if e2.Node.HaveNodeAnnouncement {
|
if e2.Node.HaveNodeAnnouncement {
|
||||||
nodeAnn := makeNodeAnn(e2.Node)
|
nodeAnn, err := makeNodeAnn(e2.Node)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
announceMessages = append(
|
announceMessages = append(
|
||||||
announceMessages, nodeAnn,
|
announceMessages, nodeAnn,
|
||||||
)
|
)
|
||||||
@ -588,7 +607,7 @@ func (d *deDupedAnnouncements) addMsg(message networkMsg) {
|
|||||||
// NodeID to create the corresponding Vertex.
|
// NodeID to create the corresponding Vertex.
|
||||||
case *lnwire.NodeAnnouncement:
|
case *lnwire.NodeAnnouncement:
|
||||||
sender := routing.NewVertex(message.peer)
|
sender := routing.NewVertex(message.peer)
|
||||||
deDupKey := routing.NewVertex(msg.NodeID)
|
deDupKey := routing.Vertex(msg.NodeID)
|
||||||
|
|
||||||
// We do the same for node announcements as we did for channel
|
// We do the same for node announcements as we did for channel
|
||||||
// updates, as they also carry a timestamp.
|
// updates, as they also carry a timestamp.
|
||||||
@ -875,6 +894,13 @@ func (d *AuthenticatedGossiper) networkHandler() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this message was recently rejected, then we won't
|
||||||
|
// attempt to re-process it.
|
||||||
|
if d.isRecentlyRejectedMsg(announcement.msg) {
|
||||||
|
announcement.err <- fmt.Errorf("recently rejected")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// We'll set up any dependent, and wait until a free
|
// We'll set up any dependent, and wait until a free
|
||||||
// slot for this job opens up, this allow us to not
|
// slot for this job opens up, this allow us to not
|
||||||
// have thousands of goroutines active.
|
// have thousands of goroutines active.
|
||||||
@ -999,6 +1025,26 @@ func (d *AuthenticatedGossiper) networkHandler() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isRecentlyRejectedMsg returns true if we recently rejected a message, and
|
||||||
|
// false otherwise, This avoids expensive reprocessing of the message.
|
||||||
|
func (d *AuthenticatedGossiper) isRecentlyRejectedMsg(msg lnwire.Message) bool {
|
||||||
|
d.rejectMtx.RLock()
|
||||||
|
defer d.rejectMtx.RUnlock()
|
||||||
|
|
||||||
|
switch m := msg.(type) {
|
||||||
|
case *lnwire.ChannelUpdate:
|
||||||
|
_, ok := d.recentRejects[m.ShortChannelID.ToUint64()]
|
||||||
|
return ok
|
||||||
|
|
||||||
|
case *lnwire.ChannelAnnouncement:
|
||||||
|
_, ok := d.recentRejects[m.ShortChannelID.ToUint64()]
|
||||||
|
return ok
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// retransmitStaleChannels examines all outgoing channels that the source node
|
// retransmitStaleChannels examines all outgoing channels that the source node
|
||||||
// is known to maintain to check to see if any of them are "stale". A channel
|
// is known to maintain to check to see if any of them are "stale". A channel
|
||||||
// is stale iff, the last timestamp of its rebroadcast is older then
|
// is stale iff, the last timestamp of its rebroadcast is older then
|
||||||
@ -1182,9 +1228,12 @@ func (d *AuthenticatedGossiper) processRejectedEdge(chanAnnMsg *lnwire.ChannelAn
|
|||||||
|
|
||||||
// We'll then create then validate the new fully assembled
|
// We'll then create then validate the new fully assembled
|
||||||
// announcement.
|
// announcement.
|
||||||
chanAnn, e1Ann, e2Ann := createChanAnnouncement(
|
chanAnn, e1Ann, e2Ann, err := createChanAnnouncement(
|
||||||
proof, chanInfo, e1, e2,
|
proof, chanInfo, e1, e2,
|
||||||
)
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
err = ValidateChannelAnn(chanAnn)
|
err = ValidateChannelAnn(chanAnn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := errors.Errorf("assembled channel announcement proof "+
|
err := errors.Errorf("assembled channel announcement proof "+
|
||||||
@ -1265,9 +1314,9 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
HaveNodeAnnouncement: true,
|
HaveNodeAnnouncement: true,
|
||||||
LastUpdate: time.Unix(int64(msg.Timestamp), 0),
|
LastUpdate: time.Unix(int64(msg.Timestamp), 0),
|
||||||
Addresses: msg.Addresses,
|
Addresses: msg.Addresses,
|
||||||
PubKey: msg.NodeID,
|
PubKeyBytes: msg.NodeID,
|
||||||
Alias: msg.Alias.String(),
|
Alias: msg.Alias.String(),
|
||||||
AuthSig: msg.Signature,
|
AuthSigBytes: msg.Signature.ToSignatureBytes(),
|
||||||
Features: features,
|
Features: features,
|
||||||
Color: msg.RGBColor,
|
Color: msg.RGBColor,
|
||||||
}
|
}
|
||||||
@ -1307,6 +1356,9 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
log.Error("Ignoring ChannelAnnouncement from "+
|
log.Error("Ignoring ChannelAnnouncement from "+
|
||||||
"chain=%v, gossiper on chain=%v", msg.ChainHash,
|
"chain=%v, gossiper on chain=%v", msg.ChainHash,
|
||||||
d.cfg.ChainHash)
|
d.cfg.ChainHash)
|
||||||
|
d.rejectMtx.Lock()
|
||||||
|
d.recentRejects[msg.ShortChannelID.ToUint64()] = struct{}{}
|
||||||
|
d.rejectMtx.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1338,6 +1390,9 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
if err := ValidateChannelAnn(msg); err != nil {
|
if err := ValidateChannelAnn(msg); err != nil {
|
||||||
err := errors.Errorf("unable to validate "+
|
err := errors.Errorf("unable to validate "+
|
||||||
"announcement: %v", err)
|
"announcement: %v", err)
|
||||||
|
d.rejectMtx.Lock()
|
||||||
|
d.recentRejects[msg.ShortChannelID.ToUint64()] = struct{}{}
|
||||||
|
d.rejectMtx.Unlock()
|
||||||
|
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
nMsg.err <- err
|
nMsg.err <- err
|
||||||
@ -1348,10 +1403,10 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
// itself to the database so we can fetch it later when
|
// itself to the database so we can fetch it later when
|
||||||
// gossiping with other nodes.
|
// gossiping with other nodes.
|
||||||
proof = &channeldb.ChannelAuthProof{
|
proof = &channeldb.ChannelAuthProof{
|
||||||
NodeSig1: msg.NodeSig1,
|
NodeSig1Bytes: msg.NodeSig1.ToSignatureBytes(),
|
||||||
NodeSig2: msg.NodeSig2,
|
NodeSig2Bytes: msg.NodeSig2.ToSignatureBytes(),
|
||||||
BitcoinSig1: msg.BitcoinSig1,
|
BitcoinSig1Bytes: msg.BitcoinSig1.ToSignatureBytes(),
|
||||||
BitcoinSig2: msg.BitcoinSig2,
|
BitcoinSig2Bytes: msg.BitcoinSig2.ToSignatureBytes(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1367,10 +1422,10 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
edge := &channeldb.ChannelEdgeInfo{
|
edge := &channeldb.ChannelEdgeInfo{
|
||||||
ChannelID: msg.ShortChannelID.ToUint64(),
|
ChannelID: msg.ShortChannelID.ToUint64(),
|
||||||
ChainHash: msg.ChainHash,
|
ChainHash: msg.ChainHash,
|
||||||
NodeKey1: msg.NodeID1,
|
NodeKey1Bytes: msg.NodeID1,
|
||||||
NodeKey2: msg.NodeID2,
|
NodeKey2Bytes: msg.NodeID2,
|
||||||
BitcoinKey1: msg.BitcoinKey1,
|
BitcoinKey1Bytes: msg.BitcoinKey1,
|
||||||
BitcoinKey2: msg.BitcoinKey2,
|
BitcoinKey2Bytes: msg.BitcoinKey2,
|
||||||
AuthProof: proof,
|
AuthProof: proof,
|
||||||
Features: featureBuf.Bytes(),
|
Features: featureBuf.Bytes(),
|
||||||
}
|
}
|
||||||
@ -1398,6 +1453,9 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
// see if we get any new announcements.
|
// see if we get any new announcements.
|
||||||
anns, rErr := d.processRejectedEdge(msg, proof)
|
anns, rErr := d.processRejectedEdge(msg, proof)
|
||||||
if rErr != nil {
|
if rErr != nil {
|
||||||
|
d.rejectMtx.Lock()
|
||||||
|
d.recentRejects[msg.ShortChannelID.ToUint64()] = struct{}{}
|
||||||
|
d.rejectMtx.Unlock()
|
||||||
nMsg.err <- rErr
|
nMsg.err <- rErr
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1499,6 +1557,9 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
log.Error("Ignoring ChannelUpdate from "+
|
log.Error("Ignoring ChannelUpdate from "+
|
||||||
"chain=%v, gossiper on chain=%v", msg.ChainHash,
|
"chain=%v, gossiper on chain=%v", msg.ChainHash,
|
||||||
d.cfg.ChainHash)
|
d.cfg.ChainHash)
|
||||||
|
d.rejectMtx.Lock()
|
||||||
|
d.recentRejects[msg.ShortChannelID.ToUint64()] = struct{}{}
|
||||||
|
d.rejectMtx.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1560,7 +1621,7 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
d.prematureChannelUpdates[shortChanID],
|
d.prematureChannelUpdates[shortChanID],
|
||||||
nMsg)
|
nMsg)
|
||||||
d.pChanUpdMtx.Unlock()
|
d.pChanUpdMtx.Unlock()
|
||||||
log.Infof("Got ChannelUpdate for edge not "+
|
log.Debugf("Got ChannelUpdate for edge not "+
|
||||||
"found in graph(shortChanID=%v), "+
|
"found in graph(shortChanID=%v), "+
|
||||||
"saving for reprocessing later",
|
"saving for reprocessing later",
|
||||||
shortChanID)
|
shortChanID)
|
||||||
@ -1572,6 +1633,10 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
shortChanID, err)
|
shortChanID, err)
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
nMsg.err <- err
|
nMsg.err <- err
|
||||||
|
|
||||||
|
d.rejectMtx.Lock()
|
||||||
|
d.recentRejects[msg.ShortChannelID.ToUint64()] = struct{}{}
|
||||||
|
d.rejectMtx.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1582,9 +1647,9 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
var pubKey *btcec.PublicKey
|
var pubKey *btcec.PublicKey
|
||||||
switch {
|
switch {
|
||||||
case msg.Flags&lnwire.ChanUpdateDirection == 0:
|
case msg.Flags&lnwire.ChanUpdateDirection == 0:
|
||||||
pubKey = chanInfo.NodeKey1
|
pubKey, _ = chanInfo.NodeKey1()
|
||||||
case msg.Flags&lnwire.ChanUpdateDirection == 1:
|
case msg.Flags&lnwire.ChanUpdateDirection == 1:
|
||||||
pubKey = chanInfo.NodeKey2
|
pubKey, _ = chanInfo.NodeKey2()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate the channel announcement with the expected public
|
// Validate the channel announcement with the expected public
|
||||||
@ -1601,7 +1666,7 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
}
|
}
|
||||||
|
|
||||||
update := &channeldb.ChannelEdgePolicy{
|
update := &channeldb.ChannelEdgePolicy{
|
||||||
Signature: msg.Signature,
|
SigBytes: msg.Signature.ToSignatureBytes(),
|
||||||
ChannelID: shortChanID,
|
ChannelID: shortChanID,
|
||||||
LastUpdate: time.Unix(int64(msg.Timestamp), 0),
|
LastUpdate: time.Unix(int64(msg.Timestamp), 0),
|
||||||
Flags: msg.Flags,
|
Flags: msg.Flags,
|
||||||
@ -1615,6 +1680,9 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
if routing.IsError(err, routing.ErrOutdated, routing.ErrIgnored) {
|
if routing.IsError(err, routing.ErrOutdated, routing.ErrIgnored) {
|
||||||
log.Debug(err)
|
log.Debug(err)
|
||||||
} else {
|
} else {
|
||||||
|
d.rejectMtx.Lock()
|
||||||
|
d.recentRejects[msg.ShortChannelID.ToUint64()] = struct{}{}
|
||||||
|
d.rejectMtx.Unlock()
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1632,9 +1700,9 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
var remotePeer *btcec.PublicKey
|
var remotePeer *btcec.PublicKey
|
||||||
switch {
|
switch {
|
||||||
case msg.Flags&lnwire.ChanUpdateDirection == 0:
|
case msg.Flags&lnwire.ChanUpdateDirection == 0:
|
||||||
remotePeer = chanInfo.NodeKey2
|
remotePeer, _ = chanInfo.NodeKey2()
|
||||||
case msg.Flags&lnwire.ChanUpdateDirection == 1:
|
case msg.Flags&lnwire.ChanUpdateDirection == 1:
|
||||||
remotePeer = chanInfo.NodeKey1
|
remotePeer, _ = chanInfo.NodeKey1()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send ChannelUpdate directly to remotePeer.
|
// Send ChannelUpdate directly to remotePeer.
|
||||||
@ -1726,9 +1794,9 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
}
|
}
|
||||||
|
|
||||||
isFirstNode := bytes.Equal(nMsg.peer.SerializeCompressed(),
|
isFirstNode := bytes.Equal(nMsg.peer.SerializeCompressed(),
|
||||||
chanInfo.NodeKey1.SerializeCompressed())
|
chanInfo.NodeKey1Bytes[:])
|
||||||
isSecondNode := bytes.Equal(nMsg.peer.SerializeCompressed(),
|
isSecondNode := bytes.Equal(nMsg.peer.SerializeCompressed(),
|
||||||
chanInfo.NodeKey2.SerializeCompressed())
|
chanInfo.NodeKey2Bytes[:])
|
||||||
|
|
||||||
// Ensure that channel that was retrieved belongs to the peer
|
// Ensure that channel that was retrieved belongs to the peer
|
||||||
// which sent the proof announcement.
|
// which sent the proof announcement.
|
||||||
@ -1748,9 +1816,9 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
if !nMsg.isRemote {
|
if !nMsg.isRemote {
|
||||||
var remotePeer *btcec.PublicKey
|
var remotePeer *btcec.PublicKey
|
||||||
if isFirstNode {
|
if isFirstNode {
|
||||||
remotePeer = chanInfo.NodeKey2
|
remotePeer, _ = chanInfo.NodeKey2()
|
||||||
} else {
|
} else {
|
||||||
remotePeer = chanInfo.NodeKey1
|
remotePeer, _ = chanInfo.NodeKey1()
|
||||||
}
|
}
|
||||||
// Since the remote peer might not be online
|
// Since the remote peer might not be online
|
||||||
// we'll call a method that will attempt to
|
// we'll call a method that will attempt to
|
||||||
@ -1786,9 +1854,14 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
msg.ChannelID,
|
msg.ChannelID,
|
||||||
peerID)
|
peerID)
|
||||||
|
|
||||||
chanAnn, _, _ := createChanAnnouncement(
|
chanAnn, _, _, err := createChanAnnouncement(
|
||||||
chanInfo.AuthProof, chanInfo, e1, e2)
|
chanInfo.AuthProof, chanInfo, e1, e2,
|
||||||
err := d.cfg.SendToPeer(nMsg.peer, chanAnn)
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("unable to gen ann: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = d.cfg.SendToPeer(nMsg.peer, chanAnn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Failed sending "+
|
log.Errorf("Failed sending "+
|
||||||
"full proof to "+
|
"full proof to "+
|
||||||
@ -1846,17 +1919,22 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n
|
|||||||
// validate it shortly below.
|
// validate it shortly below.
|
||||||
var dbProof channeldb.ChannelAuthProof
|
var dbProof channeldb.ChannelAuthProof
|
||||||
if isFirstNode {
|
if isFirstNode {
|
||||||
dbProof.NodeSig1 = msg.NodeSignature
|
dbProof.NodeSig1Bytes = msg.NodeSignature.ToSignatureBytes()
|
||||||
dbProof.NodeSig2 = oppositeProof.NodeSignature
|
dbProof.NodeSig2Bytes = oppositeProof.NodeSignature.ToSignatureBytes()
|
||||||
dbProof.BitcoinSig1 = msg.BitcoinSignature
|
dbProof.BitcoinSig1Bytes = msg.BitcoinSignature.ToSignatureBytes()
|
||||||
dbProof.BitcoinSig2 = oppositeProof.BitcoinSignature
|
dbProof.BitcoinSig2Bytes = oppositeProof.BitcoinSignature.ToSignatureBytes()
|
||||||
} else {
|
} else {
|
||||||
dbProof.NodeSig1 = oppositeProof.NodeSignature
|
dbProof.NodeSig1Bytes = oppositeProof.NodeSignature.ToSignatureBytes()
|
||||||
dbProof.NodeSig2 = msg.NodeSignature
|
dbProof.NodeSig2Bytes = msg.NodeSignature.ToSignatureBytes()
|
||||||
dbProof.BitcoinSig1 = oppositeProof.BitcoinSignature
|
dbProof.BitcoinSig1Bytes = oppositeProof.BitcoinSignature.ToSignatureBytes()
|
||||||
dbProof.BitcoinSig2 = msg.BitcoinSignature
|
dbProof.BitcoinSig2Bytes = msg.BitcoinSignature.ToSignatureBytes()
|
||||||
|
}
|
||||||
|
chanAnn, e1Ann, e2Ann, err := createChanAnnouncement(&dbProof, chanInfo, e1, e2)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
nMsg.err <- err
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
chanAnn, e1Ann, e2Ann := createChanAnnouncement(&dbProof, chanInfo, e1, e2)
|
|
||||||
|
|
||||||
// With all the necessary components assembled validate the
|
// With all the necessary components assembled validate the
|
||||||
// full channel announcement proof.
|
// full channel announcement proof.
|
||||||
@ -2017,6 +2095,8 @@ func (d *AuthenticatedGossiper) sendAnnSigReliably(
|
|||||||
func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo,
|
func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo,
|
||||||
edge *channeldb.ChannelEdgePolicy) (*lnwire.ChannelAnnouncement, *lnwire.ChannelUpdate, error) {
|
edge *channeldb.ChannelEdgePolicy) (*lnwire.ChannelAnnouncement, *lnwire.ChannelUpdate, error) {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
// Make sure timestamp is always increased, such that our update
|
// Make sure timestamp is always increased, such that our update
|
||||||
// gets propagated.
|
// gets propagated.
|
||||||
timestamp := time.Now().Unix()
|
timestamp := time.Now().Unix()
|
||||||
@ -2025,7 +2105,6 @@ func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo,
|
|||||||
}
|
}
|
||||||
edge.LastUpdate = time.Unix(timestamp, 0)
|
edge.LastUpdate = time.Unix(timestamp, 0)
|
||||||
chanUpdate := &lnwire.ChannelUpdate{
|
chanUpdate := &lnwire.ChannelUpdate{
|
||||||
Signature: edge.Signature,
|
|
||||||
ChainHash: info.ChainHash,
|
ChainHash: info.ChainHash,
|
||||||
ShortChannelID: lnwire.NewShortChanIDFromInt(edge.ChannelID),
|
ShortChannelID: lnwire.NewShortChanIDFromInt(edge.ChannelID),
|
||||||
Timestamp: uint32(timestamp),
|
Timestamp: uint32(timestamp),
|
||||||
@ -2035,6 +2114,10 @@ func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo,
|
|||||||
BaseFee: uint32(edge.FeeBaseMSat),
|
BaseFee: uint32(edge.FeeBaseMSat),
|
||||||
FeeRate: uint32(edge.FeeProportionalMillionths),
|
FeeRate: uint32(edge.FeeProportionalMillionths),
|
||||||
}
|
}
|
||||||
|
chanUpdate.Signature, err = lnwire.NewSigFromRawSignature(edge.SigBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// With the update applied, we'll generate a new signature over a
|
// With the update applied, we'll generate a new signature over a
|
||||||
// digest of the channel announcement itself.
|
// digest of the channel announcement itself.
|
||||||
@ -2045,8 +2128,11 @@ func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo,
|
|||||||
|
|
||||||
// Next, we'll set the new signature in place, and update the reference
|
// Next, we'll set the new signature in place, and update the reference
|
||||||
// in the backing slice.
|
// in the backing slice.
|
||||||
edge.Signature = sig
|
edge.SigBytes = sig.Serialize()
|
||||||
chanUpdate.Signature = sig
|
chanUpdate.Signature, err = lnwire.NewSigFromSignature(sig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// To ensure that our signature is valid, we'll verify it ourself
|
// To ensure that our signature is valid, we'll verify it ourself
|
||||||
// before committing it to the slice returned.
|
// before committing it to the slice returned.
|
||||||
@ -2057,7 +2143,6 @@ func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finally, we'll write the new edge policy to disk.
|
// Finally, we'll write the new edge policy to disk.
|
||||||
edge.Node.PubKey.Curve = nil
|
|
||||||
if err := d.cfg.Router.UpdateEdge(edge); err != nil {
|
if err := d.cfg.Router.UpdateEdge(edge); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -2069,17 +2154,37 @@ func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo,
|
|||||||
if info.AuthProof != nil {
|
if info.AuthProof != nil {
|
||||||
chanID := lnwire.NewShortChanIDFromInt(info.ChannelID)
|
chanID := lnwire.NewShortChanIDFromInt(info.ChannelID)
|
||||||
chanAnn = &lnwire.ChannelAnnouncement{
|
chanAnn = &lnwire.ChannelAnnouncement{
|
||||||
NodeSig1: info.AuthProof.NodeSig1,
|
|
||||||
NodeSig2: info.AuthProof.NodeSig2,
|
|
||||||
ShortChannelID: chanID,
|
ShortChannelID: chanID,
|
||||||
BitcoinSig1: info.AuthProof.BitcoinSig1,
|
NodeID1: info.NodeKey1Bytes,
|
||||||
BitcoinSig2: info.AuthProof.BitcoinSig2,
|
NodeID2: info.NodeKey2Bytes,
|
||||||
NodeID1: info.NodeKey1,
|
|
||||||
NodeID2: info.NodeKey2,
|
|
||||||
ChainHash: info.ChainHash,
|
ChainHash: info.ChainHash,
|
||||||
BitcoinKey1: info.BitcoinKey1,
|
BitcoinKey1: info.BitcoinKey1Bytes,
|
||||||
Features: lnwire.NewRawFeatureVector(),
|
Features: lnwire.NewRawFeatureVector(),
|
||||||
BitcoinKey2: info.BitcoinKey2,
|
BitcoinKey2: info.BitcoinKey2Bytes,
|
||||||
|
}
|
||||||
|
chanAnn.NodeSig1, err = lnwire.NewSigFromRawSignature(
|
||||||
|
info.AuthProof.NodeSig1Bytes,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
chanAnn.NodeSig2, err = lnwire.NewSigFromRawSignature(
|
||||||
|
info.AuthProof.NodeSig2Bytes,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
chanAnn.BitcoinSig1, err = lnwire.NewSigFromRawSignature(
|
||||||
|
info.AuthProof.BitcoinSig1Bytes,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
chanAnn.BitcoinSig2, err = lnwire.NewSigFromRawSignature(
|
||||||
|
info.AuthProof.BitcoinSig2Bytes,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,10 +305,6 @@ func createAnnouncements(blockHeight uint32) (*annBatch, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
batch.localChanAnn.BitcoinSig1 = nil
|
|
||||||
batch.localChanAnn.BitcoinSig2 = nil
|
|
||||||
batch.localChanAnn.NodeSig1 = nil
|
|
||||||
batch.localChanAnn.NodeSig2 = nil
|
|
||||||
|
|
||||||
batch.chanUpdAnn1, err = createUpdateAnnouncement(
|
batch.chanUpdAnn1, err = createUpdateAnnouncement(
|
||||||
blockHeight, 0, nodeKeyPriv1, timestamp,
|
blockHeight, 0, nodeKeyPriv1, timestamp,
|
||||||
@ -342,13 +338,18 @@ func createNodeAnnouncement(priv *btcec.PrivateKey,
|
|||||||
a := &lnwire.NodeAnnouncement{
|
a := &lnwire.NodeAnnouncement{
|
||||||
Timestamp: timestamp,
|
Timestamp: timestamp,
|
||||||
Addresses: testAddrs,
|
Addresses: testAddrs,
|
||||||
NodeID: priv.PubKey(),
|
|
||||||
Alias: alias,
|
Alias: alias,
|
||||||
Features: testFeatures,
|
Features: testFeatures,
|
||||||
}
|
}
|
||||||
|
copy(a.NodeID[:], priv.PubKey().SerializeCompressed())
|
||||||
|
|
||||||
signer := mockSigner{priv}
|
signer := mockSigner{priv}
|
||||||
a.Signature, err = SignAnnouncement(&signer, priv.PubKey(), a)
|
sig, err := SignAnnouncement(&signer, priv.PubKey(), a)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Signature, err = lnwire.NewSigFromSignature(sig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -376,7 +377,13 @@ func createUpdateAnnouncement(blockHeight uint32, flags lnwire.ChanUpdateFlag,
|
|||||||
|
|
||||||
pub := nodeKey.PubKey()
|
pub := nodeKey.PubKey()
|
||||||
signer := mockSigner{nodeKey}
|
signer := mockSigner{nodeKey}
|
||||||
if a.Signature, err = SignAnnouncement(&signer, pub, a); err != nil {
|
sig, err := SignAnnouncement(&signer, pub, a)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Signature, err = lnwire.NewSigFromSignature(sig)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,34 +399,54 @@ func createRemoteChannelAnnouncement(blockHeight uint32) (*lnwire.ChannelAnnounc
|
|||||||
TxIndex: 0,
|
TxIndex: 0,
|
||||||
TxPosition: 0,
|
TxPosition: 0,
|
||||||
},
|
},
|
||||||
NodeID1: nodeKeyPub1,
|
|
||||||
NodeID2: nodeKeyPub2,
|
|
||||||
BitcoinKey1: bitcoinKeyPub1,
|
|
||||||
BitcoinKey2: bitcoinKeyPub2,
|
|
||||||
Features: testFeatures,
|
Features: testFeatures,
|
||||||
}
|
}
|
||||||
|
copy(a.NodeID1[:], nodeKeyPub1.SerializeCompressed())
|
||||||
|
copy(a.NodeID2[:], nodeKeyPub2.SerializeCompressed())
|
||||||
|
copy(a.BitcoinKey1[:], bitcoinKeyPub1.SerializeCompressed())
|
||||||
|
copy(a.BitcoinKey2[:], bitcoinKeyPub2.SerializeCompressed())
|
||||||
|
|
||||||
pub := nodeKeyPriv1.PubKey()
|
pub := nodeKeyPriv1.PubKey()
|
||||||
signer := mockSigner{nodeKeyPriv1}
|
signer := mockSigner{nodeKeyPriv1}
|
||||||
if a.NodeSig1, err = SignAnnouncement(&signer, pub, a); err != nil {
|
sig, err := SignAnnouncement(&signer, pub, a)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
a.NodeSig1, err = lnwire.NewSigFromSignature(sig)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pub = nodeKeyPriv2.PubKey()
|
pub = nodeKeyPriv2.PubKey()
|
||||||
signer = mockSigner{nodeKeyPriv2}
|
signer = mockSigner{nodeKeyPriv2}
|
||||||
if a.NodeSig2, err = SignAnnouncement(&signer, pub, a); err != nil {
|
sig, err = SignAnnouncement(&signer, pub, a)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
a.NodeSig2, err = lnwire.NewSigFromSignature(sig)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pub = bitcoinKeyPriv1.PubKey()
|
pub = bitcoinKeyPriv1.PubKey()
|
||||||
signer = mockSigner{bitcoinKeyPriv1}
|
signer = mockSigner{bitcoinKeyPriv1}
|
||||||
if a.BitcoinSig1, err = SignAnnouncement(&signer, pub, a); err != nil {
|
sig, err = SignAnnouncement(&signer, pub, a)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
a.BitcoinSig1, err = lnwire.NewSigFromSignature(sig)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pub = bitcoinKeyPriv2.PubKey()
|
pub = bitcoinKeyPriv2.PubKey()
|
||||||
signer = mockSigner{bitcoinKeyPriv2}
|
signer = mockSigner{bitcoinKeyPriv2}
|
||||||
if a.BitcoinSig2, err = SignAnnouncement(&signer, pub, a); err != nil {
|
sig, err = SignAnnouncement(&signer, pub, a)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
a.BitcoinSig2, err = lnwire.NewSigFromSignature(sig)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,8 +548,10 @@ func TestProcessAnnouncement(t *testing.T) {
|
|||||||
t.Fatalf("can't create node announcement: %v", err)
|
t.Fatalf("can't create node announcement: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nodePub := nodeKeyPriv1.PubKey()
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case err = <-ctx.gossiper.ProcessRemoteAnnouncement(na, na.NodeID):
|
case err = <-ctx.gossiper.ProcessRemoteAnnouncement(na, nodePub):
|
||||||
case <-time.After(2 * time.Second):
|
case <-time.After(2 * time.Second):
|
||||||
t.Fatal("remote announcement not processed")
|
t.Fatal("remote announcement not processed")
|
||||||
}
|
}
|
||||||
@ -532,7 +561,7 @@ func TestProcessAnnouncement(t *testing.T) {
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case msg := <-ctx.broadcastedMessage:
|
case msg := <-ctx.broadcastedMessage:
|
||||||
assertSenderExistence(na.NodeID, msg)
|
assertSenderExistence(nodePub, msg)
|
||||||
case <-time.After(2 * trickleDelay):
|
case <-time.After(2 * trickleDelay):
|
||||||
t.Fatal("announcement wasn't proceeded")
|
t.Fatal("announcement wasn't proceeded")
|
||||||
}
|
}
|
||||||
@ -550,7 +579,7 @@ func TestProcessAnnouncement(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case err = <-ctx.gossiper.ProcessRemoteAnnouncement(ca, na.NodeID):
|
case err = <-ctx.gossiper.ProcessRemoteAnnouncement(ca, nodePub):
|
||||||
case <-time.After(2 * time.Second):
|
case <-time.After(2 * time.Second):
|
||||||
t.Fatal("remote announcement not processed")
|
t.Fatal("remote announcement not processed")
|
||||||
}
|
}
|
||||||
@ -560,7 +589,7 @@ func TestProcessAnnouncement(t *testing.T) {
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case msg := <-ctx.broadcastedMessage:
|
case msg := <-ctx.broadcastedMessage:
|
||||||
assertSenderExistence(na.NodeID, msg)
|
assertSenderExistence(nodePub, msg)
|
||||||
case <-time.After(2 * trickleDelay):
|
case <-time.After(2 * trickleDelay):
|
||||||
t.Fatal("announcement wasn't proceeded")
|
t.Fatal("announcement wasn't proceeded")
|
||||||
}
|
}
|
||||||
@ -578,7 +607,7 @@ func TestProcessAnnouncement(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case err = <-ctx.gossiper.ProcessRemoteAnnouncement(ua, na.NodeID):
|
case err = <-ctx.gossiper.ProcessRemoteAnnouncement(ua, nodePub):
|
||||||
case <-time.After(2 * time.Second):
|
case <-time.After(2 * time.Second):
|
||||||
t.Fatal("remote announcement not processed")
|
t.Fatal("remote announcement not processed")
|
||||||
}
|
}
|
||||||
@ -588,7 +617,7 @@ func TestProcessAnnouncement(t *testing.T) {
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case msg := <-ctx.broadcastedMessage:
|
case msg := <-ctx.broadcastedMessage:
|
||||||
assertSenderExistence(na.NodeID, msg)
|
assertSenderExistence(nodePub, msg)
|
||||||
case <-time.After(2 * trickleDelay):
|
case <-time.After(2 * trickleDelay):
|
||||||
t.Fatal("announcement wasn't proceeded")
|
t.Fatal("announcement wasn't proceeded")
|
||||||
}
|
}
|
||||||
@ -612,11 +641,13 @@ func TestPrematureAnnouncement(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
na, err := createNodeAnnouncement(nodeKeyPriv1, timestamp)
|
_, err = createNodeAnnouncement(nodeKeyPriv1, timestamp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("can't create node announcement: %v", err)
|
t.Fatalf("can't create node announcement: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nodePub := nodeKeyPriv1.PubKey()
|
||||||
|
|
||||||
// Pretending that we receive the valid channel announcement from
|
// Pretending that we receive the valid channel announcement from
|
||||||
// remote side, but block height of this announcement is greater than
|
// remote side, but block height of this announcement is greater than
|
||||||
// highest know to us, for that reason it should be added to the
|
// highest know to us, for that reason it should be added to the
|
||||||
@ -627,7 +658,7 @@ func TestPrematureAnnouncement(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.gossiper.ProcessRemoteAnnouncement(ca, na.NodeID):
|
case <-ctx.gossiper.ProcessRemoteAnnouncement(ca, nodePub):
|
||||||
t.Fatal("announcement was proceeded")
|
t.Fatal("announcement was proceeded")
|
||||||
case <-time.After(100 * time.Millisecond):
|
case <-time.After(100 * time.Millisecond):
|
||||||
}
|
}
|
||||||
@ -646,7 +677,7 @@ func TestPrematureAnnouncement(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.gossiper.ProcessRemoteAnnouncement(ua, na.NodeID):
|
case <-ctx.gossiper.ProcessRemoteAnnouncement(ua, nodePub):
|
||||||
t.Fatal("announcement was proceeded")
|
t.Fatal("announcement was proceeded")
|
||||||
case <-time.After(100 * time.Millisecond):
|
case <-time.After(100 * time.Millisecond):
|
||||||
}
|
}
|
||||||
@ -709,8 +740,14 @@ func TestSignatureAnnouncementLocalFirst(t *testing.T) {
|
|||||||
t.Fatalf("can't generate announcements: %v", err)
|
t.Fatalf("can't generate announcements: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
localKey := batch.nodeAnn1.NodeID
|
localKey, err := btcec.ParsePubKey(batch.nodeAnn1.NodeID[:], btcec.S256())
|
||||||
remoteKey := batch.nodeAnn2.NodeID
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse pubkey: %v", err)
|
||||||
|
}
|
||||||
|
remoteKey, err := btcec.ParsePubKey(batch.nodeAnn2.NodeID[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse pubkey: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Recreate lightning network topology. Initialize router with channel
|
// Recreate lightning network topology. Initialize router with channel
|
||||||
// between two nodes.
|
// between two nodes.
|
||||||
@ -865,8 +902,14 @@ func TestOrphanSignatureAnnouncement(t *testing.T) {
|
|||||||
t.Fatalf("can't generate announcements: %v", err)
|
t.Fatalf("can't generate announcements: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
localKey := batch.nodeAnn1.NodeID
|
localKey, err := btcec.ParsePubKey(batch.nodeAnn1.NodeID[:], btcec.S256())
|
||||||
remoteKey := batch.nodeAnn2.NodeID
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse pubkey: %v", err)
|
||||||
|
}
|
||||||
|
remoteKey, err := btcec.ParsePubKey(batch.nodeAnn2.NodeID[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse pubkey: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Pretending that we receive local channel announcement from funding
|
// Pretending that we receive local channel announcement from funding
|
||||||
// manager, thereby kick off the announcement exchange process, in
|
// manager, thereby kick off the announcement exchange process, in
|
||||||
@ -1021,8 +1064,14 @@ func TestSignatureAnnouncementRetry(t *testing.T) {
|
|||||||
t.Fatalf("can't generate announcements: %v", err)
|
t.Fatalf("can't generate announcements: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
localKey := batch.nodeAnn1.NodeID
|
localKey, err := btcec.ParsePubKey(batch.nodeAnn1.NodeID[:], btcec.S256())
|
||||||
remoteKey := batch.nodeAnn2.NodeID
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse pubkey: %v", err)
|
||||||
|
}
|
||||||
|
remoteKey, err := btcec.ParsePubKey(batch.nodeAnn2.NodeID[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse pubkey: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Recreate lightning network topology. Initialize router with channel
|
// Recreate lightning network topology. Initialize router with channel
|
||||||
// between two nodes.
|
// between two nodes.
|
||||||
@ -1203,8 +1252,14 @@ func TestSignatureAnnouncementRetryAtStartup(t *testing.T) {
|
|||||||
t.Fatalf("can't generate announcements: %v", err)
|
t.Fatalf("can't generate announcements: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
localKey := batch.nodeAnn1.NodeID
|
localKey, err := btcec.ParsePubKey(batch.nodeAnn1.NodeID[:], btcec.S256())
|
||||||
remoteKey := batch.nodeAnn2.NodeID
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse pubkey: %v", err)
|
||||||
|
}
|
||||||
|
remoteKey, err := btcec.ParsePubKey(batch.nodeAnn2.NodeID[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse pubkey: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Recreate lightning network topology. Initialize router with channel
|
// Recreate lightning network topology. Initialize router with channel
|
||||||
// between two nodes.
|
// between two nodes.
|
||||||
@ -1422,8 +1477,14 @@ func TestSignatureAnnouncementFullProofWhenRemoteProof(t *testing.T) {
|
|||||||
t.Fatalf("can't generate announcements: %v", err)
|
t.Fatalf("can't generate announcements: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
localKey := batch.nodeAnn1.NodeID
|
localKey, err := btcec.ParsePubKey(batch.nodeAnn1.NodeID[:], btcec.S256())
|
||||||
remoteKey := batch.nodeAnn2.NodeID
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse pubkey: %v", err)
|
||||||
|
}
|
||||||
|
remoteKey, err := btcec.ParsePubKey(batch.nodeAnn2.NodeID[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse pubkey: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Recreate lightning network topology. Initialize router with channel
|
// Recreate lightning network topology. Initialize router with channel
|
||||||
// between two nodes.
|
// between two nodes.
|
||||||
@ -1819,8 +1880,14 @@ func TestReceiveRemoteChannelUpdateFirst(t *testing.T) {
|
|||||||
t.Fatalf("can't generate announcements: %v", err)
|
t.Fatalf("can't generate announcements: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
localKey := batch.nodeAnn1.NodeID
|
localKey, err := btcec.ParsePubKey(batch.nodeAnn1.NodeID[:], btcec.S256())
|
||||||
remoteKey := batch.nodeAnn2.NodeID
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse pubkey: %v", err)
|
||||||
|
}
|
||||||
|
remoteKey, err := btcec.ParsePubKey(batch.nodeAnn2.NodeID[:], btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse pubkey: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Recreate the case where the remote node is sending us its ChannelUpdate
|
// Recreate the case where the remote node is sending us its ChannelUpdate
|
||||||
// before we have been able to process our own ChannelAnnouncement and
|
// before we have been able to process our own ChannelAnnouncement and
|
||||||
|
@ -16,24 +16,46 @@ import (
|
|||||||
func createChanAnnouncement(chanProof *channeldb.ChannelAuthProof,
|
func createChanAnnouncement(chanProof *channeldb.ChannelAuthProof,
|
||||||
chanInfo *channeldb.ChannelEdgeInfo,
|
chanInfo *channeldb.ChannelEdgeInfo,
|
||||||
e1, e2 *channeldb.ChannelEdgePolicy) (*lnwire.ChannelAnnouncement,
|
e1, e2 *channeldb.ChannelEdgePolicy) (*lnwire.ChannelAnnouncement,
|
||||||
*lnwire.ChannelUpdate, *lnwire.ChannelUpdate) {
|
*lnwire.ChannelUpdate, *lnwire.ChannelUpdate, error) {
|
||||||
|
|
||||||
// First, using the parameters of the channel, along with the channel
|
// First, using the parameters of the channel, along with the channel
|
||||||
// authentication chanProof, we'll create re-create the original
|
// authentication chanProof, we'll create re-create the original
|
||||||
// authenticated channel announcement.
|
// authenticated channel announcement.
|
||||||
chanID := lnwire.NewShortChanIDFromInt(chanInfo.ChannelID)
|
chanID := lnwire.NewShortChanIDFromInt(chanInfo.ChannelID)
|
||||||
chanAnn := &lnwire.ChannelAnnouncement{
|
chanAnn := &lnwire.ChannelAnnouncement{
|
||||||
NodeSig1: chanProof.NodeSig1,
|
|
||||||
NodeSig2: chanProof.NodeSig2,
|
|
||||||
ShortChannelID: chanID,
|
ShortChannelID: chanID,
|
||||||
BitcoinSig1: chanProof.BitcoinSig1,
|
NodeID1: chanInfo.NodeKey1Bytes,
|
||||||
BitcoinSig2: chanProof.BitcoinSig2,
|
NodeID2: chanInfo.NodeKey2Bytes,
|
||||||
NodeID1: chanInfo.NodeKey1,
|
|
||||||
NodeID2: chanInfo.NodeKey2,
|
|
||||||
ChainHash: chanInfo.ChainHash,
|
ChainHash: chanInfo.ChainHash,
|
||||||
BitcoinKey1: chanInfo.BitcoinKey1,
|
BitcoinKey1: chanInfo.BitcoinKey1Bytes,
|
||||||
|
BitcoinKey2: chanInfo.BitcoinKey2Bytes,
|
||||||
Features: lnwire.NewRawFeatureVector(),
|
Features: lnwire.NewRawFeatureVector(),
|
||||||
BitcoinKey2: chanInfo.BitcoinKey2,
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
chanAnn.BitcoinSig1, err = lnwire.NewSigFromRawSignature(
|
||||||
|
chanProof.BitcoinSig1Bytes,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
chanAnn.BitcoinSig2, err = lnwire.NewSigFromRawSignature(
|
||||||
|
chanProof.BitcoinSig2Bytes,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
chanAnn.NodeSig1, err = lnwire.NewSigFromRawSignature(
|
||||||
|
chanProof.NodeSig1Bytes,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
chanAnn.NodeSig2, err = lnwire.NewSigFromRawSignature(
|
||||||
|
chanProof.NodeSig2Bytes,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll unconditionally queue the channel's existence chanProof as it
|
// We'll unconditionally queue the channel's existence chanProof as it
|
||||||
@ -46,7 +68,6 @@ func createChanAnnouncement(chanProof *channeldb.ChannelAuthProof,
|
|||||||
var edge1Ann, edge2Ann *lnwire.ChannelUpdate
|
var edge1Ann, edge2Ann *lnwire.ChannelUpdate
|
||||||
if e1 != nil {
|
if e1 != nil {
|
||||||
edge1Ann = &lnwire.ChannelUpdate{
|
edge1Ann = &lnwire.ChannelUpdate{
|
||||||
Signature: e1.Signature,
|
|
||||||
ChainHash: chanInfo.ChainHash,
|
ChainHash: chanInfo.ChainHash,
|
||||||
ShortChannelID: chanID,
|
ShortChannelID: chanID,
|
||||||
Timestamp: uint32(e1.LastUpdate.Unix()),
|
Timestamp: uint32(e1.LastUpdate.Unix()),
|
||||||
@ -56,10 +77,13 @@ func createChanAnnouncement(chanProof *channeldb.ChannelAuthProof,
|
|||||||
BaseFee: uint32(e1.FeeBaseMSat),
|
BaseFee: uint32(e1.FeeBaseMSat),
|
||||||
FeeRate: uint32(e1.FeeProportionalMillionths),
|
FeeRate: uint32(e1.FeeProportionalMillionths),
|
||||||
}
|
}
|
||||||
|
edge1Ann.Signature, err = lnwire.NewSigFromRawSignature(e1.SigBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if e2 != nil {
|
if e2 != nil {
|
||||||
edge2Ann = &lnwire.ChannelUpdate{
|
edge2Ann = &lnwire.ChannelUpdate{
|
||||||
Signature: e2.Signature,
|
|
||||||
ChainHash: chanInfo.ChainHash,
|
ChainHash: chanInfo.ChainHash,
|
||||||
ShortChannelID: chanID,
|
ShortChannelID: chanID,
|
||||||
Timestamp: uint32(e2.LastUpdate.Unix()),
|
Timestamp: uint32(e2.LastUpdate.Unix()),
|
||||||
@ -69,9 +93,13 @@ func createChanAnnouncement(chanProof *channeldb.ChannelAuthProof,
|
|||||||
BaseFee: uint32(e2.FeeBaseMSat),
|
BaseFee: uint32(e2.FeeBaseMSat),
|
||||||
FeeRate: uint32(e2.FeeProportionalMillionths),
|
FeeRate: uint32(e2.FeeProportionalMillionths),
|
||||||
}
|
}
|
||||||
|
edge2Ann.Signature, err = lnwire.NewSigFromRawSignature(e2.SigBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return chanAnn, edge1Ann, edge2Ann
|
return chanAnn, edge1Ann, edge2Ann, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// copyPubKey performs a copy of the target public key, setting a fresh curve
|
// copyPubKey performs a copy of the target public key, setting a fresh curve
|
||||||
|
@ -1062,14 +1062,6 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) {
|
|||||||
// the commitment transaction to the remote peer.
|
// the commitment transaction to the remote peer.
|
||||||
outPoint := resCtx.reservation.FundingOutpoint()
|
outPoint := resCtx.reservation.FundingOutpoint()
|
||||||
_, sig := resCtx.reservation.OurSignatures()
|
_, sig := resCtx.reservation.OurSignatures()
|
||||||
commitSig, err := btcec.ParseSignature(sig, btcec.S256())
|
|
||||||
if err != nil {
|
|
||||||
fndgLog.Errorf("Unable to parse signature: %v", err)
|
|
||||||
f.failFundingFlow(fmsg.peerAddress.IdentityKey,
|
|
||||||
msg.PendingChannelID, []byte(err.Error()))
|
|
||||||
resCtx.err <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// A new channel has almost finished the funding process. In order to
|
// A new channel has almost finished the funding process. In order to
|
||||||
// properly synchronize with the writeHandler goroutine, we add a new
|
// properly synchronize with the writeHandler goroutine, we add a new
|
||||||
@ -1095,7 +1087,14 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) {
|
|||||||
fundingCreated := &lnwire.FundingCreated{
|
fundingCreated := &lnwire.FundingCreated{
|
||||||
PendingChannelID: pendingChanID,
|
PendingChannelID: pendingChanID,
|
||||||
FundingPoint: *outPoint,
|
FundingPoint: *outPoint,
|
||||||
CommitSig: commitSig,
|
}
|
||||||
|
fundingCreated.CommitSig, err = lnwire.NewSigFromRawSignature(sig)
|
||||||
|
if err != nil {
|
||||||
|
fndgLog.Errorf("Unable to parse signature: %v", err)
|
||||||
|
f.failFundingFlow(fmsg.peerAddress.IdentityKey,
|
||||||
|
msg.PendingChannelID, []byte(err.Error()))
|
||||||
|
resCtx.err <- err
|
||||||
|
return
|
||||||
}
|
}
|
||||||
err = f.cfg.SendToPeer(fmsg.peerAddress.IdentityKey, fundingCreated)
|
err = f.cfg.SendToPeer(fmsg.peerAddress.IdentityKey, fundingCreated)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1148,7 +1147,7 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) {
|
|||||||
// funding transaction will broadcast after our next message.
|
// funding transaction will broadcast after our next message.
|
||||||
// CompleteReservationSingle will also mark the channel as 'IsPending'
|
// CompleteReservationSingle will also mark the channel as 'IsPending'
|
||||||
// in the database.
|
// in the database.
|
||||||
commitSig := fmsg.msg.CommitSig.Serialize()
|
commitSig := fmsg.msg.CommitSig.ToSignatureBytes()
|
||||||
completeChan, err := resCtx.reservation.CompleteReservationSingle(
|
completeChan, err := resCtx.reservation.CompleteReservationSingle(
|
||||||
&fundingOut, commitSig)
|
&fundingOut, commitSig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1191,11 +1190,8 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) {
|
|||||||
|
|
||||||
// With their signature for our version of the commitment transaction
|
// With their signature for our version of the commitment transaction
|
||||||
// verified, we can now send over our signature to the remote peer.
|
// verified, we can now send over our signature to the remote peer.
|
||||||
//
|
|
||||||
// TODO(roasbeef): just have raw bytes in wire msg? avoids decoding
|
|
||||||
// then decoding shortly afterwards.
|
|
||||||
_, sig := resCtx.reservation.OurSignatures()
|
_, sig := resCtx.reservation.OurSignatures()
|
||||||
ourCommitSig, err := btcec.ParseSignature(sig, btcec.S256())
|
ourCommitSig, err := lnwire.NewSigFromRawSignature(sig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fndgLog.Errorf("unable to parse signature: %v", err)
|
fndgLog.Errorf("unable to parse signature: %v", err)
|
||||||
f.failFundingFlow(fmsg.peerAddress.IdentityKey,
|
f.failFundingFlow(fmsg.peerAddress.IdentityKey,
|
||||||
@ -1344,7 +1340,7 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) {
|
|||||||
// The remote peer has responded with a signature for our commitment
|
// The remote peer has responded with a signature for our commitment
|
||||||
// transaction. We'll verify the signature for validity, then commit
|
// transaction. We'll verify the signature for validity, then commit
|
||||||
// the state to disk as we can now open the channel.
|
// the state to disk as we can now open the channel.
|
||||||
commitSig := fmsg.msg.CommitSig.Serialize()
|
commitSig := fmsg.msg.CommitSig.ToSignatureBytes()
|
||||||
completeChan, err := resCtx.reservation.CompleteReservation(nil, commitSig)
|
completeChan, err := resCtx.reservation.CompleteReservation(nil, commitSig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fndgLog.Errorf("Unable to complete reservation sign complete: %v", err)
|
fndgLog.Errorf("Unable to complete reservation sign complete: %v", err)
|
||||||
@ -2127,19 +2123,19 @@ func (f *fundingManager) newChanAnnouncement(localPubKey, remotePubKey *btcec.Pu
|
|||||||
selfBytes := localPubKey.SerializeCompressed()
|
selfBytes := localPubKey.SerializeCompressed()
|
||||||
remoteBytes := remotePubKey.SerializeCompressed()
|
remoteBytes := remotePubKey.SerializeCompressed()
|
||||||
if bytes.Compare(selfBytes, remoteBytes) == -1 {
|
if bytes.Compare(selfBytes, remoteBytes) == -1 {
|
||||||
chanAnn.NodeID1 = localPubKey
|
copy(chanAnn.NodeID1[:], localPubKey.SerializeCompressed())
|
||||||
chanAnn.NodeID2 = remotePubKey
|
copy(chanAnn.NodeID2[:], remotePubKey.SerializeCompressed())
|
||||||
chanAnn.BitcoinKey1 = localFundingKey
|
copy(chanAnn.BitcoinKey1[:], localFundingKey.SerializeCompressed())
|
||||||
chanAnn.BitcoinKey2 = remoteFundingKey
|
copy(chanAnn.BitcoinKey2[:], remoteFundingKey.SerializeCompressed())
|
||||||
|
|
||||||
// If we're the first node then update the chanFlags to
|
// If we're the first node then update the chanFlags to
|
||||||
// indicate the "direction" of the update.
|
// indicate the "direction" of the update.
|
||||||
chanFlags = 0
|
chanFlags = 0
|
||||||
} else {
|
} else {
|
||||||
chanAnn.NodeID1 = remotePubKey
|
copy(chanAnn.NodeID1[:], remotePubKey.SerializeCompressed())
|
||||||
chanAnn.NodeID2 = localPubKey
|
copy(chanAnn.NodeID2[:], localPubKey.SerializeCompressed())
|
||||||
chanAnn.BitcoinKey1 = remoteFundingKey
|
copy(chanAnn.BitcoinKey1[:], remoteFundingKey.SerializeCompressed())
|
||||||
chanAnn.BitcoinKey2 = localFundingKey
|
copy(chanAnn.BitcoinKey2[:], localFundingKey.SerializeCompressed())
|
||||||
|
|
||||||
// If we're the second node then update the chanFlags to
|
// If we're the second node then update the chanFlags to
|
||||||
// indicate the "direction" of the update.
|
// indicate the "direction" of the update.
|
||||||
@ -2171,7 +2167,12 @@ func (f *fundingManager) newChanAnnouncement(localPubKey, remotePubKey *btcec.Pu
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
chanUpdateAnn.Signature, err = f.cfg.SignMessage(f.cfg.IDKey, chanUpdateMsg)
|
sig, err := f.cfg.SignMessage(f.cfg.IDKey, chanUpdateMsg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("unable to generate channel "+
|
||||||
|
"update announcement signature: %v", err)
|
||||||
|
}
|
||||||
|
chanUpdateAnn.Signature, err = lnwire.NewSigFromSignature(sig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("unable to generate channel "+
|
return nil, errors.Errorf("unable to generate channel "+
|
||||||
"update announcement signature: %v", err)
|
"update announcement signature: %v", err)
|
||||||
@ -2205,8 +2206,14 @@ func (f *fundingManager) newChanAnnouncement(localPubKey, remotePubKey *btcec.Pu
|
|||||||
proof := &lnwire.AnnounceSignatures{
|
proof := &lnwire.AnnounceSignatures{
|
||||||
ChannelID: chanID,
|
ChannelID: chanID,
|
||||||
ShortChannelID: shortChanID,
|
ShortChannelID: shortChanID,
|
||||||
NodeSignature: nodeSig,
|
}
|
||||||
BitcoinSignature: bitcoinSig,
|
proof.NodeSignature, err = lnwire.NewSigFromSignature(nodeSig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
proof.BitcoinSignature, err = lnwire.NewSigFromSignature(bitcoinSig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &chanAnnouncement{
|
return &chanAnnouncement{
|
||||||
|
@ -5,6 +5,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"math/big"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -79,6 +80,13 @@ var (
|
|||||||
IdentityKey: bobPubKey,
|
IdentityKey: bobPubKey,
|
||||||
Address: bobTCPAddr,
|
Address: bobTCPAddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testSig = &btcec.Signature{
|
||||||
|
R: new(big.Int),
|
||||||
|
S: new(big.Int),
|
||||||
|
}
|
||||||
|
_, _ = testSig.R.SetString("63724406601629180062774974542967536251589935445068131219452686511677818569431", 10)
|
||||||
|
_, _ = testSig.S.SetString("18801056069249825825291287104931333862866033135609736119018462340006816851118", 10)
|
||||||
)
|
)
|
||||||
|
|
||||||
type mockNotifier struct {
|
type mockNotifier struct {
|
||||||
@ -217,7 +225,7 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey,
|
|||||||
Notifier: chainNotifier,
|
Notifier: chainNotifier,
|
||||||
FeeEstimator: estimator,
|
FeeEstimator: estimator,
|
||||||
SignMessage: func(pubKey *btcec.PublicKey, msg []byte) (*btcec.Signature, error) {
|
SignMessage: func(pubKey *btcec.PublicKey, msg []byte) (*btcec.Signature, error) {
|
||||||
return nil, nil
|
return testSig, nil
|
||||||
},
|
},
|
||||||
SendAnnouncement: func(msg lnwire.Message) error {
|
SendAnnouncement: func(msg lnwire.Message) error {
|
||||||
select {
|
select {
|
||||||
@ -319,7 +327,7 @@ func recreateAliceFundingManager(t *testing.T, alice *testNode) {
|
|||||||
FeeEstimator: oldCfg.FeeEstimator,
|
FeeEstimator: oldCfg.FeeEstimator,
|
||||||
SignMessage: func(pubKey *btcec.PublicKey,
|
SignMessage: func(pubKey *btcec.PublicKey,
|
||||||
msg []byte) (*btcec.Signature, error) {
|
msg []byte) (*btcec.Signature, error) {
|
||||||
return nil, nil
|
return testSig, nil
|
||||||
},
|
},
|
||||||
SendAnnouncement: func(msg lnwire.Message) error {
|
SendAnnouncement: func(msg lnwire.Message) error {
|
||||||
select {
|
select {
|
||||||
|
@ -57,13 +57,6 @@ func messageToString(msg lnwire.Message) string {
|
|||||||
switch m := msg.(type) {
|
switch m := msg.(type) {
|
||||||
case *lnwire.RevokeAndAck:
|
case *lnwire.RevokeAndAck:
|
||||||
m.NextRevocationKey.Curve = nil
|
m.NextRevocationKey.Curve = nil
|
||||||
case *lnwire.NodeAnnouncement:
|
|
||||||
m.NodeID.Curve = nil
|
|
||||||
case *lnwire.ChannelAnnouncement:
|
|
||||||
m.NodeID1.Curve = nil
|
|
||||||
m.NodeID2.Curve = nil
|
|
||||||
m.BitcoinKey1.Curve = nil
|
|
||||||
m.BitcoinKey2.Curve = nil
|
|
||||||
case *lnwire.AcceptChannel:
|
case *lnwire.AcceptChannel:
|
||||||
m.FundingKey.Curve = nil
|
m.FundingKey.Curve = nil
|
||||||
m.RevocationPoint.Curve = nil
|
m.RevocationPoint.Curve = nil
|
||||||
|
@ -48,6 +48,7 @@ var (
|
|||||||
R: new(big.Int),
|
R: new(big.Int),
|
||||||
S: new(big.Int),
|
S: new(big.Int),
|
||||||
}
|
}
|
||||||
|
wireSig, _ = lnwire.NewSigFromSignature(testSig)
|
||||||
|
|
||||||
_, _ = testSig.R.SetString("6372440660162918006277497454296753625158993"+
|
_, _ = testSig.R.SetString("6372440660162918006277497454296753625158993"+
|
||||||
"5445068131219452686511677818569431", 10)
|
"5445068131219452686511677818569431", 10)
|
||||||
@ -55,11 +56,11 @@ var (
|
|||||||
"3135609736119018462340006816851118", 10)
|
"3135609736119018462340006816851118", 10)
|
||||||
)
|
)
|
||||||
|
|
||||||
// mockGetChanUpdateMessage helper function which returns topology update
|
// mockGetChanUpdateMessage helper function which returns topology update of
|
||||||
// of the channel
|
// the channel
|
||||||
func mockGetChanUpdateMessage() (*lnwire.ChannelUpdate, error) {
|
func mockGetChanUpdateMessage() (*lnwire.ChannelUpdate, error) {
|
||||||
return &lnwire.ChannelUpdate{
|
return &lnwire.ChannelUpdate{
|
||||||
Signature: testSig,
|
Signature: wireSig,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2557,8 +2557,8 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
|
|||||||
// new commitment to the remote party. The commit diff returned contains all
|
// new commitment to the remote party. The commit diff returned contains all
|
||||||
// information necessary for retransmission.
|
// information necessary for retransmission.
|
||||||
func (lc *LightningChannel) createCommitDiff(
|
func (lc *LightningChannel) createCommitDiff(
|
||||||
newCommit *commitment, commitSig *btcec.Signature,
|
newCommit *commitment, commitSig lnwire.Sig,
|
||||||
htlcSigs []*btcec.Signature) (*channeldb.CommitDiff, error) {
|
htlcSigs []lnwire.Sig) (*channeldb.CommitDiff, error) {
|
||||||
|
|
||||||
// First, we need to convert the funding outpoint into the ID that's
|
// First, we need to convert the funding outpoint into the ID that's
|
||||||
// used on the wire to identify this channel. We'll use this shortly
|
// used on the wire to identify this channel. We'll use this shortly
|
||||||
@ -2673,10 +2673,15 @@ func (lc *LightningChannel) createCommitDiff(
|
|||||||
// itself, while the second parameter is a slice of all HTLC signatures (if
|
// itself, while the second parameter is a slice of all HTLC signatures (if
|
||||||
// any). The HTLC signatures are sorted according to the BIP 69 order of the
|
// any). The HTLC signatures are sorted according to the BIP 69 order of the
|
||||||
// HTLC's on the commitment transaction.
|
// HTLC's on the commitment transaction.
|
||||||
func (lc *LightningChannel) SignNextCommitment() (*btcec.Signature, []*btcec.Signature, error) {
|
func (lc *LightningChannel) SignNextCommitment() (lnwire.Sig, []lnwire.Sig, error) {
|
||||||
lc.Lock()
|
lc.Lock()
|
||||||
defer lc.Unlock()
|
defer lc.Unlock()
|
||||||
|
|
||||||
|
var (
|
||||||
|
sig lnwire.Sig
|
||||||
|
htlcSigs []lnwire.Sig
|
||||||
|
)
|
||||||
|
|
||||||
// If we're awaiting for an ACK to a commitment signature, or if we
|
// If we're awaiting for an ACK to a commitment signature, or if we
|
||||||
// don't yet have the initial next revocation point of the remote
|
// don't yet have the initial next revocation point of the remote
|
||||||
// party, then we're unable to create new states. Each time we create a
|
// party, then we're unable to create new states. Each time we create a
|
||||||
@ -2684,7 +2689,7 @@ func (lc *LightningChannel) SignNextCommitment() (*btcec.Signature, []*btcec.Sig
|
|||||||
commitPoint := lc.channelState.RemoteNextRevocation
|
commitPoint := lc.channelState.RemoteNextRevocation
|
||||||
if lc.remoteCommitChain.hasUnackedCommitment() || commitPoint == nil {
|
if lc.remoteCommitChain.hasUnackedCommitment() || commitPoint == nil {
|
||||||
|
|
||||||
return nil, nil, ErrNoWindow
|
return sig, htlcSigs, ErrNoWindow
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the last update on the remote log that has been locked in.
|
// Determine the last update on the remote log that has been locked in.
|
||||||
@ -2698,7 +2703,7 @@ func (lc *LightningChannel) SignNextCommitment() (*btcec.Signature, []*btcec.Sig
|
|||||||
err := lc.validateCommitmentSanity(remoteACKedIndex,
|
err := lc.validateCommitmentSanity(remoteACKedIndex,
|
||||||
lc.localUpdateLog.logIndex, false, true, true)
|
lc.localUpdateLog.logIndex, false, true, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return sig, htlcSigs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grab the next commitment point for the remote party. This will be
|
// Grab the next commitment point for the remote party. This will be
|
||||||
@ -2719,7 +2724,7 @@ func (lc *LightningChannel) SignNextCommitment() (*btcec.Signature, []*btcec.Sig
|
|||||||
remoteACKedIndex, remoteHtlcIndex, keyRing,
|
remoteACKedIndex, remoteHtlcIndex, keyRing,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return sig, htlcSigs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
walletLog.Tracef("ChannelPoint(%v): extending remote chain to height %v, "+
|
walletLog.Tracef("ChannelPoint(%v): extending remote chain to height %v, "+
|
||||||
@ -2744,7 +2749,7 @@ func (lc *LightningChannel) SignNextCommitment() (*btcec.Signature, []*btcec.Sig
|
|||||||
lc.localChanCfg, lc.remoteChanCfg, newCommitView,
|
lc.localChanCfg, lc.remoteChanCfg, newCommitView,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return sig, htlcSigs, err
|
||||||
}
|
}
|
||||||
lc.sigPool.SubmitSignBatch(sigBatch)
|
lc.sigPool.SubmitSignBatch(sigBatch)
|
||||||
|
|
||||||
@ -2755,12 +2760,12 @@ func (lc *LightningChannel) SignNextCommitment() (*btcec.Signature, []*btcec.Sig
|
|||||||
rawSig, err := lc.signer.SignOutputRaw(newCommitView.txn, lc.signDesc)
|
rawSig, err := lc.signer.SignOutputRaw(newCommitView.txn, lc.signDesc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
close(cancelChan)
|
close(cancelChan)
|
||||||
return nil, nil, err
|
return sig, htlcSigs, err
|
||||||
}
|
}
|
||||||
sig, err := btcec.ParseSignature(rawSig, btcec.S256())
|
sig, err = lnwire.NewSigFromRawSignature(rawSig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
close(cancelChan)
|
close(cancelChan)
|
||||||
return nil, nil, err
|
return sig, htlcSigs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll need to send over the signatures to the remote party in the
|
// We'll need to send over the signatures to the remote party in the
|
||||||
@ -2772,7 +2777,7 @@ func (lc *LightningChannel) SignNextCommitment() (*btcec.Signature, []*btcec.Sig
|
|||||||
|
|
||||||
// With the jobs sorted, we'll now iterate through all the responses to
|
// With the jobs sorted, we'll now iterate through all the responses to
|
||||||
// gather each of the signatures in order.
|
// gather each of the signatures in order.
|
||||||
htlcSigs := make([]*btcec.Signature, 0, len(sigBatch))
|
htlcSigs = make([]lnwire.Sig, 0, len(sigBatch))
|
||||||
for _, htlcSigJob := range sigBatch {
|
for _, htlcSigJob := range sigBatch {
|
||||||
select {
|
select {
|
||||||
case jobResp := <-htlcSigJob.resp:
|
case jobResp := <-htlcSigJob.resp:
|
||||||
@ -2780,12 +2785,12 @@ func (lc *LightningChannel) SignNextCommitment() (*btcec.Signature, []*btcec.Sig
|
|||||||
// active jobs.
|
// active jobs.
|
||||||
if jobResp.err != nil {
|
if jobResp.err != nil {
|
||||||
close(cancelChan)
|
close(cancelChan)
|
||||||
return nil, nil, err
|
return sig, htlcSigs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
htlcSigs = append(htlcSigs, jobResp.sig)
|
htlcSigs = append(htlcSigs, jobResp.sig)
|
||||||
case <-lc.quit:
|
case <-lc.quit:
|
||||||
return nil, nil, fmt.Errorf("channel shutting down")
|
return sig, htlcSigs, fmt.Errorf("channel shutting down")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2794,10 +2799,10 @@ func (lc *LightningChannel) SignNextCommitment() (*btcec.Signature, []*btcec.Sig
|
|||||||
// can retransmit it if necessary.
|
// can retransmit it if necessary.
|
||||||
commitDiff, err := lc.createCommitDiff(newCommitView, sig, htlcSigs)
|
commitDiff, err := lc.createCommitDiff(newCommitView, sig, htlcSigs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return sig, htlcSigs, err
|
||||||
}
|
}
|
||||||
if lc.channelState.AppendRemoteCommitChain(commitDiff); err != nil {
|
if lc.channelState.AppendRemoteCommitChain(commitDiff); err != nil {
|
||||||
return nil, nil, err
|
return sig, htlcSigs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(roasbeef): check that one eclair bug
|
// TODO(roasbeef): check that one eclair bug
|
||||||
@ -3128,13 +3133,13 @@ func (lc *LightningChannel) validateCommitmentSanity(theirLogCounter,
|
|||||||
// commitment state. The jobs generated are fully populated, and can be sent
|
// commitment state. The jobs generated are fully populated, and can be sent
|
||||||
// directly into the pool of workers.
|
// directly into the pool of workers.
|
||||||
func genHtlcSigValidationJobs(localCommitmentView *commitment,
|
func genHtlcSigValidationJobs(localCommitmentView *commitment,
|
||||||
keyRing *CommitmentKeyRing, htlcSigs []*btcec.Signature,
|
keyRing *CommitmentKeyRing, htlcSigs []lnwire.Sig,
|
||||||
localChanCfg, remoteChanCfg *channeldb.ChannelConfig) []verifyJob {
|
localChanCfg, remoteChanCfg *channeldb.ChannelConfig) ([]verifyJob, error) {
|
||||||
|
|
||||||
// If this new commitment state doesn't have any HTLC's that are to be
|
// If this new commitment state doesn't have any HTLC's that are to be
|
||||||
// signed, then we'll return a nil slice.
|
// signed, then we'll return a nil slice.
|
||||||
if len(htlcSigs) == 0 {
|
if len(htlcSigs) == 0 {
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
txHash := localCommitmentView.txn.TxHash()
|
txHash := localCommitmentView.txn.TxHash()
|
||||||
@ -3154,7 +3159,11 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment,
|
|||||||
// to validate each signature within the worker pool.
|
// to validate each signature within the worker pool.
|
||||||
i := 0
|
i := 0
|
||||||
for index := range localCommitmentView.txn.TxOut {
|
for index := range localCommitmentView.txn.TxOut {
|
||||||
var sigHash func() ([]byte, error)
|
var (
|
||||||
|
sigHash func() ([]byte, error)
|
||||||
|
sig *btcec.Signature
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
outputIndex := int32(index)
|
outputIndex := int32(index)
|
||||||
switch {
|
switch {
|
||||||
@ -3197,7 +3206,11 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment,
|
|||||||
// With the sighash generated, we'll also store the
|
// With the sighash generated, we'll also store the
|
||||||
// signature so it can be written to disk if this state
|
// signature so it can be written to disk if this state
|
||||||
// is valid.
|
// is valid.
|
||||||
htlc.sig = htlcSigs[i]
|
sig, err = htlcSigs[i].ToSignature()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
htlc.sig = sig
|
||||||
|
|
||||||
// Otherwise, if this is an outgoing HTLC, then we'll need to
|
// Otherwise, if this is an outgoing HTLC, then we'll need to
|
||||||
// generate a timeout transaction so we can verify the
|
// generate a timeout transaction so we can verify the
|
||||||
@ -3239,7 +3252,11 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment,
|
|||||||
// With the sighash generated, we'll also store the
|
// With the sighash generated, we'll also store the
|
||||||
// signature so it can be written to disk if this state
|
// signature so it can be written to disk if this state
|
||||||
// is valid.
|
// is valid.
|
||||||
htlc.sig = htlcSigs[i]
|
sig, err = htlcSigs[i].ToSignature()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
htlc.sig = sig
|
||||||
|
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
@ -3247,14 +3264,14 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment,
|
|||||||
|
|
||||||
verifyJobs = append(verifyJobs, verifyJob{
|
verifyJobs = append(verifyJobs, verifyJob{
|
||||||
pubKey: keyRing.RemoteHtlcKey,
|
pubKey: keyRing.RemoteHtlcKey,
|
||||||
sig: htlcSigs[i],
|
sig: sig,
|
||||||
sigHash: sigHash,
|
sigHash: sigHash,
|
||||||
})
|
})
|
||||||
|
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
return verifyJobs
|
return verifyJobs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// InvalidCommitSigError is a struct that implements the error interface to
|
// InvalidCommitSigError is a struct that implements the error interface to
|
||||||
@ -3292,8 +3309,8 @@ var _ error = (*InvalidCommitSigError)(nil)
|
|||||||
// to our local commitment chain. Once we send a revocation for our prior
|
// to our local commitment chain. Once we send a revocation for our prior
|
||||||
// state, then this newly added commitment becomes our current accepted channel
|
// state, then this newly added commitment becomes our current accepted channel
|
||||||
// state.
|
// state.
|
||||||
func (lc *LightningChannel) ReceiveNewCommitment(commitSig *btcec.Signature,
|
func (lc *LightningChannel) ReceiveNewCommitment(commitSig lnwire.Sig,
|
||||||
htlcSigs []*btcec.Signature) error {
|
htlcSigs []lnwire.Sig) error {
|
||||||
|
|
||||||
lc.Lock()
|
lc.Lock()
|
||||||
defer lc.Unlock()
|
defer lc.Unlock()
|
||||||
@ -3366,8 +3383,14 @@ func (lc *LightningChannel) ReceiveNewCommitment(commitSig *btcec.Signature,
|
|||||||
// As an optimization, we'll generate a series of jobs for the worker
|
// As an optimization, we'll generate a series of jobs for the worker
|
||||||
// pool to verify each of the HTLc signatures presented. Once
|
// pool to verify each of the HTLc signatures presented. Once
|
||||||
// generated, we'll submit these jobs to the worker pool.
|
// generated, we'll submit these jobs to the worker pool.
|
||||||
verifyJobs := genHtlcSigValidationJobs(localCommitmentView,
|
verifyJobs, err := genHtlcSigValidationJobs(
|
||||||
keyRing, htlcSigs, lc.localChanCfg, lc.remoteChanCfg)
|
localCommitmentView, keyRing, htlcSigs, lc.localChanCfg,
|
||||||
|
lc.remoteChanCfg,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
cancelChan := make(chan struct{})
|
cancelChan := make(chan struct{})
|
||||||
verifyResps := lc.sigPool.SubmitVerifyBatch(verifyJobs, cancelChan)
|
verifyResps := lc.sigPool.SubmitVerifyBatch(verifyJobs, cancelChan)
|
||||||
|
|
||||||
@ -3379,7 +3402,11 @@ func (lc *LightningChannel) ReceiveNewCommitment(commitSig *btcec.Signature,
|
|||||||
Y: lc.remoteChanCfg.MultiSigKey.Y,
|
Y: lc.remoteChanCfg.MultiSigKey.Y,
|
||||||
Curve: btcec.S256(),
|
Curve: btcec.S256(),
|
||||||
}
|
}
|
||||||
if !commitSig.Verify(sigHash, &verifyKey) {
|
cSig, err := commitSig.ToSignature()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !cSig.Verify(sigHash, &verifyKey) {
|
||||||
close(cancelChan)
|
close(cancelChan)
|
||||||
|
|
||||||
// If we fail to validate their commitment signature, we'll
|
// If we fail to validate their commitment signature, we'll
|
||||||
@ -3390,7 +3417,7 @@ func (lc *LightningChannel) ReceiveNewCommitment(commitSig *btcec.Signature,
|
|||||||
localCommitTx.Serialize(&txBytes)
|
localCommitTx.Serialize(&txBytes)
|
||||||
return &InvalidCommitSigError{
|
return &InvalidCommitSigError{
|
||||||
commitHeight: nextHeight,
|
commitHeight: nextHeight,
|
||||||
commitSig: commitSig.Serialize(),
|
commitSig: commitSig.ToSignatureBytes(),
|
||||||
sigHash: sigHash,
|
sigHash: sigHash,
|
||||||
commitTx: txBytes.Bytes(),
|
commitTx: txBytes.Bytes(),
|
||||||
}
|
}
|
||||||
@ -3414,7 +3441,7 @@ func (lc *LightningChannel) ReceiveNewCommitment(commitSig *btcec.Signature,
|
|||||||
|
|
||||||
// The signature checks out, so we can now add the new commitment to
|
// The signature checks out, so we can now add the new commitment to
|
||||||
// our local commitment chain.
|
// our local commitment chain.
|
||||||
localCommitmentView.sig = commitSig.Serialize()
|
localCommitmentView.sig = commitSig.ToSignatureBytes()
|
||||||
lc.localCommitChain.addCommitment(localCommitmentView)
|
lc.localCommitChain.addCommitment(localCommitmentView)
|
||||||
|
|
||||||
// If we are not channel initiator, then the commitment just received
|
// If we are not channel initiator, then the commitment just received
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/big"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -2768,20 +2767,20 @@ func TestChanSyncOweCommitment(t *testing.T) {
|
|||||||
t.Fatalf("expected a CommitSig message, instead have %v",
|
t.Fatalf("expected a CommitSig message, instead have %v",
|
||||||
spew.Sdump(aliceMsgsToSend[4]))
|
spew.Sdump(aliceMsgsToSend[4]))
|
||||||
}
|
}
|
||||||
if !commitSigMsg.CommitSig.IsEqual(aliceSig) {
|
if commitSigMsg.CommitSig != aliceSig {
|
||||||
t.Fatalf("commit sig msgs don't match: expected %x got %x",
|
t.Fatalf("commit sig msgs don't match: expected %x got %x",
|
||||||
aliceSig.Serialize(), commitSigMsg.CommitSig.Serialize())
|
aliceSig, commitSigMsg.CommitSig)
|
||||||
}
|
}
|
||||||
if len(commitSigMsg.HtlcSigs) != len(aliceHtlcSigs) {
|
if len(commitSigMsg.HtlcSigs) != len(aliceHtlcSigs) {
|
||||||
t.Fatalf("wrong number of htlc sigs: expected %v, got %v",
|
t.Fatalf("wrong number of htlc sigs: expected %v, got %v",
|
||||||
len(aliceHtlcSigs), len(commitSigMsg.HtlcSigs))
|
len(aliceHtlcSigs), len(commitSigMsg.HtlcSigs))
|
||||||
}
|
}
|
||||||
for i, htlcSig := range commitSigMsg.HtlcSigs {
|
for i, htlcSig := range commitSigMsg.HtlcSigs {
|
||||||
if !htlcSig.IsEqual(aliceHtlcSigs[i]) {
|
if htlcSig != aliceHtlcSigs[i] {
|
||||||
t.Fatalf("htlc sig msgs don't match: "+
|
t.Fatalf("htlc sig msgs don't match: "+
|
||||||
"expected %x got %x",
|
"expected %x got %x",
|
||||||
aliceHtlcSigs[i].Serialize(),
|
aliceHtlcSigs[i],
|
||||||
htlcSig.Serialize())
|
htlcSig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3228,20 +3227,19 @@ func TestChanSyncOweRevocationAndCommit(t *testing.T) {
|
|||||||
t.Fatalf("expected bob to re-send commit sig, instead sending: %v",
|
t.Fatalf("expected bob to re-send commit sig, instead sending: %v",
|
||||||
spew.Sdump(bobMsgsToSend[1]))
|
spew.Sdump(bobMsgsToSend[1]))
|
||||||
}
|
}
|
||||||
if !bobReCommitSigMsg.CommitSig.IsEqual(bobSig) {
|
if bobReCommitSigMsg.CommitSig != bobSig {
|
||||||
t.Fatalf("commit sig msgs don't match: expected %x got %x",
|
t.Fatalf("commit sig msgs don't match: expected %x got %x",
|
||||||
bobSig.Serialize(), bobReCommitSigMsg.CommitSig.Serialize())
|
bobSig, bobReCommitSigMsg.CommitSig)
|
||||||
}
|
}
|
||||||
if len(bobReCommitSigMsg.HtlcSigs) != len(bobHtlcSigs) {
|
if len(bobReCommitSigMsg.HtlcSigs) != len(bobHtlcSigs) {
|
||||||
t.Fatalf("wrong number of htlc sigs: expected %v, got %v",
|
t.Fatalf("wrong number of htlc sigs: expected %v, got %v",
|
||||||
len(bobHtlcSigs), len(bobReCommitSigMsg.HtlcSigs))
|
len(bobHtlcSigs), len(bobReCommitSigMsg.HtlcSigs))
|
||||||
}
|
}
|
||||||
for i, htlcSig := range bobReCommitSigMsg.HtlcSigs {
|
for i, htlcSig := range bobReCommitSigMsg.HtlcSigs {
|
||||||
if !htlcSig.IsEqual(aliceHtlcSigs[i]) {
|
if htlcSig != aliceHtlcSigs[i] {
|
||||||
t.Fatalf("htlc sig msgs don't match: "+
|
t.Fatalf("htlc sig msgs don't match: "+
|
||||||
"expected %x got %x",
|
"expected %x got %x",
|
||||||
bobHtlcSigs[i].Serialize(),
|
bobHtlcSigs[i], htlcSig)
|
||||||
htlcSig.Serialize())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3426,21 +3424,20 @@ func TestChanSyncOweRevocationAndCommitForceTransition(t *testing.T) {
|
|||||||
t.Fatalf("revocation msgs don't match: expected %v, got %v",
|
t.Fatalf("revocation msgs don't match: expected %v, got %v",
|
||||||
bobRevocation, bobReRevoke)
|
bobRevocation, bobReRevoke)
|
||||||
}
|
}
|
||||||
if !bobReCommitSigMsg.CommitSig.IsEqual(bobSigMsg.CommitSig) {
|
if bobReCommitSigMsg.CommitSig != bobSigMsg.CommitSig {
|
||||||
t.Fatalf("commit sig msgs don't match: expected %x got %x",
|
t.Fatalf("commit sig msgs don't match: expected %x got %x",
|
||||||
bobSigMsg.CommitSig.Serialize(),
|
bobSigMsg.CommitSig,
|
||||||
bobReCommitSigMsg.CommitSig.Serialize())
|
bobReCommitSigMsg.CommitSig)
|
||||||
}
|
}
|
||||||
if len(bobReCommitSigMsg.HtlcSigs) != len(bobSigMsg.HtlcSigs) {
|
if len(bobReCommitSigMsg.HtlcSigs) != len(bobSigMsg.HtlcSigs) {
|
||||||
t.Fatalf("wrong number of htlc sigs: expected %v, got %v",
|
t.Fatalf("wrong number of htlc sigs: expected %v, got %v",
|
||||||
len(bobSigMsg.HtlcSigs), len(bobReCommitSigMsg.HtlcSigs))
|
len(bobSigMsg.HtlcSigs), len(bobReCommitSigMsg.HtlcSigs))
|
||||||
}
|
}
|
||||||
for i, htlcSig := range bobReCommitSigMsg.HtlcSigs {
|
for i, htlcSig := range bobReCommitSigMsg.HtlcSigs {
|
||||||
if htlcSig.IsEqual(bobSigMsg.HtlcSigs[i]) {
|
if htlcSig != bobSigMsg.HtlcSigs[i] {
|
||||||
t.Fatalf("htlc sig msgs don't match: "+
|
t.Fatalf("htlc sig msgs don't match: "+
|
||||||
"expected %x got %x",
|
"expected %x got %x",
|
||||||
bobSigMsg.HtlcSigs[i].Serialize(),
|
bobSigMsg.HtlcSigs[i], htlcSig)
|
||||||
htlcSig.Serialize())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3598,20 +3595,19 @@ func TestChannelRetransmissionFeeUpdate(t *testing.T) {
|
|||||||
t.Fatalf("expected a CommitSig message, instead have %v",
|
t.Fatalf("expected a CommitSig message, instead have %v",
|
||||||
spew.Sdump(aliceMsgsToSend[1]))
|
spew.Sdump(aliceMsgsToSend[1]))
|
||||||
}
|
}
|
||||||
if !commitSigMsg.CommitSig.IsEqual(aliceSig) {
|
if commitSigMsg.CommitSig != aliceSig {
|
||||||
t.Fatalf("commit sig msgs don't match: expected %x got %x",
|
t.Fatalf("commit sig msgs don't match: expected %x got %x",
|
||||||
aliceSig.Serialize(), commitSigMsg.CommitSig.Serialize())
|
aliceSig, commitSigMsg.CommitSig)
|
||||||
}
|
}
|
||||||
if len(commitSigMsg.HtlcSigs) != len(aliceHtlcSigs) {
|
if len(commitSigMsg.HtlcSigs) != len(aliceHtlcSigs) {
|
||||||
t.Fatalf("wrong number of htlc sigs: expected %v, got %v",
|
t.Fatalf("wrong number of htlc sigs: expected %v, got %v",
|
||||||
len(aliceHtlcSigs), len(commitSigMsg.HtlcSigs))
|
len(aliceHtlcSigs), len(commitSigMsg.HtlcSigs))
|
||||||
}
|
}
|
||||||
for i, htlcSig := range commitSigMsg.HtlcSigs {
|
for i, htlcSig := range commitSigMsg.HtlcSigs {
|
||||||
if !htlcSig.IsEqual(aliceHtlcSigs[i]) {
|
if htlcSig != aliceHtlcSigs[i] {
|
||||||
t.Fatalf("htlc sig msgs don't match: "+
|
t.Fatalf("htlc sig msgs don't match: "+
|
||||||
"expected %x got %x",
|
"expected %x got %x",
|
||||||
aliceHtlcSigs[i].Serialize(),
|
aliceHtlcSigs[i], htlcSig)
|
||||||
htlcSig.Serialize())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4127,7 +4123,7 @@ func TestInvalidCommitSigError(t *testing.T) {
|
|||||||
|
|
||||||
// Before the signature gets to Bob, we'll mutate it, such that the
|
// Before the signature gets to Bob, we'll mutate it, such that the
|
||||||
// signature is now actually invalid.
|
// signature is now actually invalid.
|
||||||
aliceSig.R.Add(aliceSig.R, new(big.Int).SetInt64(1))
|
aliceSig[0] ^= 88
|
||||||
|
|
||||||
// Bob should reject this new state, and return the proper error.
|
// Bob should reject this new state, and return the proper error.
|
||||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/roasbeef/btcd/btcec"
|
"github.com/roasbeef/btcd/btcec"
|
||||||
"github.com/roasbeef/btcd/wire"
|
"github.com/roasbeef/btcd/wire"
|
||||||
)
|
)
|
||||||
@ -90,7 +91,7 @@ type signJobResp struct {
|
|||||||
// sig is the generated signature for a particular signJob In the case
|
// sig is the generated signature for a particular signJob In the case
|
||||||
// of an error during signature generation, then this value sent will
|
// of an error during signature generation, then this value sent will
|
||||||
// be nil.
|
// be nil.
|
||||||
sig *btcec.Signature
|
sig lnwire.Sig
|
||||||
|
|
||||||
// err is the error that occurred when executing the specified
|
// err is the error that occurred when executing the specified
|
||||||
// signature job. In the case that no error occurred, this value will
|
// signature job. In the case that no error occurred, this value will
|
||||||
@ -185,7 +186,7 @@ func (s *sigPool) poolWorker() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
select {
|
select {
|
||||||
case sigMsg.resp <- signJobResp{
|
case sigMsg.resp <- signJobResp{
|
||||||
sig: nil,
|
sig: lnwire.Sig{},
|
||||||
err: err,
|
err: err,
|
||||||
}:
|
}:
|
||||||
continue
|
continue
|
||||||
@ -196,7 +197,7 @@ func (s *sigPool) poolWorker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sig, err := btcec.ParseSignature(rawSig, btcec.S256())
|
sig, err := lnwire.NewSigFromRawSignature(rawSig)
|
||||||
select {
|
select {
|
||||||
case sigMsg.resp <- signJobResp{
|
case sigMsg.resp <- signJobResp{
|
||||||
sig: sig,
|
sig: sig,
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
package lnwire
|
package lnwire
|
||||||
|
|
||||||
import (
|
import "io"
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/roasbeef/btcd/btcec"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AnnounceSignatures this is a direct message between two endpoints of a
|
// AnnounceSignatures this is a direct message between two endpoints of a
|
||||||
// channel and serves as an opt-in mechanism to allow the announcement of
|
// channel and serves as an opt-in mechanism to allow the announcement of
|
||||||
@ -27,13 +23,13 @@ type AnnounceSignatures struct {
|
|||||||
// NodeSignature is the signature which contains the signed announce
|
// NodeSignature is the signature which contains the signed announce
|
||||||
// channel message, by this signature we proof that we possess of the
|
// channel message, by this signature we proof that we possess of the
|
||||||
// node pub key and creating the reference node_key -> bitcoin_key.
|
// node pub key and creating the reference node_key -> bitcoin_key.
|
||||||
NodeSignature *btcec.Signature
|
NodeSignature Sig
|
||||||
|
|
||||||
// BitcoinSignature is the signature which contains the signed node
|
// BitcoinSignature is the signature which contains the signed node
|
||||||
// public key, by this signature we proof that we possess of the
|
// public key, by this signature we proof that we possess of the
|
||||||
// bitcoin key and and creating the reverse reference bitcoin_key ->
|
// bitcoin key and and creating the reverse reference bitcoin_key ->
|
||||||
// node_key.
|
// node_key.
|
||||||
BitcoinSignature *btcec.Signature
|
BitcoinSignature Sig
|
||||||
}
|
}
|
||||||
|
|
||||||
// A compile time check to ensure AnnounceSignatures implements the
|
// A compile time check to ensure AnnounceSignatures implements the
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/roasbeef/btcd/btcec"
|
|
||||||
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -16,14 +15,14 @@ type ChannelAnnouncement struct {
|
|||||||
// references between node's channel and node. Requiring both nodes
|
// references between node's channel and node. Requiring both nodes
|
||||||
// to sign indicates they are both willing to route other payments via
|
// to sign indicates they are both willing to route other payments via
|
||||||
// this node.
|
// this node.
|
||||||
NodeSig1 *btcec.Signature
|
NodeSig1 Sig
|
||||||
NodeSig2 *btcec.Signature
|
NodeSig2 Sig
|
||||||
|
|
||||||
// This signatures are used by nodes in order to create cross
|
// This signatures are used by nodes in order to create cross
|
||||||
// references between node's channel and node. Requiring the bitcoin
|
// references between node's channel and node. Requiring the bitcoin
|
||||||
// signatures proves they control the channel.
|
// signatures proves they control the channel.
|
||||||
BitcoinSig1 *btcec.Signature
|
BitcoinSig1 Sig
|
||||||
BitcoinSig2 *btcec.Signature
|
BitcoinSig2 Sig
|
||||||
|
|
||||||
// Features is the feature vector that encodes the features supported
|
// Features is the feature vector that encodes the features supported
|
||||||
// by the target node. This field can be used to signal the type of the
|
// by the target node. This field can be used to signal the type of the
|
||||||
@ -42,13 +41,13 @@ type ChannelAnnouncement struct {
|
|||||||
// The public keys of the two nodes who are operating the channel, such
|
// The public keys of the two nodes who are operating the channel, such
|
||||||
// that is NodeID1 the numerically-lesser than NodeID2 (ascending
|
// that is NodeID1 the numerically-lesser than NodeID2 (ascending
|
||||||
// numerical order).
|
// numerical order).
|
||||||
NodeID1 *btcec.PublicKey
|
NodeID1 [33]byte
|
||||||
NodeID2 *btcec.PublicKey
|
NodeID2 [33]byte
|
||||||
|
|
||||||
// Public keys which corresponds to the keys which was declared in
|
// Public keys which corresponds to the keys which was declared in
|
||||||
// multisig funding transaction output.
|
// multisig funding transaction output.
|
||||||
BitcoinKey1 *btcec.PublicKey
|
BitcoinKey1 [33]byte
|
||||||
BitcoinKey2 *btcec.PublicKey
|
BitcoinKey2 [33]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// A compile time check to ensure ChannelAnnouncement implements the
|
// A compile time check to ensure ChannelAnnouncement implements the
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/roasbeef/btcd/btcec"
|
|
||||||
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,7 +31,7 @@ const (
|
|||||||
type ChannelUpdate struct {
|
type ChannelUpdate struct {
|
||||||
// Signature is used to validate the announced data and prove the
|
// Signature is used to validate the announced data and prove the
|
||||||
// ownership of node id.
|
// ownership of node id.
|
||||||
Signature *btcec.Signature
|
Signature Sig
|
||||||
|
|
||||||
// ChainHash denotes the target chain that this channel was opened
|
// ChainHash denotes the target chain that this channel was opened
|
||||||
// within. This value should be the genesis hash of the target chain.
|
// within. This value should be the genesis hash of the target chain.
|
||||||
|
@ -3,7 +3,6 @@ package lnwire
|
|||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/roasbeef/btcd/btcec"
|
|
||||||
"github.com/roasbeef/btcutil"
|
"github.com/roasbeef/btcutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,12 +26,12 @@ type ClosingSigned struct {
|
|||||||
FeeSatoshis btcutil.Amount
|
FeeSatoshis btcutil.Amount
|
||||||
|
|
||||||
// Signature is for the proposed channel close transaction.
|
// Signature is for the proposed channel close transaction.
|
||||||
Signature *btcec.Signature
|
Signature Sig
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClosingSigned creates a new empty ClosingSigned message.
|
// NewClosingSigned creates a new empty ClosingSigned message.
|
||||||
func NewClosingSigned(cid ChannelID, fs btcutil.Amount,
|
func NewClosingSigned(cid ChannelID, fs btcutil.Amount,
|
||||||
sig *btcec.Signature) *ClosingSigned {
|
sig Sig) *ClosingSigned {
|
||||||
|
|
||||||
return &ClosingSigned{
|
return &ClosingSigned{
|
||||||
ChannelID: cid,
|
ChannelID: cid,
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
package lnwire
|
package lnwire
|
||||||
|
|
||||||
import (
|
import "io"
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/roasbeef/btcd/btcec"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CommitSig is sent by either side to stage any pending HTLC's in the
|
// CommitSig is sent by either side to stage any pending HTLC's in the
|
||||||
// receiver's pending set into a new commitment state. Implicitly, the new
|
// receiver's pending set into a new commitment state. Implicitly, the new
|
||||||
@ -26,7 +22,7 @@ type CommitSig struct {
|
|||||||
// If initiating a new commitment state, this signature should ONLY
|
// If initiating a new commitment state, this signature should ONLY
|
||||||
// cover all of the sending party's pending log updates, and the log
|
// cover all of the sending party's pending log updates, and the log
|
||||||
// updates of the remote party that have been ACK'd.
|
// updates of the remote party that have been ACK'd.
|
||||||
CommitSig *btcec.Signature
|
CommitSig Sig
|
||||||
|
|
||||||
// HtlcSigs is a signature for each relevant HTLC output within the
|
// HtlcSigs is a signature for each relevant HTLC output within the
|
||||||
// created commitment. The order of the signatures is expected to be
|
// created commitment. The order of the signatures is expected to be
|
||||||
@ -35,7 +31,7 @@ type CommitSig struct {
|
|||||||
// sender of this message), a signature for a HTLC timeout transaction
|
// sender of this message), a signature for a HTLC timeout transaction
|
||||||
// should be signed, for each incoming HTLC the HTLC timeout
|
// should be signed, for each incoming HTLC the HTLC timeout
|
||||||
// transaction should be signed.
|
// transaction should be signed.
|
||||||
HtlcSigs []*btcec.Signature
|
HtlcSigs []Sig
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCommitSig creates a new empty CommitSig message.
|
// NewCommitSig creates a new empty CommitSig message.
|
||||||
|
@ -3,7 +3,6 @@ package lnwire
|
|||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/roasbeef/btcd/btcec"
|
|
||||||
"github.com/roasbeef/btcd/wire"
|
"github.com/roasbeef/btcd/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -24,7 +23,7 @@ type FundingCreated struct {
|
|||||||
|
|
||||||
// CommitSig is Alice's signature from Bob's version of the commitment
|
// CommitSig is Alice's signature from Bob's version of the commitment
|
||||||
// transaction.
|
// transaction.
|
||||||
CommitSig *btcec.Signature
|
CommitSig Sig
|
||||||
}
|
}
|
||||||
|
|
||||||
// A compile time check to ensure FundingCreated implements the lnwire.Message
|
// A compile time check to ensure FundingCreated implements the lnwire.Message
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
package lnwire
|
package lnwire
|
||||||
|
|
||||||
import (
|
import "io"
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/roasbeef/btcd/btcec"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FundingSigned is sent from Bob (the responder) to Alice (the initiator)
|
// FundingSigned is sent from Bob (the responder) to Alice (the initiator)
|
||||||
// after receiving the funding outpoint and her signature for Bob's version of
|
// after receiving the funding outpoint and her signature for Bob's version of
|
||||||
@ -16,7 +12,7 @@ type FundingSigned struct {
|
|||||||
|
|
||||||
// CommitSig is Bob's signature for Alice's version of the commitment
|
// CommitSig is Bob's signature for Alice's version of the commitment
|
||||||
// transaction.
|
// transaction.
|
||||||
CommitSig *btcec.Signature
|
CommitSig Sig
|
||||||
}
|
}
|
||||||
|
|
||||||
// A compile time check to ensure FundingSigned implements the lnwire.Message
|
// A compile time check to ensure FundingSigned implements the lnwire.Message
|
||||||
|
@ -146,7 +146,7 @@ func writeElement(w io.Writer, element interface{}) error {
|
|||||||
if _, err := w.Write(b[:]); err != nil {
|
if _, err := w.Write(b[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case []*btcec.Signature:
|
case []Sig:
|
||||||
var b [2]byte
|
var b [2]byte
|
||||||
numSigs := uint16(len(e))
|
numSigs := uint16(len(e))
|
||||||
binary.BigEndian.PutUint16(b[:], numSigs)
|
binary.BigEndian.PutUint16(b[:], numSigs)
|
||||||
@ -159,18 +159,9 @@ func writeElement(w io.Writer, element interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *btcec.Signature:
|
case Sig:
|
||||||
if e == nil {
|
|
||||||
return fmt.Errorf("cannot write nil signature")
|
|
||||||
}
|
|
||||||
|
|
||||||
var b [64]byte
|
|
||||||
err := SerializeSigToWire(&b, e)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Write buffer
|
// Write buffer
|
||||||
if _, err = w.Write(b[:]); err != nil {
|
if _, err := w.Write(e[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case PingPayload:
|
case PingPayload:
|
||||||
@ -210,6 +201,10 @@ func writeElement(w io.Writer, element interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err := w.Write(e[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case [33]byte:
|
||||||
if _, err := w.Write(e[:]); err != nil {
|
if _, err := w.Write(e[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -469,16 +464,16 @@ func readElement(r io.Reader, element interface{}) error {
|
|||||||
|
|
||||||
*e = f
|
*e = f
|
||||||
|
|
||||||
case *[]*btcec.Signature:
|
case *[]Sig:
|
||||||
var l [2]byte
|
var l [2]byte
|
||||||
if _, err := io.ReadFull(r, l[:]); err != nil {
|
if _, err := io.ReadFull(r, l[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
numSigs := binary.BigEndian.Uint16(l[:])
|
numSigs := binary.BigEndian.Uint16(l[:])
|
||||||
|
|
||||||
var sigs []*btcec.Signature
|
var sigs []Sig
|
||||||
if numSigs > 0 {
|
if numSigs > 0 {
|
||||||
sigs = make([]*btcec.Signature, numSigs)
|
sigs = make([]Sig, numSigs)
|
||||||
for i := 0; i < int(numSigs); i++ {
|
for i := 0; i < int(numSigs); i++ {
|
||||||
if err := readElement(r, &sigs[i]); err != nil {
|
if err := readElement(r, &sigs[i]); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -488,13 +483,8 @@ func readElement(r io.Reader, element interface{}) error {
|
|||||||
|
|
||||||
*e = sigs
|
*e = sigs
|
||||||
|
|
||||||
case **btcec.Signature:
|
case *Sig:
|
||||||
var b [64]byte
|
if _, err := io.ReadFull(r, e[:]); err != nil {
|
||||||
if _, err := io.ReadFull(r, b[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = DeserializeSigFromWire(e, b)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case *OpaqueReason:
|
case *OpaqueReason:
|
||||||
@ -541,6 +531,10 @@ func readElement(r io.Reader, element interface{}) error {
|
|||||||
if _, err := io.ReadFull(r, *e); err != nil {
|
if _, err := io.ReadFull(r, *e); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case *[33]byte:
|
||||||
|
if _, err := io.ReadFull(r, e[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
case []byte:
|
case []byte:
|
||||||
if _, err := io.ReadFull(r, e); err != nil {
|
if _, err := io.ReadFull(r, e); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -52,6 +52,19 @@ func randPubKey() (*btcec.PublicKey, error) {
|
|||||||
return priv.PubKey(), nil
|
return priv.PubKey(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func randRawKey() ([33]byte, error) {
|
||||||
|
var n [33]byte
|
||||||
|
|
||||||
|
priv, err := btcec.NewPrivateKey(btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(n[:], priv.PubKey().SerializeCompressed())
|
||||||
|
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
func randRawFeatureVector(r *rand.Rand) *RawFeatureVector {
|
func randRawFeatureVector(r *rand.Rand) *RawFeatureVector {
|
||||||
featureVec := NewRawFeatureVector()
|
featureVec := NewRawFeatureVector()
|
||||||
for i := 0; i < 10000; i++ {
|
for i := 0; i < 10000; i++ {
|
||||||
@ -266,20 +279,30 @@ func TestLightningWireProtocol(t *testing.T) {
|
|||||||
}
|
}
|
||||||
req.FundingPoint.Index = uint32(r.Int31()) % math.MaxUint16
|
req.FundingPoint.Index = uint32(r.Int31()) % math.MaxUint16
|
||||||
|
|
||||||
req.CommitSig = testSig
|
var err error
|
||||||
|
req.CommitSig, err = NewSigFromSignature(testSig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse sig: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
v[0] = reflect.ValueOf(req)
|
v[0] = reflect.ValueOf(req)
|
||||||
},
|
},
|
||||||
MsgFundingSigned: func(v []reflect.Value, r *rand.Rand) {
|
MsgFundingSigned: func(v []reflect.Value, r *rand.Rand) {
|
||||||
var c [32]byte
|
var c [32]byte
|
||||||
if _, err := r.Read(c[:]); err != nil {
|
_, err := r.Read(c[:])
|
||||||
|
if err != nil {
|
||||||
t.Fatalf("unable to generate chan id: %v", err)
|
t.Fatalf("unable to generate chan id: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
req := FundingSigned{
|
req := FundingSigned{
|
||||||
ChanID: ChannelID(c),
|
ChanID: ChannelID(c),
|
||||||
CommitSig: testSig,
|
}
|
||||||
|
req.CommitSig, err = NewSigFromSignature(testSig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse sig: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
v[0] = reflect.ValueOf(req)
|
v[0] = reflect.ValueOf(req)
|
||||||
@ -305,7 +328,12 @@ func TestLightningWireProtocol(t *testing.T) {
|
|||||||
MsgClosingSigned: func(v []reflect.Value, r *rand.Rand) {
|
MsgClosingSigned: func(v []reflect.Value, r *rand.Rand) {
|
||||||
req := ClosingSigned{
|
req := ClosingSigned{
|
||||||
FeeSatoshis: btcutil.Amount(r.Int63()),
|
FeeSatoshis: btcutil.Amount(r.Int63()),
|
||||||
Signature: testSig,
|
}
|
||||||
|
var err error
|
||||||
|
req.Signature, err = NewSigFromSignature(testSig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse sig: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := r.Read(req.ChannelID[:]); err != nil {
|
if _, err := r.Read(req.ChannelID[:]); err != nil {
|
||||||
@ -321,17 +349,27 @@ func TestLightningWireProtocol(t *testing.T) {
|
|||||||
t.Fatalf("unable to generate chan id: %v", err)
|
t.Fatalf("unable to generate chan id: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
req.CommitSig = testSig
|
|
||||||
|
var err error
|
||||||
|
req.CommitSig, err = NewSigFromSignature(testSig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse sig: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Only create the slice if there will be any signatures
|
// Only create the slice if there will be any signatures
|
||||||
// in it to prevent false positive test failures due to
|
// in it to prevent false positive test failures due to
|
||||||
// an empty slice versus a nil slice.
|
// an empty slice versus a nil slice.
|
||||||
numSigs := uint16(r.Int31n(1020))
|
numSigs := uint16(r.Int31n(1020))
|
||||||
if numSigs > 0 {
|
if numSigs > 0 {
|
||||||
req.HtlcSigs = make([]*btcec.Signature, numSigs)
|
req.HtlcSigs = make([]Sig, numSigs)
|
||||||
}
|
}
|
||||||
for i := 0; i < int(numSigs); i++ {
|
for i := 0; i < int(numSigs); i++ {
|
||||||
req.HtlcSigs[i] = testSig
|
req.HtlcSigs[i], err = NewSigFromSignature(testSig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse sig: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v[0] = reflect.ValueOf(*req)
|
v[0] = reflect.ValueOf(*req)
|
||||||
@ -356,32 +394,48 @@ func TestLightningWireProtocol(t *testing.T) {
|
|||||||
v[0] = reflect.ValueOf(*req)
|
v[0] = reflect.ValueOf(*req)
|
||||||
},
|
},
|
||||||
MsgChannelAnnouncement: func(v []reflect.Value, r *rand.Rand) {
|
MsgChannelAnnouncement: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
var err error
|
||||||
req := ChannelAnnouncement{
|
req := ChannelAnnouncement{
|
||||||
ShortChannelID: NewShortChanIDFromInt(uint64(r.Int63())),
|
ShortChannelID: NewShortChanIDFromInt(uint64(r.Int63())),
|
||||||
Features: randRawFeatureVector(r),
|
Features: randRawFeatureVector(r),
|
||||||
}
|
}
|
||||||
req.NodeSig1 = testSig
|
req.NodeSig1, err = NewSigFromSignature(testSig)
|
||||||
req.NodeSig2 = testSig
|
if err != nil {
|
||||||
req.BitcoinSig1 = testSig
|
t.Fatalf("unable to parse sig: %v", err)
|
||||||
req.BitcoinSig2 = testSig
|
return
|
||||||
|
}
|
||||||
|
req.NodeSig2, err = NewSigFromSignature(testSig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse sig: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.BitcoinSig1, err = NewSigFromSignature(testSig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse sig: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.BitcoinSig2, err = NewSigFromSignature(testSig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse sig: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
req.NodeID1, err = randRawKey()
|
||||||
req.NodeID1, err = randPubKey()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to generate key: %v", err)
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
req.NodeID2, err = randPubKey()
|
req.NodeID2, err = randRawKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to generate key: %v", err)
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
req.BitcoinKey1, err = randPubKey()
|
req.BitcoinKey1, err = randRawKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to generate key: %v", err)
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
req.BitcoinKey2, err = randPubKey()
|
req.BitcoinKey2, err = randRawKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to generate key: %v", err)
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
return
|
return
|
||||||
@ -400,8 +454,8 @@ func TestLightningWireProtocol(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
req := NodeAnnouncement{
|
req := NodeAnnouncement{
|
||||||
Signature: testSig,
|
|
||||||
Features: randRawFeatureVector(r),
|
Features: randRawFeatureVector(r),
|
||||||
Timestamp: uint32(r.Int31()),
|
Timestamp: uint32(r.Int31()),
|
||||||
Alias: a,
|
Alias: a,
|
||||||
@ -413,9 +467,13 @@ func TestLightningWireProtocol(t *testing.T) {
|
|||||||
// TODO(roasbeef): proper gen rand addrs
|
// TODO(roasbeef): proper gen rand addrs
|
||||||
Addresses: testAddrs,
|
Addresses: testAddrs,
|
||||||
}
|
}
|
||||||
|
req.Signature, err = NewSigFromSignature(testSig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse sig: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
req.NodeID, err = randRawKey()
|
||||||
req.NodeID, err = randPubKey()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to generate key: %v", err)
|
t.Fatalf("unable to generate key: %v", err)
|
||||||
return
|
return
|
||||||
@ -424,8 +482,8 @@ func TestLightningWireProtocol(t *testing.T) {
|
|||||||
v[0] = reflect.ValueOf(req)
|
v[0] = reflect.ValueOf(req)
|
||||||
},
|
},
|
||||||
MsgChannelUpdate: func(v []reflect.Value, r *rand.Rand) {
|
MsgChannelUpdate: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
var err error
|
||||||
req := ChannelUpdate{
|
req := ChannelUpdate{
|
||||||
Signature: testSig,
|
|
||||||
ShortChannelID: NewShortChanIDFromInt(uint64(r.Int63())),
|
ShortChannelID: NewShortChanIDFromInt(uint64(r.Int63())),
|
||||||
Timestamp: uint32(r.Int31()),
|
Timestamp: uint32(r.Int31()),
|
||||||
Flags: ChanUpdateFlag(r.Int31()),
|
Flags: ChanUpdateFlag(r.Int31()),
|
||||||
@ -434,6 +492,12 @@ func TestLightningWireProtocol(t *testing.T) {
|
|||||||
BaseFee: uint32(r.Int31()),
|
BaseFee: uint32(r.Int31()),
|
||||||
FeeRate: uint32(r.Int31()),
|
FeeRate: uint32(r.Int31()),
|
||||||
}
|
}
|
||||||
|
req.Signature, err = NewSigFromSignature(testSig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse sig: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := r.Read(req.ChainHash[:]); err != nil {
|
if _, err := r.Read(req.ChainHash[:]); err != nil {
|
||||||
t.Fatalf("unable to generate chain hash: %v", err)
|
t.Fatalf("unable to generate chain hash: %v", err)
|
||||||
return
|
return
|
||||||
@ -442,11 +506,23 @@ func TestLightningWireProtocol(t *testing.T) {
|
|||||||
v[0] = reflect.ValueOf(req)
|
v[0] = reflect.ValueOf(req)
|
||||||
},
|
},
|
||||||
MsgAnnounceSignatures: func(v []reflect.Value, r *rand.Rand) {
|
MsgAnnounceSignatures: func(v []reflect.Value, r *rand.Rand) {
|
||||||
|
var err error
|
||||||
req := AnnounceSignatures{
|
req := AnnounceSignatures{
|
||||||
ShortChannelID: NewShortChanIDFromInt(uint64(r.Int63())),
|
ShortChannelID: NewShortChanIDFromInt(uint64(r.Int63())),
|
||||||
NodeSignature: testSig,
|
|
||||||
BitcoinSignature: testSig,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
req.NodeSignature, err = NewSigFromSignature(testSig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse sig: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req.BitcoinSignature, err = NewSigFromSignature(testSig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to parse sig: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := r.Read(req.ChannelID[:]); err != nil {
|
if _, err := r.Read(req.ChannelID[:]); err != nil {
|
||||||
t.Fatalf("unable to generate chan id: %v", err)
|
t.Fatalf("unable to generate chan id: %v", err)
|
||||||
return
|
return
|
||||||
|
@ -7,8 +7,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/roasbeef/btcd/btcec"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -50,7 +48,7 @@ func (n NodeAlias) String() string {
|
|||||||
// announcement via a signature using the advertised node pubkey.
|
// announcement via a signature using the advertised node pubkey.
|
||||||
type NodeAnnouncement struct {
|
type NodeAnnouncement struct {
|
||||||
// Signature is used to prove the ownership of node id.
|
// Signature is used to prove the ownership of node id.
|
||||||
Signature *btcec.Signature
|
Signature Sig
|
||||||
|
|
||||||
// Features is the list of protocol features this node supports.
|
// Features is the list of protocol features this node supports.
|
||||||
Features *RawFeatureVector
|
Features *RawFeatureVector
|
||||||
@ -59,7 +57,7 @@ type NodeAnnouncement struct {
|
|||||||
Timestamp uint32
|
Timestamp uint32
|
||||||
|
|
||||||
// NodeID is a public key which is used as node identification.
|
// NodeID is a public key which is used as node identification.
|
||||||
NodeID *btcec.PublicKey
|
NodeID [33]byte
|
||||||
|
|
||||||
// RGBColor is used to customize their node's appearance in maps and
|
// RGBColor is used to customize their node's appearance in maps and
|
||||||
// graphs
|
// graphs
|
||||||
|
@ -11,8 +11,9 @@ var (
|
|||||||
testAmount = MilliSatoshi(1)
|
testAmount = MilliSatoshi(1)
|
||||||
testCtlvExpiry = uint32(2)
|
testCtlvExpiry = uint32(2)
|
||||||
testFlags = uint16(2)
|
testFlags = uint16(2)
|
||||||
|
sig, _ = NewSigFromSignature(testSig)
|
||||||
testChannelUpdate = ChannelUpdate{
|
testChannelUpdate = ChannelUpdate{
|
||||||
Signature: testSig,
|
Signature: sig,
|
||||||
ShortChannelID: NewShortChanIDFromInt(1),
|
ShortChannelID: NewShortChanIDFromInt(1),
|
||||||
Timestamp: 1,
|
Timestamp: 1,
|
||||||
Flags: 1,
|
Flags: 1,
|
||||||
|
@ -6,12 +6,16 @@ import (
|
|||||||
"github.com/roasbeef/btcd/btcec"
|
"github.com/roasbeef/btcd/btcec"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SerializeSigToWire serializes a *Signature to [64]byte in the format
|
// Sig is a fixed-sized ECDSA signature. Unlike Bitcoin, we use fixed sized
|
||||||
// specified by the Lightning RFC.
|
// signatures on the wire, instead of DER encoded signatures. This type
|
||||||
func SerializeSigToWire(b *[64]byte, e *btcec.Signature) error {
|
// provides several methods to convert to/from a regular Bitcoin DER encoded
|
||||||
|
// signature (raw bytes and *btcec.Signature).
|
||||||
|
type Sig [64]byte
|
||||||
|
|
||||||
// Serialize the signature with all the checks that entails.
|
// NewSigFromRawSignature returns a Sig from a Bitcoin raw signature encoded in
|
||||||
sig := e.Serialize()
|
// the cannonical DER encoding.
|
||||||
|
func NewSigFromRawSignature(sig []byte) (Sig, error) {
|
||||||
|
var b Sig
|
||||||
|
|
||||||
// Extract lengths of R and S. The DER representation is laid out as
|
// Extract lengths of R and S. The DER representation is laid out as
|
||||||
// 0x30 <length> 0x02 <length r> r 0x02 <length s> s
|
// 0x30 <length> 0x02 <length r> r 0x02 <length s> s
|
||||||
@ -23,14 +27,14 @@ func SerializeSigToWire(b *[64]byte, e *btcec.Signature) error {
|
|||||||
sLen := sig[5+rLen]
|
sLen := sig[5+rLen]
|
||||||
|
|
||||||
// Check to make sure R and S can both fit into their intended buffers.
|
// Check to make sure R and S can both fit into their intended buffers.
|
||||||
// We check S first because these code blocks decrement sLen and
|
// We check S first because these code blocks decrement sLen and rLen
|
||||||
// rLen in the case of a 33-byte 0-padded integer returned from
|
// in the case of a 33-byte 0-padded integer returned from Serialize()
|
||||||
// Serialize() and rLen is used in calculating array indices for
|
// and rLen is used in calculating array indices for S. We can track
|
||||||
// S. We can track this with additional variables, but it's more
|
// this with additional variables, but it's more efficient to just
|
||||||
// efficient to just check S first.
|
// check S first.
|
||||||
if sLen > 32 {
|
if sLen > 32 {
|
||||||
if (sLen > 33) || (sig[6+rLen] != 0x00) {
|
if (sLen > 33) || (sig[6+rLen] != 0x00) {
|
||||||
return fmt.Errorf("S is over 32 bytes long " +
|
return b, fmt.Errorf("S is over 32 bytes long " +
|
||||||
"without padding")
|
"without padding")
|
||||||
}
|
}
|
||||||
sLen--
|
sLen--
|
||||||
@ -42,7 +46,7 @@ func SerializeSigToWire(b *[64]byte, e *btcec.Signature) error {
|
|||||||
// Do the same for R as we did for S
|
// Do the same for R as we did for S
|
||||||
if rLen > 32 {
|
if rLen > 32 {
|
||||||
if (rLen > 33) || (sig[4] != 0x00) {
|
if (rLen > 33) || (sig[4] != 0x00) {
|
||||||
return fmt.Errorf("R is over 32 bytes long " +
|
return b, fmt.Errorf("R is over 32 bytes long " +
|
||||||
"without padding")
|
"without padding")
|
||||||
}
|
}
|
||||||
rLen--
|
rLen--
|
||||||
@ -50,13 +54,33 @@ func SerializeSigToWire(b *[64]byte, e *btcec.Signature) error {
|
|||||||
} else {
|
} else {
|
||||||
copy(b[32-rLen:], sig[4:4+rLen])
|
copy(b[32-rLen:], sig[4:4+rLen])
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeserializeSigFromWire deserializes a *Signature from [64]byte in the format
|
// NewSigFromSignature creates a new signature as used on the wire, from an
|
||||||
// specified by the Lightning RFC.
|
// existing btcec.Signature.
|
||||||
func DeserializeSigFromWire(e **btcec.Signature, b [64]byte) error {
|
func NewSigFromSignature(e *btcec.Signature) (Sig, error) {
|
||||||
|
// Serialize the signature with all the checks that entails.
|
||||||
|
return NewSigFromRawSignature(e.Serialize())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToSignature converts the fixed-sized signature to a btcec.Signature objects
|
||||||
|
// which can be used for signature validation checks.
|
||||||
|
func (b *Sig) ToSignature() (*btcec.Signature, error) {
|
||||||
|
// Parse the signature with strict checks.
|
||||||
|
sigBytes := b.ToSignatureBytes()
|
||||||
|
sig, err := btcec.ParseDERSignature(sigBytes, btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return sig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToSignatureBytes serializes the target fixed-sized signature into the raw
|
||||||
|
// bytes of a DER encoding.
|
||||||
|
func (b *Sig) ToSignatureBytes() []byte {
|
||||||
// Extract canonically-padded bigint representations from buffer
|
// Extract canonically-padded bigint representations from buffer
|
||||||
r := extractCanonicalPadding(b[0:32])
|
r := extractCanonicalPadding(b[0:32])
|
||||||
s := extractCanonicalPadding(b[32:64])
|
s := extractCanonicalPadding(b[32:64])
|
||||||
@ -75,13 +99,7 @@ func DeserializeSigFromWire(e **btcec.Signature, b [64]byte) error {
|
|||||||
copy(sigBytes[4:], r) // Copy R
|
copy(sigBytes[4:], r) // Copy R
|
||||||
copy(sigBytes[rLen+6:], s) // Copy S
|
copy(sigBytes[rLen+6:], s) // Copy S
|
||||||
|
|
||||||
// Parse the signature with strict checks.
|
return sigBytes
|
||||||
sig, err := btcec.ParseDERSignature(sigBytes, btcec.S256())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*e = sig
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// extractCanonicalPadding is a utility function to extract the canonical
|
// extractCanonicalPadding is a utility function to extract the canonical
|
||||||
|
@ -14,16 +14,16 @@ func TestSignatureSerializeDeserialize(t *testing.T) {
|
|||||||
// Local-scoped closure to serialize and deserialize a Signature and
|
// Local-scoped closure to serialize and deserialize a Signature and
|
||||||
// check for errors as well as check if the results are correct.
|
// check for errors as well as check if the results are correct.
|
||||||
signatureSerializeDeserialize := func(e btcec.Signature) error {
|
signatureSerializeDeserialize := func(e btcec.Signature) error {
|
||||||
var b [64]byte
|
sig, err := NewSigFromSignature(&e)
|
||||||
err := SerializeSigToWire(&b, &e)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var e2 *btcec.Signature
|
|
||||||
err = DeserializeSigFromWire(&e2, b)
|
e2, err := sig.ToSignature()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.R.Cmp(e2.R) != 0 {
|
if e.R.Cmp(e2.R) != 0 {
|
||||||
return fmt.Errorf("Pre/post-serialize Rs don't match"+
|
return fmt.Errorf("Pre/post-serialize Rs don't match"+
|
||||||
": %s, %s", e.R, e2.R)
|
": %s, %s", e.R, e2.R)
|
||||||
|
25
peer.go
25
peer.go
@ -344,7 +344,9 @@ func (p *peer) loadActiveChannels(chans []*channeldb.OpenChannel) error {
|
|||||||
// TODO(roasbeef): can add helper method to get policy for
|
// TODO(roasbeef): can add helper method to get policy for
|
||||||
// particular channel.
|
// particular channel.
|
||||||
var selfPolicy *channeldb.ChannelEdgePolicy
|
var selfPolicy *channeldb.ChannelEdgePolicy
|
||||||
if info != nil && info.NodeKey1.IsEqual(p.server.identityPriv.PubKey()) {
|
if info != nil && bytes.Equal(info.NodeKey1Bytes[:],
|
||||||
|
p.server.identityPriv.PubKey().SerializeCompressed()) {
|
||||||
|
|
||||||
selfPolicy = p1
|
selfPolicy = p1
|
||||||
} else {
|
} else {
|
||||||
selfPolicy = p2
|
selfPolicy = p2
|
||||||
@ -900,8 +902,7 @@ func messageSummary(msg lnwire.Message) string {
|
|||||||
|
|
||||||
case *lnwire.NodeAnnouncement:
|
case *lnwire.NodeAnnouncement:
|
||||||
return fmt.Sprintf("node=%x, update_time=%v",
|
return fmt.Sprintf("node=%x, update_time=%v",
|
||||||
msg.NodeID.SerializeCompressed(),
|
msg.NodeID, time.Unix(int64(msg.Timestamp), 0))
|
||||||
time.Unix(int64(msg.Timestamp), 0))
|
|
||||||
|
|
||||||
case *lnwire.Ping:
|
case *lnwire.Ping:
|
||||||
// No summary.
|
// No summary.
|
||||||
@ -957,13 +958,6 @@ func (p *peer) logWireMessage(msg lnwire.Message, read bool) {
|
|||||||
}
|
}
|
||||||
case *lnwire.RevokeAndAck:
|
case *lnwire.RevokeAndAck:
|
||||||
m.NextRevocationKey.Curve = nil
|
m.NextRevocationKey.Curve = nil
|
||||||
case *lnwire.NodeAnnouncement:
|
|
||||||
m.NodeID.Curve = nil
|
|
||||||
case *lnwire.ChannelAnnouncement:
|
|
||||||
m.NodeID1.Curve = nil
|
|
||||||
m.NodeID2.Curve = nil
|
|
||||||
m.BitcoinKey1.Curve = nil
|
|
||||||
m.BitcoinKey2.Curve = nil
|
|
||||||
case *lnwire.AcceptChannel:
|
case *lnwire.AcceptChannel:
|
||||||
m.FundingKey.Curve = nil
|
m.FundingKey.Curve = nil
|
||||||
m.RevocationPoint.Curve = nil
|
m.RevocationPoint.Curve = nil
|
||||||
@ -1774,16 +1768,17 @@ func createGetLastUpdate(router *routing.ChannelRouter,
|
|||||||
"channel by ShortChannelID(%v)", chanID)
|
"channel by ShortChannelID(%v)", chanID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're the outgoing node on the first edge, then that
|
||||||
|
// means the second edge is our policy. Otherwise, the first
|
||||||
|
// edge is our policy.
|
||||||
var local *channeldb.ChannelEdgePolicy
|
var local *channeldb.ChannelEdgePolicy
|
||||||
if bytes.Compare(edge1.Node.PubKey.SerializeCompressed(),
|
if bytes.Equal(edge1.Node.PubKeyBytes[:], pubKey[:]) {
|
||||||
pubKey[:]) == 0 {
|
|
||||||
local = edge2
|
local = edge2
|
||||||
} else {
|
} else {
|
||||||
local = edge1
|
local = edge1
|
||||||
}
|
}
|
||||||
|
|
||||||
update := &lnwire.ChannelUpdate{
|
update := &lnwire.ChannelUpdate{
|
||||||
Signature: local.Signature,
|
|
||||||
ChainHash: info.ChainHash,
|
ChainHash: info.ChainHash,
|
||||||
ShortChannelID: lnwire.NewShortChanIDFromInt(local.ChannelID),
|
ShortChannelID: lnwire.NewShortChanIDFromInt(local.ChannelID),
|
||||||
Timestamp: uint32(local.LastUpdate.Unix()),
|
Timestamp: uint32(local.LastUpdate.Unix()),
|
||||||
@ -1793,6 +1788,10 @@ func createGetLastUpdate(router *routing.ChannelRouter,
|
|||||||
BaseFee: uint32(local.FeeBaseMSat),
|
BaseFee: uint32(local.FeeBaseMSat),
|
||||||
FeeRate: uint32(local.FeeProportionalMillionths),
|
FeeRate: uint32(local.FeeProportionalMillionths),
|
||||||
}
|
}
|
||||||
|
update.Signature, err = lnwire.NewSigFromRawSignature(local.SigBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
hswcLog.Debugf("Sending latest channel_update: %v",
|
hswcLog.Debugf("Sending latest channel_update: %v",
|
||||||
spew.Sdump(update))
|
spew.Sdump(update))
|
||||||
|
21
peer_test.go
21
peer_test.go
@ -14,8 +14,6 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/roasbeef/btcd/btcec"
|
|
||||||
"github.com/roasbeef/btcd/txscript"
|
|
||||||
"github.com/roasbeef/btcd/wire"
|
"github.com/roasbeef/btcd/wire"
|
||||||
"github.com/roasbeef/btcutil"
|
"github.com/roasbeef/btcutil"
|
||||||
)
|
)
|
||||||
@ -95,8 +93,7 @@ func TestPeerChannelClosureAcceptFeeResponder(t *testing.T) {
|
|||||||
t.Fatalf("error creating close proposal: %v", err)
|
t.Fatalf("error creating close proposal: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
initSig := append(initiatorSig, byte(txscript.SigHashAll))
|
parsedSig, err := lnwire.NewSigFromRawSignature(initiatorSig)
|
||||||
parsedSig, err := btcec.ParseSignature(initSig, btcec.S256())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error parsing signature: %v", err)
|
t.Fatalf("error parsing signature: %v", err)
|
||||||
}
|
}
|
||||||
@ -183,7 +180,7 @@ func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create close proposal: %v", err)
|
t.Fatalf("unable to create close proposal: %v", err)
|
||||||
}
|
}
|
||||||
parsedSig, err := btcec.ParseSignature(closeSig, btcec.S256())
|
parsedSig, err := lnwire.NewSigFromRawSignature(closeSig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to parse signature: %v", err)
|
t.Fatalf("unable to parse signature: %v", err)
|
||||||
}
|
}
|
||||||
@ -295,7 +292,7 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) {
|
|||||||
t.Fatalf("error creating close proposal: %v", err)
|
t.Fatalf("error creating close proposal: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedSig, err := btcec.ParseSignature(initiatorSig, btcec.S256())
|
parsedSig, err := lnwire.NewSigFromRawSignature(initiatorSig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error parsing signature: %v", err)
|
t.Fatalf("error parsing signature: %v", err)
|
||||||
}
|
}
|
||||||
@ -339,7 +336,7 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) {
|
|||||||
t.Fatalf("error creating close proposal: %v", err)
|
t.Fatalf("error creating close proposal: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedSig, err = btcec.ParseSignature(initiatorSig, btcec.S256())
|
parsedSig, err = lnwire.NewSigFromRawSignature(initiatorSig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error parsing signature: %v", err)
|
t.Fatalf("error parsing signature: %v", err)
|
||||||
}
|
}
|
||||||
@ -384,8 +381,7 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) {
|
|||||||
t.Fatalf("error creating close proposal: %v", err)
|
t.Fatalf("error creating close proposal: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
initSig := append(initiatorSig, byte(txscript.SigHashAll))
|
parsedSig, err = lnwire.NewSigFromRawSignature(initiatorSig)
|
||||||
parsedSig, err = btcec.ParseSignature(initSig, btcec.S256())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error parsing signature: %v", err)
|
t.Fatalf("error parsing signature: %v", err)
|
||||||
}
|
}
|
||||||
@ -478,7 +474,7 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create close proposal: %v", err)
|
t.Fatalf("unable to create close proposal: %v", err)
|
||||||
}
|
}
|
||||||
parsedSig, err := btcec.ParseSignature(closeSig, btcec.S256())
|
parsedSig, err := lnwire.NewSigFromRawSignature(closeSig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to parse signature: %v", err)
|
t.Fatalf("unable to parse signature: %v", err)
|
||||||
}
|
}
|
||||||
@ -544,7 +540,7 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) {
|
|||||||
t.Fatalf("error creating close proposal: %v", err)
|
t.Fatalf("error creating close proposal: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedSig, err = btcec.ParseSignature(responderSig, btcec.S256())
|
parsedSig, err = lnwire.NewSigFromRawSignature(responderSig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error parsing signature: %v", err)
|
t.Fatalf("error parsing signature: %v", err)
|
||||||
}
|
}
|
||||||
@ -590,8 +586,7 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) {
|
|||||||
t.Fatalf("error creating close proposal: %v", err)
|
t.Fatalf("error creating close proposal: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
respSig := append(responderSig, byte(txscript.SigHashAll))
|
parsedSig, err = lnwire.NewSigFromRawSignature(responderSig)
|
||||||
parsedSig, err = btcec.ParseSignature(respSig, btcec.S256())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error parsing signature: %v", err)
|
t.Fatalf("error parsing signature: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -239,7 +239,7 @@ func (p *paymentSession) RequestRoute(payment *LightningPayment,
|
|||||||
|
|
||||||
// With the next candidate path found, we'll attempt to turn this into
|
// With the next candidate path found, we'll attempt to turn this into
|
||||||
// a route by applying the time-lock and fee requirements.
|
// a route by applying the time-lock and fee requirements.
|
||||||
sourceVertex := NewVertex(p.mc.selfNode.PubKey)
|
sourceVertex := Vertex(p.mc.selfNode.PubKeyBytes)
|
||||||
route, err := newRoute(payment.Amount, sourceVertex, path, height,
|
route, err := newRoute(payment.Amount, sourceVertex, path, height,
|
||||||
finalCltvDelta)
|
finalCltvDelta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -296,9 +296,13 @@ func addToTopologyChange(graph *channeldb.ChannelGraph, update *TopologyChange,
|
|||||||
// Any node announcement maps directly to a NetworkNodeUpdate struct.
|
// Any node announcement maps directly to a NetworkNodeUpdate struct.
|
||||||
// No further data munging or db queries are required.
|
// No further data munging or db queries are required.
|
||||||
case *channeldb.LightningNode:
|
case *channeldb.LightningNode:
|
||||||
|
pubKey, err := m.PubKey()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
nodeUpdate := &NetworkNodeUpdate{
|
nodeUpdate := &NetworkNodeUpdate{
|
||||||
Addresses: m.Addresses,
|
Addresses: m.Addresses,
|
||||||
IdentityKey: m.PubKey,
|
IdentityKey: pubKey,
|
||||||
Alias: m.Alias,
|
Alias: m.Alias,
|
||||||
}
|
}
|
||||||
nodeUpdate.IdentityKey.Curve = nil
|
nodeUpdate.IdentityKey.Curve = nil
|
||||||
@ -332,6 +336,15 @@ func addToTopologyChange(graph *channeldb.ChannelGraph, update *TopologyChange,
|
|||||||
connectingNode = edgeInfo.NodeKey1
|
connectingNode = edgeInfo.NodeKey1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aNode, err := sourceNode()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cNode, err := connectingNode()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
edgeUpdate := &ChannelEdgeUpdate{
|
edgeUpdate := &ChannelEdgeUpdate{
|
||||||
ChanID: m.ChannelID,
|
ChanID: m.ChannelID,
|
||||||
ChanPoint: edgeInfo.ChannelPoint,
|
ChanPoint: edgeInfo.ChannelPoint,
|
||||||
@ -340,8 +353,8 @@ func addToTopologyChange(graph *channeldb.ChannelGraph, update *TopologyChange,
|
|||||||
MinHTLC: m.MinHTLC,
|
MinHTLC: m.MinHTLC,
|
||||||
BaseFee: m.FeeBaseMSat,
|
BaseFee: m.FeeBaseMSat,
|
||||||
FeeRate: m.FeeProportionalMillionths,
|
FeeRate: m.FeeProportionalMillionths,
|
||||||
AdvertisingNode: sourceNode,
|
AdvertisingNode: aNode,
|
||||||
ConnectingNode: connectingNode,
|
ConnectingNode: cNode,
|
||||||
}
|
}
|
||||||
edgeUpdate.AdvertisingNode.Curve = nil
|
edgeUpdate.AdvertisingNode.Curve = nil
|
||||||
edgeUpdate.ConnectingNode.Curve = nil
|
edgeUpdate.ConnectingNode.Curve = nil
|
||||||
|
@ -51,23 +51,25 @@ func createTestNode() (*channeldb.LightningNode, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub := priv.PubKey().SerializeCompressed()
|
pub := priv.PubKey().SerializeCompressed()
|
||||||
return &channeldb.LightningNode{
|
n := &channeldb.LightningNode{
|
||||||
HaveNodeAnnouncement: true,
|
HaveNodeAnnouncement: true,
|
||||||
LastUpdate: time.Unix(updateTime, 0),
|
LastUpdate: time.Unix(updateTime, 0),
|
||||||
Addresses: testAddrs,
|
Addresses: testAddrs,
|
||||||
PubKey: priv.PubKey(),
|
|
||||||
Color: color.RGBA{1, 2, 3, 0},
|
Color: color.RGBA{1, 2, 3, 0},
|
||||||
Alias: "kek" + string(pub[:]),
|
Alias: "kek" + string(pub[:]),
|
||||||
AuthSig: testSig,
|
AuthSigBytes: testSig.Serialize(),
|
||||||
Features: testFeatures,
|
Features: testFeatures,
|
||||||
}, nil
|
}
|
||||||
|
copy(n.PubKeyBytes[:], pub)
|
||||||
|
|
||||||
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func randEdgePolicy(chanID *lnwire.ShortChannelID,
|
func randEdgePolicy(chanID *lnwire.ShortChannelID,
|
||||||
node *channeldb.LightningNode) *channeldb.ChannelEdgePolicy {
|
node *channeldb.LightningNode) *channeldb.ChannelEdgePolicy {
|
||||||
|
|
||||||
return &channeldb.ChannelEdgePolicy{
|
return &channeldb.ChannelEdgePolicy{
|
||||||
Signature: testSig,
|
SigBytes: testSig.Serialize(),
|
||||||
ChannelID: chanID.ToUint64(),
|
ChannelID: chanID.ToUint64(),
|
||||||
LastUpdate: time.Unix(int64(prand.Int31()), 0),
|
LastUpdate: time.Unix(int64(prand.Int31()), 0),
|
||||||
TimeLockDelta: uint16(prand.Int63()),
|
TimeLockDelta: uint16(prand.Int63()),
|
||||||
@ -372,17 +374,17 @@ func TestEdgeUpdateNotification(t *testing.T) {
|
|||||||
// update to announce the created channel between the two nodes.
|
// update to announce the created channel between the two nodes.
|
||||||
edge := &channeldb.ChannelEdgeInfo{
|
edge := &channeldb.ChannelEdgeInfo{
|
||||||
ChannelID: chanID.ToUint64(),
|
ChannelID: chanID.ToUint64(),
|
||||||
NodeKey1: node1.PubKey,
|
NodeKey1Bytes: node1.PubKeyBytes,
|
||||||
NodeKey2: node2.PubKey,
|
NodeKey2Bytes: node2.PubKeyBytes,
|
||||||
BitcoinKey1: bitcoinKey1,
|
|
||||||
BitcoinKey2: bitcoinKey2,
|
|
||||||
AuthProof: &channeldb.ChannelAuthProof{
|
AuthProof: &channeldb.ChannelAuthProof{
|
||||||
NodeSig1: testSig,
|
NodeSig1Bytes: testSig.Serialize(),
|
||||||
NodeSig2: testSig,
|
NodeSig2Bytes: testSig.Serialize(),
|
||||||
BitcoinSig1: testSig,
|
BitcoinSig1Bytes: testSig.Serialize(),
|
||||||
BitcoinSig2: testSig,
|
BitcoinSig2Bytes: testSig.Serialize(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
copy(edge.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed())
|
||||||
|
copy(edge.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed())
|
||||||
|
|
||||||
if err := ctx.router.AddEdge(edge); err != nil {
|
if err := ctx.router.AddEdge(edge); err != nil {
|
||||||
t.Fatalf("unable to add edge: %v", err)
|
t.Fatalf("unable to add edge: %v", err)
|
||||||
@ -450,8 +452,17 @@ func TestEdgeUpdateNotification(t *testing.T) {
|
|||||||
// Create lookup map for notifications we are intending to receive. Entries
|
// Create lookup map for notifications we are intending to receive. Entries
|
||||||
// are removed from the map when the anticipated notification is received.
|
// are removed from the map when the anticipated notification is received.
|
||||||
var waitingFor = map[Vertex]int{
|
var waitingFor = map[Vertex]int{
|
||||||
NewVertex(node1.PubKey): 1,
|
Vertex(node1.PubKeyBytes): 1,
|
||||||
NewVertex(node2.PubKey): 2,
|
Vertex(node2.PubKeyBytes): 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
node1Pub, err := node1.PubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to encode key: %v", err)
|
||||||
|
}
|
||||||
|
node2Pub, err := node2.PubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to encode key: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
const numEdgePolicies = 2
|
const numEdgePolicies = 2
|
||||||
@ -473,20 +484,20 @@ func TestEdgeUpdateNotification(t *testing.T) {
|
|||||||
case 1:
|
case 1:
|
||||||
// Received notification corresponding to edge1.
|
// Received notification corresponding to edge1.
|
||||||
assertEdgeCorrect(t, edgeUpdate, edge1)
|
assertEdgeCorrect(t, edgeUpdate, edge1)
|
||||||
if !edgeUpdate.AdvertisingNode.IsEqual(node1.PubKey) {
|
if !edgeUpdate.AdvertisingNode.IsEqual(node1Pub) {
|
||||||
t.Fatal("advertising node mismatch")
|
t.Fatal("advertising node mismatch")
|
||||||
}
|
}
|
||||||
if !edgeUpdate.ConnectingNode.IsEqual(node2.PubKey) {
|
if !edgeUpdate.ConnectingNode.IsEqual(node2Pub) {
|
||||||
t.Fatal("connecting node mismatch")
|
t.Fatal("connecting node mismatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
// Received notification corresponding to edge2.
|
// Received notification corresponding to edge2.
|
||||||
assertEdgeCorrect(t, edgeUpdate, edge2)
|
assertEdgeCorrect(t, edgeUpdate, edge2)
|
||||||
if !edgeUpdate.AdvertisingNode.IsEqual(node2.PubKey) {
|
if !edgeUpdate.AdvertisingNode.IsEqual(node2Pub) {
|
||||||
t.Fatal("advertising node mismatch")
|
t.Fatal("advertising node mismatch")
|
||||||
}
|
}
|
||||||
if !edgeUpdate.ConnectingNode.IsEqual(node1.PubKey) {
|
if !edgeUpdate.ConnectingNode.IsEqual(node1Pub) {
|
||||||
t.Fatal("connecting node mismatch")
|
t.Fatal("connecting node mismatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,8 +505,8 @@ func TestEdgeUpdateNotification(t *testing.T) {
|
|||||||
t.Fatal("invalid edge index")
|
t.Fatal("invalid edge index")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove entry from waitingFor map to ensure we don't double count a
|
// Remove entry from waitingFor map to ensure
|
||||||
// repeat notification.
|
// we don't double count a repeat notification.
|
||||||
delete(waitingFor, nodeVertex)
|
delete(waitingFor, nodeVertex)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -553,17 +564,17 @@ func TestNodeUpdateNotification(t *testing.T) {
|
|||||||
|
|
||||||
edge := &channeldb.ChannelEdgeInfo{
|
edge := &channeldb.ChannelEdgeInfo{
|
||||||
ChannelID: chanID.ToUint64(),
|
ChannelID: chanID.ToUint64(),
|
||||||
NodeKey1: node1.PubKey,
|
NodeKey1Bytes: node1.PubKeyBytes,
|
||||||
NodeKey2: node2.PubKey,
|
NodeKey2Bytes: node2.PubKeyBytes,
|
||||||
BitcoinKey1: bitcoinKey1,
|
|
||||||
BitcoinKey2: bitcoinKey2,
|
|
||||||
AuthProof: &channeldb.ChannelAuthProof{
|
AuthProof: &channeldb.ChannelAuthProof{
|
||||||
NodeSig1: testSig,
|
NodeSig1Bytes: testSig.Serialize(),
|
||||||
NodeSig2: testSig,
|
NodeSig2Bytes: testSig.Serialize(),
|
||||||
BitcoinSig1: testSig,
|
BitcoinSig1Bytes: testSig.Serialize(),
|
||||||
BitcoinSig2: testSig,
|
BitcoinSig2Bytes: testSig.Serialize(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
copy(edge.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed())
|
||||||
|
copy(edge.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed())
|
||||||
|
|
||||||
// Adding the edge will add the nodes to the graph, but with no info
|
// Adding the edge will add the nodes to the graph, but with no info
|
||||||
// except the pubkey known.
|
// except the pubkey known.
|
||||||
@ -589,15 +600,17 @@ func TestNodeUpdateNotification(t *testing.T) {
|
|||||||
assertNodeNtfnCorrect := func(t *testing.T, ann *channeldb.LightningNode,
|
assertNodeNtfnCorrect := func(t *testing.T, ann *channeldb.LightningNode,
|
||||||
nodeUpdate *NetworkNodeUpdate) {
|
nodeUpdate *NetworkNodeUpdate) {
|
||||||
|
|
||||||
|
nodeKey, _ := ann.PubKey()
|
||||||
|
|
||||||
// The notification received should directly map the
|
// The notification received should directly map the
|
||||||
// announcement originally sent.
|
// announcement originally sent.
|
||||||
if nodeUpdate.Addresses[0] != ann.Addresses[0] {
|
if nodeUpdate.Addresses[0] != ann.Addresses[0] {
|
||||||
t.Fatalf("node address doesn't match: expected %v, got %v",
|
t.Fatalf("node address doesn't match: expected %v, got %v",
|
||||||
nodeUpdate.Addresses[0], ann.Addresses[0])
|
nodeUpdate.Addresses[0], ann.Addresses[0])
|
||||||
}
|
}
|
||||||
if !nodeUpdate.IdentityKey.IsEqual(ann.PubKey) {
|
if !nodeUpdate.IdentityKey.IsEqual(nodeKey) {
|
||||||
t.Fatalf("node identity keys don't match: expected %x, "+
|
t.Fatalf("node identity keys don't match: expected %x, "+
|
||||||
"got %x", ann.PubKey.SerializeCompressed(),
|
"got %x", nodeKey.SerializeCompressed(),
|
||||||
nodeUpdate.IdentityKey.SerializeCompressed())
|
nodeUpdate.IdentityKey.SerializeCompressed())
|
||||||
}
|
}
|
||||||
if nodeUpdate.Alias != ann.Alias {
|
if nodeUpdate.Alias != ann.Alias {
|
||||||
@ -609,8 +622,8 @@ func TestNodeUpdateNotification(t *testing.T) {
|
|||||||
// Create lookup map for notifications we are intending to receive. Entries
|
// Create lookup map for notifications we are intending to receive. Entries
|
||||||
// are removed from the map when the anticipated notification is received.
|
// are removed from the map when the anticipated notification is received.
|
||||||
var waitingFor = map[Vertex]int{
|
var waitingFor = map[Vertex]int{
|
||||||
NewVertex(node1.PubKey): 1,
|
Vertex(node1.PubKeyBytes): 1,
|
||||||
NewVertex(node2.PubKey): 2,
|
Vertex(node2.PubKeyBytes): 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exactly two notifications should be sent, each corresponding to the
|
// Exactly two notifications should be sent, each corresponding to the
|
||||||
@ -739,17 +752,17 @@ func TestNotificationCancellation(t *testing.T) {
|
|||||||
|
|
||||||
edge := &channeldb.ChannelEdgeInfo{
|
edge := &channeldb.ChannelEdgeInfo{
|
||||||
ChannelID: chanID.ToUint64(),
|
ChannelID: chanID.ToUint64(),
|
||||||
NodeKey1: node1.PubKey,
|
NodeKey1Bytes: node1.PubKeyBytes,
|
||||||
NodeKey2: node2.PubKey,
|
NodeKey2Bytes: node2.PubKeyBytes,
|
||||||
BitcoinKey1: bitcoinKey1,
|
|
||||||
BitcoinKey2: bitcoinKey2,
|
|
||||||
AuthProof: &channeldb.ChannelAuthProof{
|
AuthProof: &channeldb.ChannelAuthProof{
|
||||||
NodeSig1: testSig,
|
NodeSig1Bytes: testSig.Serialize(),
|
||||||
NodeSig2: testSig,
|
NodeSig2Bytes: testSig.Serialize(),
|
||||||
BitcoinSig1: testSig,
|
BitcoinSig1Bytes: testSig.Serialize(),
|
||||||
BitcoinSig2: testSig,
|
BitcoinSig2Bytes: testSig.Serialize(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
copy(edge.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed())
|
||||||
|
copy(edge.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed())
|
||||||
if err := ctx.router.AddEdge(edge); err != nil {
|
if err := ctx.router.AddEdge(edge); err != nil {
|
||||||
t.Fatalf("unable to add edge: %v", err)
|
t.Fatalf("unable to add edge: %v", err)
|
||||||
}
|
}
|
||||||
@ -820,17 +833,17 @@ func TestChannelCloseNotification(t *testing.T) {
|
|||||||
// announcement to announce the created channel between the two nodes.
|
// announcement to announce the created channel between the two nodes.
|
||||||
edge := &channeldb.ChannelEdgeInfo{
|
edge := &channeldb.ChannelEdgeInfo{
|
||||||
ChannelID: chanID.ToUint64(),
|
ChannelID: chanID.ToUint64(),
|
||||||
NodeKey1: node1.PubKey,
|
NodeKey1Bytes: node1.PubKeyBytes,
|
||||||
NodeKey2: node2.PubKey,
|
NodeKey2Bytes: node2.PubKeyBytes,
|
||||||
BitcoinKey1: bitcoinKey1,
|
|
||||||
BitcoinKey2: bitcoinKey2,
|
|
||||||
AuthProof: &channeldb.ChannelAuthProof{
|
AuthProof: &channeldb.ChannelAuthProof{
|
||||||
NodeSig1: testSig,
|
NodeSig1Bytes: testSig.Serialize(),
|
||||||
NodeSig2: testSig,
|
NodeSig2Bytes: testSig.Serialize(),
|
||||||
BitcoinSig1: testSig,
|
BitcoinSig1Bytes: testSig.Serialize(),
|
||||||
BitcoinSig2: testSig,
|
BitcoinSig2Bytes: testSig.Serialize(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
copy(edge.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed())
|
||||||
|
copy(edge.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed())
|
||||||
if err := ctx.router.AddEdge(edge); err != nil {
|
if err := ctx.router.AddEdge(edge); err != nil {
|
||||||
t.Fatalf("unable to add edge: %v", err)
|
t.Fatalf("unable to add edge: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package routing
|
package routing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
@ -148,7 +149,7 @@ type Route struct {
|
|||||||
// target node is not found in the route, then false is returned.
|
// target node is not found in the route, then false is returned.
|
||||||
func (r *Route) nextHopVertex(n *btcec.PublicKey) (Vertex, bool) {
|
func (r *Route) nextHopVertex(n *btcec.PublicKey) (Vertex, bool) {
|
||||||
hop, ok := r.nextHopMap[NewVertex(n)]
|
hop, ok := r.nextHopMap[NewVertex(n)]
|
||||||
return NewVertex(hop.Node.PubKey), ok
|
return Vertex(hop.Node.PubKeyBytes), ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// nextHopChannel returns the uint64 channel ID of the next hop after the
|
// nextHopChannel returns the uint64 channel ID of the next hop after the
|
||||||
@ -259,7 +260,7 @@ func newRoute(amtToSend lnwire.MilliSatoshi, sourceVertex Vertex,
|
|||||||
// First, we'll update both the node and channel index, to
|
// First, we'll update both the node and channel index, to
|
||||||
// indicate that this Vertex, and outgoing channel link are
|
// indicate that this Vertex, and outgoing channel link are
|
||||||
// present within this route.
|
// present within this route.
|
||||||
v := NewVertex(edge.Node.PubKey)
|
v := Vertex(edge.Node.PubKeyBytes)
|
||||||
route.nodeIndex[v] = struct{}{}
|
route.nodeIndex[v] = struct{}{}
|
||||||
route.chanIndex[edge.ChannelID] = struct{}{}
|
route.chanIndex[edge.ChannelID] = struct{}{}
|
||||||
|
|
||||||
@ -314,7 +315,6 @@ func newRoute(amtToSend lnwire.MilliSatoshi, sourceVertex Vertex,
|
|||||||
AmtToForward: amtToForward,
|
AmtToForward: amtToForward,
|
||||||
Fee: fee,
|
Fee: fee,
|
||||||
}
|
}
|
||||||
edge.Node.PubKey.Curve = nil
|
|
||||||
|
|
||||||
route.TotalFees += nextHop.Fee
|
route.TotalFees += nextHop.Fee
|
||||||
|
|
||||||
@ -361,7 +361,7 @@ func newRoute(amtToSend lnwire.MilliSatoshi, sourceVertex Vertex,
|
|||||||
// We'll then make a second run through our route in order to set up
|
// We'll then make a second run through our route in order to set up
|
||||||
// our prev hop mapping.
|
// our prev hop mapping.
|
||||||
for _, hop := range route.Hops {
|
for _, hop := range route.Hops {
|
||||||
vertex := NewVertex(hop.Channel.Node.PubKey)
|
vertex := Vertex(hop.Channel.Node.PubKeyBytes)
|
||||||
route.prevHopMap[vertex] = hop.Channel
|
route.prevHopMap[vertex] = hop.Channel
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,7 +393,7 @@ func (v Vertex) String() string {
|
|||||||
// directional edge with the node's ID in the opposite direction.
|
// directional edge with the node's ID in the opposite direction.
|
||||||
type edgeWithPrev struct {
|
type edgeWithPrev struct {
|
||||||
edge *ChannelHop
|
edge *ChannelHop
|
||||||
prevNode *btcec.PublicKey
|
prevNode [33]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// edgeWeight computes the weight of an edge. This value is used when searching
|
// edgeWeight computes the weight of an edge. This value is used when searching
|
||||||
@ -440,7 +440,7 @@ func findPath(tx *bolt.Tx, graph *channeldb.ChannelGraph,
|
|||||||
if err := graph.ForEachNode(tx, func(_ *bolt.Tx, node *channeldb.LightningNode) error {
|
if err := graph.ForEachNode(tx, func(_ *bolt.Tx, node *channeldb.LightningNode) error {
|
||||||
// TODO(roasbeef): with larger graph can just use disk seeks
|
// TODO(roasbeef): with larger graph can just use disk seeks
|
||||||
// with a visited map
|
// with a visited map
|
||||||
distance[NewVertex(node.PubKey)] = nodeWithDist{
|
distance[Vertex(node.PubKeyBytes)] = nodeWithDist{
|
||||||
dist: infinity,
|
dist: infinity,
|
||||||
node: node,
|
node: node,
|
||||||
}
|
}
|
||||||
@ -455,7 +455,7 @@ func findPath(tx *bolt.Tx, graph *channeldb.ChannelGraph,
|
|||||||
// To start, we add the source of our path finding attempt to the
|
// To start, we add the source of our path finding attempt to the
|
||||||
// distance map with with a distance of 0. This indicates our starting
|
// distance map with with a distance of 0. This indicates our starting
|
||||||
// point in the graph traversal.
|
// point in the graph traversal.
|
||||||
sourceVertex := NewVertex(sourceNode.PubKey)
|
sourceVertex := Vertex(sourceNode.PubKeyBytes)
|
||||||
distance[sourceVertex] = nodeWithDist{
|
distance[sourceVertex] = nodeWithDist{
|
||||||
dist: 0,
|
dist: 0,
|
||||||
node: sourceNode,
|
node: sourceNode,
|
||||||
@ -465,6 +465,8 @@ func findPath(tx *bolt.Tx, graph *channeldb.ChannelGraph,
|
|||||||
// heap.
|
// heap.
|
||||||
heap.Push(&nodeHeap, distance[sourceVertex])
|
heap.Push(&nodeHeap, distance[sourceVertex])
|
||||||
|
|
||||||
|
targetBytes := target.SerializeCompressed()
|
||||||
|
|
||||||
// We'll use this map as a series of "previous" hop pointers. So to get
|
// We'll use this map as a series of "previous" hop pointers. So to get
|
||||||
// to `Vertex` we'll take the edge that it's mapped to within `prev`.
|
// to `Vertex` we'll take the edge that it's mapped to within `prev`.
|
||||||
prev := make(map[Vertex]edgeWithPrev)
|
prev := make(map[Vertex]edgeWithPrev)
|
||||||
@ -477,19 +479,19 @@ func findPath(tx *bolt.Tx, graph *channeldb.ChannelGraph,
|
|||||||
// If we've reached our target (or we don't have any outgoing
|
// If we've reached our target (or we don't have any outgoing
|
||||||
// edges), then we're done here and can exit the graph
|
// edges), then we're done here and can exit the graph
|
||||||
// traversal early.
|
// traversal early.
|
||||||
if bestNode.PubKey.IsEqual(target) {
|
if bytes.Equal(bestNode.PubKeyBytes[:], targetBytes) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we've found the next potential step to take we'll
|
// Now that we've found the next potential step to take we'll
|
||||||
// examine all the outgoing edge (channels) from this node to
|
// examine all the outgoing edge (channels) from this node to
|
||||||
// further our graph traversal.
|
// further our graph traversal.
|
||||||
pivot := NewVertex(bestNode.PubKey)
|
pivot := Vertex(bestNode.PubKeyBytes)
|
||||||
err := bestNode.ForEachChannel(tx, func(tx *bolt.Tx,
|
err := bestNode.ForEachChannel(tx, func(tx *bolt.Tx,
|
||||||
edgeInfo *channeldb.ChannelEdgeInfo,
|
edgeInfo *channeldb.ChannelEdgeInfo,
|
||||||
outEdge, inEdge *channeldb.ChannelEdgePolicy) error {
|
outEdge, inEdge *channeldb.ChannelEdgePolicy) error {
|
||||||
|
|
||||||
v := NewVertex(outEdge.Node.PubKey)
|
v := Vertex(outEdge.Node.PubKeyBytes)
|
||||||
|
|
||||||
// If the outgoing edge is currently disabled, then
|
// If the outgoing edge is currently disabled, then
|
||||||
// we'll stop here, as we shouldn't attempt to route
|
// we'll stop here, as we shouldn't attempt to route
|
||||||
@ -538,7 +540,7 @@ func findPath(tx *bolt.Tx, graph *channeldb.ChannelGraph,
|
|||||||
ChannelEdgePolicy: outEdge,
|
ChannelEdgePolicy: outEdge,
|
||||||
Capacity: edgeInfo.Capacity,
|
Capacity: edgeInfo.Capacity,
|
||||||
},
|
},
|
||||||
prevNode: bestNode.PubKey,
|
prevNode: bestNode.PubKeyBytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add this new node to our heap as we'd like
|
// Add this new node to our heap as we'd like
|
||||||
@ -573,9 +575,8 @@ func findPath(tx *bolt.Tx, graph *channeldb.ChannelGraph,
|
|||||||
// backwards from this hop via the prev pointer for this hop
|
// backwards from this hop via the prev pointer for this hop
|
||||||
// within the prevHop map.
|
// within the prevHop map.
|
||||||
pathEdges = append(pathEdges, prev[prevNode].edge)
|
pathEdges = append(pathEdges, prev[prevNode].edge)
|
||||||
prev[prevNode].edge.Node.PubKey.Curve = nil
|
|
||||||
|
|
||||||
prevNode = NewVertex(prev[prevNode].prevNode)
|
prevNode = Vertex(prev[prevNode].prevNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The route is invalid if it spans more than 20 hops. The current
|
// The route is invalid if it spans more than 20 hops. The current
|
||||||
@ -648,8 +649,6 @@ func findPaths(tx *bolt.Tx, graph *channeldb.ChannelGraph,
|
|||||||
|
|
||||||
shortestPaths = append(shortestPaths, firstPath)
|
shortestPaths = append(shortestPaths, firstPath)
|
||||||
|
|
||||||
source.PubKey.Curve = nil
|
|
||||||
|
|
||||||
// While we still have candidate paths to explore we'll keep exploring
|
// While we still have candidate paths to explore we'll keep exploring
|
||||||
// the sub-graphs created to find the next k-th shortest path.
|
// the sub-graphs created to find the next k-th shortest path.
|
||||||
for k := 1; k < 100; k++ {
|
for k := 1; k < 100; k++ {
|
||||||
@ -688,12 +687,12 @@ func findPaths(tx *bolt.Tx, graph *channeldb.ChannelGraph,
|
|||||||
// Next we'll remove all entries in the root path that
|
// Next we'll remove all entries in the root path that
|
||||||
// aren't the current spur node from the graph.
|
// aren't the current spur node from the graph.
|
||||||
for _, hop := range rootPath {
|
for _, hop := range rootPath {
|
||||||
node := hop.Node.PubKey
|
node := hop.Node.PubKeyBytes
|
||||||
if node.IsEqual(spurNode.PubKey) {
|
if node == spurNode.PubKeyBytes {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
ignoredVertexes[NewVertex(node)] = struct{}{}
|
ignoredVertexes[Vertex(node)] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// With the edges that are part of our root path, and
|
// With the edges that are part of our root path, and
|
||||||
|
@ -53,10 +53,10 @@ var (
|
|||||||
_, _ = testSig.S.SetString("18801056069249825825291287104931333862866033135609736119018462340006816851118", 10)
|
_, _ = testSig.S.SetString("18801056069249825825291287104931333862866033135609736119018462340006816851118", 10)
|
||||||
|
|
||||||
testAuthProof = channeldb.ChannelAuthProof{
|
testAuthProof = channeldb.ChannelAuthProof{
|
||||||
NodeSig1: testSig,
|
NodeSig1Bytes: testSig.Serialize(),
|
||||||
NodeSig2: testSig,
|
NodeSig2Bytes: testSig.Serialize(),
|
||||||
BitcoinSig1: testSig,
|
BitcoinSig1Bytes: testSig.Serialize(),
|
||||||
BitcoinSig2: testSig,
|
BitcoinSig2Bytes: testSig.Serialize(),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -165,20 +165,16 @@ func parseTestGraph(path string) (*channeldb.ChannelGraph, func(), aliasMap, err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
pub, err := btcec.ParsePubKey(pubBytes, btcec.S256())
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
dbNode := &channeldb.LightningNode{
|
dbNode := &channeldb.LightningNode{
|
||||||
HaveNodeAnnouncement: true,
|
HaveNodeAnnouncement: true,
|
||||||
AuthSig: testSig,
|
AuthSigBytes: testSig.Serialize(),
|
||||||
LastUpdate: time.Now(),
|
LastUpdate: time.Now(),
|
||||||
Addresses: testAddrs,
|
Addresses: testAddrs,
|
||||||
PubKey: pub,
|
|
||||||
Alias: node.Alias,
|
Alias: node.Alias,
|
||||||
Features: testFeatures,
|
Features: testFeatures,
|
||||||
}
|
}
|
||||||
|
copy(dbNode.PubKeyBytes[:], pubBytes)
|
||||||
|
|
||||||
// We require all aliases within the graph to be unique for our
|
// We require all aliases within the graph to be unique for our
|
||||||
// tests.
|
// tests.
|
||||||
@ -187,6 +183,11 @@ func parseTestGraph(path string) (*channeldb.ChannelGraph, func(), aliasMap, err
|
|||||||
"must be unique!")
|
"must be unique!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub, err := btcec.ParsePubKey(pubBytes, btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// If the alias is unique, then add the node to the
|
// If the alias is unique, then add the node to the
|
||||||
// alias map for easy lookup.
|
// alias map for easy lookup.
|
||||||
aliasMap[node.Alias] = pub
|
aliasMap[node.Alias] = pub
|
||||||
@ -228,19 +229,11 @@ func parseTestGraph(path string) (*channeldb.ChannelGraph, func(), aliasMap, err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
node1Pub, err := btcec.ParsePubKey(node1Bytes, btcec.S256())
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
node2Bytes, err := hex.DecodeString(edge.Node2)
|
node2Bytes, err := hex.DecodeString(edge.Node2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
node2Pub, err := btcec.ParsePubKey(node2Bytes, btcec.S256())
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fundingTXID := strings.Split(edge.ChannelPoint, ":")[0]
|
fundingTXID := strings.Split(edge.ChannelPoint, ":")[0]
|
||||||
txidBytes, err := chainhash.NewHashFromStr(fundingTXID)
|
txidBytes, err := chainhash.NewHashFromStr(fundingTXID)
|
||||||
@ -256,21 +249,23 @@ func parseTestGraph(path string) (*channeldb.ChannelGraph, func(), aliasMap, err
|
|||||||
// nodes.
|
// nodes.
|
||||||
edgeInfo := channeldb.ChannelEdgeInfo{
|
edgeInfo := channeldb.ChannelEdgeInfo{
|
||||||
ChannelID: edge.ChannelID,
|
ChannelID: edge.ChannelID,
|
||||||
NodeKey1: node1Pub,
|
|
||||||
NodeKey2: node2Pub,
|
|
||||||
BitcoinKey1: node1Pub,
|
|
||||||
BitcoinKey2: node2Pub,
|
|
||||||
AuthProof: &testAuthProof,
|
AuthProof: &testAuthProof,
|
||||||
ChannelPoint: fundingPoint,
|
ChannelPoint: fundingPoint,
|
||||||
Capacity: btcutil.Amount(edge.Capacity),
|
Capacity: btcutil.Amount(edge.Capacity),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
copy(edgeInfo.NodeKey1Bytes[:], node1Bytes)
|
||||||
|
copy(edgeInfo.NodeKey2Bytes[:], node2Bytes)
|
||||||
|
copy(edgeInfo.BitcoinKey1Bytes[:], node1Bytes)
|
||||||
|
copy(edgeInfo.BitcoinKey2Bytes[:], node2Bytes)
|
||||||
|
|
||||||
err = graph.AddChannelEdge(&edgeInfo)
|
err = graph.AddChannelEdge(&edgeInfo)
|
||||||
if err != nil && err != channeldb.ErrEdgeAlreadyExist {
|
if err != nil && err != channeldb.ErrEdgeAlreadyExist {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
edgePolicy := &channeldb.ChannelEdgePolicy{
|
edgePolicy := &channeldb.ChannelEdgePolicy{
|
||||||
Signature: testSig,
|
SigBytes: testSig.Serialize(),
|
||||||
Flags: lnwire.ChanUpdateFlag(edge.Flags),
|
Flags: lnwire.ChanUpdateFlag(edge.Flags),
|
||||||
ChannelID: edge.ChannelID,
|
ChannelID: edge.ChannelID,
|
||||||
LastUpdate: time.Now(),
|
LastUpdate: time.Now(),
|
||||||
@ -300,7 +295,7 @@ func TestBasicGraphPathFinding(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to fetch source node: %v", err)
|
t.Fatalf("unable to fetch source node: %v", err)
|
||||||
}
|
}
|
||||||
sourceVertex := NewVertex(sourceNode.PubKey)
|
sourceVertex := Vertex(sourceNode.PubKeyBytes)
|
||||||
|
|
||||||
ignoredEdges := make(map[uint64]struct{})
|
ignoredEdges := make(map[uint64]struct{})
|
||||||
ignoredVertexes := make(map[Vertex]struct{})
|
ignoredVertexes := make(map[Vertex]struct{})
|
||||||
@ -342,13 +337,17 @@ func TestBasicGraphPathFinding(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The first hop in the path should be an edge from roasbeef to goku.
|
// The first hop in the path should be an edge from roasbeef to goku.
|
||||||
if !route.Hops[0].Channel.Node.PubKey.IsEqual(aliases["songoku"]) {
|
if !bytes.Equal(route.Hops[0].Channel.Node.PubKeyBytes[:],
|
||||||
|
aliases["songoku"].SerializeCompressed()) {
|
||||||
|
|
||||||
t.Fatalf("first hop should be goku, is instead: %v",
|
t.Fatalf("first hop should be goku, is instead: %v",
|
||||||
route.Hops[0].Channel.Node.Alias)
|
route.Hops[0].Channel.Node.Alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The second hop should be from goku to sophon.
|
// The second hop should be from goku to sophon.
|
||||||
if !route.Hops[1].Channel.Node.PubKey.IsEqual(aliases["sophon"]) {
|
if !bytes.Equal(route.Hops[1].Channel.Node.PubKeyBytes[:],
|
||||||
|
aliases["sophon"].SerializeCompressed()) {
|
||||||
|
|
||||||
t.Fatalf("second hop should be sophon, is instead: %v",
|
t.Fatalf("second hop should be sophon, is instead: %v",
|
||||||
route.Hops[0].Channel.Node.Alias)
|
route.Hops[0].Channel.Node.Alias)
|
||||||
}
|
}
|
||||||
@ -833,7 +832,7 @@ func TestPathFindSpecExample(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to retrieve source node: %v", err)
|
t.Fatalf("unable to retrieve source node: %v", err)
|
||||||
}
|
}
|
||||||
if !source.PubKey.IsEqual(alice) {
|
if !bytes.Equal(source.PubKeyBytes[:], alice.SerializeCompressed()) {
|
||||||
t.Fatalf("source node not set")
|
t.Fatalf("source node not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ type Config struct {
|
|||||||
// forward a fully encoded payment to the first hop in the route
|
// forward a fully encoded payment to the first hop in the route
|
||||||
// denoted by its public key. A non-nil error is to be returned if the
|
// denoted by its public key. A non-nil error is to be returned if the
|
||||||
// payment was unsuccessful.
|
// payment was unsuccessful.
|
||||||
SendToSwitch func(firstHop *btcec.PublicKey, htlcAdd *lnwire.UpdateAddHTLC,
|
SendToSwitch func(firstHop [33]byte, htlcAdd *lnwire.UpdateAddHTLC,
|
||||||
circuit *sphinx.Circuit) ([sha256.Size]byte, error)
|
circuit *sphinx.Circuit) ([sha256.Size]byte, error)
|
||||||
|
|
||||||
// ChannelPruneExpiry is the duration used to determine if a channel
|
// ChannelPruneExpiry is the duration used to determine if a channel
|
||||||
@ -237,6 +237,9 @@ type ChannelRouter struct {
|
|||||||
// consistency between the various database accesses.
|
// consistency between the various database accesses.
|
||||||
channelEdgeMtx *multimutex.Mutex
|
channelEdgeMtx *multimutex.Mutex
|
||||||
|
|
||||||
|
rejectMtx sync.RWMutex
|
||||||
|
rejectCache map[uint64]struct{}
|
||||||
|
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
|
|
||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
@ -268,6 +271,7 @@ func New(cfg Config) (*ChannelRouter, error) {
|
|||||||
channelEdgeMtx: multimutex.NewMutex(),
|
channelEdgeMtx: multimutex.NewMutex(),
|
||||||
selfNode: selfNode,
|
selfNode: selfNode,
|
||||||
routeCache: make(map[routeTuple][]*Route),
|
routeCache: make(map[routeTuple][]*Route),
|
||||||
|
rejectCache: make(map[uint64]struct{}),
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -504,6 +508,93 @@ func (r *ChannelRouter) syncGraphWithChain() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pruneZombieChans is a method that will be called periodically to prune out
|
||||||
|
// any "zombie" channels. We consider channels zombies if *both* edges haven't
|
||||||
|
// been updated since our zombie horizon. We do this periodically to keep a
|
||||||
|
// health, lively routing table.
|
||||||
|
func (r *ChannelRouter) pruneZombieChans() error {
|
||||||
|
var chansToPrune []wire.OutPoint
|
||||||
|
chanExpiry := r.cfg.ChannelPruneExpiry
|
||||||
|
|
||||||
|
log.Infof("Examining Channel Graph for zombie channels")
|
||||||
|
|
||||||
|
// First, we'll collect all the channels which are eligible for garbage
|
||||||
|
// collection due to being zombies.
|
||||||
|
filterPruneChans := func(info *channeldb.ChannelEdgeInfo,
|
||||||
|
e1, e2 *channeldb.ChannelEdgePolicy) error {
|
||||||
|
|
||||||
|
// We'll ensure that we don't attempt to prune our *own*
|
||||||
|
// channels from the graph, as in any case this should be
|
||||||
|
// re-advertised by the sub-system above us.
|
||||||
|
if info.NodeKey1Bytes == r.selfNode.PubKeyBytes ||
|
||||||
|
info.NodeKey2Bytes == r.selfNode.PubKeyBytes {
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If *both* edges haven't been updated for a period of
|
||||||
|
// chanExpiry, then we'll mark the channel itself as eligible
|
||||||
|
// for graph pruning.
|
||||||
|
e1Zombie, e2Zombie := true, true
|
||||||
|
if e1 != nil {
|
||||||
|
e1Zombie = time.Since(e1.LastUpdate) >= chanExpiry
|
||||||
|
if e1Zombie {
|
||||||
|
log.Tracef("Edge #1 of ChannelPoint(%v) "+
|
||||||
|
"last update: %v",
|
||||||
|
info.ChannelPoint, e1.LastUpdate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if e2 != nil {
|
||||||
|
e2Zombie = time.Since(e2.LastUpdate) >= chanExpiry
|
||||||
|
if e2Zombie {
|
||||||
|
log.Tracef("Edge #2 of ChannelPoint(%v) "+
|
||||||
|
"last update: %v",
|
||||||
|
info.ChannelPoint, e2.LastUpdate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if e1Zombie && e2Zombie {
|
||||||
|
log.Debugf("ChannelPoint(%v) is a zombie, collecting "+
|
||||||
|
"to prune", info.ChannelPoint)
|
||||||
|
|
||||||
|
// TODO(roasbeef): add ability to delete single
|
||||||
|
// directional edge
|
||||||
|
chansToPrune = append(chansToPrune, info.ChannelPoint)
|
||||||
|
|
||||||
|
// As we're detecting this as a zombie channel, we'll
|
||||||
|
// add this to the set of recently rejected items so we
|
||||||
|
// don't re-accept it shortly after.
|
||||||
|
r.rejectCache[info.ChannelID] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
r.rejectMtx.Lock()
|
||||||
|
defer r.rejectMtx.Unlock()
|
||||||
|
|
||||||
|
err := r.cfg.Graph.ForEachChannel(filterPruneChans)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Unable to filter local zombie "+
|
||||||
|
"chans: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("Pruning %v Zombie Channels", len(chansToPrune))
|
||||||
|
|
||||||
|
// With the set zombie-like channels obtained, we'll do another pass to
|
||||||
|
// delete al zombie channels from the channel graph.
|
||||||
|
for _, chanToPrune := range chansToPrune {
|
||||||
|
log.Tracef("Pruning zombie chan ChannelPoint(%v)", chanToPrune)
|
||||||
|
|
||||||
|
err := r.cfg.Graph.DeleteChannelEdge(&chanToPrune)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Unable to prune zombie "+
|
||||||
|
"chans: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// networkHandler is the primary goroutine for the ChannelRouter. The roles of
|
// networkHandler is the primary goroutine for the ChannelRouter. The roles of
|
||||||
// this goroutine include answering queries related to the state of the
|
// this goroutine include answering queries related to the state of the
|
||||||
// network, pruning the graph on new block notification, applying network
|
// network, pruning the graph on new block notification, applying network
|
||||||
@ -716,79 +807,8 @@ func (r *ChannelRouter) networkHandler() {
|
|||||||
// state of the known graph to filter out any zombie channels
|
// state of the known graph to filter out any zombie channels
|
||||||
// for pruning.
|
// for pruning.
|
||||||
case <-graphPruneTicker.C:
|
case <-graphPruneTicker.C:
|
||||||
|
if err := r.pruneZombieChans(); err != nil {
|
||||||
var chansToPrune []wire.OutPoint
|
log.Errorf("unable to prune zombies: %v", err)
|
||||||
chanExpiry := r.cfg.ChannelPruneExpiry
|
|
||||||
|
|
||||||
log.Infof("Examining Channel Graph for zombie channels")
|
|
||||||
|
|
||||||
// First, we'll collect all the channels which are
|
|
||||||
// eligible for garbage collection due to being
|
|
||||||
// zombies.
|
|
||||||
filterPruneChans := func(info *channeldb.ChannelEdgeInfo,
|
|
||||||
e1, e2 *channeldb.ChannelEdgePolicy) error {
|
|
||||||
|
|
||||||
// We'll ensure that we don't attempt to prune
|
|
||||||
// our *own* channels from the graph, as in any
|
|
||||||
// case this should be re-advertised by the
|
|
||||||
// sub-system above us.
|
|
||||||
if info.NodeKey1.IsEqual(r.selfNode.PubKey) ||
|
|
||||||
info.NodeKey2.IsEqual(r.selfNode.PubKey) {
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// If *both* edges haven't been updated for a
|
|
||||||
// period of chanExpiry, then we'll mark the
|
|
||||||
// channel itself as eligible for graph
|
|
||||||
// pruning.
|
|
||||||
e1Zombie, e2Zombie := true, true
|
|
||||||
if e1 != nil {
|
|
||||||
e1Zombie = time.Since(e1.LastUpdate) >= chanExpiry
|
|
||||||
log.Tracef("Edge #1 of ChannelPoint(%v) "+
|
|
||||||
"last update: %v",
|
|
||||||
info.ChannelPoint, e1.LastUpdate)
|
|
||||||
}
|
|
||||||
if e2 != nil {
|
|
||||||
e2Zombie = time.Since(e2.LastUpdate) >= chanExpiry
|
|
||||||
log.Tracef("Edge #2 of ChannelPoint(%v) "+
|
|
||||||
"last update: %v",
|
|
||||||
info.ChannelPoint, e2.LastUpdate)
|
|
||||||
}
|
|
||||||
if e1Zombie && e2Zombie {
|
|
||||||
log.Infof("ChannelPoint(%v) is a "+
|
|
||||||
"zombie, collecting to prune",
|
|
||||||
info.ChannelPoint)
|
|
||||||
|
|
||||||
// TODO(roasbeef): add ability to
|
|
||||||
// delete single directional edge
|
|
||||||
chansToPrune = append(chansToPrune,
|
|
||||||
info.ChannelPoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err := r.cfg.Graph.ForEachChannel(filterPruneChans)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Unable to local zombie chans: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("Pruning %v Zombie Channels", len(chansToPrune))
|
|
||||||
|
|
||||||
// With the set zombie-like channels obtained, we'll do
|
|
||||||
// another pass to delete al zombie channels from the
|
|
||||||
// channel graph.
|
|
||||||
for _, chanToPrune := range chansToPrune {
|
|
||||||
log.Tracef("Pruning zombie chan ChannelPoint(%v)",
|
|
||||||
chanToPrune)
|
|
||||||
|
|
||||||
err := r.cfg.Graph.DeleteChannelEdge(&chanToPrune)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Unable to prune zombie "+
|
|
||||||
"chans: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The router has been signalled to exit, to we exit our main
|
// The router has been signalled to exit, to we exit our main
|
||||||
@ -814,7 +834,7 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
// attack by node announcements, we will ignore such nodes. If
|
// attack by node announcements, we will ignore such nodes. If
|
||||||
// we do know about this node, check that this update brings
|
// we do know about this node, check that this update brings
|
||||||
// info newer than what we already have.
|
// info newer than what we already have.
|
||||||
lastUpdate, exists, err := r.cfg.Graph.HasLightningNode(msg.PubKey)
|
lastUpdate, exists, err := r.cfg.Graph.HasLightningNode(msg.PubKeyBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("unable to query for the "+
|
return errors.Errorf("unable to query for the "+
|
||||||
"existence of node: %v", err)
|
"existence of node: %v", err)
|
||||||
@ -822,7 +842,7 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
if !exists {
|
if !exists {
|
||||||
return newErrf(ErrIgnored, "Ignoring node announcement"+
|
return newErrf(ErrIgnored, "Ignoring node announcement"+
|
||||||
" for node not found in channel graph (%x)",
|
" for node not found in channel graph (%x)",
|
||||||
msg.PubKey.SerializeCompressed())
|
msg.PubKeyBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we've reached this point then we're aware of the vertex
|
// If we've reached this point then we're aware of the vertex
|
||||||
@ -833,18 +853,27 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
lastUpdate.Equal(msg.LastUpdate) {
|
lastUpdate.Equal(msg.LastUpdate) {
|
||||||
|
|
||||||
return newErrf(ErrOutdated, "Ignoring outdated "+
|
return newErrf(ErrOutdated, "Ignoring outdated "+
|
||||||
"announcement for %x", msg.PubKey.SerializeCompressed())
|
"announcement for %x", msg.PubKeyBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.cfg.Graph.AddLightningNode(msg); err != nil {
|
if err := r.cfg.Graph.AddLightningNode(msg); err != nil {
|
||||||
return errors.Errorf("unable to add node %v to the "+
|
return errors.Errorf("unable to add node %v to the "+
|
||||||
"graph: %v", msg.PubKey.SerializeCompressed(), err)
|
"graph: %v", msg.PubKeyBytes, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Updated vertex data for node=%x",
|
log.Infof("Updated vertex data for node=%x", msg.PubKeyBytes)
|
||||||
msg.PubKey.SerializeCompressed())
|
|
||||||
|
|
||||||
case *channeldb.ChannelEdgeInfo:
|
case *channeldb.ChannelEdgeInfo:
|
||||||
|
// If we recently rejected this channel edge, then we won't
|
||||||
|
// attempt to re-process it.
|
||||||
|
r.rejectMtx.RLock()
|
||||||
|
if _, ok := r.rejectCache[msg.ChannelID]; ok {
|
||||||
|
r.rejectMtx.RUnlock()
|
||||||
|
return newErrf(ErrIgnored, "recently rejected "+
|
||||||
|
"chan_id=%v", msg.ChannelID)
|
||||||
|
}
|
||||||
|
r.rejectMtx.RUnlock()
|
||||||
|
|
||||||
// Prior to processing the announcement we first check if we
|
// Prior to processing the announcement we first check if we
|
||||||
// already know of this channel, if so, then we can exit early.
|
// already know of this channel, if so, then we can exit early.
|
||||||
_, _, exists, err := r.cfg.Graph.HasChannelEdge(msg.ChannelID)
|
_, _, exists, err := r.cfg.Graph.HasChannelEdge(msg.ChannelID)
|
||||||
@ -859,30 +888,28 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
// Query the database for the existence of the two nodes in this
|
// Query the database for the existence of the two nodes in this
|
||||||
// channel. If not found, add a partial node to the database,
|
// channel. If not found, add a partial node to the database,
|
||||||
// containing only the node keys.
|
// containing only the node keys.
|
||||||
_, exists, _ = r.cfg.Graph.HasLightningNode(msg.NodeKey1)
|
_, exists, _ = r.cfg.Graph.HasLightningNode(msg.NodeKey1Bytes)
|
||||||
if !exists {
|
if !exists {
|
||||||
node1 := &channeldb.LightningNode{
|
node1 := &channeldb.LightningNode{
|
||||||
PubKey: msg.NodeKey1,
|
PubKeyBytes: msg.NodeKey1Bytes,
|
||||||
HaveNodeAnnouncement: false,
|
HaveNodeAnnouncement: false,
|
||||||
}
|
}
|
||||||
err := r.cfg.Graph.AddLightningNode(node1)
|
err := r.cfg.Graph.AddLightningNode(node1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("unable to add node %v to"+
|
return errors.Errorf("unable to add node %v to"+
|
||||||
" the graph: %v",
|
" the graph: %v", node1.PubKeyBytes, err)
|
||||||
node1.PubKey.SerializeCompressed(), err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, exists, _ = r.cfg.Graph.HasLightningNode(msg.NodeKey2)
|
_, exists, _ = r.cfg.Graph.HasLightningNode(msg.NodeKey2Bytes)
|
||||||
if !exists {
|
if !exists {
|
||||||
node2 := &channeldb.LightningNode{
|
node2 := &channeldb.LightningNode{
|
||||||
PubKey: msg.NodeKey2,
|
PubKeyBytes: msg.NodeKey2Bytes,
|
||||||
HaveNodeAnnouncement: false,
|
HaveNodeAnnouncement: false,
|
||||||
}
|
}
|
||||||
err := r.cfg.Graph.AddLightningNode(node2)
|
err := r.cfg.Graph.AddLightningNode(node2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Errorf("unable to add node %v to"+
|
return errors.Errorf("unable to add node %v to"+
|
||||||
" the graph: %v",
|
" the graph: %v", node2.PubKeyBytes, err)
|
||||||
node2.PubKey.SerializeCompressed(), err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -911,8 +938,7 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
// edge bitcoin keys and channel value corresponds to the
|
// edge bitcoin keys and channel value corresponds to the
|
||||||
// reality.
|
// reality.
|
||||||
_, witnessOutput, err := lnwallet.GenFundingPkScript(
|
_, witnessOutput, err := lnwallet.GenFundingPkScript(
|
||||||
msg.BitcoinKey1.SerializeCompressed(),
|
msg.BitcoinKey1Bytes[:], msg.BitcoinKey2Bytes[:],
|
||||||
msg.BitcoinKey2.SerializeCompressed(),
|
|
||||||
chanUtxo.Value,
|
chanUtxo.Value,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -942,8 +968,7 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
log.Infof("New channel discovered! Link "+
|
log.Infof("New channel discovered! Link "+
|
||||||
"connects %x and %x with ChannelPoint(%v): "+
|
"connects %x and %x with ChannelPoint(%v): "+
|
||||||
"chan_id=%v, capacity=%v",
|
"chan_id=%v, capacity=%v",
|
||||||
msg.NodeKey1.SerializeCompressed(),
|
msg.NodeKey1Bytes, msg.NodeKey2Bytes,
|
||||||
msg.NodeKey2.SerializeCompressed(),
|
|
||||||
fundingPoint, msg.ChannelID, msg.Capacity)
|
fundingPoint, msg.ChannelID, msg.Capacity)
|
||||||
|
|
||||||
// As a new edge has been added to the channel graph, we'll
|
// As a new edge has been added to the channel graph, we'll
|
||||||
@ -960,6 +985,16 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case *channeldb.ChannelEdgePolicy:
|
case *channeldb.ChannelEdgePolicy:
|
||||||
|
// If we recently rejected this channel edge, then we won't
|
||||||
|
// attempt to re-process it.
|
||||||
|
r.rejectMtx.RLock()
|
||||||
|
if _, ok := r.rejectCache[msg.ChannelID]; ok {
|
||||||
|
r.rejectMtx.RUnlock()
|
||||||
|
return newErrf(ErrIgnored, "recently rejected "+
|
||||||
|
"chan_id=%v", msg.ChannelID)
|
||||||
|
}
|
||||||
|
r.rejectMtx.RUnlock()
|
||||||
|
|
||||||
channelID := lnwire.NewShortChanIDFromInt(msg.ChannelID)
|
channelID := lnwire.NewShortChanIDFromInt(msg.ChannelID)
|
||||||
|
|
||||||
// We make sure to hold the mutex for this channel ID,
|
// We make sure to hold the mutex for this channel ID,
|
||||||
@ -1183,7 +1218,8 @@ func (r *ChannelRouter) FindRoutes(target *btcec.PublicKey,
|
|||||||
|
|
||||||
// We can short circuit the routing by opportunistically checking to
|
// We can short circuit the routing by opportunistically checking to
|
||||||
// see if the target vertex event exists in the current graph.
|
// see if the target vertex event exists in the current graph.
|
||||||
if _, exists, err := r.cfg.Graph.HasLightningNode(target); err != nil {
|
targetVertex := NewVertex(target)
|
||||||
|
if _, exists, err := r.cfg.Graph.HasLightningNode(targetVertex); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if !exists {
|
} else if !exists {
|
||||||
log.Debugf("Target %x is not in known graph", dest)
|
log.Debugf("Target %x is not in known graph", dest)
|
||||||
@ -1221,7 +1257,7 @@ func (r *ChannelRouter) FindRoutes(target *btcec.PublicKey,
|
|||||||
// aren't able to support the total satoshis flow once fees have been
|
// aren't able to support the total satoshis flow once fees have been
|
||||||
// factored in.
|
// factored in.
|
||||||
validRoutes := make([]*Route, 0, len(shortestPaths))
|
validRoutes := make([]*Route, 0, len(shortestPaths))
|
||||||
sourceVertex := NewVertex(r.selfNode.PubKey)
|
sourceVertex := Vertex(r.selfNode.PubKeyBytes)
|
||||||
for _, path := range shortestPaths {
|
for _, path := range shortestPaths {
|
||||||
// Attempt to make the path into a route. We snip off the first
|
// Attempt to make the path into a route. We snip off the first
|
||||||
// hop in the path as it contains a "self-hop" that is inserted
|
// hop in the path as it contains a "self-hop" that is inserted
|
||||||
@ -1289,10 +1325,14 @@ func generateSphinxPacket(route *Route, paymentHash []byte) ([]byte,
|
|||||||
// We create a new instance of the public key to avoid possibly
|
// We create a new instance of the public key to avoid possibly
|
||||||
// mutating the curve parameters, which are unset in a higher
|
// mutating the curve parameters, which are unset in a higher
|
||||||
// level in order to avoid spamming the logs.
|
// level in order to avoid spamming the logs.
|
||||||
|
nodePub, err := hop.Channel.Node.PubKey()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
pub := btcec.PublicKey{
|
pub := btcec.PublicKey{
|
||||||
Curve: btcec.S256(),
|
Curve: btcec.S256(),
|
||||||
X: hop.Channel.Node.PubKey.X,
|
X: nodePub.X,
|
||||||
Y: hop.Channel.Node.PubKey.Y,
|
Y: nodePub.Y,
|
||||||
}
|
}
|
||||||
nodes[i] = &pub
|
nodes[i] = &pub
|
||||||
}
|
}
|
||||||
@ -1453,7 +1493,7 @@ func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte, *Route
|
|||||||
// Attempt to send this payment through the network to complete
|
// Attempt to send this payment through the network to complete
|
||||||
// the payment. If this attempt fails, then we'll continue on
|
// the payment. If this attempt fails, then we'll continue on
|
||||||
// to the next available route.
|
// to the next available route.
|
||||||
firstHop := route.Hops[0].Channel.Node.PubKey
|
firstHop := route.Hops[0].Channel.Node.PubKeyBytes
|
||||||
preImage, sendError = r.cfg.SendToSwitch(firstHop, htlcAdd,
|
preImage, sendError = r.cfg.SendToSwitch(firstHop, htlcAdd,
|
||||||
circuit)
|
circuit)
|
||||||
if sendError != nil {
|
if sendError != nil {
|
||||||
@ -1693,7 +1733,7 @@ func (r *ChannelRouter) applyChannelUpdate(msg *lnwire.ChannelUpdate) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := r.UpdateEdge(&channeldb.ChannelEdgePolicy{
|
err := r.UpdateEdge(&channeldb.ChannelEdgePolicy{
|
||||||
Signature: msg.Signature,
|
SigBytes: msg.Signature.ToSignatureBytes(),
|
||||||
ChannelID: msg.ShortChannelID.ToUint64(),
|
ChannelID: msg.ShortChannelID.ToUint64(),
|
||||||
LastUpdate: time.Unix(int64(msg.Timestamp), 0),
|
LastUpdate: time.Unix(int64(msg.Timestamp), 0),
|
||||||
Flags: msg.Flags,
|
Flags: msg.Flags,
|
||||||
|
@ -42,7 +42,7 @@ func (c *testCtx) RestartRouter() error {
|
|||||||
Graph: c.graph,
|
Graph: c.graph,
|
||||||
Chain: c.chain,
|
Chain: c.chain,
|
||||||
ChainView: c.chainView,
|
ChainView: c.chainView,
|
||||||
SendToSwitch: func(_ *btcec.PublicKey,
|
SendToSwitch: func(_ [33]byte,
|
||||||
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
||||||
return [32]byte{}, nil
|
return [32]byte{}, nil
|
||||||
},
|
},
|
||||||
@ -117,8 +117,9 @@ func createTestCtx(startingHeight uint32, testGraph ...string) (*testCtx, func()
|
|||||||
Graph: graph,
|
Graph: graph,
|
||||||
Chain: chain,
|
Chain: chain,
|
||||||
ChainView: chainView,
|
ChainView: chainView,
|
||||||
SendToSwitch: func(_ *btcec.PublicKey,
|
SendToSwitch: func(_ [33]byte, _ *lnwire.UpdateAddHTLC,
|
||||||
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
_ *sphinx.Circuit) ([32]byte, error) {
|
||||||
|
|
||||||
return [32]byte{}, nil
|
return [32]byte{}, nil
|
||||||
},
|
},
|
||||||
ChannelPruneExpiry: time.Hour * 24,
|
ChannelPruneExpiry: time.Hour * 24,
|
||||||
@ -230,12 +231,16 @@ func TestSendPaymentRouteFailureFallback(t *testing.T) {
|
|||||||
// router's configuration to ignore the path that has luo ji as the
|
// router's configuration to ignore the path that has luo ji as the
|
||||||
// first hop. This should force the router to instead take the
|
// first hop. This should force the router to instead take the
|
||||||
// available two hop path (through satoshi).
|
// available two hop path (through satoshi).
|
||||||
ctx.router.cfg.SendToSwitch = func(n *btcec.PublicKey,
|
ctx.router.cfg.SendToSwitch = func(n [33]byte,
|
||||||
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
||||||
|
|
||||||
if ctx.aliases["luoji"].IsEqual(n) {
|
if bytes.Equal(ctx.aliases["luoji"].SerializeCompressed(), n[:]) {
|
||||||
|
pub, err := sourceNode.PubKey()
|
||||||
|
if err != nil {
|
||||||
|
return preImage, err
|
||||||
|
}
|
||||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||||
ErrorSource: sourceNode.PubKey,
|
ErrorSource: pub,
|
||||||
// TODO(roasbeef): temp node failure should be?
|
// TODO(roasbeef): temp node failure should be?
|
||||||
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
||||||
}
|
}
|
||||||
@ -301,21 +306,26 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
|
|||||||
t.Fatalf("unable to fetch source node: %v", err)
|
t.Fatalf("unable to fetch source node: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sourcePub, err := sourceNode.PubKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to fetch source node pub: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// First, we'll modify the SendToSwitch method to return an error
|
// First, we'll modify the SendToSwitch method to return an error
|
||||||
// indicating that the channel from roasbeef to luoji is not operable
|
// indicating that the channel from roasbeef to luoji is not operable
|
||||||
// with an UnknownNextPeer.
|
// with an UnknownNextPeer.
|
||||||
//
|
//
|
||||||
// TODO(roasbeef): filtering should be intelligent enough so just not
|
// TODO(roasbeef): filtering should be intelligent enough so just not
|
||||||
// go through satoshi at all at this point.
|
// go through satoshi at all at this point.
|
||||||
ctx.router.cfg.SendToSwitch = func(n *btcec.PublicKey,
|
ctx.router.cfg.SendToSwitch = func(n [33]byte,
|
||||||
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
||||||
|
|
||||||
if ctx.aliases["luoji"].IsEqual(n) {
|
if bytes.Equal(ctx.aliases["luoji"].SerializeCompressed(), n[:]) {
|
||||||
// We'll first simulate an error from the first
|
// We'll first simulate an error from the first
|
||||||
// outgoing link to simulate the channel from luo ji to
|
// outgoing link to simulate the channel from luo ji to
|
||||||
// roasbeef not having enough capacity.
|
// roasbeef not having enough capacity.
|
||||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||||
ErrorSource: sourceNode.PubKey,
|
ErrorSource: sourcePub,
|
||||||
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -323,7 +333,7 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
|
|||||||
// Next, we'll create an error from satoshi to indicate
|
// Next, we'll create an error from satoshi to indicate
|
||||||
// that the luoji node is not longer online, which should
|
// that the luoji node is not longer online, which should
|
||||||
// prune out the rest of the routes.
|
// prune out the rest of the routes.
|
||||||
if ctx.aliases["satoshi"].IsEqual(n) {
|
if bytes.Equal(ctx.aliases["satoshi"].SerializeCompressed(), n[:]) {
|
||||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||||
ErrorSource: ctx.aliases["satoshi"],
|
ErrorSource: ctx.aliases["satoshi"],
|
||||||
FailureMessage: &lnwire.FailUnknownNextPeer{},
|
FailureMessage: &lnwire.FailUnknownNextPeer{},
|
||||||
@ -353,12 +363,12 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
|
|||||||
// Next, we'll modify the SendToSwitch method to indicate that luo ji
|
// Next, we'll modify the SendToSwitch method to indicate that luo ji
|
||||||
// wasn't originally online. This should also halt the send all
|
// wasn't originally online. This should also halt the send all
|
||||||
// together as all paths contain luoji and he can't be reached.
|
// together as all paths contain luoji and he can't be reached.
|
||||||
ctx.router.cfg.SendToSwitch = func(n *btcec.PublicKey,
|
ctx.router.cfg.SendToSwitch = func(n [33]byte,
|
||||||
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
||||||
|
|
||||||
if ctx.aliases["luoji"].IsEqual(n) {
|
if bytes.Equal(ctx.aliases["luoji"].SerializeCompressed(), n[:]) {
|
||||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||||
ErrorSource: sourceNode.PubKey,
|
ErrorSource: sourcePub,
|
||||||
FailureMessage: &lnwire.FailUnknownNextPeer{},
|
FailureMessage: &lnwire.FailUnknownNextPeer{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -380,14 +390,14 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
|
|||||||
|
|
||||||
// Finally, we'll modify the SendToSwitch function to indicate that the
|
// Finally, we'll modify the SendToSwitch function to indicate that the
|
||||||
// roasbeef -> luoji channel has insufficient capacity.
|
// roasbeef -> luoji channel has insufficient capacity.
|
||||||
ctx.router.cfg.SendToSwitch = func(n *btcec.PublicKey,
|
ctx.router.cfg.SendToSwitch = func(n [33]byte,
|
||||||
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
||||||
if ctx.aliases["luoji"].IsEqual(n) {
|
if bytes.Equal(ctx.aliases["luoji"].SerializeCompressed(), n[:]) {
|
||||||
// We'll first simulate an error from the first
|
// We'll first simulate an error from the first
|
||||||
// outgoing link to simulate the channel from luo ji to
|
// outgoing link to simulate the channel from luo ji to
|
||||||
// roasbeef not having enough capacity.
|
// roasbeef not having enough capacity.
|
||||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||||
ErrorSource: sourceNode.PubKey,
|
ErrorSource: sourcePub,
|
||||||
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
FailureMessage: &lnwire.FailTemporaryChannelFailure{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -458,12 +468,12 @@ func TestAddProof(t *testing.T) {
|
|||||||
// After utxo was recreated adding the edge without the proof.
|
// After utxo was recreated adding the edge without the proof.
|
||||||
edge := &channeldb.ChannelEdgeInfo{
|
edge := &channeldb.ChannelEdgeInfo{
|
||||||
ChannelID: chanID.ToUint64(),
|
ChannelID: chanID.ToUint64(),
|
||||||
NodeKey1: copyPubKey(node1.PubKey),
|
NodeKey1Bytes: node1.PubKeyBytes,
|
||||||
NodeKey2: copyPubKey(node2.PubKey),
|
NodeKey2Bytes: node2.PubKeyBytes,
|
||||||
BitcoinKey1: copyPubKey(bitcoinKey1),
|
|
||||||
BitcoinKey2: copyPubKey(bitcoinKey2),
|
|
||||||
AuthProof: nil,
|
AuthProof: nil,
|
||||||
}
|
}
|
||||||
|
copy(edge.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed())
|
||||||
|
copy(edge.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed())
|
||||||
|
|
||||||
if err := ctx.router.AddEdge(edge); err != nil {
|
if err := ctx.router.AddEdge(edge); err != nil {
|
||||||
t.Fatalf("unable to add edge: %v", err)
|
t.Fatalf("unable to add edge: %v", err)
|
||||||
@ -495,16 +505,17 @@ func TestIgnoreNodeAnnouncement(t *testing.T) {
|
|||||||
t.Fatalf("unable to create router: %v", err)
|
t.Fatalf("unable to create router: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub := priv1.PubKey()
|
||||||
node := &channeldb.LightningNode{
|
node := &channeldb.LightningNode{
|
||||||
HaveNodeAnnouncement: true,
|
HaveNodeAnnouncement: true,
|
||||||
LastUpdate: time.Unix(123, 0),
|
LastUpdate: time.Unix(123, 0),
|
||||||
Addresses: testAddrs,
|
Addresses: testAddrs,
|
||||||
PubKey: copyPubKey(priv1.PubKey()),
|
|
||||||
Color: color.RGBA{1, 2, 3, 0},
|
Color: color.RGBA{1, 2, 3, 0},
|
||||||
Alias: "node11",
|
Alias: "node11",
|
||||||
AuthSig: testSig,
|
AuthSigBytes: testSig.Serialize(),
|
||||||
Features: testFeatures,
|
Features: testFeatures,
|
||||||
}
|
}
|
||||||
|
copy(node.PubKeyBytes[:], pub.SerializeCompressed())
|
||||||
|
|
||||||
err = ctx.router.AddNode(node)
|
err = ctx.router.AddNode(node)
|
||||||
if !IsError(err, ErrIgnored) {
|
if !IsError(err, ErrIgnored) {
|
||||||
@ -527,15 +538,21 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
|
|||||||
t.Fatalf("unable to create router: %v", err)
|
t.Fatalf("unable to create router: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var pub1 [33]byte
|
||||||
|
copy(pub1[:], priv1.PubKey().SerializeCompressed())
|
||||||
|
|
||||||
|
var pub2 [33]byte
|
||||||
|
copy(pub2[:], priv2.PubKey().SerializeCompressed())
|
||||||
|
|
||||||
// The two nodes we are about to add should not exist yet.
|
// The two nodes we are about to add should not exist yet.
|
||||||
_, exists1, err := ctx.graph.HasLightningNode(priv1.PubKey())
|
_, exists1, err := ctx.graph.HasLightningNode(pub1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to query graph: %v", err)
|
t.Fatalf("unable to query graph: %v", err)
|
||||||
}
|
}
|
||||||
if exists1 {
|
if exists1 {
|
||||||
t.Fatalf("node already existed")
|
t.Fatalf("node already existed")
|
||||||
}
|
}
|
||||||
_, exists2, err := ctx.graph.HasLightningNode(priv2.PubKey())
|
_, exists2, err := ctx.graph.HasLightningNode(pub2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to query graph: %v", err)
|
t.Fatalf("unable to query graph: %v", err)
|
||||||
}
|
}
|
||||||
@ -559,10 +576,10 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
|
|||||||
|
|
||||||
edge := &channeldb.ChannelEdgeInfo{
|
edge := &channeldb.ChannelEdgeInfo{
|
||||||
ChannelID: chanID.ToUint64(),
|
ChannelID: chanID.ToUint64(),
|
||||||
NodeKey1: copyPubKey(priv1.PubKey()),
|
NodeKey1Bytes: pub1,
|
||||||
NodeKey2: copyPubKey(priv2.PubKey()),
|
NodeKey2Bytes: pub2,
|
||||||
BitcoinKey1: copyPubKey(bitcoinKey1),
|
BitcoinKey1Bytes: pub1,
|
||||||
BitcoinKey2: copyPubKey(bitcoinKey2),
|
BitcoinKey2Bytes: pub2,
|
||||||
AuthProof: nil,
|
AuthProof: nil,
|
||||||
}
|
}
|
||||||
if err := ctx.router.AddEdge(edge); err != nil {
|
if err := ctx.router.AddEdge(edge); err != nil {
|
||||||
@ -573,7 +590,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
|
|||||||
// We must add the edge policy to be able to use the edge for route
|
// We must add the edge policy to be able to use the edge for route
|
||||||
// finding.
|
// finding.
|
||||||
edgePolicy := &channeldb.ChannelEdgePolicy{
|
edgePolicy := &channeldb.ChannelEdgePolicy{
|
||||||
Signature: testSig,
|
SigBytes: testSig.Serialize(),
|
||||||
ChannelID: edge.ChannelID,
|
ChannelID: edge.ChannelID,
|
||||||
LastUpdate: time.Now(),
|
LastUpdate: time.Now(),
|
||||||
TimeLockDelta: 10,
|
TimeLockDelta: 10,
|
||||||
@ -589,7 +606,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
|
|||||||
|
|
||||||
// Create edge in the other direction as well.
|
// Create edge in the other direction as well.
|
||||||
edgePolicy = &channeldb.ChannelEdgePolicy{
|
edgePolicy = &channeldb.ChannelEdgePolicy{
|
||||||
Signature: testSig,
|
SigBytes: testSig.Serialize(),
|
||||||
ChannelID: edge.ChannelID,
|
ChannelID: edge.ChannelID,
|
||||||
LastUpdate: time.Now(),
|
LastUpdate: time.Now(),
|
||||||
TimeLockDelta: 10,
|
TimeLockDelta: 10,
|
||||||
@ -605,14 +622,14 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
|
|||||||
|
|
||||||
// After adding the edge between the two previously unknown nodes, they
|
// After adding the edge between the two previously unknown nodes, they
|
||||||
// should have been added to the graph.
|
// should have been added to the graph.
|
||||||
_, exists1, err = ctx.graph.HasLightningNode(priv1.PubKey())
|
_, exists1, err = ctx.graph.HasLightningNode(pub1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to query graph: %v", err)
|
t.Fatalf("unable to query graph: %v", err)
|
||||||
}
|
}
|
||||||
if !exists1 {
|
if !exists1 {
|
||||||
t.Fatalf("node1 was not added to the graph")
|
t.Fatalf("node1 was not added to the graph")
|
||||||
}
|
}
|
||||||
_, exists2, err = ctx.graph.HasLightningNode(priv2.PubKey())
|
_, exists2, err = ctx.graph.HasLightningNode(pub2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to query graph: %v", err)
|
t.Fatalf("unable to query graph: %v", err)
|
||||||
}
|
}
|
||||||
@ -657,19 +674,19 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
|
|||||||
|
|
||||||
edge = &channeldb.ChannelEdgeInfo{
|
edge = &channeldb.ChannelEdgeInfo{
|
||||||
ChannelID: chanID.ToUint64(),
|
ChannelID: chanID.ToUint64(),
|
||||||
NodeKey1: pubKey1,
|
|
||||||
NodeKey2: pubKey2,
|
|
||||||
BitcoinKey1: pubKey1,
|
|
||||||
BitcoinKey2: pubKey2,
|
|
||||||
AuthProof: nil,
|
AuthProof: nil,
|
||||||
}
|
}
|
||||||
|
copy(edge.NodeKey1Bytes[:], node1Bytes)
|
||||||
|
copy(edge.NodeKey2Bytes[:], node2Bytes)
|
||||||
|
copy(edge.BitcoinKey1Bytes[:], node1Bytes)
|
||||||
|
copy(edge.BitcoinKey2Bytes[:], node2Bytes)
|
||||||
|
|
||||||
if err := ctx.router.AddEdge(edge); err != nil {
|
if err := ctx.router.AddEdge(edge); err != nil {
|
||||||
t.Fatalf("unable to add edge to the channel graph: %v.", err)
|
t.Fatalf("unable to add edge to the channel graph: %v.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
edgePolicy = &channeldb.ChannelEdgePolicy{
|
edgePolicy = &channeldb.ChannelEdgePolicy{
|
||||||
Signature: testSig,
|
SigBytes: testSig.Serialize(),
|
||||||
ChannelID: edge.ChannelID,
|
ChannelID: edge.ChannelID,
|
||||||
LastUpdate: time.Now(),
|
LastUpdate: time.Now(),
|
||||||
TimeLockDelta: 10,
|
TimeLockDelta: 10,
|
||||||
@ -684,7 +701,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
edgePolicy = &channeldb.ChannelEdgePolicy{
|
edgePolicy = &channeldb.ChannelEdgePolicy{
|
||||||
Signature: testSig,
|
SigBytes: testSig.Serialize(),
|
||||||
ChannelID: edge.ChannelID,
|
ChannelID: edge.ChannelID,
|
||||||
LastUpdate: time.Now(),
|
LastUpdate: time.Now(),
|
||||||
TimeLockDelta: 10,
|
TimeLockDelta: 10,
|
||||||
@ -716,12 +733,12 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
|
|||||||
HaveNodeAnnouncement: true,
|
HaveNodeAnnouncement: true,
|
||||||
LastUpdate: time.Unix(123, 0),
|
LastUpdate: time.Unix(123, 0),
|
||||||
Addresses: testAddrs,
|
Addresses: testAddrs,
|
||||||
PubKey: copyPubKey(priv1.PubKey()),
|
|
||||||
Color: color.RGBA{1, 2, 3, 0},
|
Color: color.RGBA{1, 2, 3, 0},
|
||||||
Alias: "node11",
|
Alias: "node11",
|
||||||
AuthSig: testSig,
|
AuthSigBytes: testSig.Serialize(),
|
||||||
Features: testFeatures,
|
Features: testFeatures,
|
||||||
}
|
}
|
||||||
|
copy(n1.PubKeyBytes[:], priv1.PubKey().SerializeCompressed())
|
||||||
|
|
||||||
if err := ctx.router.AddNode(n1); err != nil {
|
if err := ctx.router.AddNode(n1); err != nil {
|
||||||
t.Fatalf("could not add node: %v", err)
|
t.Fatalf("could not add node: %v", err)
|
||||||
@ -731,12 +748,12 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
|
|||||||
HaveNodeAnnouncement: true,
|
HaveNodeAnnouncement: true,
|
||||||
LastUpdate: time.Unix(123, 0),
|
LastUpdate: time.Unix(123, 0),
|
||||||
Addresses: testAddrs,
|
Addresses: testAddrs,
|
||||||
PubKey: copyPubKey(priv2.PubKey()),
|
|
||||||
Color: color.RGBA{1, 2, 3, 0},
|
Color: color.RGBA{1, 2, 3, 0},
|
||||||
Alias: "node22",
|
Alias: "node22",
|
||||||
AuthSig: testSig,
|
AuthSigBytes: testSig.Serialize(),
|
||||||
Features: testFeatures,
|
Features: testFeatures,
|
||||||
}
|
}
|
||||||
|
copy(n2.PubKeyBytes[:], priv2.PubKey().SerializeCompressed())
|
||||||
|
|
||||||
if err := ctx.router.AddNode(n2); err != nil {
|
if err := ctx.router.AddNode(n2); err != nil {
|
||||||
t.Fatalf("could not add node: %v", err)
|
t.Fatalf("could not add node: %v", err)
|
||||||
@ -866,17 +883,17 @@ func TestWakeUpOnStaleBranch(t *testing.T) {
|
|||||||
|
|
||||||
edge1 := &channeldb.ChannelEdgeInfo{
|
edge1 := &channeldb.ChannelEdgeInfo{
|
||||||
ChannelID: chanID1,
|
ChannelID: chanID1,
|
||||||
NodeKey1: copyPubKey(node1.PubKey),
|
NodeKey1Bytes: node1.PubKeyBytes,
|
||||||
NodeKey2: copyPubKey(node2.PubKey),
|
NodeKey2Bytes: node2.PubKeyBytes,
|
||||||
BitcoinKey1: copyPubKey(bitcoinKey1),
|
|
||||||
BitcoinKey2: copyPubKey(bitcoinKey2),
|
|
||||||
AuthProof: &channeldb.ChannelAuthProof{
|
AuthProof: &channeldb.ChannelAuthProof{
|
||||||
NodeSig1: testSig,
|
NodeSig1Bytes: testSig.Serialize(),
|
||||||
NodeSig2: testSig,
|
NodeSig2Bytes: testSig.Serialize(),
|
||||||
BitcoinSig1: testSig,
|
BitcoinSig1Bytes: testSig.Serialize(),
|
||||||
BitcoinSig2: testSig,
|
BitcoinSig2Bytes: testSig.Serialize(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
copy(edge1.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed())
|
||||||
|
copy(edge1.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed())
|
||||||
|
|
||||||
if err := ctx.router.AddEdge(edge1); err != nil {
|
if err := ctx.router.AddEdge(edge1); err != nil {
|
||||||
t.Fatalf("unable to add edge: %v", err)
|
t.Fatalf("unable to add edge: %v", err)
|
||||||
@ -884,17 +901,17 @@ func TestWakeUpOnStaleBranch(t *testing.T) {
|
|||||||
|
|
||||||
edge2 := &channeldb.ChannelEdgeInfo{
|
edge2 := &channeldb.ChannelEdgeInfo{
|
||||||
ChannelID: chanID2,
|
ChannelID: chanID2,
|
||||||
NodeKey1: copyPubKey(node1.PubKey),
|
NodeKey1Bytes: node1.PubKeyBytes,
|
||||||
NodeKey2: copyPubKey(node2.PubKey),
|
NodeKey2Bytes: node2.PubKeyBytes,
|
||||||
BitcoinKey1: copyPubKey(bitcoinKey1),
|
|
||||||
BitcoinKey2: copyPubKey(bitcoinKey2),
|
|
||||||
AuthProof: &channeldb.ChannelAuthProof{
|
AuthProof: &channeldb.ChannelAuthProof{
|
||||||
NodeSig1: testSig,
|
NodeSig1Bytes: testSig.Serialize(),
|
||||||
NodeSig2: testSig,
|
NodeSig2Bytes: testSig.Serialize(),
|
||||||
BitcoinSig1: testSig,
|
BitcoinSig1Bytes: testSig.Serialize(),
|
||||||
BitcoinSig2: testSig,
|
BitcoinSig2Bytes: testSig.Serialize(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
copy(edge2.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed())
|
||||||
|
copy(edge2.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed())
|
||||||
|
|
||||||
if err := ctx.router.AddEdge(edge2); err != nil {
|
if err := ctx.router.AddEdge(edge2); err != nil {
|
||||||
t.Fatalf("unable to add edge: %v", err)
|
t.Fatalf("unable to add edge: %v", err)
|
||||||
@ -940,7 +957,7 @@ func TestWakeUpOnStaleBranch(t *testing.T) {
|
|||||||
Graph: ctx.graph,
|
Graph: ctx.graph,
|
||||||
Chain: ctx.chain,
|
Chain: ctx.chain,
|
||||||
ChainView: ctx.chainView,
|
ChainView: ctx.chainView,
|
||||||
SendToSwitch: func(_ *btcec.PublicKey,
|
SendToSwitch: func(_ [33]byte,
|
||||||
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
||||||
return [32]byte{}, nil
|
return [32]byte{}, nil
|
||||||
},
|
},
|
||||||
@ -1068,17 +1085,19 @@ func TestDisconnectedBlocks(t *testing.T) {
|
|||||||
|
|
||||||
edge1 := &channeldb.ChannelEdgeInfo{
|
edge1 := &channeldb.ChannelEdgeInfo{
|
||||||
ChannelID: chanID1,
|
ChannelID: chanID1,
|
||||||
NodeKey1: copyPubKey(node1.PubKey),
|
NodeKey1Bytes: node1.PubKeyBytes,
|
||||||
NodeKey2: copyPubKey(node2.PubKey),
|
NodeKey2Bytes: node2.PubKeyBytes,
|
||||||
BitcoinKey1: copyPubKey(bitcoinKey1),
|
BitcoinKey1Bytes: node1.PubKeyBytes,
|
||||||
BitcoinKey2: copyPubKey(bitcoinKey2),
|
BitcoinKey2Bytes: node2.PubKeyBytes,
|
||||||
AuthProof: &channeldb.ChannelAuthProof{
|
AuthProof: &channeldb.ChannelAuthProof{
|
||||||
NodeSig1: testSig,
|
NodeSig1Bytes: testSig.Serialize(),
|
||||||
NodeSig2: testSig,
|
NodeSig2Bytes: testSig.Serialize(),
|
||||||
BitcoinSig1: testSig,
|
BitcoinSig1Bytes: testSig.Serialize(),
|
||||||
BitcoinSig2: testSig,
|
BitcoinSig2Bytes: testSig.Serialize(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
copy(edge1.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed())
|
||||||
|
copy(edge1.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed())
|
||||||
|
|
||||||
if err := ctx.router.AddEdge(edge1); err != nil {
|
if err := ctx.router.AddEdge(edge1); err != nil {
|
||||||
t.Fatalf("unable to add edge: %v", err)
|
t.Fatalf("unable to add edge: %v", err)
|
||||||
@ -1086,17 +1105,19 @@ func TestDisconnectedBlocks(t *testing.T) {
|
|||||||
|
|
||||||
edge2 := &channeldb.ChannelEdgeInfo{
|
edge2 := &channeldb.ChannelEdgeInfo{
|
||||||
ChannelID: chanID2,
|
ChannelID: chanID2,
|
||||||
NodeKey1: copyPubKey(node1.PubKey),
|
NodeKey1Bytes: node1.PubKeyBytes,
|
||||||
NodeKey2: copyPubKey(node2.PubKey),
|
NodeKey2Bytes: node2.PubKeyBytes,
|
||||||
BitcoinKey1: copyPubKey(bitcoinKey1),
|
BitcoinKey1Bytes: node1.PubKeyBytes,
|
||||||
BitcoinKey2: copyPubKey(bitcoinKey2),
|
BitcoinKey2Bytes: node2.PubKeyBytes,
|
||||||
AuthProof: &channeldb.ChannelAuthProof{
|
AuthProof: &channeldb.ChannelAuthProof{
|
||||||
NodeSig1: testSig,
|
NodeSig1Bytes: testSig.Serialize(),
|
||||||
NodeSig2: testSig,
|
NodeSig2Bytes: testSig.Serialize(),
|
||||||
BitcoinSig1: testSig,
|
BitcoinSig1Bytes: testSig.Serialize(),
|
||||||
BitcoinSig2: testSig,
|
BitcoinSig2Bytes: testSig.Serialize(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
copy(edge2.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed())
|
||||||
|
copy(edge2.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed())
|
||||||
|
|
||||||
if err := ctx.router.AddEdge(edge2); err != nil {
|
if err := ctx.router.AddEdge(edge2); err != nil {
|
||||||
t.Fatalf("unable to add edge: %v", err)
|
t.Fatalf("unable to add edge: %v", err)
|
||||||
@ -1208,17 +1229,17 @@ func TestRouterChansClosedOfflinePruneGraph(t *testing.T) {
|
|||||||
}
|
}
|
||||||
edge1 := &channeldb.ChannelEdgeInfo{
|
edge1 := &channeldb.ChannelEdgeInfo{
|
||||||
ChannelID: chanID1.ToUint64(),
|
ChannelID: chanID1.ToUint64(),
|
||||||
NodeKey1: copyPubKey(node1.PubKey),
|
NodeKey1Bytes: node1.PubKeyBytes,
|
||||||
NodeKey2: copyPubKey(node2.PubKey),
|
NodeKey2Bytes: node2.PubKeyBytes,
|
||||||
BitcoinKey1: copyPubKey(bitcoinKey1),
|
|
||||||
BitcoinKey2: copyPubKey(bitcoinKey2),
|
|
||||||
AuthProof: &channeldb.ChannelAuthProof{
|
AuthProof: &channeldb.ChannelAuthProof{
|
||||||
NodeSig1: testSig,
|
NodeSig1Bytes: testSig.Serialize(),
|
||||||
NodeSig2: testSig,
|
NodeSig2Bytes: testSig.Serialize(),
|
||||||
BitcoinSig1: testSig,
|
BitcoinSig1Bytes: testSig.Serialize(),
|
||||||
BitcoinSig2: testSig,
|
BitcoinSig2Bytes: testSig.Serialize(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
copy(edge1.BitcoinKey1Bytes[:], bitcoinKey1.SerializeCompressed())
|
||||||
|
copy(edge1.BitcoinKey2Bytes[:], bitcoinKey2.SerializeCompressed())
|
||||||
if err := ctx.router.AddEdge(edge1); err != nil {
|
if err := ctx.router.AddEdge(edge1); err != nil {
|
||||||
t.Fatalf("unable to add edge: %v", err)
|
t.Fatalf("unable to add edge: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -104,8 +104,8 @@ func (v *ValidationBarrier) InitJobDependencies(job interface{}) {
|
|||||||
v.chanAnnFinSignal[msg.ShortChannelID] = annFinCond
|
v.chanAnnFinSignal[msg.ShortChannelID] = annFinCond
|
||||||
v.chanEdgeDependencies[msg.ShortChannelID] = annFinCond
|
v.chanEdgeDependencies[msg.ShortChannelID] = annFinCond
|
||||||
|
|
||||||
v.nodeAnnDependencies[NewVertex(msg.NodeID1)] = annFinCond
|
v.nodeAnnDependencies[Vertex(msg.NodeID1)] = annFinCond
|
||||||
v.nodeAnnDependencies[NewVertex(msg.NodeID2)] = annFinCond
|
v.nodeAnnDependencies[Vertex(msg.NodeID2)] = annFinCond
|
||||||
}
|
}
|
||||||
case *channeldb.ChannelEdgeInfo:
|
case *channeldb.ChannelEdgeInfo:
|
||||||
|
|
||||||
@ -116,8 +116,8 @@ func (v *ValidationBarrier) InitJobDependencies(job interface{}) {
|
|||||||
v.chanAnnFinSignal[shortID] = annFinCond
|
v.chanAnnFinSignal[shortID] = annFinCond
|
||||||
v.chanEdgeDependencies[shortID] = annFinCond
|
v.chanEdgeDependencies[shortID] = annFinCond
|
||||||
|
|
||||||
v.nodeAnnDependencies[NewVertex(msg.NodeKey1)] = annFinCond
|
v.nodeAnnDependencies[Vertex(msg.NodeKey1Bytes)] = annFinCond
|
||||||
v.nodeAnnDependencies[NewVertex(msg.NodeKey2)] = annFinCond
|
v.nodeAnnDependencies[Vertex(msg.NodeKey2Bytes)] = annFinCond
|
||||||
}
|
}
|
||||||
|
|
||||||
// These other types don't have any dependants, so no further
|
// These other types don't have any dependants, so no further
|
||||||
@ -127,6 +127,7 @@ func (v *ValidationBarrier) InitJobDependencies(job interface{}) {
|
|||||||
case *lnwire.ChannelUpdate:
|
case *lnwire.ChannelUpdate:
|
||||||
return
|
return
|
||||||
case *lnwire.NodeAnnouncement:
|
case *lnwire.NodeAnnouncement:
|
||||||
|
// TODO(roasbeef): node ann needs to wait on existing channel updates
|
||||||
return
|
return
|
||||||
case *channeldb.LightningNode:
|
case *channeldb.LightningNode:
|
||||||
return
|
return
|
||||||
@ -167,12 +168,12 @@ func (v *ValidationBarrier) WaitForDependants(job interface{}) {
|
|||||||
shortID := lnwire.NewShortChanIDFromInt(msg.ChannelID)
|
shortID := lnwire.NewShortChanIDFromInt(msg.ChannelID)
|
||||||
signal, ok = v.chanEdgeDependencies[shortID]
|
signal, ok = v.chanEdgeDependencies[shortID]
|
||||||
case *channeldb.LightningNode:
|
case *channeldb.LightningNode:
|
||||||
vertex := NewVertex(msg.PubKey)
|
vertex := Vertex(msg.PubKeyBytes)
|
||||||
signal, ok = v.nodeAnnDependencies[vertex]
|
signal, ok = v.nodeAnnDependencies[vertex]
|
||||||
case *lnwire.ChannelUpdate:
|
case *lnwire.ChannelUpdate:
|
||||||
signal, ok = v.chanEdgeDependencies[msg.ShortChannelID]
|
signal, ok = v.chanEdgeDependencies[msg.ShortChannelID]
|
||||||
case *lnwire.NodeAnnouncement:
|
case *lnwire.NodeAnnouncement:
|
||||||
vertex := NewVertex(msg.NodeID)
|
vertex := Vertex(msg.NodeID)
|
||||||
signal, ok = v.nodeAnnDependencies[vertex]
|
signal, ok = v.nodeAnnDependencies[vertex]
|
||||||
|
|
||||||
// Other types of jobs can be executed immediately, so we'll just
|
// Other types of jobs can be executed immediately, so we'll just
|
||||||
@ -233,9 +234,9 @@ func (v *ValidationBarrier) SignalDependants(job interface{}) {
|
|||||||
// map, as if we reach this point, then all dependants have already
|
// map, as if we reach this point, then all dependants have already
|
||||||
// finished executing and we can proceed.
|
// finished executing and we can proceed.
|
||||||
case *channeldb.LightningNode:
|
case *channeldb.LightningNode:
|
||||||
delete(v.nodeAnnDependencies, NewVertex(msg.PubKey))
|
delete(v.nodeAnnDependencies, Vertex(msg.PubKeyBytes))
|
||||||
case *lnwire.NodeAnnouncement:
|
case *lnwire.NodeAnnouncement:
|
||||||
delete(v.nodeAnnDependencies, NewVertex(msg.NodeID))
|
delete(v.nodeAnnDependencies, Vertex(msg.NodeID))
|
||||||
case *lnwire.ChannelUpdate:
|
case *lnwire.ChannelUpdate:
|
||||||
delete(v.chanEdgeDependencies, msg.ShortChannelID)
|
delete(v.chanEdgeDependencies, msg.ShortChannelID)
|
||||||
case *channeldb.ChannelEdgePolicy:
|
case *channeldb.ChannelEdgePolicy:
|
||||||
|
15
rpcserver.go
15
rpcserver.go
@ -535,11 +535,14 @@ func (r *rpcServer) VerifyMessage(ctx context.Context,
|
|||||||
}
|
}
|
||||||
pubKeyHex := hex.EncodeToString(pubKey.SerializeCompressed())
|
pubKeyHex := hex.EncodeToString(pubKey.SerializeCompressed())
|
||||||
|
|
||||||
|
var pub [33]byte
|
||||||
|
copy(pub[:], pubKey.SerializeCompressed())
|
||||||
|
|
||||||
// Query the channel graph to ensure a node in the network with active
|
// Query the channel graph to ensure a node in the network with active
|
||||||
// channels signed the message.
|
// channels signed the message.
|
||||||
// TODO(phlip9): Require valid nodes to have capital in active channels.
|
// TODO(phlip9): Require valid nodes to have capital in active channels.
|
||||||
graph := r.server.chanDB.ChannelGraph()
|
graph := r.server.chanDB.ChannelGraph()
|
||||||
_, active, err := graph.HasLightningNode(pubKey)
|
_, active, err := graph.HasLightningNode(pub)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to query graph: %v", err)
|
return nil, fmt.Errorf("failed to query graph: %v", err)
|
||||||
}
|
}
|
||||||
@ -1576,8 +1579,8 @@ func (r *rpcServer) savePayment(route *routing.Route, amount lnwire.MilliSatoshi
|
|||||||
|
|
||||||
paymentPath := make([][33]byte, len(route.Hops))
|
paymentPath := make([][33]byte, len(route.Hops))
|
||||||
for i, hop := range route.Hops {
|
for i, hop := range route.Hops {
|
||||||
hopPub := hop.Channel.Node.PubKey.SerializeCompressed()
|
hopPub := hop.Channel.Node.PubKeyBytes
|
||||||
copy(paymentPath[i][:], hopPub)
|
copy(paymentPath[i][:], hopPub[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
payment := &channeldb.OutgoingPayment{
|
payment := &channeldb.OutgoingPayment{
|
||||||
@ -2407,7 +2410,7 @@ func (r *rpcServer) DescribeGraph(ctx context.Context,
|
|||||||
nodeColor := fmt.Sprintf("#%02x%02x%02x", node.Color.R, node.Color.G, node.Color.B)
|
nodeColor := fmt.Sprintf("#%02x%02x%02x", node.Color.R, node.Color.G, node.Color.B)
|
||||||
resp.Nodes = append(resp.Nodes, &lnrpc.LightningNode{
|
resp.Nodes = append(resp.Nodes, &lnrpc.LightningNode{
|
||||||
LastUpdate: uint32(node.LastUpdate.Unix()),
|
LastUpdate: uint32(node.LastUpdate.Unix()),
|
||||||
PubKey: hex.EncodeToString(node.PubKey.SerializeCompressed()),
|
PubKey: hex.EncodeToString(node.PubKeyBytes[:]),
|
||||||
Addresses: nodeAddrs,
|
Addresses: nodeAddrs,
|
||||||
Alias: node.Alias,
|
Alias: node.Alias,
|
||||||
Color: nodeColor,
|
Color: nodeColor,
|
||||||
@ -2455,8 +2458,8 @@ func marshalDbEdge(edgeInfo *channeldb.ChannelEdgeInfo,
|
|||||||
ChanPoint: edgeInfo.ChannelPoint.String(),
|
ChanPoint: edgeInfo.ChannelPoint.String(),
|
||||||
// TODO(roasbeef): update should be on edge info itself
|
// TODO(roasbeef): update should be on edge info itself
|
||||||
LastUpdate: uint32(lastUpdate),
|
LastUpdate: uint32(lastUpdate),
|
||||||
Node1Pub: hex.EncodeToString(edgeInfo.NodeKey1.SerializeCompressed()),
|
Node1Pub: hex.EncodeToString(edgeInfo.NodeKey1Bytes[:]),
|
||||||
Node2Pub: hex.EncodeToString(edgeInfo.NodeKey2.SerializeCompressed()),
|
Node2Pub: hex.EncodeToString(edgeInfo.NodeKey2Bytes[:]),
|
||||||
Capacity: int64(edgeInfo.Capacity),
|
Capacity: int64(edgeInfo.Capacity),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
45
server.go
45
server.go
@ -258,11 +258,11 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl,
|
|||||||
HaveNodeAnnouncement: true,
|
HaveNodeAnnouncement: true,
|
||||||
LastUpdate: time.Now(),
|
LastUpdate: time.Now(),
|
||||||
Addresses: selfAddrs,
|
Addresses: selfAddrs,
|
||||||
PubKey: privKey.PubKey(),
|
|
||||||
Alias: nodeAlias.String(),
|
Alias: nodeAlias.String(),
|
||||||
Features: s.globalFeatures,
|
Features: s.globalFeatures,
|
||||||
Color: color,
|
Color: color,
|
||||||
}
|
}
|
||||||
|
copy(selfNode.PubKeyBytes[:], privKey.PubKey().SerializeCompressed())
|
||||||
|
|
||||||
// If our information has changed since our last boot, then we'll
|
// If our information has changed since our last boot, then we'll
|
||||||
// re-sign our node announcement so a fresh authenticated version of it
|
// re-sign our node announcement so a fresh authenticated version of it
|
||||||
@ -272,31 +272,35 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl,
|
|||||||
nodeAnn := &lnwire.NodeAnnouncement{
|
nodeAnn := &lnwire.NodeAnnouncement{
|
||||||
Timestamp: uint32(selfNode.LastUpdate.Unix()),
|
Timestamp: uint32(selfNode.LastUpdate.Unix()),
|
||||||
Addresses: selfNode.Addresses,
|
Addresses: selfNode.Addresses,
|
||||||
NodeID: selfNode.PubKey,
|
NodeID: selfNode.PubKeyBytes,
|
||||||
Alias: nodeAlias,
|
Alias: nodeAlias,
|
||||||
Features: selfNode.Features.RawFeatureVector,
|
Features: selfNode.Features.RawFeatureVector,
|
||||||
RGBColor: color,
|
RGBColor: color,
|
||||||
}
|
}
|
||||||
selfNode.AuthSig, err = discovery.SignAnnouncement(s.nodeSigner,
|
authSig, err := discovery.SignAnnouncement(
|
||||||
s.identityPriv.PubKey(), nodeAnn,
|
s.nodeSigner, s.identityPriv.PubKey(), nodeAnn,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to generate signature for "+
|
return nil, fmt.Errorf("unable to generate signature for "+
|
||||||
"self node announcement: %v", err)
|
"self node announcement: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selfNode.AuthSigBytes = authSig.Serialize()
|
||||||
|
s.currentNodeAnn = nodeAnn
|
||||||
|
|
||||||
if err := chanGraph.SetSourceNode(selfNode); err != nil {
|
if err := chanGraph.SetSourceNode(selfNode); err != nil {
|
||||||
return nil, fmt.Errorf("can't set self node: %v", err)
|
return nil, fmt.Errorf("can't set self node: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeAnn.Signature = selfNode.AuthSig
|
nodeAnn.Signature, err = lnwire.NewSigFromRawSignature(selfNode.AuthSigBytes)
|
||||||
s.currentNodeAnn = nodeAnn
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
s.chanRouter, err = routing.New(routing.Config{
|
s.chanRouter, err = routing.New(routing.Config{
|
||||||
Graph: chanGraph,
|
Graph: chanGraph,
|
||||||
Chain: cc.chainIO,
|
Chain: cc.chainIO,
|
||||||
ChainView: cc.chainView,
|
ChainView: cc.chainView,
|
||||||
SendToSwitch: func(firstHop *btcec.PublicKey,
|
SendToSwitch: func(firstHopPub [33]byte,
|
||||||
htlcAdd *lnwire.UpdateAddHTLC,
|
htlcAdd *lnwire.UpdateAddHTLC,
|
||||||
circuit *sphinx.Circuit) ([32]byte, error) {
|
circuit *sphinx.Circuit) ([32]byte, error) {
|
||||||
|
|
||||||
@ -307,9 +311,6 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl,
|
|||||||
OnionErrorDecrypter: sphinx.NewOnionErrorDecrypter(circuit),
|
OnionErrorDecrypter: sphinx.NewOnionErrorDecrypter(circuit),
|
||||||
}
|
}
|
||||||
|
|
||||||
var firstHopPub [33]byte
|
|
||||||
copy(firstHopPub[:], firstHop.SerializeCompressed())
|
|
||||||
|
|
||||||
return s.htlcSwitch.SendHTLC(firstHopPub, htlcAdd, errorDecryptor)
|
return s.htlcSwitch.SendHTLC(firstHopPub, htlcAdd, errorDecryptor)
|
||||||
},
|
},
|
||||||
ChannelPruneExpiry: time.Duration(time.Hour * 24 * 14),
|
ChannelPruneExpiry: time.Duration(time.Hour * 24 * 14),
|
||||||
@ -806,11 +807,19 @@ func (s *server) genNodeAnnouncement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.currentNodeAnn.Timestamp = newStamp
|
s.currentNodeAnn.Timestamp = newStamp
|
||||||
s.currentNodeAnn.Signature, err = discovery.SignAnnouncement(
|
sig, err := discovery.SignAnnouncement(
|
||||||
s.nodeSigner, s.identityPriv.PubKey(), s.currentNodeAnn,
|
s.nodeSigner, s.identityPriv.PubKey(), s.currentNodeAnn,
|
||||||
)
|
)
|
||||||
|
if err != nil {
|
||||||
|
return lnwire.NodeAnnouncement{}, err
|
||||||
|
}
|
||||||
|
|
||||||
return *s.currentNodeAnn, err
|
s.currentNodeAnn.Signature, err = lnwire.NewSigFromSignature(sig)
|
||||||
|
if err != nil {
|
||||||
|
return lnwire.NodeAnnouncement{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return *s.currentNodeAnn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type nodeAddresses struct {
|
type nodeAddresses struct {
|
||||||
@ -870,7 +879,7 @@ func (s *server) establishPersistentConnections() error {
|
|||||||
_ *channeldb.ChannelEdgeInfo,
|
_ *channeldb.ChannelEdgeInfo,
|
||||||
policy, _ *channeldb.ChannelEdgePolicy) error {
|
policy, _ *channeldb.ChannelEdgePolicy) error {
|
||||||
|
|
||||||
pubStr := string(policy.Node.PubKey.SerializeCompressed())
|
pubStr := string(policy.Node.PubKeyBytes[:])
|
||||||
|
|
||||||
// Add addresses from channel graph/NodeAnnouncements to the
|
// Add addresses from channel graph/NodeAnnouncements to the
|
||||||
// list of addresses we'll connect to. If there are duplicates
|
// list of addresses we'll connect to. If there are duplicates
|
||||||
@ -906,11 +915,15 @@ func (s *server) establishPersistentConnections() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeAddrsMap[pubStr] = &nodeAddresses{
|
n := &nodeAddresses{
|
||||||
pubKey: policy.Node.PubKey,
|
|
||||||
addresses: addrs,
|
addresses: addrs,
|
||||||
}
|
}
|
||||||
|
n.pubKey, err = policy.Node.PubKey()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeAddrsMap[pubStr] = n
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil && err != channeldb.ErrGraphNoEdgesFound {
|
if err != nil && err != channeldb.ErrGraphNoEdgesFound {
|
||||||
|
@ -327,8 +327,8 @@ func Decode(invoice string) (*Invoice, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var sigBytes [64]byte
|
var sig lnwire.Sig
|
||||||
copy(sigBytes[:], sigBase256[:64])
|
copy(sig[:], sigBase256[:64])
|
||||||
recoveryID := sigBase256[64]
|
recoveryID := sigBase256[64]
|
||||||
|
|
||||||
// The signature is over the hrp + the data the invoice, encoded in
|
// The signature is over the hrp + the data the invoice, encoded in
|
||||||
@ -347,8 +347,7 @@ func Decode(invoice string) (*Invoice, error) {
|
|||||||
// If the destination pubkey was provided as a tagged field, use that
|
// If the destination pubkey was provided as a tagged field, use that
|
||||||
// to verify the signature, if not do public key recovery.
|
// to verify the signature, if not do public key recovery.
|
||||||
if decodedInvoice.Destination != nil {
|
if decodedInvoice.Destination != nil {
|
||||||
var signature *btcec.Signature
|
signature, err := sig.ToSignature()
|
||||||
err := lnwire.DeserializeSigFromWire(&signature, sigBytes)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to deserialize "+
|
return nil, fmt.Errorf("unable to deserialize "+
|
||||||
"signature: %v", err)
|
"signature: %v", err)
|
||||||
@ -358,7 +357,7 @@ func Decode(invoice string) (*Invoice, error) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
headerByte := recoveryID + 27 + 4
|
headerByte := recoveryID + 27 + 4
|
||||||
compactSign := append([]byte{headerByte}, sigBytes[:]...)
|
compactSign := append([]byte{headerByte}, sig[:]...)
|
||||||
pubkey, _, err := btcec.RecoverCompact(btcec.S256(),
|
pubkey, _, err := btcec.RecoverCompact(btcec.S256(),
|
||||||
compactSign, hash)
|
compactSign, hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -449,18 +448,18 @@ func (invoice *Invoice) Encode(signer MessageSigner) (string, error) {
|
|||||||
// From the header byte we can extract the recovery ID, and the last 64
|
// From the header byte we can extract the recovery ID, and the last 64
|
||||||
// bytes encode the signature.
|
// bytes encode the signature.
|
||||||
recoveryID := sign[0] - 27 - 4
|
recoveryID := sign[0] - 27 - 4
|
||||||
var sigBytes [64]byte
|
var sig lnwire.Sig
|
||||||
copy(sigBytes[:], sign[1:])
|
copy(sig[:], sign[1:])
|
||||||
|
|
||||||
// If the pubkey field was explicitly set, it must be set to the pubkey
|
// If the pubkey field was explicitly set, it must be set to the pubkey
|
||||||
// used to create the signature.
|
// used to create the signature.
|
||||||
if invoice.Destination != nil {
|
if invoice.Destination != nil {
|
||||||
var signature *btcec.Signature
|
signature, err := sig.ToSignature()
|
||||||
err = lnwire.DeserializeSigFromWire(&signature, sigBytes)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("unable to deserialize "+
|
return "", fmt.Errorf("unable to deserialize "+
|
||||||
"signature: %v", err)
|
"signature: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
valid := signature.Verify(hash, invoice.Destination)
|
valid := signature.Verify(hash, invoice.Destination)
|
||||||
if !valid {
|
if !valid {
|
||||||
return "", fmt.Errorf("signature does not match " +
|
return "", fmt.Errorf("signature does not match " +
|
||||||
@ -469,7 +468,7 @@ func (invoice *Invoice) Encode(signer MessageSigner) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert the signature to base32 before writing it to the buffer.
|
// Convert the signature to base32 before writing it to the buffer.
|
||||||
signBase32, err := bech32.ConvertBits(append(sigBytes[:], recoveryID), 8, 5, true)
|
signBase32, err := bech32.ConvertBits(append(sig[:], recoveryID), 8, 5, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user