Skip to content

Commit 50110b7

Browse files
Merge pull request #5908 from BitGo/BTC-1966.babylon-unstaking-tx
feat(utxo-staking): implement babylon unstaking tests
2 parents 0ea3211 + 531fc3d commit 50110b7

File tree

9 files changed

+915
-55
lines changed

9 files changed

+915
-55
lines changed

modules/utxo-core/src/descriptor/psbt/createPsbt.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,19 @@ export type PsbtParams = {
4848
sequence?: number;
4949
};
5050

51+
export type DerivedDescriptorTransactionInput = DerivedDescriptorWalletOutput & {
52+
sequence?: number;
53+
};
54+
5155
export function createPsbt(
5256
params: PsbtParams,
53-
inputs: DerivedDescriptorWalletOutput[],
57+
inputs: DerivedDescriptorTransactionInput[],
5458
outputs: WithOptDescriptor<Output>[]
5559
): utxolib.bitgo.UtxoPsbt {
5660
const psbt = utxolib.bitgo.UtxoPsbt.createPsbt({ network: params.network });
5761
psbt.setVersion(params.version ?? 2);
5862
psbt.setLocktime(params.locktime ?? 0);
59-
psbt.addInputs(inputs.map((i) => ({ ...i, sequence: params.sequence ?? MAX_BIP125_RBF_SEQUENCE })));
63+
psbt.addInputs(inputs.map((i) => ({ ...i, sequence: i.sequence ?? params.sequence ?? MAX_BIP125_RBF_SEQUENCE })));
6064
psbt.addOutputs(outputs);
6165
updateInputsWithDescriptors(
6266
psbt,

modules/utxo-core/src/descriptor/psbt/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ export * from './createPsbt';
33
export * from './parse';
44
export * from './findDescriptors';
55
export * from './wrap';
6+
export * from './sign';
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import assert from 'assert';
2+
3+
import * as utxolib from '@bitgo/utxo-lib';
4+
import { Psbt as WasmPsbt } from '@bitgo/wasm-miniscript';
5+
6+
/** These can be replaced when @bitgo/wasm-miniscript is updated */
7+
export type SignPsbtInputResult = { Schnorr: string[] } | { Ecdsa: string[] };
8+
export type SignPsbtResult = {
9+
[inputIndex: number]: SignPsbtInputResult;
10+
};
11+
12+
/**
13+
* @param signResult
14+
* @return the number of new signatures created by the signResult for a single input
15+
*/
16+
export function getNewSignatureCountForInput(signResult: SignPsbtInputResult): number {
17+
if ('Schnorr' in signResult) {
18+
return signResult.Schnorr.length;
19+
}
20+
if ('Ecdsa' in signResult) {
21+
return signResult.Ecdsa.length;
22+
}
23+
throw new Error(`Unknown signature type ${Object.keys(signResult).join(', ')}`);
24+
}
25+
26+
/**
27+
* @param signResult
28+
* @return the number of new signatures created by the signResult
29+
*/
30+
export function getNewSignatureCount(signResult: SignPsbtResult): number {
31+
return Object.values(signResult).reduce((sum, signatures) => sum + getNewSignatureCountForInput(signatures), 0);
32+
}
33+
34+
type Key = Buffer | utxolib.BIP32Interface | utxolib.ECPairInterface;
35+
36+
/** Convenience function to sign a PSBT with a key */
37+
export function signWithKey(psbt: WasmPsbt, key: Key): SignPsbtResult {
38+
// we need to do casting here because the type definitions in wasm-miniscript are a little bit buggy
39+
if (Buffer.isBuffer(key)) {
40+
return psbt.signWithPrv(key) as unknown as SignPsbtResult;
41+
}
42+
if ('toBase58' in key) {
43+
return psbt.signWithXprv(key.toBase58()) as unknown as SignPsbtResult;
44+
}
45+
assert(key.privateKey);
46+
return psbt.signWithPrv(key.privateKey) as unknown as SignPsbtResult;
47+
}

modules/utxo-core/src/testutil/descriptor/mock.utils.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import { Descriptor } from '@bitgo/wasm-miniscript';
22
import * as utxolib from '@bitgo/utxo-lib';
33

4-
import { PsbtParams, createPsbt, createScriptPubKeyFromDescriptor } from '../../descriptor';
5-
import { DerivedDescriptorWalletOutput } from '../../descriptor/Output';
4+
import {
5+
PsbtParams,
6+
createPsbt,
7+
createScriptPubKeyFromDescriptor,
8+
DerivedDescriptorTransactionInput,
9+
} from '../../descriptor';
610

711
import { DescriptorTemplate, getDefaultXPubs, getDescriptor } from './descriptors';
812

@@ -12,6 +16,7 @@ type BaseMockDescriptorOutputParams = {
1216
id?: MockOutputIdParams;
1317
index?: number;
1418
value?: bigint;
19+
sequence?: number;
1520
};
1621

1722
function mockOutputId(id?: MockOutputIdParams): {
@@ -26,7 +31,7 @@ function mockOutputId(id?: MockOutputIdParams): {
2631
export function mockDerivedDescriptorWalletOutput(
2732
descriptor: Descriptor,
2833
outputParams: BaseMockDescriptorOutputParams = {}
29-
): DerivedDescriptorWalletOutput {
34+
): DerivedDescriptorTransactionInput {
3035
const { value = BigInt(1e6) } = outputParams;
3136
const { hash, vout } = mockOutputId(outputParams.id);
3237
return {
@@ -37,6 +42,7 @@ export function mockDerivedDescriptorWalletOutput(
3742
value,
3843
},
3944
descriptor,
45+
sequence: outputParams.sequence,
4046
};
4147
}
4248

0 commit comments

Comments
 (0)