-
-
Notifications
You must be signed in to change notification settings - Fork 48
/
taptree.test.ts
94 lines (78 loc) · 3.94 KB
/
taptree.test.ts
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
import { Test } from 'tape'
import { util } from '@cmdcode/crypto-utils'
import { Address, Signer, Tap, Tx, } from '../../../src/index.js'
export async function tree_spend (t : Test) : Promise<void> {
t.test('Spend a script inside a tree.', async t => {
// Switch this to true to enable console output.
const VERBOSE = false
// Create a keypair to use for testing.
const secret = '0a7d01d1c2e1592a02ea7671bb79ecd31d8d5e660b008f4b10e67787f4f24712'
const seckey = util.getSecretKey(secret)
const pubkey = util.getPublicKey(seckey, true)
// Specify an array of scripts to use for testing.
const scripts = [
[ 1, 7, 'OP_ADD', 8, 'OP_EQUALVERIFY', pubkey, 'OP_CHECKSIG' ],
[ 2, 6, 'OP_ADD', 8, 'OP_EQUALVERIFY', pubkey, 'OP_CHECKSIG' ],
[ 3, 5, 'OP_ADD', 8, 'OP_EQUALVERIFY', pubkey, 'OP_CHECKSIG' ],
[ 4, 4, 'OP_ADD', 8, 'OP_EQUALVERIFY', pubkey, 'OP_CHECKSIG' ],
[ 5, 3, 'OP_ADD', 8, 'OP_EQUALVERIFY', pubkey, 'OP_CHECKSIG' ],
[ 6, 2, 'OP_ADD', 8, 'OP_EQUALVERIFY', pubkey, 'OP_CHECKSIG' ],
[ 7, 1, 'OP_ADD', 8, 'OP_EQUALVERIFY', pubkey, 'OP_CHECKSIG' ]
]
// Convert our array of scripts into tapleaves.
const tree = scripts.map(s => Tap.encodeScript(s))
if (VERBOSE) console.log('tree:', tree)
// Pick one of our scripts as a target for spending.
const index = Math.floor(Math.random() * 10) % 7
const script = scripts[index]
const target = Tap.encodeScript(script)
if (VERBOSE) console.log('target:', target)
// Generate a tapkey that includes our tree. Also, create a merlke proof
// (cblock) that targets our leaf and proves its inclusion in the tapkey.
const [ tpubkey, cblock ] = Tap.getPubKey(pubkey, { tree, target })
// A taproot address is simply the tweaked public key, encoded in bech32 format.
const address = Address.p2tr.fromPubKey(tpubkey, 'regtest')
if (VERBOSE) console.log('Your address:', address)
/* NOTE: To continue with this example, send 100_000 sats to the above address.
You will also need to make a note of the txid and vout of that transaction,
so that you can include that information below in the redeem tx.
*/
const txdata = Tx.create({
vin : [{
// Use the txid of the funding transaction used to send the sats.
txid: 'e0b1b0aea95095bf7e113c37562a51cb8c3f50f5145c17952e766f7a84fcc5d7',
// Specify the index value of the output that you are going to spend from.
vout: 0,
// Also include the value and script of that ouput.
prevout: {
// Feel free to change this if you sent a different amount.
value: 100_000,
// This is what our address looks like in script form.
scriptPubKey: [ 'OP_1', tpubkey ]
},
}],
vout : [{
// We are leaving behind 1000 sats as a fee to the miners.
value: 99_000,
// This is the new script that we are locking our funds to.
scriptPubKey: Address.toScriptPubKey('bcrt1q6zpf4gefu4ckuud3pjch563nm7x27u4ruahz3y')
}]
})
// For this example, we are signing for input 0 of our transaction,
// using the untweaked secret key. We are also extending the signature
// to include a commitment to the tapleaf script that we wish to use.
const sig = Signer.taproot.sign(seckey, txdata, 0, { extension: target })
// Add the signature to our witness data for input 0, along with the script
// and merkle proof (cblock) for the script.
txdata.vin[0].witness = [ sig.hex, script, cblock ]
// Check if the signature is valid for the provided public key, and that the
// transaction is also valid (the merkle proof will be validated as well).
const isValid = await Signer.taproot.verify(txdata, 0, { pubkey })
if (VERBOSE) {
console.log('Your txhex:', Tx.encode(txdata).hex)
console.dir(txdata, { depth: null })
}
t.plan(1)
t.equal(isValid, true, 'Transaction should pass validation.')
})
}