@ledgerhq/hw-app-btc 10.16.0-nightly.20260115024415 → 10.16.0-nightly.20260116124336
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -3
- package/README.md +106 -56
- package/lib/Btc.d.ts +37 -0
- package/lib/Btc.d.ts.map +1 -1
- package/lib/Btc.js +30 -2
- package/lib/Btc.js.map +1 -1
- package/lib/BtcNew.d.ts +84 -0
- package/lib/BtcNew.d.ts.map +1 -1
- package/lib/BtcNew.js +326 -9
- package/lib/BtcNew.js.map +1 -1
- package/lib/createTransaction.d.ts.map +1 -1
- package/lib/createTransaction.js +3 -2
- package/lib/createTransaction.js.map +1 -1
- package/lib/getTrustedInputBIP143.d.ts +1 -2
- package/lib/getTrustedInputBIP143.d.ts.map +1 -1
- package/lib/getTrustedInputBIP143.js +1 -1
- package/lib/getTrustedInputBIP143.js.map +1 -1
- package/lib/newops/accounttype.d.ts +3 -3
- package/lib/newops/accounttype.d.ts.map +1 -1
- package/lib/newops/accounttype.js +15 -14
- package/lib/newops/accounttype.js.map +1 -1
- package/lib/newops/appClient.d.ts +1 -1
- package/lib/newops/appClient.d.ts.map +1 -1
- package/lib/newops/clientCommands.js +2 -2
- package/lib/newops/clientCommands.js.map +1 -1
- package/lib/newops/merkelizedPsbt.d.ts +1 -1
- package/lib/newops/merkelizedPsbt.d.ts.map +1 -1
- package/lib/newops/merkelizedPsbt.js +1 -1
- package/lib/newops/merkelizedPsbt.js.map +1 -1
- package/lib/newops/policy.js +2 -2
- package/lib/newops/policy.js.map +1 -1
- package/lib/newops/psbtExtractor.d.ts +1 -1
- package/lib/newops/psbtExtractor.d.ts.map +1 -1
- package/lib/newops/psbtExtractor.js +3 -3
- package/lib/newops/psbtExtractor.js.map +1 -1
- package/lib/newops/psbtFinalizer.d.ts +1 -1
- package/lib/newops/psbtFinalizer.d.ts.map +1 -1
- package/lib/newops/psbtFinalizer.js +5 -6
- package/lib/newops/psbtFinalizer.js.map +1 -1
- package/lib/signP2SHTransaction.d.ts.map +1 -1
- package/lib/signP2SHTransaction.js +3 -2
- package/lib/signP2SHTransaction.js.map +1 -1
- package/lib-es/Btc.d.ts +37 -0
- package/lib-es/Btc.d.ts.map +1 -1
- package/lib-es/Btc.js +30 -2
- package/lib-es/Btc.js.map +1 -1
- package/lib-es/BtcNew.d.ts +84 -0
- package/lib-es/BtcNew.d.ts.map +1 -1
- package/lib-es/BtcNew.js +325 -8
- package/lib-es/BtcNew.js.map +1 -1
- package/lib-es/createTransaction.d.ts.map +1 -1
- package/lib-es/createTransaction.js +3 -2
- package/lib-es/createTransaction.js.map +1 -1
- package/lib-es/getTrustedInputBIP143.d.ts +1 -2
- package/lib-es/getTrustedInputBIP143.d.ts.map +1 -1
- package/lib-es/getTrustedInputBIP143.js +1 -1
- package/lib-es/getTrustedInputBIP143.js.map +1 -1
- package/lib-es/newops/accounttype.d.ts +3 -3
- package/lib-es/newops/accounttype.d.ts.map +1 -1
- package/lib-es/newops/accounttype.js +11 -10
- package/lib-es/newops/accounttype.js.map +1 -1
- package/lib-es/newops/appClient.d.ts +1 -1
- package/lib-es/newops/appClient.d.ts.map +1 -1
- package/lib-es/newops/clientCommands.js +1 -1
- package/lib-es/newops/clientCommands.js.map +1 -1
- package/lib-es/newops/merkelizedPsbt.d.ts +1 -1
- package/lib-es/newops/merkelizedPsbt.d.ts.map +1 -1
- package/lib-es/newops/merkelizedPsbt.js +1 -1
- package/lib-es/newops/merkelizedPsbt.js.map +1 -1
- package/lib-es/newops/policy.js +1 -1
- package/lib-es/newops/policy.js.map +1 -1
- package/lib-es/newops/psbtExtractor.d.ts +1 -1
- package/lib-es/newops/psbtExtractor.d.ts.map +1 -1
- package/lib-es/newops/psbtExtractor.js +1 -1
- package/lib-es/newops/psbtExtractor.js.map +1 -1
- package/lib-es/newops/psbtFinalizer.d.ts +1 -1
- package/lib-es/newops/psbtFinalizer.d.ts.map +1 -1
- package/lib-es/newops/psbtFinalizer.js +1 -2
- package/lib-es/newops/psbtFinalizer.js.map +1 -1
- package/lib-es/signP2SHTransaction.d.ts.map +1 -1
- package/lib-es/signP2SHTransaction.js +3 -2
- package/lib-es/signP2SHTransaction.js.map +1 -1
- package/package.json +6 -6
- package/src/Btc.ts +41 -2
- package/src/BtcNew.ts +483 -9
- package/src/createTransaction.ts +4 -3
- package/src/getTrustedInputBIP143.ts +0 -2
- package/src/newops/accounttype.ts +11 -12
- package/src/newops/appClient.ts +1 -1
- package/src/newops/clientCommands.ts +1 -1
- package/src/newops/merkelizedPsbt.ts +1 -1
- package/src/newops/policy.ts +1 -1
- package/src/newops/psbtExtractor.ts +1 -2
- package/src/newops/psbtFinalizer.ts +1 -2
- package/src/signP2SHTransaction.ts +3 -2
- package/tests/Btc.test.ts +848 -20
- package/tests/newops/BtcNew.signMessage.test.ts +35 -0
- package/tests/newops/BtcNew.signPsbtBuffer.test.ts +391 -0
- package/tests/newops/BtcNew.test.ts +13 -1
- package/tests/newops/integrationtools.ts +1 -1
- package/lib/buffertools.d.ts +0 -31
- package/lib/buffertools.d.ts.map +0 -1
- package/lib/buffertools.js +0 -129
- package/lib/buffertools.js.map +0 -1
- package/lib/newops/psbtv2.d.ts +0 -150
- package/lib/newops/psbtv2.d.ts.map +0 -1
- package/lib/newops/psbtv2.js +0 -469
- package/lib/newops/psbtv2.js.map +0 -1
- package/lib-es/buffertools.d.ts +0 -31
- package/lib-es/buffertools.d.ts.map +0 -1
- package/lib-es/buffertools.js +0 -119
- package/lib-es/buffertools.js.map +0 -1
- package/lib-es/newops/psbtv2.d.ts +0 -150
- package/lib-es/newops/psbtv2.d.ts.map +0 -1
- package/lib-es/newops/psbtv2.js +0 -464
- package/lib-es/newops/psbtv2.js.map +0 -1
- package/src/buffertools.ts +0 -137
- package/src/newops/psbtv2.ts +0 -525
- package/tests/buffertools.test.ts +0 -25
- package/tests/newops/psbtv2.test.ts +0 -15
package/src/newops/psbtv2.ts
DELETED
|
@@ -1,525 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2
|
-
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
3
|
-
import { BufferReader, BufferWriter, unsafeFrom64bitLE, unsafeTo64bitLE } from "../buffertools";
|
|
4
|
-
|
|
5
|
-
export enum psbtGlobal {
|
|
6
|
-
TX_VERSION = 0x02,
|
|
7
|
-
FALLBACK_LOCKTIME = 0x03,
|
|
8
|
-
INPUT_COUNT = 0x04,
|
|
9
|
-
OUTPUT_COUNT = 0x05,
|
|
10
|
-
TX_MODIFIABLE = 0x06,
|
|
11
|
-
VERSION = 0xfb,
|
|
12
|
-
}
|
|
13
|
-
export enum psbtIn {
|
|
14
|
-
NON_WITNESS_UTXO = 0x00,
|
|
15
|
-
WITNESS_UTXO = 0x01,
|
|
16
|
-
PARTIAL_SIG = 0x02,
|
|
17
|
-
SIGHASH_TYPE = 0x03,
|
|
18
|
-
REDEEM_SCRIPT = 0x04,
|
|
19
|
-
BIP32_DERIVATION = 0x06,
|
|
20
|
-
FINAL_SCRIPTSIG = 0x07,
|
|
21
|
-
FINAL_SCRIPTWITNESS = 0x08,
|
|
22
|
-
PREVIOUS_TXID = 0x0e,
|
|
23
|
-
OUTPUT_INDEX = 0x0f,
|
|
24
|
-
SEQUENCE = 0x10,
|
|
25
|
-
TAP_KEY_SIG = 0x13,
|
|
26
|
-
TAP_BIP32_DERIVATION = 0x16,
|
|
27
|
-
}
|
|
28
|
-
export enum psbtOut {
|
|
29
|
-
REDEEM_SCRIPT = 0x00,
|
|
30
|
-
BIP_32_DERIVATION = 0x02,
|
|
31
|
-
AMOUNT = 0x03,
|
|
32
|
-
SCRIPT = 0x04,
|
|
33
|
-
TAP_BIP32_DERIVATION = 0x07,
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const PSBT_MAGIC_BYTES = Buffer.from([0x70, 0x73, 0x62, 0x74, 0xff]);
|
|
37
|
-
|
|
38
|
-
export class NoSuchEntry extends Error {}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Implements Partially Signed Bitcoin Transaction version 2, BIP370, as
|
|
42
|
-
* documented at https://github.com/bitcoin/bips/blob/master/bip-0370.mediawiki
|
|
43
|
-
* and https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
|
|
44
|
-
*
|
|
45
|
-
* A psbt is a data structure that can carry all relevant information about a
|
|
46
|
-
* transaction through all stages of the signing process. From constructing an
|
|
47
|
-
* unsigned transaction to extracting the final serialized transaction ready for
|
|
48
|
-
* broadcast.
|
|
49
|
-
*
|
|
50
|
-
* This implementation is limited to what's needed in ledgerjs to carry out its
|
|
51
|
-
* duties, which means that support for features like multisig or taproot script
|
|
52
|
-
* path spending are not implemented. Specifically, it supports p2pkh,
|
|
53
|
-
* p2wpkhWrappedInP2sh, p2wpkh and p2tr key path spending.
|
|
54
|
-
*
|
|
55
|
-
* This class is made purposefully dumb, so it's easy to add support for
|
|
56
|
-
* complemantary fields as needed in the future.
|
|
57
|
-
*/
|
|
58
|
-
export class PsbtV2 {
|
|
59
|
-
protected globalMap: Map<string, Buffer> = new Map();
|
|
60
|
-
protected inputMaps: Map<string, Buffer>[] = [];
|
|
61
|
-
protected outputMaps: Map<string, Buffer>[] = [];
|
|
62
|
-
|
|
63
|
-
setGlobalTxVersion(version: number) {
|
|
64
|
-
this.setGlobal(psbtGlobal.TX_VERSION, uint32LE(version));
|
|
65
|
-
}
|
|
66
|
-
getGlobalTxVersion(): number {
|
|
67
|
-
return this.getGlobal(psbtGlobal.TX_VERSION).readUInt32LE(0);
|
|
68
|
-
}
|
|
69
|
-
setGlobalFallbackLocktime(locktime: number) {
|
|
70
|
-
this.setGlobal(psbtGlobal.FALLBACK_LOCKTIME, uint32LE(locktime));
|
|
71
|
-
}
|
|
72
|
-
getGlobalFallbackLocktime(): number | undefined {
|
|
73
|
-
return this.getGlobalOptional(psbtGlobal.FALLBACK_LOCKTIME)?.readUInt32LE(0);
|
|
74
|
-
}
|
|
75
|
-
setGlobalInputCount(inputCount: number) {
|
|
76
|
-
this.setGlobal(psbtGlobal.INPUT_COUNT, varint(inputCount));
|
|
77
|
-
}
|
|
78
|
-
getGlobalInputCount(): number {
|
|
79
|
-
return fromVarint(this.getGlobal(psbtGlobal.INPUT_COUNT));
|
|
80
|
-
}
|
|
81
|
-
setGlobalOutputCount(outputCount: number) {
|
|
82
|
-
this.setGlobal(psbtGlobal.OUTPUT_COUNT, varint(outputCount));
|
|
83
|
-
}
|
|
84
|
-
getGlobalOutputCount(): number {
|
|
85
|
-
return fromVarint(this.getGlobal(psbtGlobal.OUTPUT_COUNT));
|
|
86
|
-
}
|
|
87
|
-
setGlobalTxModifiable(byte: Buffer) {
|
|
88
|
-
this.setGlobal(psbtGlobal.TX_MODIFIABLE, byte);
|
|
89
|
-
}
|
|
90
|
-
getGlobalTxModifiable(): Buffer | undefined {
|
|
91
|
-
return this.getGlobalOptional(psbtGlobal.TX_MODIFIABLE);
|
|
92
|
-
}
|
|
93
|
-
setGlobalPsbtVersion(psbtVersion: number) {
|
|
94
|
-
this.setGlobal(psbtGlobal.VERSION, uint32LE(psbtVersion));
|
|
95
|
-
}
|
|
96
|
-
getGlobalPsbtVersion(): number {
|
|
97
|
-
return this.getGlobal(psbtGlobal.VERSION).readUInt32LE(0);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
setInputNonWitnessUtxo(inputIndex: number, transaction: Buffer) {
|
|
101
|
-
this.setInput(inputIndex, psbtIn.NON_WITNESS_UTXO, b(), transaction);
|
|
102
|
-
}
|
|
103
|
-
getInputNonWitnessUtxo(inputIndex: number): Buffer | undefined {
|
|
104
|
-
return this.getInputOptional(inputIndex, psbtIn.NON_WITNESS_UTXO, b());
|
|
105
|
-
}
|
|
106
|
-
setInputWitnessUtxo(inputIndex: number, amount: Buffer, scriptPubKey: Buffer) {
|
|
107
|
-
const buf = new BufferWriter();
|
|
108
|
-
buf.writeSlice(amount);
|
|
109
|
-
buf.writeVarSlice(scriptPubKey);
|
|
110
|
-
this.setInput(inputIndex, psbtIn.WITNESS_UTXO, b(), buf.buffer());
|
|
111
|
-
}
|
|
112
|
-
getInputWitnessUtxo(inputIndex: number): { amount: Buffer; scriptPubKey: Buffer } | undefined {
|
|
113
|
-
const utxo = this.getInputOptional(inputIndex, psbtIn.WITNESS_UTXO, b());
|
|
114
|
-
if (!utxo) return undefined;
|
|
115
|
-
const buf = new BufferReader(utxo);
|
|
116
|
-
return { amount: buf.readSlice(8), scriptPubKey: buf.readVarSlice() };
|
|
117
|
-
}
|
|
118
|
-
setInputPartialSig(inputIndex: number, pubkey: Buffer, signature: Buffer) {
|
|
119
|
-
this.setInput(inputIndex, psbtIn.PARTIAL_SIG, pubkey, signature);
|
|
120
|
-
}
|
|
121
|
-
getInputPartialSig(inputIndex: number, pubkey: Buffer): Buffer | undefined {
|
|
122
|
-
return this.getInputOptional(inputIndex, psbtIn.PARTIAL_SIG, pubkey);
|
|
123
|
-
}
|
|
124
|
-
setInputSighashType(inputIndex: number, sigHashtype: number) {
|
|
125
|
-
this.setInput(inputIndex, psbtIn.SIGHASH_TYPE, b(), uint32LE(sigHashtype));
|
|
126
|
-
}
|
|
127
|
-
getInputSighashType(inputIndex: number): number | undefined {
|
|
128
|
-
const result = this.getInputOptional(inputIndex, psbtIn.SIGHASH_TYPE, b());
|
|
129
|
-
if (!result) return undefined;
|
|
130
|
-
return result.readUInt32LE(0);
|
|
131
|
-
}
|
|
132
|
-
setInputRedeemScript(inputIndex: number, redeemScript: Buffer) {
|
|
133
|
-
this.setInput(inputIndex, psbtIn.REDEEM_SCRIPT, b(), redeemScript);
|
|
134
|
-
}
|
|
135
|
-
getInputRedeemScript(inputIndex: number): Buffer | undefined {
|
|
136
|
-
return this.getInputOptional(inputIndex, psbtIn.REDEEM_SCRIPT, b());
|
|
137
|
-
}
|
|
138
|
-
setInputBip32Derivation(
|
|
139
|
-
inputIndex: number,
|
|
140
|
-
pubkey: Buffer,
|
|
141
|
-
masterFingerprint: Buffer,
|
|
142
|
-
path: number[],
|
|
143
|
-
) {
|
|
144
|
-
if (pubkey.length != 33) throw new Error("Invalid pubkey length: " + pubkey.length);
|
|
145
|
-
this.setInput(
|
|
146
|
-
inputIndex,
|
|
147
|
-
psbtIn.BIP32_DERIVATION,
|
|
148
|
-
pubkey,
|
|
149
|
-
this.encodeBip32Derivation(masterFingerprint, path),
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
getInputBip32Derivation(
|
|
153
|
-
inputIndex: number,
|
|
154
|
-
pubkey: Buffer,
|
|
155
|
-
): { masterFingerprint: Buffer; path: number[] } | undefined {
|
|
156
|
-
const buf = this.getInputOptional(inputIndex, psbtIn.BIP32_DERIVATION, pubkey);
|
|
157
|
-
if (!buf) return undefined;
|
|
158
|
-
return this.decodeBip32Derivation(buf);
|
|
159
|
-
}
|
|
160
|
-
setInputFinalScriptsig(inputIndex: number, scriptSig: Buffer) {
|
|
161
|
-
this.setInput(inputIndex, psbtIn.FINAL_SCRIPTSIG, b(), scriptSig);
|
|
162
|
-
}
|
|
163
|
-
getInputFinalScriptsig(inputIndex: number): Buffer | undefined {
|
|
164
|
-
return this.getInputOptional(inputIndex, psbtIn.FINAL_SCRIPTSIG, b());
|
|
165
|
-
}
|
|
166
|
-
setInputFinalScriptwitness(inputIndex: number, scriptWitness: Buffer) {
|
|
167
|
-
this.setInput(inputIndex, psbtIn.FINAL_SCRIPTWITNESS, b(), scriptWitness);
|
|
168
|
-
}
|
|
169
|
-
getInputFinalScriptwitness(inputIndex: number): Buffer {
|
|
170
|
-
return this.getInput(inputIndex, psbtIn.FINAL_SCRIPTWITNESS, b());
|
|
171
|
-
}
|
|
172
|
-
setInputPreviousTxId(inputIndex: number, txid: Buffer) {
|
|
173
|
-
this.setInput(inputIndex, psbtIn.PREVIOUS_TXID, b(), txid);
|
|
174
|
-
}
|
|
175
|
-
getInputPreviousTxid(inputIndex: number): Buffer {
|
|
176
|
-
return this.getInput(inputIndex, psbtIn.PREVIOUS_TXID, b());
|
|
177
|
-
}
|
|
178
|
-
setInputOutputIndex(inputIndex: number, outputIndex: number) {
|
|
179
|
-
this.setInput(inputIndex, psbtIn.OUTPUT_INDEX, b(), uint32LE(outputIndex));
|
|
180
|
-
}
|
|
181
|
-
getInputOutputIndex(inputIndex: number): number {
|
|
182
|
-
return this.getInput(inputIndex, psbtIn.OUTPUT_INDEX, b()).readUInt32LE(0);
|
|
183
|
-
}
|
|
184
|
-
setInputSequence(inputIndex: number, sequence: number) {
|
|
185
|
-
this.setInput(inputIndex, psbtIn.SEQUENCE, b(), uint32LE(sequence));
|
|
186
|
-
}
|
|
187
|
-
getInputSequence(inputIndex: number): number {
|
|
188
|
-
return this.getInputOptional(inputIndex, psbtIn.SEQUENCE, b())?.readUInt32LE(0) ?? 0xffffffff;
|
|
189
|
-
}
|
|
190
|
-
setInputTapKeySig(inputIndex: number, sig: Buffer) {
|
|
191
|
-
this.setInput(inputIndex, psbtIn.TAP_KEY_SIG, b(), sig);
|
|
192
|
-
}
|
|
193
|
-
getInputTapKeySig(inputIndex: number): Buffer | undefined {
|
|
194
|
-
return this.getInputOptional(inputIndex, psbtIn.TAP_KEY_SIG, b());
|
|
195
|
-
}
|
|
196
|
-
setInputTapBip32Derivation(
|
|
197
|
-
inputIndex: number,
|
|
198
|
-
pubkey: Buffer,
|
|
199
|
-
hashes: Buffer[],
|
|
200
|
-
masterFingerprint: Buffer,
|
|
201
|
-
path: number[],
|
|
202
|
-
) {
|
|
203
|
-
if (pubkey.length != 32) throw new Error("Invalid pubkey length: " + pubkey.length);
|
|
204
|
-
const buf = this.encodeTapBip32Derivation(hashes, masterFingerprint, path);
|
|
205
|
-
this.setInput(inputIndex, psbtIn.TAP_BIP32_DERIVATION, pubkey, buf);
|
|
206
|
-
}
|
|
207
|
-
getInputTapBip32Derivation(
|
|
208
|
-
inputIndex: number,
|
|
209
|
-
pubkey: Buffer,
|
|
210
|
-
): { hashes: Buffer[]; masterFingerprint: Buffer; path: number[] } {
|
|
211
|
-
const buf = this.getInput(inputIndex, psbtIn.TAP_BIP32_DERIVATION, pubkey);
|
|
212
|
-
return this.decodeTapBip32Derivation(buf);
|
|
213
|
-
}
|
|
214
|
-
getInputKeyDatas(inputIndex: number, keyType: KeyType): Buffer[] {
|
|
215
|
-
return this.getKeyDatas(this.inputMaps[inputIndex], keyType);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
setOutputRedeemScript(outputIndex: number, redeemScript: Buffer) {
|
|
219
|
-
this.setOutput(outputIndex, psbtOut.REDEEM_SCRIPT, b(), redeemScript);
|
|
220
|
-
}
|
|
221
|
-
getOutputRedeemScript(outputIndex: number): Buffer {
|
|
222
|
-
return this.getOutput(outputIndex, psbtOut.REDEEM_SCRIPT, b());
|
|
223
|
-
}
|
|
224
|
-
setOutputBip32Derivation(
|
|
225
|
-
outputIndex: number,
|
|
226
|
-
pubkey: Buffer,
|
|
227
|
-
masterFingerprint: Buffer,
|
|
228
|
-
path: number[],
|
|
229
|
-
) {
|
|
230
|
-
this.setOutput(
|
|
231
|
-
outputIndex,
|
|
232
|
-
psbtOut.BIP_32_DERIVATION,
|
|
233
|
-
pubkey,
|
|
234
|
-
this.encodeBip32Derivation(masterFingerprint, path),
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
getOutputBip32Derivation(
|
|
238
|
-
outputIndex: number,
|
|
239
|
-
pubkey: Buffer,
|
|
240
|
-
): { masterFingerprint: Buffer; path: number[] } {
|
|
241
|
-
const buf = this.getOutput(outputIndex, psbtOut.BIP_32_DERIVATION, pubkey);
|
|
242
|
-
return this.decodeBip32Derivation(buf);
|
|
243
|
-
}
|
|
244
|
-
setOutputAmount(outputIndex: number, amount: number) {
|
|
245
|
-
this.setOutput(outputIndex, psbtOut.AMOUNT, b(), uint64LE(amount));
|
|
246
|
-
}
|
|
247
|
-
getOutputAmount(outputIndex: number): number {
|
|
248
|
-
const buf = this.getOutput(outputIndex, psbtOut.AMOUNT, b());
|
|
249
|
-
return unsafeFrom64bitLE(buf);
|
|
250
|
-
}
|
|
251
|
-
setOutputScript(outputIndex: number, scriptPubKey: Buffer) {
|
|
252
|
-
this.setOutput(outputIndex, psbtOut.SCRIPT, b(), scriptPubKey);
|
|
253
|
-
}
|
|
254
|
-
getOutputScript(outputIndex: number): Buffer {
|
|
255
|
-
return this.getOutput(outputIndex, psbtOut.SCRIPT, b());
|
|
256
|
-
}
|
|
257
|
-
setOutputTapBip32Derivation(
|
|
258
|
-
outputIndex: number,
|
|
259
|
-
pubkey: Buffer,
|
|
260
|
-
hashes: Buffer[],
|
|
261
|
-
fingerprint: Buffer,
|
|
262
|
-
path: number[],
|
|
263
|
-
) {
|
|
264
|
-
const buf = this.encodeTapBip32Derivation(hashes, fingerprint, path);
|
|
265
|
-
this.setOutput(outputIndex, psbtOut.TAP_BIP32_DERIVATION, pubkey, buf);
|
|
266
|
-
}
|
|
267
|
-
getOutputTapBip32Derivation(
|
|
268
|
-
outputIndex: number,
|
|
269
|
-
pubkey: Buffer,
|
|
270
|
-
): { hashes: Buffer[]; masterFingerprint: Buffer; path: number[] } {
|
|
271
|
-
const buf = this.getOutput(outputIndex, psbtOut.TAP_BIP32_DERIVATION, pubkey);
|
|
272
|
-
return this.decodeTapBip32Derivation(buf);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
deleteInputEntries(inputIndex: number, keyTypes: psbtIn[]) {
|
|
276
|
-
const map = this.inputMaps[inputIndex];
|
|
277
|
-
map.forEach((_v, k, m) => {
|
|
278
|
-
if (this.isKeyType(k, keyTypes)) {
|
|
279
|
-
m.delete(k);
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
copy(to: PsbtV2) {
|
|
285
|
-
this.copyMap(this.globalMap, to.globalMap);
|
|
286
|
-
this.copyMaps(this.inputMaps, to.inputMaps);
|
|
287
|
-
this.copyMaps(this.outputMaps, to.outputMaps);
|
|
288
|
-
}
|
|
289
|
-
copyMaps(from: Map<string, Buffer>[], to: Map<string, Buffer>[]) {
|
|
290
|
-
from.forEach((m, index) => {
|
|
291
|
-
const to_index = new Map();
|
|
292
|
-
this.copyMap(m, to_index);
|
|
293
|
-
to[index] = to_index;
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
copyMap(from: Map<string, Buffer>, to: Map<string, Buffer>) {
|
|
297
|
-
from.forEach((v, k) => to.set(k, Buffer.from(v)));
|
|
298
|
-
}
|
|
299
|
-
serialize(): Buffer {
|
|
300
|
-
const buf = new BufferWriter();
|
|
301
|
-
buf.writeSlice(Buffer.from([0x70, 0x73, 0x62, 0x74, 0xff]));
|
|
302
|
-
serializeMap(buf, this.globalMap);
|
|
303
|
-
this.inputMaps.forEach(map => {
|
|
304
|
-
serializeMap(buf, map);
|
|
305
|
-
});
|
|
306
|
-
this.outputMaps.forEach(map => {
|
|
307
|
-
serializeMap(buf, map);
|
|
308
|
-
});
|
|
309
|
-
return buf.buffer();
|
|
310
|
-
}
|
|
311
|
-
deserialize(psbt: Buffer) {
|
|
312
|
-
const buf = new BufferReader(psbt);
|
|
313
|
-
if (!buf.readSlice(5).equals(PSBT_MAGIC_BYTES)) {
|
|
314
|
-
throw new Error("Invalid magic bytes");
|
|
315
|
-
}
|
|
316
|
-
while (this.readKeyPair(this.globalMap, buf));
|
|
317
|
-
for (let i = 0; i < this.getGlobalInputCount(); i++) {
|
|
318
|
-
this.inputMaps[i] = new Map();
|
|
319
|
-
while (this.readKeyPair(this.inputMaps[i], buf));
|
|
320
|
-
}
|
|
321
|
-
for (let i = 0; i < this.getGlobalOutputCount(); i++) {
|
|
322
|
-
this.outputMaps[i] = new Map();
|
|
323
|
-
while (this.readKeyPair(this.outputMaps[i], buf));
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
private readKeyPair(map: Map<string, Buffer>, buf: BufferReader): boolean {
|
|
327
|
-
const keyLen = buf.readVarInt();
|
|
328
|
-
if (keyLen == 0) {
|
|
329
|
-
return false;
|
|
330
|
-
}
|
|
331
|
-
const keyType = buf.readUInt8();
|
|
332
|
-
const keyData = buf.readSlice(keyLen - 1);
|
|
333
|
-
const value = buf.readVarSlice();
|
|
334
|
-
set(map, keyType, keyData, value);
|
|
335
|
-
return true;
|
|
336
|
-
}
|
|
337
|
-
private getKeyDatas(map: Map<string, Buffer>, keyType: KeyType): Buffer[] {
|
|
338
|
-
const result: Buffer[] = [];
|
|
339
|
-
map.forEach((_v, k) => {
|
|
340
|
-
if (this.isKeyType(k, [keyType])) {
|
|
341
|
-
result.push(Buffer.from(k.substring(2), "hex"));
|
|
342
|
-
}
|
|
343
|
-
});
|
|
344
|
-
return result;
|
|
345
|
-
}
|
|
346
|
-
private isKeyType(hexKey: string, keyTypes: KeyType[]): boolean {
|
|
347
|
-
const keyType = Buffer.from(hexKey.substring(0, 2), "hex").readUInt8(0);
|
|
348
|
-
return keyTypes.some(k => k == keyType);
|
|
349
|
-
}
|
|
350
|
-
private setGlobal(keyType: KeyType, value: Buffer) {
|
|
351
|
-
const key = new Key(keyType, Buffer.from([]));
|
|
352
|
-
this.globalMap.set(key.toString(), value);
|
|
353
|
-
}
|
|
354
|
-
private getGlobal(keyType: KeyType): Buffer {
|
|
355
|
-
return get(this.globalMap, keyType, b(), false)!;
|
|
356
|
-
}
|
|
357
|
-
private getGlobalOptional(keyType: KeyType): Buffer | undefined {
|
|
358
|
-
return get(this.globalMap, keyType, b(), true);
|
|
359
|
-
}
|
|
360
|
-
private setInput(index: number, keyType: KeyType, keyData: Buffer, value: Buffer) {
|
|
361
|
-
set(this.getMap(index, this.inputMaps), keyType, keyData, value);
|
|
362
|
-
}
|
|
363
|
-
private getInput(index: number, keyType: KeyType, keyData: Buffer): Buffer {
|
|
364
|
-
return get(this.inputMaps[index], keyType, keyData, false)!;
|
|
365
|
-
}
|
|
366
|
-
private getInputOptional(index: number, keyType: KeyType, keyData: Buffer): Buffer | undefined {
|
|
367
|
-
return get(this.inputMaps[index], keyType, keyData, true);
|
|
368
|
-
}
|
|
369
|
-
private setOutput(index: number, keyType: KeyType, keyData: Buffer, value: Buffer) {
|
|
370
|
-
set(this.getMap(index, this.outputMaps), keyType, keyData, value);
|
|
371
|
-
}
|
|
372
|
-
private getOutput(index: number, keyType: KeyType, keyData: Buffer): Buffer {
|
|
373
|
-
return get(this.outputMaps[index], keyType, keyData, false)!;
|
|
374
|
-
}
|
|
375
|
-
private getMap(index: number, maps: Map<string, Buffer>[]): Map<string, Buffer> {
|
|
376
|
-
if (maps[index]) {
|
|
377
|
-
return maps[index];
|
|
378
|
-
}
|
|
379
|
-
return (maps[index] = new Map());
|
|
380
|
-
}
|
|
381
|
-
private encodeBip32Derivation(masterFingerprint: Buffer, path: number[]) {
|
|
382
|
-
const buf = new BufferWriter();
|
|
383
|
-
this.writeBip32Derivation(buf, masterFingerprint, path);
|
|
384
|
-
return buf.buffer();
|
|
385
|
-
}
|
|
386
|
-
private decodeBip32Derivation(buffer: Buffer): {
|
|
387
|
-
masterFingerprint: Buffer;
|
|
388
|
-
path: number[];
|
|
389
|
-
} {
|
|
390
|
-
const buf = new BufferReader(buffer);
|
|
391
|
-
return this.readBip32Derivation(buf);
|
|
392
|
-
}
|
|
393
|
-
private writeBip32Derivation(buf: BufferWriter, masterFingerprint: Buffer, path: number[]) {
|
|
394
|
-
buf.writeSlice(masterFingerprint);
|
|
395
|
-
path.forEach(element => {
|
|
396
|
-
buf.writeUInt32(element);
|
|
397
|
-
});
|
|
398
|
-
}
|
|
399
|
-
private readBip32Derivation(buf: BufferReader): {
|
|
400
|
-
masterFingerprint: Buffer;
|
|
401
|
-
path: number[];
|
|
402
|
-
} {
|
|
403
|
-
const masterFingerprint = buf.readSlice(4);
|
|
404
|
-
const path: number[] = [];
|
|
405
|
-
while (buf.offset < buf.buffer.length) {
|
|
406
|
-
path.push(buf.readUInt32());
|
|
407
|
-
}
|
|
408
|
-
return { masterFingerprint, path };
|
|
409
|
-
}
|
|
410
|
-
private encodeTapBip32Derivation(
|
|
411
|
-
hashes: Buffer[],
|
|
412
|
-
masterFingerprint: Buffer,
|
|
413
|
-
path: number[],
|
|
414
|
-
): Buffer {
|
|
415
|
-
const buf = new BufferWriter();
|
|
416
|
-
buf.writeVarInt(hashes.length);
|
|
417
|
-
hashes.forEach(h => {
|
|
418
|
-
buf.writeSlice(h);
|
|
419
|
-
});
|
|
420
|
-
this.writeBip32Derivation(buf, masterFingerprint, path);
|
|
421
|
-
return buf.buffer();
|
|
422
|
-
}
|
|
423
|
-
private decodeTapBip32Derivation(buffer: Buffer): {
|
|
424
|
-
hashes: Buffer[];
|
|
425
|
-
masterFingerprint: Buffer;
|
|
426
|
-
path: number[];
|
|
427
|
-
} {
|
|
428
|
-
const buf = new BufferReader(buffer);
|
|
429
|
-
const hashCount = buf.readVarInt();
|
|
430
|
-
const hashes: Buffer[] = [];
|
|
431
|
-
for (let i = 0; i < hashCount; i++) {
|
|
432
|
-
hashes.push(buf.readSlice(32));
|
|
433
|
-
}
|
|
434
|
-
const deriv = this.readBip32Derivation(buf);
|
|
435
|
-
return { hashes, ...deriv };
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
function get(
|
|
439
|
-
map: Map<string, Buffer>,
|
|
440
|
-
keyType: KeyType,
|
|
441
|
-
keyData: Buffer,
|
|
442
|
-
acceptUndefined: boolean,
|
|
443
|
-
): Buffer | undefined {
|
|
444
|
-
if (!map) throw Error("No such map");
|
|
445
|
-
const key = new Key(keyType, keyData);
|
|
446
|
-
const value = map.get(key.toString());
|
|
447
|
-
if (!value) {
|
|
448
|
-
if (acceptUndefined) {
|
|
449
|
-
return undefined;
|
|
450
|
-
}
|
|
451
|
-
throw new NoSuchEntry(key.toString());
|
|
452
|
-
}
|
|
453
|
-
// Make sure to return a copy, to protect the underlying data.
|
|
454
|
-
return Buffer.from(value);
|
|
455
|
-
}
|
|
456
|
-
type KeyType = number;
|
|
457
|
-
|
|
458
|
-
class Key {
|
|
459
|
-
keyType: KeyType;
|
|
460
|
-
keyData: Buffer;
|
|
461
|
-
constructor(keyType: KeyType, keyData: Buffer) {
|
|
462
|
-
this.keyType = keyType;
|
|
463
|
-
this.keyData = keyData;
|
|
464
|
-
}
|
|
465
|
-
toString(): string {
|
|
466
|
-
const buf = new BufferWriter();
|
|
467
|
-
this.toBuffer(buf);
|
|
468
|
-
return buf.buffer().toString("hex");
|
|
469
|
-
}
|
|
470
|
-
serialize(buf: BufferWriter) {
|
|
471
|
-
buf.writeVarInt(1 + this.keyData.length);
|
|
472
|
-
this.toBuffer(buf);
|
|
473
|
-
}
|
|
474
|
-
private toBuffer(buf: BufferWriter) {
|
|
475
|
-
buf.writeUInt8(this.keyType);
|
|
476
|
-
buf.writeSlice(this.keyData);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
class KeyPair {
|
|
480
|
-
key: Key;
|
|
481
|
-
value: Buffer;
|
|
482
|
-
constructor(key: Key, value: Buffer) {
|
|
483
|
-
this.key = key;
|
|
484
|
-
this.value = value;
|
|
485
|
-
}
|
|
486
|
-
serialize(buf: BufferWriter) {
|
|
487
|
-
this.key.serialize(buf);
|
|
488
|
-
buf.writeVarSlice(this.value);
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
function createKey(buf: Buffer): Key {
|
|
492
|
-
return new Key(buf.readUInt8(0), buf.slice(1));
|
|
493
|
-
}
|
|
494
|
-
function serializeMap(buf: BufferWriter, map: Map<string, Buffer>) {
|
|
495
|
-
for (const k of map.keys()) {
|
|
496
|
-
const value = map.get(k)!;
|
|
497
|
-
const keyPair = new KeyPair(createKey(Buffer.from(k, "hex")), value);
|
|
498
|
-
keyPair.serialize(buf);
|
|
499
|
-
}
|
|
500
|
-
buf.writeUInt8(0);
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
function b(): Buffer {
|
|
504
|
-
return Buffer.from([]);
|
|
505
|
-
}
|
|
506
|
-
function set(map: Map<string, Buffer>, keyType: KeyType, keyData: Buffer, value: Buffer) {
|
|
507
|
-
const key = new Key(keyType, keyData);
|
|
508
|
-
map.set(key.toString(), value);
|
|
509
|
-
}
|
|
510
|
-
function uint32LE(n: number): Buffer {
|
|
511
|
-
const b = Buffer.alloc(4);
|
|
512
|
-
b.writeUInt32LE(n, 0);
|
|
513
|
-
return b;
|
|
514
|
-
}
|
|
515
|
-
function uint64LE(n: number): Buffer {
|
|
516
|
-
return unsafeTo64bitLE(n);
|
|
517
|
-
}
|
|
518
|
-
function varint(n: number): Buffer {
|
|
519
|
-
const b = new BufferWriter();
|
|
520
|
-
b.writeVarInt(n);
|
|
521
|
-
return b.buffer();
|
|
522
|
-
}
|
|
523
|
-
function fromVarint(buf: Buffer): number {
|
|
524
|
-
return new BufferReader(buf).readVarInt();
|
|
525
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { BufferReader, BufferWriter } from "../src/buffertools";
|
|
2
|
-
|
|
3
|
-
function run(n: number, expectedHex: string) {
|
|
4
|
-
const w = new BufferWriter();
|
|
5
|
-
w.writeUInt64(n);
|
|
6
|
-
expect(w.buffer()).toEqual(Buffer.from(expectedHex, "hex"));
|
|
7
|
-
const r = new BufferReader(w.buffer());
|
|
8
|
-
expect(r.readUInt64()).toEqual(n);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
test("Test 64 bit numbers", () => {
|
|
12
|
-
run(0, "0000000000000000");
|
|
13
|
-
run(1, "0100000000000000");
|
|
14
|
-
run(0xffffffff, "ffffffff00000000");
|
|
15
|
-
run(0x0100000000, "0000000001000000");
|
|
16
|
-
run(0x010203040506, "0605040302010000");
|
|
17
|
-
run(Number.MAX_SAFE_INTEGER, "FFFFFFFFFFFF1F00");
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
test("Too big 64 bit number", () => {
|
|
21
|
-
const w = new BufferWriter();
|
|
22
|
-
expect(() => w.writeUInt64(Number.MAX_SAFE_INTEGER + 1)).toThrow();
|
|
23
|
-
const r = new BufferReader(Buffer.from("FFFFFFFFFFFF2000", "hex"));
|
|
24
|
-
expect(() => r.readUInt64()).toThrow();
|
|
25
|
-
});
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { PsbtV2 } from "../../src/newops/psbtv2";
|
|
2
|
-
|
|
3
|
-
describe("PsbtV2", () => {
|
|
4
|
-
it("deserializes a psbt and reserializes it unchanged", async () => {
|
|
5
|
-
const psbtBuf = Buffer.from(
|
|
6
|
-
"cHNidP8BAAoBAAAAAAAAAAAAAQIEAgAAAAEDBAAAAAABBAECAQUBAgH7BAIAAAAAAQBxAgAAAAGTarLgEHL3k8/kyXdU3hth/gPn22U2yLLyHdC1dCxIRQEAAAAA/v///wLe4ccAAAAAABYAFOt418QL8QY7Dj/OKcNWW2ichVmrECcAAAAAAAAWABQjGNZvhP71xIdfkzsDjcY4MfjaE/mXHgABAR8QJwAAAAAAABYAFCMY1m+E/vXEh1+TOwONxjgx+NoTIgYDRV7nztyXsLpDW4AGb8ksljo0xgAxeYHRNTMMTuQ6x6MY9azC/VQAAIABAACAAAAAgAAAAAABAAAAAQ4gniz+J/Cth7eKI31ddAXUowZmyjYdWFpGew3+QiYrTbQBDwQBAAAAARAE/f///wESBAAAAAAAAQBxAQAAAAEORx706Sway1HvyGYPjT9pk26pybK/9y/5vIHFHvz0ZAEAAAAAAAAAAAJgrgoAAAAAABYAFDXG4N1tPISxa6iF3Kc6yGPQtZPsrwYyAAAAAAAWABTcKG4M0ua9N86+nsNJ+18IkFZy/AAAAAABAR9grgoAAAAAABYAFDXG4N1tPISxa6iF3Kc6yGPQtZPsIgYCcbW3ea2HCDhYd5e89vDHrsWr52pwnXJPSNLibPh08KAY9azC/VQAAIABAACAAAAAgAEAAAAAAAAAAQ4gr7+uBlkPdB/xr1m2rEYRJjNqTEqC21U99v76tzesM/MBDwQAAAAAARAE/f///wESBAAAAAAAIgICKexHcnEx7SWIogxG7amrt9qm9J/VC6/nC5xappYcTswY9azC/VQAAIABAACAAAAAgAEAAAAKAAAAAQMIqDoGAAAAAAABBBYAFOs4+puBKPgfJule2wxf+uqDaQ/kAAEDCOCTBAAAAAAAAQQiACA/qWbJ3c3C/ZbkpeG8dlufr2zos+tPEQSq1r33cyTlvgA=",
|
|
7
|
-
"base64",
|
|
8
|
-
);
|
|
9
|
-
|
|
10
|
-
const psbt = new PsbtV2();
|
|
11
|
-
psbt.deserialize(psbtBuf);
|
|
12
|
-
|
|
13
|
-
expect(psbt.serialize()).toEqual(psbtBuf);
|
|
14
|
-
});
|
|
15
|
-
});
|