@bitgo/wasm-utxo 1.6.0 → 1.8.0
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/dist/cjs/js/bip32.d.ts +140 -0
- package/dist/cjs/js/bip32.js +177 -0
- package/dist/cjs/js/ecpair.d.ts +96 -0
- package/dist/cjs/js/ecpair.js +134 -0
- package/dist/cjs/js/fixedScriptWallet/BitGoPsbt.d.ts +242 -0
- package/dist/cjs/js/fixedScriptWallet/BitGoPsbt.js +274 -0
- package/dist/cjs/js/fixedScriptWallet/ReplayProtection.d.ts +58 -0
- package/dist/cjs/js/fixedScriptWallet/ReplayProtection.js +89 -0
- package/dist/cjs/js/fixedScriptWallet/RootWalletKeys.d.ts +66 -0
- package/dist/cjs/js/fixedScriptWallet/RootWalletKeys.js +108 -0
- package/dist/cjs/js/fixedScriptWallet/address.d.ts +20 -0
- package/dist/cjs/js/fixedScriptWallet/address.js +29 -0
- package/dist/cjs/js/fixedScriptWallet/index.d.ts +4 -0
- package/dist/cjs/js/fixedScriptWallet/index.js +12 -0
- package/dist/cjs/js/index.d.ts +5 -1
- package/dist/cjs/js/index.js +11 -2
- package/dist/cjs/js/utxolibCompat.d.ts +0 -18
- package/dist/cjs/js/wasm/wasm_utxo.d.ts +333 -15
- package/dist/cjs/js/wasm/wasm_utxo.js +1311 -201
- package/dist/cjs/js/wasm/wasm_utxo_bg.wasm +0 -0
- package/dist/cjs/js/wasm/wasm_utxo_bg.wasm.d.ts +64 -15
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/js/bip32.d.ts +140 -0
- package/dist/esm/js/bip32.js +173 -0
- package/dist/esm/js/ecpair.d.ts +96 -0
- package/dist/esm/js/ecpair.js +130 -0
- package/dist/esm/js/fixedScriptWallet/BitGoPsbt.d.ts +242 -0
- package/dist/esm/js/fixedScriptWallet/BitGoPsbt.js +270 -0
- package/dist/esm/js/fixedScriptWallet/ReplayProtection.d.ts +58 -0
- package/dist/esm/js/fixedScriptWallet/ReplayProtection.js +85 -0
- package/dist/esm/js/fixedScriptWallet/RootWalletKeys.d.ts +66 -0
- package/dist/esm/js/fixedScriptWallet/RootWalletKeys.js +104 -0
- package/dist/esm/js/fixedScriptWallet/address.d.ts +20 -0
- package/dist/esm/js/fixedScriptWallet/address.js +25 -0
- package/dist/esm/js/fixedScriptWallet/index.d.ts +4 -0
- package/dist/esm/js/fixedScriptWallet/index.js +4 -0
- package/dist/esm/js/index.d.ts +5 -1
- package/dist/esm/js/index.js +8 -1
- package/dist/esm/js/utxolibCompat.d.ts +0 -18
- package/dist/esm/js/wasm/wasm_utxo.d.ts +333 -15
- package/dist/esm/js/wasm/wasm_utxo_bg.js +1301 -199
- package/dist/esm/js/wasm/wasm_utxo_bg.wasm +0 -0
- package/dist/esm/js/wasm/wasm_utxo_bg.wasm.d.ts +64 -15
- package/dist/esm/test/bip32.js +242 -0
- package/dist/esm/test/ecpair.d.ts +1 -0
- package/dist/esm/test/ecpair.js +137 -0
- package/dist/esm/test/fixedScript/fixtureUtil.d.ts +12 -2
- package/dist/esm/test/fixedScript/fixtureUtil.js +28 -7
- package/dist/esm/test/fixedScript/musig2Nonces.d.ts +1 -0
- package/dist/esm/test/fixedScript/musig2Nonces.js +77 -0
- package/dist/esm/test/fixedScript/parseTransactionWithWalletKeys.js +7 -7
- package/dist/esm/test/fixedScript/signAndVerifySignature.d.ts +1 -0
- package/dist/esm/test/fixedScript/signAndVerifySignature.js +268 -0
- package/dist/esm/test/fixedScript/walletKeys.util.d.ts +12 -0
- package/dist/esm/test/fixedScript/walletKeys.util.js +17 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/dist/cjs/js/fixedScriptWallet.d.ts +0 -146
- package/dist/cjs/js/fixedScriptWallet.js +0 -138
- package/dist/esm/js/fixedScriptWallet.d.ts +0 -146
- package/dist/esm/js/fixedScriptWallet.js +0 -132
- package/dist/esm/test/fixedScript/verifySignature.js +0 -141
- /package/dist/esm/test/{fixedScript/verifySignature.d.ts → bip32.d.ts} +0 -0
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BitGoPsbt = void 0;
|
|
4
|
-
exports.outputScript = outputScript;
|
|
5
|
-
exports.address = address;
|
|
6
|
-
const wasm_utxo_js_1 = require("./wasm/wasm_utxo.js");
|
|
7
|
-
/**
|
|
8
|
-
* Create the output script for a given wallet keys and chain and index
|
|
9
|
-
*/
|
|
10
|
-
function outputScript(keys, chain, index, network) {
|
|
11
|
-
return wasm_utxo_js_1.FixedScriptWalletNamespace.output_script(keys, chain, index, network);
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Create the address for a given wallet keys and chain and index and network.
|
|
15
|
-
* Wrapper for outputScript that also encodes the script to an address.
|
|
16
|
-
* @param keys - The wallet keys to use.
|
|
17
|
-
* @param chain - The chain to use.
|
|
18
|
-
* @param index - The index to use.
|
|
19
|
-
* @param network - The network to use.
|
|
20
|
-
* @param addressFormat - The address format to use.
|
|
21
|
-
* Only relevant for Bitcoin Cash and eCash networks, where:
|
|
22
|
-
* - "default" means base58check,
|
|
23
|
-
* - "cashaddr" means cashaddr.
|
|
24
|
-
*/
|
|
25
|
-
function address(keys, chain, index, network, addressFormat) {
|
|
26
|
-
return wasm_utxo_js_1.FixedScriptWalletNamespace.address(keys, chain, index, network, addressFormat);
|
|
27
|
-
}
|
|
28
|
-
const wasm_utxo_js_2 = require("./wasm/wasm_utxo.js");
|
|
29
|
-
class BitGoPsbt {
|
|
30
|
-
wasm;
|
|
31
|
-
constructor(wasm) {
|
|
32
|
-
this.wasm = wasm;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Deserialize a PSBT from bytes
|
|
36
|
-
* @param bytes - The PSBT bytes
|
|
37
|
-
* @param network - The network to use for deserialization (either utxolib name like "bitcoin" or coin name like "btc")
|
|
38
|
-
* @returns A BitGoPsbt instance
|
|
39
|
-
*/
|
|
40
|
-
static fromBytes(bytes, network) {
|
|
41
|
-
const wasm = wasm_utxo_js_2.BitGoPsbt.from_bytes(bytes, network);
|
|
42
|
-
return new BitGoPsbt(wasm);
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Get the unsigned transaction ID
|
|
46
|
-
* @returns The unsigned transaction ID
|
|
47
|
-
*/
|
|
48
|
-
unsignedTxid() {
|
|
49
|
-
return this.wasm.unsigned_txid();
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Parse transaction with wallet keys to identify wallet inputs/outputs
|
|
53
|
-
* @param walletKeys - The wallet keys to use for identification
|
|
54
|
-
* @param replayProtection - Scripts that are allowed as inputs without wallet validation
|
|
55
|
-
* @returns Parsed transaction information
|
|
56
|
-
*/
|
|
57
|
-
parseTransactionWithWalletKeys(walletKeys, replayProtection) {
|
|
58
|
-
return this.wasm.parse_transaction_with_wallet_keys(walletKeys, replayProtection);
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Parse outputs with wallet keys to identify which outputs belong to a wallet
|
|
62
|
-
* with the given wallet keys.
|
|
63
|
-
*
|
|
64
|
-
* This is useful in cases where we want to identify outputs that belong to a different
|
|
65
|
-
* wallet than the inputs.
|
|
66
|
-
*
|
|
67
|
-
* @param walletKeys - The wallet keys to use for identification
|
|
68
|
-
* @returns Array of parsed outputs
|
|
69
|
-
* @note This method does NOT validate wallet inputs. It only parses outputs.
|
|
70
|
-
*/
|
|
71
|
-
parseOutputsWithWalletKeys(walletKeys) {
|
|
72
|
-
return this.wasm.parse_outputs_with_wallet_keys(walletKeys);
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Verify if a valid signature exists for a given extended public key at the specified input index.
|
|
76
|
-
*
|
|
77
|
-
* This method derives the public key from the xpub using the derivation path found in the
|
|
78
|
-
* PSBT input, then verifies the signature. It supports:
|
|
79
|
-
* - ECDSA signatures (for legacy/SegWit inputs)
|
|
80
|
-
* - Schnorr signatures (for Taproot script path inputs)
|
|
81
|
-
* - MuSig2 partial signatures (for Taproot keypath MuSig2 inputs)
|
|
82
|
-
*
|
|
83
|
-
* @param inputIndex - The index of the input to check (0-based)
|
|
84
|
-
* @param xpub - The extended public key as a base58-encoded string
|
|
85
|
-
* @returns true if a valid signature exists, false if no signature exists
|
|
86
|
-
* @throws Error if input index is out of bounds, xpub is invalid, or verification fails
|
|
87
|
-
*/
|
|
88
|
-
verifySignature(inputIndex, xpub) {
|
|
89
|
-
return this.wasm.verify_signature(inputIndex, xpub);
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Verify if a replay protection input has a valid signature.
|
|
93
|
-
*
|
|
94
|
-
* This method checks if a given input is a replay protection input (like P2shP2pk) and verifies
|
|
95
|
-
* the signature. Replay protection inputs don't use standard derivation paths, so this method
|
|
96
|
-
* verifies signatures without deriving from xpub.
|
|
97
|
-
*
|
|
98
|
-
* For P2PK replay protection inputs, this:
|
|
99
|
-
* - Extracts the signature from final_script_sig
|
|
100
|
-
* - Extracts the public key from redeem_script
|
|
101
|
-
* - Computes the legacy P2SH sighash
|
|
102
|
-
* - Verifies the ECDSA signature cryptographically
|
|
103
|
-
*
|
|
104
|
-
* @param inputIndex - The index of the input to check (0-based)
|
|
105
|
-
* @param replayProtection - Scripts that identify replay protection inputs (same format as parseTransactionWithWalletKeys)
|
|
106
|
-
* @returns true if the input is a replay protection input and has a valid signature, false if no valid signature
|
|
107
|
-
* @throws Error if the input is not a replay protection input, index is out of bounds, or scripts are invalid
|
|
108
|
-
*/
|
|
109
|
-
verifyReplayProtectionSignature(inputIndex, replayProtection) {
|
|
110
|
-
return this.wasm.verify_replay_protection_signature(inputIndex, replayProtection);
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Serialize the PSBT to bytes
|
|
114
|
-
*
|
|
115
|
-
* @returns The serialized PSBT as a byte array
|
|
116
|
-
*/
|
|
117
|
-
serialize() {
|
|
118
|
-
return this.wasm.serialize();
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Finalize all inputs in the PSBT
|
|
122
|
-
*
|
|
123
|
-
* @throws Error if any input failed to finalize
|
|
124
|
-
*/
|
|
125
|
-
finalizeAllInputs() {
|
|
126
|
-
this.wasm.finalize_all_inputs();
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Extract the final transaction from a finalized PSBT
|
|
130
|
-
*
|
|
131
|
-
* @returns The serialized transaction bytes
|
|
132
|
-
* @throws Error if the PSBT is not fully finalized or extraction fails
|
|
133
|
-
*/
|
|
134
|
-
extractTransaction() {
|
|
135
|
-
return this.wasm.extract_transaction();
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
exports.BitGoPsbt = BitGoPsbt;
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import type { UtxolibName, UtxolibNetwork, UtxolibRootWalletKeys } from "./utxolibCompat.js";
|
|
2
|
-
import type { CoinName } from "./coinName.js";
|
|
3
|
-
import { Triple } from "./triple.js";
|
|
4
|
-
import { AddressFormat } from "./address.js";
|
|
5
|
-
export type NetworkName = UtxolibName | CoinName;
|
|
6
|
-
export type WalletKeys =
|
|
7
|
-
/** Just an xpub triple, will assume default derivation prefixes */
|
|
8
|
-
Triple<string>
|
|
9
|
-
/** Compatible with utxolib RootWalletKeys */
|
|
10
|
-
| UtxolibRootWalletKeys;
|
|
11
|
-
/**
|
|
12
|
-
* Create the output script for a given wallet keys and chain and index
|
|
13
|
-
*/
|
|
14
|
-
export declare function outputScript(keys: WalletKeys, chain: number, index: number, network: UtxolibNetwork): Uint8Array;
|
|
15
|
-
/**
|
|
16
|
-
* Create the address for a given wallet keys and chain and index and network.
|
|
17
|
-
* Wrapper for outputScript that also encodes the script to an address.
|
|
18
|
-
* @param keys - The wallet keys to use.
|
|
19
|
-
* @param chain - The chain to use.
|
|
20
|
-
* @param index - The index to use.
|
|
21
|
-
* @param network - The network to use.
|
|
22
|
-
* @param addressFormat - The address format to use.
|
|
23
|
-
* Only relevant for Bitcoin Cash and eCash networks, where:
|
|
24
|
-
* - "default" means base58check,
|
|
25
|
-
* - "cashaddr" means cashaddr.
|
|
26
|
-
*/
|
|
27
|
-
export declare function address(keys: WalletKeys, chain: number, index: number, network: UtxolibNetwork, addressFormat?: AddressFormat): string;
|
|
28
|
-
type ReplayProtection = {
|
|
29
|
-
outputScripts: Uint8Array[];
|
|
30
|
-
} | {
|
|
31
|
-
addresses: string[];
|
|
32
|
-
};
|
|
33
|
-
export type ScriptId = {
|
|
34
|
-
chain: number;
|
|
35
|
-
index: number;
|
|
36
|
-
};
|
|
37
|
-
export type InputScriptType = "p2shP2pk" | "p2sh" | "p2shP2wsh" | "p2wsh" | "p2trLegacy" | "p2trMusig2ScriptPath" | "p2trMusig2KeyPath";
|
|
38
|
-
export type ParsedInput = {
|
|
39
|
-
address: string;
|
|
40
|
-
script: Uint8Array;
|
|
41
|
-
value: bigint;
|
|
42
|
-
scriptId: ScriptId | null;
|
|
43
|
-
scriptType: InputScriptType;
|
|
44
|
-
};
|
|
45
|
-
export type ParsedOutput = {
|
|
46
|
-
address: string | null;
|
|
47
|
-
script: Uint8Array;
|
|
48
|
-
value: bigint;
|
|
49
|
-
scriptId: ScriptId | null;
|
|
50
|
-
};
|
|
51
|
-
export type ParsedTransaction = {
|
|
52
|
-
inputs: ParsedInput[];
|
|
53
|
-
outputs: ParsedOutput[];
|
|
54
|
-
spendAmount: bigint;
|
|
55
|
-
minerFee: bigint;
|
|
56
|
-
virtualSize: number;
|
|
57
|
-
};
|
|
58
|
-
export declare class BitGoPsbt {
|
|
59
|
-
private wasm;
|
|
60
|
-
private constructor();
|
|
61
|
-
/**
|
|
62
|
-
* Deserialize a PSBT from bytes
|
|
63
|
-
* @param bytes - The PSBT bytes
|
|
64
|
-
* @param network - The network to use for deserialization (either utxolib name like "bitcoin" or coin name like "btc")
|
|
65
|
-
* @returns A BitGoPsbt instance
|
|
66
|
-
*/
|
|
67
|
-
static fromBytes(bytes: Uint8Array, network: NetworkName): BitGoPsbt;
|
|
68
|
-
/**
|
|
69
|
-
* Get the unsigned transaction ID
|
|
70
|
-
* @returns The unsigned transaction ID
|
|
71
|
-
*/
|
|
72
|
-
unsignedTxid(): string;
|
|
73
|
-
/**
|
|
74
|
-
* Parse transaction with wallet keys to identify wallet inputs/outputs
|
|
75
|
-
* @param walletKeys - The wallet keys to use for identification
|
|
76
|
-
* @param replayProtection - Scripts that are allowed as inputs without wallet validation
|
|
77
|
-
* @returns Parsed transaction information
|
|
78
|
-
*/
|
|
79
|
-
parseTransactionWithWalletKeys(walletKeys: WalletKeys, replayProtection: ReplayProtection): ParsedTransaction;
|
|
80
|
-
/**
|
|
81
|
-
* Parse outputs with wallet keys to identify which outputs belong to a wallet
|
|
82
|
-
* with the given wallet keys.
|
|
83
|
-
*
|
|
84
|
-
* This is useful in cases where we want to identify outputs that belong to a different
|
|
85
|
-
* wallet than the inputs.
|
|
86
|
-
*
|
|
87
|
-
* @param walletKeys - The wallet keys to use for identification
|
|
88
|
-
* @returns Array of parsed outputs
|
|
89
|
-
* @note This method does NOT validate wallet inputs. It only parses outputs.
|
|
90
|
-
*/
|
|
91
|
-
parseOutputsWithWalletKeys(walletKeys: WalletKeys): ParsedOutput[];
|
|
92
|
-
/**
|
|
93
|
-
* Verify if a valid signature exists for a given extended public key at the specified input index.
|
|
94
|
-
*
|
|
95
|
-
* This method derives the public key from the xpub using the derivation path found in the
|
|
96
|
-
* PSBT input, then verifies the signature. It supports:
|
|
97
|
-
* - ECDSA signatures (for legacy/SegWit inputs)
|
|
98
|
-
* - Schnorr signatures (for Taproot script path inputs)
|
|
99
|
-
* - MuSig2 partial signatures (for Taproot keypath MuSig2 inputs)
|
|
100
|
-
*
|
|
101
|
-
* @param inputIndex - The index of the input to check (0-based)
|
|
102
|
-
* @param xpub - The extended public key as a base58-encoded string
|
|
103
|
-
* @returns true if a valid signature exists, false if no signature exists
|
|
104
|
-
* @throws Error if input index is out of bounds, xpub is invalid, or verification fails
|
|
105
|
-
*/
|
|
106
|
-
verifySignature(inputIndex: number, xpub: string): boolean;
|
|
107
|
-
/**
|
|
108
|
-
* Verify if a replay protection input has a valid signature.
|
|
109
|
-
*
|
|
110
|
-
* This method checks if a given input is a replay protection input (like P2shP2pk) and verifies
|
|
111
|
-
* the signature. Replay protection inputs don't use standard derivation paths, so this method
|
|
112
|
-
* verifies signatures without deriving from xpub.
|
|
113
|
-
*
|
|
114
|
-
* For P2PK replay protection inputs, this:
|
|
115
|
-
* - Extracts the signature from final_script_sig
|
|
116
|
-
* - Extracts the public key from redeem_script
|
|
117
|
-
* - Computes the legacy P2SH sighash
|
|
118
|
-
* - Verifies the ECDSA signature cryptographically
|
|
119
|
-
*
|
|
120
|
-
* @param inputIndex - The index of the input to check (0-based)
|
|
121
|
-
* @param replayProtection - Scripts that identify replay protection inputs (same format as parseTransactionWithWalletKeys)
|
|
122
|
-
* @returns true if the input is a replay protection input and has a valid signature, false if no valid signature
|
|
123
|
-
* @throws Error if the input is not a replay protection input, index is out of bounds, or scripts are invalid
|
|
124
|
-
*/
|
|
125
|
-
verifyReplayProtectionSignature(inputIndex: number, replayProtection: ReplayProtection): boolean;
|
|
126
|
-
/**
|
|
127
|
-
* Serialize the PSBT to bytes
|
|
128
|
-
*
|
|
129
|
-
* @returns The serialized PSBT as a byte array
|
|
130
|
-
*/
|
|
131
|
-
serialize(): Uint8Array;
|
|
132
|
-
/**
|
|
133
|
-
* Finalize all inputs in the PSBT
|
|
134
|
-
*
|
|
135
|
-
* @throws Error if any input failed to finalize
|
|
136
|
-
*/
|
|
137
|
-
finalizeAllInputs(): void;
|
|
138
|
-
/**
|
|
139
|
-
* Extract the final transaction from a finalized PSBT
|
|
140
|
-
*
|
|
141
|
-
* @returns The serialized transaction bytes
|
|
142
|
-
* @throws Error if the PSBT is not fully finalized or extraction fails
|
|
143
|
-
*/
|
|
144
|
-
extractTransaction(): Uint8Array;
|
|
145
|
-
}
|
|
146
|
-
export {};
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { FixedScriptWalletNamespace } from "./wasm/wasm_utxo.js";
|
|
2
|
-
/**
|
|
3
|
-
* Create the output script for a given wallet keys and chain and index
|
|
4
|
-
*/
|
|
5
|
-
export function outputScript(keys, chain, index, network) {
|
|
6
|
-
return FixedScriptWalletNamespace.output_script(keys, chain, index, network);
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Create the address for a given wallet keys and chain and index and network.
|
|
10
|
-
* Wrapper for outputScript that also encodes the script to an address.
|
|
11
|
-
* @param keys - The wallet keys to use.
|
|
12
|
-
* @param chain - The chain to use.
|
|
13
|
-
* @param index - The index to use.
|
|
14
|
-
* @param network - The network to use.
|
|
15
|
-
* @param addressFormat - The address format to use.
|
|
16
|
-
* Only relevant for Bitcoin Cash and eCash networks, where:
|
|
17
|
-
* - "default" means base58check,
|
|
18
|
-
* - "cashaddr" means cashaddr.
|
|
19
|
-
*/
|
|
20
|
-
export function address(keys, chain, index, network, addressFormat) {
|
|
21
|
-
return FixedScriptWalletNamespace.address(keys, chain, index, network, addressFormat);
|
|
22
|
-
}
|
|
23
|
-
import { BitGoPsbt as WasmBitGoPsbt } from "./wasm/wasm_utxo.js";
|
|
24
|
-
export class BitGoPsbt {
|
|
25
|
-
wasm;
|
|
26
|
-
constructor(wasm) {
|
|
27
|
-
this.wasm = wasm;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Deserialize a PSBT from bytes
|
|
31
|
-
* @param bytes - The PSBT bytes
|
|
32
|
-
* @param network - The network to use for deserialization (either utxolib name like "bitcoin" or coin name like "btc")
|
|
33
|
-
* @returns A BitGoPsbt instance
|
|
34
|
-
*/
|
|
35
|
-
static fromBytes(bytes, network) {
|
|
36
|
-
const wasm = WasmBitGoPsbt.from_bytes(bytes, network);
|
|
37
|
-
return new BitGoPsbt(wasm);
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Get the unsigned transaction ID
|
|
41
|
-
* @returns The unsigned transaction ID
|
|
42
|
-
*/
|
|
43
|
-
unsignedTxid() {
|
|
44
|
-
return this.wasm.unsigned_txid();
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Parse transaction with wallet keys to identify wallet inputs/outputs
|
|
48
|
-
* @param walletKeys - The wallet keys to use for identification
|
|
49
|
-
* @param replayProtection - Scripts that are allowed as inputs without wallet validation
|
|
50
|
-
* @returns Parsed transaction information
|
|
51
|
-
*/
|
|
52
|
-
parseTransactionWithWalletKeys(walletKeys, replayProtection) {
|
|
53
|
-
return this.wasm.parse_transaction_with_wallet_keys(walletKeys, replayProtection);
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Parse outputs with wallet keys to identify which outputs belong to a wallet
|
|
57
|
-
* with the given wallet keys.
|
|
58
|
-
*
|
|
59
|
-
* This is useful in cases where we want to identify outputs that belong to a different
|
|
60
|
-
* wallet than the inputs.
|
|
61
|
-
*
|
|
62
|
-
* @param walletKeys - The wallet keys to use for identification
|
|
63
|
-
* @returns Array of parsed outputs
|
|
64
|
-
* @note This method does NOT validate wallet inputs. It only parses outputs.
|
|
65
|
-
*/
|
|
66
|
-
parseOutputsWithWalletKeys(walletKeys) {
|
|
67
|
-
return this.wasm.parse_outputs_with_wallet_keys(walletKeys);
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Verify if a valid signature exists for a given extended public key at the specified input index.
|
|
71
|
-
*
|
|
72
|
-
* This method derives the public key from the xpub using the derivation path found in the
|
|
73
|
-
* PSBT input, then verifies the signature. It supports:
|
|
74
|
-
* - ECDSA signatures (for legacy/SegWit inputs)
|
|
75
|
-
* - Schnorr signatures (for Taproot script path inputs)
|
|
76
|
-
* - MuSig2 partial signatures (for Taproot keypath MuSig2 inputs)
|
|
77
|
-
*
|
|
78
|
-
* @param inputIndex - The index of the input to check (0-based)
|
|
79
|
-
* @param xpub - The extended public key as a base58-encoded string
|
|
80
|
-
* @returns true if a valid signature exists, false if no signature exists
|
|
81
|
-
* @throws Error if input index is out of bounds, xpub is invalid, or verification fails
|
|
82
|
-
*/
|
|
83
|
-
verifySignature(inputIndex, xpub) {
|
|
84
|
-
return this.wasm.verify_signature(inputIndex, xpub);
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Verify if a replay protection input has a valid signature.
|
|
88
|
-
*
|
|
89
|
-
* This method checks if a given input is a replay protection input (like P2shP2pk) and verifies
|
|
90
|
-
* the signature. Replay protection inputs don't use standard derivation paths, so this method
|
|
91
|
-
* verifies signatures without deriving from xpub.
|
|
92
|
-
*
|
|
93
|
-
* For P2PK replay protection inputs, this:
|
|
94
|
-
* - Extracts the signature from final_script_sig
|
|
95
|
-
* - Extracts the public key from redeem_script
|
|
96
|
-
* - Computes the legacy P2SH sighash
|
|
97
|
-
* - Verifies the ECDSA signature cryptographically
|
|
98
|
-
*
|
|
99
|
-
* @param inputIndex - The index of the input to check (0-based)
|
|
100
|
-
* @param replayProtection - Scripts that identify replay protection inputs (same format as parseTransactionWithWalletKeys)
|
|
101
|
-
* @returns true if the input is a replay protection input and has a valid signature, false if no valid signature
|
|
102
|
-
* @throws Error if the input is not a replay protection input, index is out of bounds, or scripts are invalid
|
|
103
|
-
*/
|
|
104
|
-
verifyReplayProtectionSignature(inputIndex, replayProtection) {
|
|
105
|
-
return this.wasm.verify_replay_protection_signature(inputIndex, replayProtection);
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Serialize the PSBT to bytes
|
|
109
|
-
*
|
|
110
|
-
* @returns The serialized PSBT as a byte array
|
|
111
|
-
*/
|
|
112
|
-
serialize() {
|
|
113
|
-
return this.wasm.serialize();
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Finalize all inputs in the PSBT
|
|
117
|
-
*
|
|
118
|
-
* @throws Error if any input failed to finalize
|
|
119
|
-
*/
|
|
120
|
-
finalizeAllInputs() {
|
|
121
|
-
this.wasm.finalize_all_inputs();
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Extract the final transaction from a finalized PSBT
|
|
125
|
-
*
|
|
126
|
-
* @returns The serialized transaction bytes
|
|
127
|
-
* @throws Error if the PSBT is not fully finalized or extraction fails
|
|
128
|
-
*/
|
|
129
|
-
extractTransaction() {
|
|
130
|
-
return this.wasm.extract_transaction();
|
|
131
|
-
}
|
|
132
|
-
}
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert";
|
|
2
|
-
import * as utxolib from "@bitgo/utxo-lib";
|
|
3
|
-
import { fixedScriptWallet } from "../../js/index.js";
|
|
4
|
-
import { loadPsbtFixture, loadWalletKeysFromFixture, getPsbtBuffer, } from "./fixtureUtil.js";
|
|
5
|
-
/**
|
|
6
|
-
* Get expected signature state for an input based on type and signing stage
|
|
7
|
-
* @param inputType - The type of input (e.g., "p2shP2pk", "p2trMusig2")
|
|
8
|
-
* @param signatureStage - The signing stage (unsigned, halfsigned, fullsigned)
|
|
9
|
-
* @returns Expected signature state for replay protection OR multi-key signatures
|
|
10
|
-
*/
|
|
11
|
-
function getExpectedSignatures(inputType, signatureStage) {
|
|
12
|
-
// p2shP2pk inputs use replay protection signature verification
|
|
13
|
-
if (inputType === "p2shP2pk") {
|
|
14
|
-
return {
|
|
15
|
-
hasReplayProtectionSignature: signatureStage === "halfsigned" || signatureStage === "fullsigned",
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
switch (signatureStage) {
|
|
19
|
-
case "unsigned":
|
|
20
|
-
return { user: false, backup: false, bitgo: false };
|
|
21
|
-
case "halfsigned":
|
|
22
|
-
// User signs first
|
|
23
|
-
return { user: true, backup: false, bitgo: false };
|
|
24
|
-
case "fullsigned":
|
|
25
|
-
// p2trMusig2 uses user + backup for 2-of-2 MuSig2
|
|
26
|
-
if (inputType === "p2trMusig2") {
|
|
27
|
-
return { user: true, backup: true, bitgo: false };
|
|
28
|
-
}
|
|
29
|
-
// Regular multisig uses user + bitgo
|
|
30
|
-
return { user: true, backup: false, bitgo: true };
|
|
31
|
-
default:
|
|
32
|
-
throw new Error(`Unknown signature stage: ${String(signatureStage)}`);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Verify signature state for a specific input in a PSBT
|
|
37
|
-
* @param bitgoPsbt - The PSBT to verify
|
|
38
|
-
* @param rootWalletKeys - Wallet keys for verification
|
|
39
|
-
* @param inputIndex - The input index to verify
|
|
40
|
-
* @param inputType - The type of input (for replay protection handling)
|
|
41
|
-
* @param expectedSignatures - Expected signature state for each key or replay protection
|
|
42
|
-
*/
|
|
43
|
-
function verifyInputSignatures(bitgoPsbt, rootWalletKeys, inputIndex, expectedSignatures) {
|
|
44
|
-
// Handle replay protection inputs (P2shP2pk)
|
|
45
|
-
if ("hasReplayProtectionSignature" in expectedSignatures) {
|
|
46
|
-
const replayProtectionScript = Buffer.from("a91420b37094d82a513451ff0ccd9db23aba05bc5ef387", "hex");
|
|
47
|
-
const hasReplaySig = bitgoPsbt.verifyReplayProtectionSignature(inputIndex, {
|
|
48
|
-
outputScripts: [replayProtectionScript],
|
|
49
|
-
});
|
|
50
|
-
assert.strictEqual(hasReplaySig, expectedSignatures.hasReplayProtectionSignature, `Input ${inputIndex} replay protection signature mismatch`);
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
// Handle standard multisig inputs
|
|
54
|
-
const xpubs = rootWalletKeys.triple;
|
|
55
|
-
const hasUserSig = bitgoPsbt.verifySignature(inputIndex, xpubs[0].toBase58());
|
|
56
|
-
const hasBackupSig = bitgoPsbt.verifySignature(inputIndex, xpubs[1].toBase58());
|
|
57
|
-
const hasBitGoSig = bitgoPsbt.verifySignature(inputIndex, xpubs[2].toBase58());
|
|
58
|
-
assert.strictEqual(hasUserSig, expectedSignatures.user, `Input ${inputIndex} user key signature mismatch`);
|
|
59
|
-
assert.strictEqual(hasBackupSig, expectedSignatures.backup, `Input ${inputIndex} backup key signature mismatch`);
|
|
60
|
-
assert.strictEqual(hasBitGoSig, expectedSignatures.bitgo, `Input ${inputIndex} BitGo key signature mismatch`);
|
|
61
|
-
}
|
|
62
|
-
describe("verifySignature", function () {
|
|
63
|
-
const supportedNetworks = utxolib.getNetworkList().filter((network) => {
|
|
64
|
-
return (utxolib.isMainnet(network) &&
|
|
65
|
-
network !== utxolib.networks.bitcoincash &&
|
|
66
|
-
network !== utxolib.networks.bitcoingold &&
|
|
67
|
-
network !== utxolib.networks.bitcoinsv &&
|
|
68
|
-
network !== utxolib.networks.ecash &&
|
|
69
|
-
network !== utxolib.networks.zcash);
|
|
70
|
-
});
|
|
71
|
-
supportedNetworks.forEach((network) => {
|
|
72
|
-
const networkName = utxolib.getNetworkName(network);
|
|
73
|
-
describe(`network: ${networkName}`, function () {
|
|
74
|
-
let rootWalletKeys;
|
|
75
|
-
let unsignedFixture;
|
|
76
|
-
let halfsignedFixture;
|
|
77
|
-
let fullsignedFixture;
|
|
78
|
-
let unsignedBitgoPsbt;
|
|
79
|
-
let halfsignedBitgoPsbt;
|
|
80
|
-
let fullsignedBitgoPsbt;
|
|
81
|
-
before(function () {
|
|
82
|
-
rootWalletKeys = loadWalletKeysFromFixture(networkName);
|
|
83
|
-
unsignedFixture = loadPsbtFixture(networkName, "unsigned");
|
|
84
|
-
halfsignedFixture = loadPsbtFixture(networkName, "halfsigned");
|
|
85
|
-
fullsignedFixture = loadPsbtFixture(networkName, "fullsigned");
|
|
86
|
-
unsignedBitgoPsbt = fixedScriptWallet.BitGoPsbt.fromBytes(getPsbtBuffer(unsignedFixture), networkName);
|
|
87
|
-
halfsignedBitgoPsbt = fixedScriptWallet.BitGoPsbt.fromBytes(getPsbtBuffer(halfsignedFixture), networkName);
|
|
88
|
-
fullsignedBitgoPsbt = fixedScriptWallet.BitGoPsbt.fromBytes(getPsbtBuffer(fullsignedFixture), networkName);
|
|
89
|
-
});
|
|
90
|
-
describe("unsigned PSBT", function () {
|
|
91
|
-
it("should return false for unsigned inputs", function () {
|
|
92
|
-
// Verify all xpubs return false for all inputs
|
|
93
|
-
unsignedFixture.psbtInputs.forEach((input, index) => {
|
|
94
|
-
verifyInputSignatures(unsignedBitgoPsbt, rootWalletKeys, index, getExpectedSignatures(input.type, "unsigned"));
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
describe("half-signed PSBT", function () {
|
|
99
|
-
it("should return true for signed xpubs and false for unsigned", function () {
|
|
100
|
-
halfsignedFixture.psbtInputs.forEach((input, index) => {
|
|
101
|
-
verifyInputSignatures(halfsignedBitgoPsbt, rootWalletKeys, index, getExpectedSignatures(input.type, "halfsigned"));
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
describe("fully signed PSBT", function () {
|
|
106
|
-
it("should have 2 signatures (2-of-3 multisig)", function () {
|
|
107
|
-
// In fullsigned fixtures, verify 2 signatures exist per multisig input
|
|
108
|
-
fullsignedFixture.psbtInputs.forEach((input, index) => {
|
|
109
|
-
verifyInputSignatures(fullsignedBitgoPsbt, rootWalletKeys, index, getExpectedSignatures(input.type, "fullsigned"));
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
describe("error handling", function () {
|
|
114
|
-
it("should throw error for out of bounds input index", function () {
|
|
115
|
-
const xpubs = rootWalletKeys.triple;
|
|
116
|
-
assert.throws(() => {
|
|
117
|
-
fullsignedBitgoPsbt.verifySignature(999, xpubs[0].toBase58());
|
|
118
|
-
}, (error) => {
|
|
119
|
-
return error.message.includes("Input index 999 out of bounds");
|
|
120
|
-
}, "Should throw error for out of bounds input index");
|
|
121
|
-
});
|
|
122
|
-
it("should throw error for invalid xpub", function () {
|
|
123
|
-
assert.throws(() => {
|
|
124
|
-
fullsignedBitgoPsbt.verifySignature(0, "invalid-xpub");
|
|
125
|
-
}, (error) => {
|
|
126
|
-
return error.message.includes("Invalid xpub");
|
|
127
|
-
}, "Should throw error for invalid xpub");
|
|
128
|
-
});
|
|
129
|
-
it("should return false for xpub not in derivation path", function () {
|
|
130
|
-
// Create a different xpub that's not in the wallet
|
|
131
|
-
// Use a proper 32-byte seed (256 bits)
|
|
132
|
-
const differentSeed = Buffer.alloc(32, 0xaa); // 32 bytes filled with 0xaa
|
|
133
|
-
const differentKey = utxolib.bip32.fromSeed(differentSeed, network);
|
|
134
|
-
const differentXpub = differentKey.neutered();
|
|
135
|
-
const result = fullsignedBitgoPsbt.verifySignature(0, differentXpub.toBase58());
|
|
136
|
-
assert.strictEqual(result, false, "Should return false for xpub not in PSBT derivation paths");
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
});
|
|
File without changes
|