forked from lightningnetwork/lnd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ann_validation.go
146 lines (127 loc) · 4.08 KB
/
ann_validation.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package routing
import (
"bytes"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/davecgh/go-spew/spew"
"github.com/go-errors/errors"
"github.com/lightningnetwork/lnd/lnwire"
)
// ValidateChannelAnn validates the channel announcement message and checks
// that node signatures covers the announcement message, and that the bitcoin
// signatures covers the node keys.
func ValidateChannelAnn(a *lnwire.ChannelAnnouncement) error {
// First, we'll compute the digest (h) which is to be signed by each of
// the keys included within the node announcement message. This hash
// digest includes all the keys, so the (up to 4 signatures) will
// attest to the validity of each of the keys.
data, err := a.DataToSign()
if err != nil {
return err
}
dataHash := chainhash.DoubleHashB(data)
// First we'll verify that the passed bitcoin key signature is indeed a
// signature over the computed hash digest.
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")
}
// If that checks out, then we'll verify that the second bitcoin
// signature is a valid signature of the bitcoin public key over hash
// digest as well.
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")
}
// Both node signatures attached should indeed be a valid signature
// over the selected digest of the channel announcement signature.
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")
}
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 nil
}
// ValidateNodeAnn validates the node announcement by ensuring that the
// attached signature is needed a signature of the node announcement under the
// specified node public key.
func ValidateNodeAnn(a *lnwire.NodeAnnouncement) error {
// Reconstruct the data of announcement which should be covered by the
// signature so we can verify the signature shortly below
data, err := a.DataToSign()
if err != nil {
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
// return an error so this node announcement can be rejected.
dataHash := chainhash.DoubleHashB(data)
if !nodeSig.Verify(dataHash, nodeKey) {
var msgBuf bytes.Buffer
if _, err := lnwire.WriteMessage(&msgBuf, a, 0); err != nil {
return err
}
return errors.Errorf("signature on NodeAnnouncement(%x) is "+
"invalid: %x", nodeKey.SerializeCompressed(),
msgBuf.Bytes())
}
return nil
}
// ValidateChannelUpdateAnn validates the channel update announcement by
// checking that the included signature covers he announcement and has been
// signed by the node's private key.
func ValidateChannelUpdateAnn(pubKey *btcec.PublicKey,
a *lnwire.ChannelUpdate) error {
data, err := a.DataToSign()
if err != nil {
return errors.Errorf("unable to reconstruct message: %v", err)
}
dataHash := chainhash.DoubleHashB(data)
nodeSig, err := a.Signature.ToSignature()
if err != nil {
return err
}
if !nodeSig.Verify(dataHash, pubKey) {
return errors.Errorf("invalid signature for channel "+
"update %v", spew.Sdump(a))
}
return nil
}