Skip to content

Commit ab363ef

Browse files
authored
test: fix flakiness with pox-4-btc-address-formats tests (#1849)
* test: fix flakiness with `pox-4-btc-address-formats` tests * test: specify new bitcoin wallet name * test: fix main bitcoin wallet private key pollution in more tests
1 parent 554e6ee commit ab363ef

8 files changed

+108
-113
lines changed

docker/docker-compose.dev.stacks-blockchain.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
version: '3.7'
22
services:
33
stacks-blockchain:
4-
image: 'hirosystems/stacks-api-e2e:stacks3.0-204ab4c'
4+
image: 'hirosystems/stacks-api-e2e:stacks3.0-1d675fd'
55
restart: on-failure
66
environment:
77
STACKS_EVENT_OBSERVER: host.docker.internal:3700

docker/docker-compose.dev.stacks-krypton.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
version: '3.7'
22
services:
33
stacks-blockchain:
4-
image: 'hirosystems/stacks-api-e2e:stacks3.0-204ab4c'
4+
image: 'hirosystems/stacks-api-e2e:stacks3.0-1d675fd'
55
ports:
66
- '18443:18443' # bitcoin regtest JSON-RPC interface
77
- '18444:18444' # bitcoin regtest p2p

src/tests-2.5/env-setup.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ beforeAll(async () => {
3434
user: BTC_RPC_USER,
3535
pass: BTC_RPC_PW,
3636
timeout: 120000,
37-
wallet: '',
37+
wallet: 'main',
3838
});
3939

4040
testEnv = {

src/tests-2.5/pox-4-btc-address-formats.ts

+76-81
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
standByUntilBurnBlock,
2727
testEnv,
2828
} from '../test-utils/test-helpers';
29+
import { RPCClient } from 'rpc-bitcoin';
2930

3031
const BTC_PRIVATE_KEY = '0000000000000000000000000000000000000000000000000000000000000002';
3132

@@ -44,35 +45,49 @@ describe.each([P2SH_P2WPKH, P2WPKH, P2WSH, P2TR])(
4445

4546
const { btcAddr, btcAddrDecoded, btcAddrRegtest, btcDescriptor } = addressSetup();
4647

48+
let bitcoinRpcClient: RPCClient;
49+
50+
test('setup BTC wallet client', async () => {
51+
const { BTC_RPC_PORT, BTC_RPC_HOST, BTC_RPC_PW, BTC_RPC_USER } = process.env;
52+
bitcoinRpcClient = new RPCClient({
53+
url: BTC_RPC_HOST,
54+
port: Number(BTC_RPC_PORT),
55+
user: BTC_RPC_USER,
56+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
57+
pass: BTC_RPC_PW!,
58+
timeout: 120000,
59+
wallet: btcAddrRegtest,
60+
});
61+
const createWalletResult = await bitcoinRpcClient.createwallet({
62+
wallet_name: btcAddrRegtest,
63+
blank: true,
64+
disable_private_keys: true,
65+
descriptors: true,
66+
load_on_startup: false,
67+
} as any);
68+
expect(createWalletResult.name).toBe(btcAddrRegtest);
69+
expect(createWalletResult.warning).toBeFalsy();
70+
71+
// descriptor wallets, if legacy wallet import fails
72+
const info = await bitcoinRpcClient.getdescriptorinfo({
73+
descriptor: btcDescriptor,
74+
});
75+
const request = { label: btcAddrRegtest, desc: info.descriptor, timestamp: 'now' };
76+
const importDescriptorRes: { success: boolean }[] = await bitcoinRpcClient.rpc(
77+
'importdescriptors',
78+
{ requests: [request] },
79+
btcAddrRegtest
80+
);
81+
expect(importDescriptorRes[0].success).toBe(true);
82+
const btcWalletAddrs = await bitcoinRpcClient.getaddressesbylabel({
83+
label: btcAddrRegtest,
84+
});
85+
expect(Object.keys(btcWalletAddrs)).toEqual([btcAddrRegtest]);
86+
});
87+
4788
test('prepare', async () => {
4889
await standByForPoxCycle();
4990

50-
try {
51-
// legacy wallets
52-
await testEnv.bitcoinRpcClient.importaddress({
53-
address: btcAddrRegtest,
54-
label: btcAddrRegtest,
55-
});
56-
const btcWalletAddrs = await testEnv.bitcoinRpcClient.getaddressesbylabel({
57-
label: btcAddrRegtest,
58-
});
59-
expect(Object.keys(btcWalletAddrs)).toContain(btcAddrRegtest);
60-
} catch (e) {
61-
// descriptor wallets, if legacy wallet import fails
62-
await withDescriptorWallet(async walletName => {
63-
const info = await testEnv.bitcoinRpcClient.getdescriptorinfo({
64-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
65-
descriptor: btcDescriptor!,
66-
});
67-
const request = { label: btcAddrRegtest, desc: info.descriptor, timestamp: 'now' };
68-
await testEnv.bitcoinRpcClient.rpc(
69-
'importdescriptors',
70-
{ requests: [request] },
71-
walletName
72-
);
73-
});
74-
}
75-
7691
poxInfo = await testEnv.client.getPox();
7792

7893
burnBlockHeight = poxInfo.current_burnchain_block_height as number;
@@ -172,7 +187,7 @@ describe.each([P2SH_P2WPKH, P2WPKH, P2WSH, P2TR])(
172187
const rewards = await fetchGet<BurnchainRewardListResponse>(
173188
`/extended/v1/burnchain/rewards/${btcAddr}`
174189
);
175-
expect(rewards.results).toHaveLength(1);
190+
expect(rewards.results.length).toBeGreaterThan(0);
176191

177192
const firstReward = rewards.results.sort(
178193
(a, b) => a.burn_block_height - b.burn_block_height
@@ -207,7 +222,7 @@ describe.each([P2SH_P2WPKH, P2WPKH, P2WSH, P2TR])(
207222

208223
const blockResult: {
209224
tx: { vout?: { scriptPubKey: { address?: string }; value?: number }[] }[];
210-
} = await testEnv.bitcoinRpcClient.getblock({
225+
} = await bitcoinRpcClient.getblock({
211226
blockhash: hexToBuffer(firstReward.burn_block_hash).toString('hex'),
212227
verbosity: 2,
213228
});
@@ -231,43 +246,45 @@ describe.each([P2SH_P2WPKH, P2WPKH, P2WSH, P2TR])(
231246
(a, b) => a.burn_block_height - b.burn_block_height
232247
)[0];
233248

234-
let txs = await withDescriptorWallet(
235-
async walletName =>
236-
(await testEnv.bitcoinRpcClient.listtransactions(
237-
{
238-
label: btcAddrRegtest,
239-
include_watchonly: true,
240-
},
241-
btcDescriptor ? walletName : undefined
242-
)) as {
243-
address: string;
244-
category: string;
245-
amount: number;
246-
blockhash: string;
247-
blockheight: number;
248-
}[]
249+
let txs: {
250+
address: string;
251+
category: string;
252+
amount: number;
253+
blockhash: string;
254+
blockheight: number;
255+
}[] = await bitcoinRpcClient.listtransactions(
256+
{
257+
label: btcAddrRegtest,
258+
include_watchonly: true,
259+
},
260+
btcAddrRegtest
249261
);
250262
txs = txs.filter(r => r.address === btcAddrRegtest);
251-
expect(txs.length).toBe(1);
252-
expect(txs[0].category).toBe('receive');
253-
expect(txs[0].blockhash).toBe(hexToBuffer(firstReward.burn_block_hash).toString('hex'));
254-
const sats = new bignumber(txs[0].amount).shiftedBy(8).toString();
263+
264+
expect(txs.length).toBeGreaterThan(0);
265+
266+
const firstTx = txs.sort((a, b) => a.blockheight - b.blockheight)[0];
267+
expect(firstTx.category).toBe('receive');
268+
expect(firstTx.blockhash).toBe(hexToBuffer(firstReward.burn_block_hash).toString('hex'));
269+
const sats = new bignumber(firstTx.amount).shiftedBy(8).toString();
255270
expect(sats).toBe(firstReward.reward_amount);
256271
});
257272

258273
test('BTC stacking reward received', async () => {
259-
const received = await withDescriptorWallet(
260-
async walletName =>
261-
(await testEnv.bitcoinRpcClient.getreceivedbyaddress(
262-
{
263-
address: btcAddrRegtest,
264-
minconf: 0,
265-
},
266-
btcDescriptor ? walletName : undefined
267-
)) as number
274+
const received: number = await bitcoinRpcClient.getreceivedbyaddress(
275+
{
276+
address: btcAddrRegtest,
277+
minconf: 0,
278+
},
279+
btcAddrRegtest
268280
);
269281
expect(received).toBeGreaterThan(0);
270282
});
283+
284+
afterAll(async () => {
285+
// after: unload descriptor wallet
286+
await bitcoinRpcClient.unloadwallet({ wallet_name: btcAddrRegtest });
287+
});
271288
}
272289
);
273290

@@ -300,7 +317,7 @@ function P2SH_P2WPKH() {
300317
btcAddrDecoded,
301318
btcAddrRegtest,
302319
btcPubKey,
303-
btcDescriptor: undefined,
320+
btcDescriptor: `sh(wpkh(${btcPubKey}))`,
304321
};
305322
}
306323

@@ -336,7 +353,7 @@ function P2WSH() {
336353
btcAddrDecoded,
337354
btcAddrRegtest,
338355
btcPubKey,
339-
btcDescriptor: undefined,
356+
btcDescriptor: `wsh(multi(1,${btcPubKey}))`,
340357
};
341358
}
342359

@@ -369,7 +386,7 @@ function P2WPKH() {
369386
btcAddrDecoded,
370387
btcAddrRegtest,
371388
btcPubKey,
372-
btcDescriptor: undefined,
389+
btcDescriptor: `wpkh(${btcPubKey})`,
373390
};
374391
}
375392

@@ -408,25 +425,3 @@ function P2TR() {
408425
btcDescriptor: `tr(${btcPubKey})`,
409426
};
410427
}
411-
412-
// helper
413-
async function withDescriptorWallet<R>(fn: (walletName: string) => Promise<R> | R): Promise<R> {
414-
// before: load or create descriptor wallet
415-
try {
416-
await testEnv.bitcoinRpcClient.loadwallet({ filename: 'descriptor-wallet' });
417-
} catch (e) {
418-
await testEnv.bitcoinRpcClient.createwallet({
419-
wallet_name: 'descriptor-wallet',
420-
disable_private_keys: true,
421-
descriptors: true,
422-
load_on_startup: false,
423-
} as any);
424-
}
425-
426-
const res = await fn('descriptor-wallet');
427-
428-
// after: unload descriptor walletl
429-
await testEnv.bitcoinRpcClient.unloadwallet({ wallet_name: 'descriptor-wallet' });
430-
431-
return res;
432-
}

src/tests-2.5/pox-4-delegate-aggregation.ts

+14-9
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,12 @@ describe('PoX-4 - Delegate aggregation increase operations', () => {
5858
});
5959

6060
test('Import testing accounts to bitcoind', async () => {
61-
// register delegate accounts to bitcoind wallet
62-
// TODO: only one of these (delegatee ?) should be required..
63-
for (const account of [delegatorAccount, delegateeAccount]) {
64-
await testEnv.bitcoinRpcClient.importprivkey({
65-
privkey: account.wif,
66-
label: account.btcAddr,
67-
rescan: false,
68-
});
69-
}
61+
// register delegatee account to bitcoind wallet
62+
await testEnv.bitcoinRpcClient.importaddress({
63+
address: delegateeAccount.btcAddr,
64+
label: delegateeAccount.btcAddr,
65+
rescan: false,
66+
});
7067
});
7168

7269
test('Seed delegate accounts', async () => {
@@ -446,4 +443,12 @@ describe('PoX-4 - Delegate aggregation increase operations', () => {
446443
expect(BigInt(apiBalance.locked)).toBe(BigInt(BigInt(coreBalanceInfo.locked)));
447444
expect(apiBalance.burnchain_unlock_height).toBe(coreBalanceInfo.unlock_height);
448445
});
446+
447+
test('BTC stacking reward received', async () => {
448+
const received: number = await testEnv.bitcoinRpcClient.getreceivedbyaddress({
449+
address: delegateeAccount.btcAddr,
450+
minconf: 0,
451+
});
452+
expect(received).toBeGreaterThan(0);
453+
});
449454
});

src/tests-2.5/pox-4-delegate-revoked-stacking.ts

-10
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,6 @@ describe('PoX-4 - Delegate Revoked Stacking', () => {
5353
STACKER = accountFromKey(delegateeKey);
5454
});
5555

56-
test('Import testing accounts to bitcoind', async () => {
57-
for (const account of [POOL, STACKER]) {
58-
await testEnv.bitcoinRpcClient.importprivkey({
59-
privkey: account.wif,
60-
label: account.btcAddr,
61-
rescan: false,
62-
});
63-
}
64-
});
65-
6656
test('Seed delegate accounts', async () => {
6757
poxInfo = await testEnv.client.getPox();
6858

src/tests-2.5/pox-4-delegate-stacking.ts

+14-9
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,12 @@ describe('PoX-4 - Delegate Stacking operations', () => {
4848
});
4949

5050
test('Import testing accounts to bitcoind', async () => {
51-
// register delegate accounts to bitcoind wallet
52-
// TODO: only one of these (delegatee ?) should be required..
53-
for (const account of [delegatorAccount, delegateeAccount]) {
54-
await testEnv.bitcoinRpcClient.importprivkey({
55-
privkey: account.wif,
56-
label: account.btcAddr,
57-
rescan: false,
58-
});
59-
}
51+
// register delegatee account to bitcoind wallet
52+
await testEnv.bitcoinRpcClient.importaddress({
53+
address: delegateeAccount.btcAddr,
54+
label: delegateeAccount.btcAddr,
55+
rescan: false,
56+
});
6057
});
6158

6259
test('Seed delegate accounts', async () => {
@@ -449,4 +446,12 @@ describe('PoX-4 - Delegate Stacking operations', () => {
449446
expect(BigInt(apiBalance.locked)).toBe(BigInt(BigInt(coreBalanceInfo.locked)));
450447
expect(apiBalance.burnchain_unlock_height).toBe(coreBalanceInfo.unlock_height);
451448
});
449+
450+
test('BTC stacking reward received', async () => {
451+
const received: number = await testEnv.bitcoinRpcClient.getreceivedbyaddress({
452+
address: delegateeAccount.btcAddr,
453+
minconf: 0,
454+
});
455+
expect(received).toBeGreaterThan(0);
456+
});
452457
});

stacks-blockchain/docker/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Pointed to stacks-blockchain `2.1.0.0.0` git tag
2-
FROM --platform=linux/amd64 hirosystems/stacks-api-e2e:stacks3.0-204ab4c as build
2+
FROM --platform=linux/amd64 hirosystems/stacks-api-e2e:stacks3.0-1d675fd as build
33

44
FROM --platform=linux/amd64 debian:bookworm
55

0 commit comments

Comments
 (0)