Skip to content

Commit 5f11c67

Browse files
reardencodeOttoAllmendingerTyler Levinesangaman
committed
feat: Import v5-based BitGo Taproot
Imported from: 165f26a Co-authored-by: Otto Allmendinger <[email protected]> Co-authored-by: Tyler Levine <[email protected]> Co-authored-by: Daniel McNally <[email protected]>
1 parent 2631625 commit 5f11c67

File tree

11 files changed

+1896
-11
lines changed

11 files changed

+1896
-11
lines changed

test/fixtures/p2tr.json

Lines changed: 486 additions & 0 deletions
Large diffs are not rendered by default.

test/fixtures/p2tr_ns.json

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
{
2+
"valid": [
3+
{
4+
"description": "p2tr_ns(1), pubkey, in (from out, sigs)",
5+
"arguments": {
6+
"output": "8f5173bc367914e1574aceb3c7232a178a764fb6f14730b6b20bd36394c6c717 OP_CHECKSIG",
7+
"signatures": [
8+
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
9+
],
10+
"network": "regtest"
11+
},
12+
"options": {},
13+
"expected": {
14+
"name": "p2tr_ns(1)",
15+
"n": 1,
16+
"pubkeys": ["8f5173bc367914e1574aceb3c7232a178a764fb6f14730b6b20bd36394c6c717"],
17+
"input": "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
18+
}
19+
},
20+
{
21+
"description": "p2tr_ns(1), pubkey, in (from out, sigs) incomplete",
22+
"arguments": {
23+
"output": "8f5173bc367914e1574aceb3c7232a178a764fb6f14730b6b20bd36394c6c717 OP_CHECKSIG",
24+
"signatures": [
25+
0
26+
],
27+
"network": "regtest"
28+
},
29+
"options": { "allowIncomplete": true },
30+
"expected": {
31+
"name": "p2tr_ns(1)",
32+
"n": 1,
33+
"pubkeys": ["8f5173bc367914e1574aceb3c7232a178a764fb6f14730b6b20bd36394c6c717"],
34+
"input": "OP_0"
35+
}
36+
},
37+
{
38+
"description": "p2tr_ns(1), out, sigs (from key, in)",
39+
"arguments": {
40+
"pubkeys": ["af455f4989d122e9185f8c351dbaecd13adca3eef8a9d38ef8ffed6867e342e3"],
41+
"input": "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
42+
"network": "regtest"
43+
},
44+
"options": {},
45+
"expected": {
46+
"name": "p2tr_ns(1)",
47+
"n": 1,
48+
"output": "af455f4989d122e9185f8c351dbaecd13adca3eef8a9d38ef8ffed6867e342e3 OP_CHECKSIG",
49+
"signatures": [
50+
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
51+
]
52+
}
53+
},
54+
{
55+
"description": "p2tr_ns(2), out, in (from keys, out, sigs)",
56+
"arguments": {
57+
"pubkeys": [
58+
"20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3",
59+
"d806a63b6e2d83f11f22f9a11ba7a49ac451e8acf57591ec058e422eb997d55e"
60+
],
61+
"output": "20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY d806a63b6e2d83f11f22f9a11ba7a49ac451e8acf57591ec058e422eb997d55e OP_CHECKSIG",
62+
"signatures": [
63+
"beefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead",
64+
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
65+
],
66+
"network": "regtest"
67+
},
68+
"options": {},
69+
"expected": {
70+
"name": "p2tr_ns(2)",
71+
"n": 2,
72+
"outputHex": "2020040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3ad20d806a63b6e2d83f11f22f9a11ba7a49ac451e8acf57591ec058e422eb997d55ead",
73+
"input": "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef beefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead"
74+
}
75+
},
76+
{
77+
"description": "p2tr_ns(2), out, in (from keys, sigs)",
78+
"arguments": {
79+
"pubkeys": [
80+
"20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3",
81+
"d806a63b6e2d83f11f22f9a11ba7a49ac451e8acf57591ec058e422eb997d55e"
82+
],
83+
"signatures": [
84+
"beefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead",
85+
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
86+
],
87+
"network": "regtest"
88+
},
89+
"options": {},
90+
"expected": {
91+
"name": "p2tr_ns(2)",
92+
"n": 2,
93+
"outputHex": "2020040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3ad20d806a63b6e2d83f11f22f9a11ba7a49ac451e8acf57591ec058e422eb997d55ead",
94+
"input": "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef beefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead"
95+
}
96+
}
97+
],
98+
"invalid": [
99+
{
100+
"description": "p2tr_ns(2), mismatched keys/sigs",
101+
"arguments": {
102+
"pubkeys": [
103+
"d806a63b6e2d83f11f22f9a11ba7a49ac451e8acf57591ec058e422eb997d55e"
104+
],
105+
"signatures": [
106+
"beefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead",
107+
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
108+
],
109+
"network": "regtest"
110+
},
111+
"options": {}
112+
},
113+
{
114+
"description": "p2tr_ns(2), mismatched keys/sigs",
115+
"arguments": {
116+
"pubkeys": [
117+
"20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3",
118+
"d806a63b6e2d83f11f22f9a11ba7a49ac451e8acf57591ec058e422eb997d55e"
119+
],
120+
"signatures": [
121+
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
122+
],
123+
"network": "regtest"
124+
},
125+
"options": {}
126+
},
127+
{
128+
"description": "p2tr_ns(2), mismatched sigs/input",
129+
"arguments": {
130+
"pubkeys": [
131+
"20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3",
132+
"d806a63b6e2d83f11f22f9a11ba7a49ac451e8acf57591ec058e422eb997d55e"
133+
],
134+
"input": "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
135+
"signatures": [
136+
"beefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead",
137+
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
138+
],
139+
"network": "regtest"
140+
},
141+
"options": {}
142+
},
143+
{
144+
"description": "p2tr_ns(2), mismatched keys/input",
145+
"arguments": {
146+
"pubkeys": [
147+
"20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3",
148+
"d806a63b6e2d83f11f22f9a11ba7a49ac451e8acf57591ec058e422eb997d55e"
149+
],
150+
"input": "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
151+
"network": "regtest"
152+
},
153+
"options": {}
154+
},
155+
{
156+
"description": "p2tr_ns(1) no data",
157+
"arguments": {
158+
"network": "regtest"
159+
},
160+
"options": {}
161+
},
162+
{
163+
"description": "p2tr_ns(1), bad sig",
164+
"arguments": {
165+
"pubkeys": [
166+
"20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3"
167+
],
168+
"input": "deadbeef",
169+
"network": "regtest"
170+
},
171+
"options": {}
172+
},
173+
{
174+
"description": "p2tr_ns(2) swapped opcodes",
175+
"arguments": {
176+
"output": "20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIG 8f5173bc367914e1574aceb3c7232a178a764fb6f14730b6b20bd36394c6c717 OP_CHECKSIGVERIFY",
177+
"network": "regtest"
178+
},
179+
"options": {}
180+
},
181+
{
182+
"description": "p2tr_ns(2) wrong internal opcode",
183+
"arguments": {
184+
"output": "20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIG 8f5173bc367914e1574aceb3c7232a178a764fb6f14730b6b20bd36394c6c717 OP_CHECKSIG",
185+
"network": "regtest"
186+
},
187+
"options": {}
188+
},
189+
{
190+
"description": "p2tr_ns(2) too many pubkeys",
191+
"arguments": {
192+
"output": "20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 8f5173bc367914e1574aceb3c7232a178a764fb6f14730b6b20bd36394c6c717 OP_CHECKSIG",
193+
"network": "regtest"
194+
},
195+
"options": {}
196+
},
197+
{
198+
"description": "p2tr_ns(2) pubkey mismatch",
199+
"arguments": {
200+
"output": "20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3 OP_CHECKSIGVERIFY 8f5173bc367914e1574aceb3c7232a178a764fb6f14730b6b20bd36394c6c717 OP_CHECKSIG",
201+
"pubkeys": [
202+
"8f5173bc367914e1574aceb3c7232a178a764fb6f14730b6b20bd36394c6c717",
203+
"20040c8338b34cb9c06c6b1bd38095eafa8f9b72398a1084fdb67473d82dfda3"
204+
],
205+
"network": "regtest"
206+
},
207+
"options": {}
208+
},
209+
{
210+
"description": "p2tr_ns(2) bad pubkey",
211+
"arguments": {
212+
"output": "ff20040c8338b34cb9c06c6b1d38095eafa8f9b72398a1084fdb67473d8dfda3 OP_CHECKSIGVERIFY 8f5173bc367914e1574aceb3c7232a178a764fb6f14730b6b20bd36394c6c717 OP_CHECKSIG",
213+
"network": "regtest"
214+
},
215+
"options": {}
216+
}
217+
]
218+
}

test/payments.spec.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,17 @@ import * as assert from 'assert';
22
import { describe, it } from 'mocha';
33
import { PaymentCreator } from '../src/payments';
44
import * as u from './payments.utils';
5-
['embed', 'p2ms', 'p2pk', 'p2pkh', 'p2sh', 'p2wpkh', 'p2wsh'].forEach(p => {
5+
[
6+
'embed',
7+
'p2ms',
8+
'p2pk',
9+
'p2pkh',
10+
'p2sh',
11+
'p2tr',
12+
'p2tr_ns',
13+
'p2wpkh',
14+
'p2wsh',
15+
].forEach(p => {
616
describe(p, () => {
717
let fn: PaymentCreator;
818
const payment = require('../src/payments/' + p);

test/payments.utils.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ export function equate(a: any, b: any, args?: any): void {
108108
);
109109
if ('data' in b)
110110
t.deepStrictEqual(tryHex(a.data), tryHex(b.data), 'Inequal *.data');
111+
if ('controlBlock' in b)
112+
t.strictEqual(
113+
tryHex(a.controlBlock),
114+
tryHex(b.controlBlock),
115+
'Inequal control block',
116+
);
117+
if ('annex' in b)
118+
t.strictEqual(tryHex(a.annex), tryHex(b.annex), 'Inequal annex');
111119
}
112120

113121
export function preform(x: any): any {
@@ -130,21 +138,18 @@ export function preform(x: any): any {
130138
if (x.hash) x.hash = Buffer.from(x.hash, 'hex');
131139
if (x.pubkey) x.pubkey = Buffer.from(x.pubkey, 'hex');
132140
if (x.signature) x.signature = Buffer.from(x.signature, 'hex');
141+
if (x.controlBlock) x.controlBlock = Buffer.from(x.controlBlock, 'hex');
142+
if (x.annex) x.annex = Buffer.from(x.annex, 'hex');
133143
if (x.pubkeys) x.pubkeys = x.pubkeys.map(fromHex);
134144
if (x.signatures)
135145
x.signatures = x.signatures.map((y: any) => {
136146
return Number.isFinite(y) ? y : Buffer.from(y, 'hex');
137147
});
138148
if (x.redeem) {
139-
x.redeem = Object.assign({}, x.redeem);
140-
if (typeof x.redeem.input === 'string')
141-
x.redeem.input = asmToBuffer(x.redeem.input);
142-
if (typeof x.redeem.output === 'string')
143-
x.redeem.output = asmToBuffer(x.redeem.output);
144-
if (Array.isArray(x.redeem.witness))
145-
x.redeem.witness = x.redeem.witness.map(fromHex);
146-
if (x.redeem.network)
147-
x.redeem.network = (BNETWORKS as any)[x.redeem.network];
149+
x.redeem = preform(x.redeem);
150+
}
151+
if (x.redeems) {
152+
x.redeems = x.redeems.map(preform);
148153
}
149154

150155
return x;

0 commit comments

Comments
 (0)