forked from bitcoinjs/bitcoinjs-lib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplay2.mjs
110 lines (98 loc) · 3.65 KB
/
play2.mjs
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
import { BIP32Factory } from 'bip32';
import { ECPairFactory } from 'ecpair'
import * as ecc from 'tiny-secp256k1';
import * as bitcoin from './src/index.js';
import { testnet as network } from './src/networks.js'
const ECPair = ECPairFactory(ecc);
const bip32 = BIP32Factory(ecc);
const hex = (s) => Buffer.from(s, 'hex')
// Order of the curve (N) - 1
const N_LESS_1 = Buffer.from(
'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140',
'hex',
);
// 1 represented as 32 bytes BE
const ONE = Buffer.from(
'0000000000000000000000000000000000000000000000000000000000000001',
'hex',
);
const myKey = ECPair.fromPrivateKey(hex('accaf12e04e11b08fc28f5fe75b47ea663843b698981e31f1cafa2224d6e28c0'))
const output = createKeySpendOutput(myKey.publicKey);
const address = bitcoin.address.fromOutputScript(output, network);
const amount = 100000;
const sendAmount = 75000
console.log('### output', output.toString('hex'))
console.log('### address', address)
const unspent = { txId: '8162b0310f37182049429e147b0ba7ac17eb4dd5c6d3016927e4c993b63edc2b', vout: 0}
const tx = createSigned(
myKey,
unspent.txId,
unspent.vout,
sendAmount,
[output], // public key
[amount],
);
const txHex = tx.toHex();
console.log('### txHex', txHex)
// txId: a618fdb361a6cfbc345d2b030ab7533dc88b3c097af58df6979b4d9aa4472379
function createKeySpendOutput(publicKey) {
// x-only pubkey (remove 1 byte y parity)
const myXOnlyPubkey = publicKey.slice(1, 33);
const commitHash = bitcoin.crypto.taggedHash('TapTweak', myXOnlyPubkey);
console.log('### commitHash ', commitHash.toString('hex'))
const tweakResult = ecc.xOnlyPointAddTweak(myXOnlyPubkey, commitHash);
console.log('### tweakResult xOnlyPubkey', Buffer.from(tweakResult.xOnlyPubkey).toString('hex'))
if (tweakResult === null) throw new Error('Invalid Tweak');
const { xOnlyPubkey: tweaked } = tweakResult;
// scriptPubkey
return Buffer.concat([
// witness v1, PUSH_DATA 32 bytes
Buffer.from([0x51, 0x20]),
// x-only tweaked pubkey
tweaked,
]);
}
function signTweaked(messageHash, key) {
const privateKey =
key.publicKey[0] === 2
? key.privateKey
: ecc.privateAdd(ecc.privateSub(N_LESS_1, key.privateKey), ONE);
const tweakHash = bitcoin.crypto.taggedHash(
'TapTweak',
key.publicKey.slice(1, 33),
);
const newPrivateKey = ecc.privateAdd(privateKey, tweakHash);
if (newPrivateKey === null) throw new Error('Invalid Tweak');
return ecc.signSchnorr(messageHash, newPrivateKey, Buffer.alloc(32));
}
// Function for creating signed tx
function createSigned(
key,
txid,
vout,
amountToSend,
scriptPubkeys,
values,
) {
console.log('### scriptPubkeys', scriptPubkeys.map(s => s.toString('hex')))
console.log('### values', values)
const tx = new bitcoin.Transaction();
tx.version = 2;
// Add input
tx.addInput(Buffer.from(txid, 'hex').reverse(), vout);
// Add output
tx.addOutput(scriptPubkeys[0], amountToSend);
const sighash = tx.hashForWitnessV1(
0, // which input
scriptPubkeys, // All previous outputs of all inputs
values, // All previous values of all inputs
bitcoin.Transaction.SIGHASH_DEFAULT, // sighash flag, DEFAULT is schnorr-only (DEFAULT == ALL)
);
console.log('### sighash', sighash.toString('hex'))
console.log('### unsignedTx', tx.toHex())
const signature = Buffer.from(signTweaked(sighash, key));
// witness stack for keypath spend is just the signature.
// If sighash is not SIGHASH_DEFAULT (ALL) then you must add 1 byte with sighash value
tx.ins[0].witness = [signature];
return tx;
}