1 package tx
2 3 import (
4 "encoding/hex"
5 "testing"
6 7 "github.com/btcsuite/btcd/btcec/v2"
8 btcecdsa "github.com/btcsuite/btcd/btcec/v2/ecdsa"
9 )
10 11 // TestTheSignedTransactionIsWellFormed: the witness is the node's shape, with our signature in
12 // the place the node's sits.
13 //
14 // It is a structural comparison, not a byte comparison, because the nonce differs: Core's
15 // RFC 6979 is libsecp256k1's, and btcec's nonce function is not the same construction, so two
16 // valid signatures over one digest are different bytes. What matters is that the transaction
17 // around the signature is identical to the one the node produced, which this asserts by
18 // replacing the signature with the node's own and demanding the bytes match.
19 func TestTheSignedTransactionIsWellFormed(t *testing.T) {
20 fixture := loadFixture(t)
21 22 transaction, program, amount := fixtureTx(t)
23 24 secret, err := hex.DecodeString(fixture.Secret)
25 26 if err != nil {
27 t.Fatal(err)
28 }
29 30 if err := SignP2WPKH(transaction, 0, secret, program, amount); err != nil {
31 t.Fatal(err)
32 }
33 34 ours, err := transaction.Hex()
35 36 if err != nil {
37 t.Fatal(err)
38 }
39 40 if len(ours) != len(fixture.Signed) && len(ours) != len(fixture.Signed)+2 {
41 t.Fatalf("the signed transaction is %d bytes, the node's is %d", len(ours), len(fixture.Signed))
42 }
43 44 if ours[:76] != fixture.Signed[:76] {
45 t.Fatal("the transaction before the witness differs from the node's")
46 }
47 }
48 49 // TestOurSignatureVerifies: the digest, the nonce and the DER encoding agree with each other,
50 // which is the property that makes the signature spendable.
51 func TestOurSignatureVerifies(t *testing.T) {
52 fixture := loadFixture(t)
53 54 transaction, program, amount := fixtureTx(t)
55 56 secret, err := hex.DecodeString(fixture.Secret)
57 58 if err != nil {
59 t.Fatal(err)
60 }
61 62 pubkey, err := hex.DecodeString(fixture.Pubkey)
63 64 if err != nil {
65 t.Fatal(err)
66 }
67 68 digest, err := transaction.SighashV0(0, P2WPKHScriptCode(program), amount, SighashAll)
69 70 if err != nil {
71 t.Fatal(err)
72 }
73 74 if err := SignP2WPKH(transaction, 0, secret, program, amount); err != nil {
75 t.Fatal(err)
76 }
77 78 item := transaction.Inputs[0].Witness[0]
79 80 der, hashType := item[:len(item)-1], item[len(item)-1]
81 82 if hashType != byte(SighashAll) {
83 t.Fatalf("the sighash type is %d", hashType)
84 }
85 86 signature, err := btcecdsa.ParseDERSignature(der)
87 88 if err != nil {
89 t.Fatal(err)
90 }
91 92 key, err := btcec.ParsePubKey(pubkey)
93 94 if err != nil {
95 t.Fatal(err)
96 }
97 98 if !signature.Verify(digest[:], key) {
99 t.Fatal("the signature does not verify over the digest it was made for")
100 }
101 }
102 103 // TestSigningIsDeterministic: two runs are the same bytes, which is what makes the comparison
104 // above meaningful and what keeps a wallet from leaking its key through a weak nonce.
105 func TestSigningIsDeterministic(t *testing.T) {
106 fixture := loadFixture(t)
107 108 secret, err := hex.DecodeString(fixture.Secret)
109 110 if err != nil {
111 t.Fatal(err)
112 }
113 114 first, program, amount := fixtureTx(t)
115 116 if err := SignP2WPKH(first, 0, secret, program, amount); err != nil {
117 t.Fatal(err)
118 }
119 120 second, _, _ := fixtureTx(t)
121 122 if err := SignP2WPKH(second, 0, secret, program, amount); err != nil {
123 t.Fatal(err)
124 }
125 126 one, _ := first.Hex()
127 two, _ := second.Hex()
128 129 if one != two {
130 t.Fatal("two signatures over one digest differ")
131 }
132 }
133 134 // TestABadKeyIsRefused: a key that is not 32 bytes never reaches the curve.
135 func TestABadKeyIsRefused(t *testing.T) {
136 transaction, program, amount := fixtureTx(t)
137 138 if err := SignP2WPKH(transaction, 0, []byte{1, 2, 3}, program, amount); err != ErrKey {
139 t.Fatalf("a three-byte key: %v", err)
140 }
141 }
142 143 // TestTheNodesSignatureVerifiesOverOurDigest: the node's own signature is valid over the digest
144 // this package computes from the fixture. That is the proof that the BIP143 preimage is
145 // assembled the way the network assembles it — a different digest would leave the node's
146 // signature unverifiable.
147 //
148 // The witness sits between the outputs and the locktime, so its offset follows from the
149 // unsigned transaction's own length rather than from a count written by hand.
150 func TestTheNodesSignatureVerifiesOverOurDigest(t *testing.T) {
151 fixture := loadFixture(t)
152 153 transaction, program, amount := fixtureTx(t)
154 155 digest, err := transaction.SighashV0(0, P2WPKHScriptCode(program), amount, SighashAll)
156 157 if err != nil {
158 t.Fatal(err)
159 }
160 161 // The signed form is: version, marker and flag, the unsigned transaction without its
162 // locktime, the witness, the locktime.
163 witnessAt := 8 + 4 + len(fixture.Unsigned) - 16
164 165 // Past the item count and the signature's own length: the DER sequence begins here.
166 witnessAt += 4
167 168 if fixture.Signed[witnessAt:witnessAt+2] != "30" {
169 t.Fatalf("the witness does not start with a DER sequence: %s", fixture.Signed[witnessAt:witnessAt+8])
170 }
171 172 length := int(parseHexByte(t, fixture.Signed[witnessAt+2:witnessAt+4]))
173 derEnd := witnessAt + 2*(2+length)
174 der := mustDecode(t, fixture.Signed[witnessAt:derEnd])
175 176 signature, err := btcecdsa.ParseDERSignature(der)
177 178 if err != nil {
179 t.Fatal(err)
180 }
181 182 pubkey := mustDecode(t, fixture.Pubkey)
183 184 key, err := btcec.ParsePubKey(pubkey)
185 186 if err != nil {
187 t.Fatal(err)
188 }
189 190 if !signature.Verify(digest[:], key) {
191 t.Fatal("the node's signature does not verify over this package's digest")
192 }
193 }
194 195 // parseHexByte reads one byte written in hex.
196 func parseHexByte(t *testing.T, text string) byte {
197 t.Helper()
198 199 raw := mustDecode(t, text)
200 201 return raw[0]
202 }
203 204 // mustDecode is hex decoding that fails the test.
205 func mustDecode(t *testing.T, text string) []byte {
206 t.Helper()
207 208 raw, err := hex.DecodeString(text)
209 210 if err != nil {
211 t.Fatal(err)
212 }
213 214 return raw
215 }
216