Skip to content

Commit aad58a2

Browse files
OttoAllmendingerllm-git
andcommitted
feat(utxo-lib): add AcidTest.suite() for testing utilities
Adds a utility function to generate a comprehensive test suite for PSBT functionality across networks, sign stages, and tx formats. Improves test organization by using const arrays and type refinements, and adds a name getter to AcidTest for better test reporting. Issue: BTC-2732 Co-authored-by: llm-git <[email protected]>
1 parent 5d1dae5 commit aad58a2

File tree

3 files changed

+33
-41
lines changed

3 files changed

+33
-41
lines changed

modules/utxo-lib/src/testutil/psbt.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
addXpubsToPsbt,
3030
clonePsbtWithoutNonWitnessUtxo,
3131
} from '../bitgo';
32-
import { Network } from '../networks';
32+
import { getNetworkList, getNetworkName, isMainnet, Network, networks } from '../networks';
3333
import { mockReplayProtectionUnspent, mockWalletUnspent } from './mock';
3434
import { toOutputScript } from '../address';
3535
import { getDefaultWalletKeys, getWalletKeysForSeed } from './keys';
@@ -51,7 +51,8 @@ export type Input = {
5151
value: bigint;
5252
};
5353

54-
export type SignStage = 'unsigned' | 'halfsigned' | 'fullsigned';
54+
export const signStages = ['unsigned', 'halfsigned', 'fullsigned'] as const;
55+
export type SignStage = (typeof signStages)[number];
5556

5657
/**
5758
* Set isInternalAddress=true for internal output address
@@ -254,7 +255,8 @@ export function constructPsbt(
254255
return psbt;
255256
}
256257

257-
export type TxFormat = 'psbt' | 'psbt-lite';
258+
export const txFormats = ['psbt', 'psbt-lite'] as const;
259+
export type TxFormat = (typeof txFormats)[number];
258260

259261
/**
260262
* Creates a valid PSBT with as many features as possible.
@@ -321,6 +323,11 @@ export class AcidTest {
321323
return new AcidTest(network, signStage, txFormat, rootWalletKeys, otherWalletKeys, inputs, outputs);
322324
}
323325

326+
get name(): string {
327+
const networkName = getNetworkName(this.network);
328+
return `${networkName} ${this.signStage} ${this.txFormat}`;
329+
}
330+
324331
createPsbt(): UtxoPsbt {
325332
const psbt = constructPsbt(this.inputs, this.outputs, this.network, this.rootWalletKeys, this.signStage, {
326333
deterministic: true,
@@ -331,6 +338,16 @@ export class AcidTest {
331338
}
332339
return psbt;
333340
}
341+
342+
static suite(): AcidTest[] {
343+
return getNetworkList()
344+
.filter((network) => isMainnet(network) && network !== networks.bitcoinsv)
345+
.flatMap((network) =>
346+
signStages.flatMap((signStage) =>
347+
txFormats.flatMap((txFormat) => AcidTest.withDefaults(network, signStage, txFormat))
348+
)
349+
);
350+
}
334351
}
335352

336353
/**

modules/utxo-lib/test/bitgo/psbt/SignVerifyLegacy.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ import * as assert from 'assert';
33
import { getStrictSignatureCount, getStrictSignatureCounts } from '../../../src/bitgo';
44
import { constructTxnBuilder, TxnInput } from '../../../src/testutil';
55
import { AcidTest, SignStage } from '../../../src/testutil/psbt';
6-
import { getNetworkList, getNetworkName, isMainnet, networks } from '../../../src';
7-
8-
const signs = ['unsigned', 'halfsigned', 'fullsigned'] as const;
6+
import { getNetworkName } from '../../../src';
97

108
function signCount(signStage: SignStage) {
119
return signStage === 'unsigned' ? 0 : signStage === 'halfsigned' ? 1 : 2;
@@ -47,10 +45,8 @@ function runTx(acidTest: AcidTest) {
4745
});
4846
}
4947

50-
signs.forEach((sign) => {
51-
getNetworkList()
52-
.filter((v) => isMainnet(v) && v !== networks.bitcoinsv)
53-
.forEach((network) => {
54-
runTx(AcidTest.withDefaults(network, sign, 'psbt'));
55-
});
56-
});
48+
AcidTest.suite()
49+
.filter((acidTest) => acidTest.txFormat === 'psbt')
50+
.forEach((acidTest) => {
51+
runTx(acidTest);
52+
});

modules/utxo-lib/test/bitgo/psbt/SignVerifyPsbt.ts

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,14 @@ import {
1414
} from '../../../src/bitgo';
1515
import { Input as TestUtilInput } from '../../../src/testutil';
1616
import { AcidTest, InputScriptType, SignStage } from '../../../src/testutil/psbt';
17-
import { getNetworkList, getNetworkName, isMainnet, networks } from '../../../src';
17+
import { getNetworkName } from '../../../src';
1818
import {
1919
parsePsbtMusig2Nonces,
2020
parsePsbtMusig2PartialSigs,
2121
parsePsbtMusig2Participants,
2222
} from '../../../src/bitgo/Musig2';
2323
import { getFixture } from '../../fixture.util';
2424

25-
const signs = ['unsigned', 'halfsigned', 'fullsigned'] as const;
26-
2725
function getSigValidArray(scriptType: InputScriptType, signStage: SignStage): Triple<boolean> {
2826
if (scriptType === 'p2shP2pk' || signStage === 'unsigned') {
2927
return [false, false, false];
@@ -83,7 +81,7 @@ function runPsbt(acidTest: AcidTest) {
8381
const coin = getNetworkName(acidTest.network);
8482
const signatureCount = signCount(acidTest.signStage);
8583

86-
describe(`psbt build, sign and verify for ${coin} ${acidTest.signStage}`, function () {
84+
describe(`psbt suite for ${acidTest.name}`, function () {
8785
let psbt: UtxoPsbt;
8886

8987
before(function () {
@@ -94,20 +92,6 @@ function runPsbt(acidTest: AcidTest) {
9492
assert.deepStrictEqual(psbt.toBuffer(), createPsbtFromBuffer(psbt.toBuffer(), acidTest.network).toBuffer());
9593
});
9694

97-
it(`getSignatureValidationArray with globalXpub ${coin} ${acidTest.signStage}`, function () {
98-
psbt.data.inputs.forEach((input, inputIndex) => {
99-
const isP2shP2pk = acidTest.inputs[inputIndex].scriptType === 'p2shP2pk';
100-
const expectedSigValid = getSigValidArray(acidTest.inputs[inputIndex].scriptType, acidTest.signStage);
101-
psbt.getSignatureValidationArray(inputIndex, { rootNodes: acidTest.rootWalletKeys.triple }).forEach((sv, i) => {
102-
if (isP2shP2pk && acidTest.signStage !== 'unsigned' && i === 0) {
103-
assert.strictEqual(sv, true);
104-
} else {
105-
assert.strictEqual(sv, expectedSigValid[i]);
106-
}
107-
});
108-
});
109-
});
110-
11195
it('matches fixture', async function () {
11296
let finalizedPsbt: UtxoPsbt | undefined;
11397
let extractedTransaction: Buffer | undefined;
@@ -130,7 +114,7 @@ function runPsbt(acidTest: AcidTest) {
130114
assert.deepStrictEqual(fixture, await getFixture(`${__dirname}/../fixtures/psbt/${filename}`, fixture));
131115
});
132116

133-
it(`getSignatureValidationArray with rootNodes ${coin} ${acidTest.signStage}`, function () {
117+
it(`getSignatureValidationArray`, function () {
134118
psbt.data.inputs.forEach((input, inputIndex) => {
135119
const isP2shP2pk = acidTest.inputs[inputIndex].scriptType === 'p2shP2pk';
136120
const expectedSigValid = getSigValidArray(acidTest.inputs[inputIndex].scriptType, acidTest.signStage);
@@ -144,7 +128,7 @@ function runPsbt(acidTest: AcidTest) {
144128
});
145129
});
146130

147-
it(`getSignatureValidationArrayPsbt ${coin} ${acidTest.signStage}`, function () {
131+
it(`getSignatureValidationArrayPsbt`, function () {
148132
const sigValidations = getSignatureValidationArrayPsbt(psbt, acidTest.rootWalletKeys);
149133
psbt.data.inputs.forEach((input, inputIndex) => {
150134
const expectedSigValid = getSigValidArray(acidTest.inputs[inputIndex].scriptType, acidTest.signStage);
@@ -154,7 +138,7 @@ function runPsbt(acidTest: AcidTest) {
154138
});
155139
});
156140

157-
it(`psbt signature counts ${coin} ${acidTest.signStage}`, function () {
141+
it(`psbt signature counts`, function () {
158142
const counts = getStrictSignatureCounts(psbt);
159143
const countsFromInputs = getStrictSignatureCounts(psbt.data.inputs);
160144

@@ -186,11 +170,6 @@ function runPsbt(acidTest: AcidTest) {
186170
});
187171
}
188172

189-
signs.forEach((sign) => {
190-
getNetworkList()
191-
.filter((v) => isMainnet(v) && v !== networks.bitcoinsv)
192-
.forEach((network) => {
193-
runPsbt(AcidTest.withDefaults(network, sign, 'psbt'));
194-
runPsbt(AcidTest.withDefaults(network, sign, 'psbt-lite'));
195-
});
173+
AcidTest.suite().forEach((acidTest) => {
174+
runPsbt(acidTest);
196175
});

0 commit comments

Comments
 (0)