Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: fix flakiness with pox-4-btc-address-formats tests #1849

Merged
merged 3 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker/docker-compose.dev.stacks-blockchain.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: '3.7'
services:
stacks-blockchain:
image: 'hirosystems/stacks-api-e2e:stacks3.0-204ab4c'
image: 'hirosystems/stacks-api-e2e:stacks3.0-1d675fd'
restart: on-failure
environment:
STACKS_EVENT_OBSERVER: host.docker.internal:3700
Expand Down
2 changes: 1 addition & 1 deletion docker/docker-compose.dev.stacks-krypton.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: '3.7'
services:
stacks-blockchain:
image: 'hirosystems/stacks-api-e2e:stacks3.0-204ab4c'
image: 'hirosystems/stacks-api-e2e:stacks3.0-1d675fd'
ports:
- '18443:18443' # bitcoin regtest JSON-RPC interface
- '18444:18444' # bitcoin regtest p2p
Expand Down
2 changes: 1 addition & 1 deletion src/tests-2.5/env-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ beforeAll(async () => {
user: BTC_RPC_USER,
pass: BTC_RPC_PW,
timeout: 120000,
wallet: '',
wallet: 'main',
});

testEnv = {
Expand Down
157 changes: 76 additions & 81 deletions src/tests-2.5/pox-4-btc-address-formats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
standByUntilBurnBlock,
testEnv,
} from '../test-utils/test-helpers';
import { RPCClient } from 'rpc-bitcoin';

const BTC_PRIVATE_KEY = '0000000000000000000000000000000000000000000000000000000000000002';

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

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

let bitcoinRpcClient: RPCClient;

test('setup BTC wallet client', async () => {
const { BTC_RPC_PORT, BTC_RPC_HOST, BTC_RPC_PW, BTC_RPC_USER } = process.env;
bitcoinRpcClient = new RPCClient({
url: BTC_RPC_HOST,
port: Number(BTC_RPC_PORT),
user: BTC_RPC_USER,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
pass: BTC_RPC_PW!,
timeout: 120000,
wallet: btcAddrRegtest,
});
const createWalletResult = await bitcoinRpcClient.createwallet({
wallet_name: btcAddrRegtest,
blank: true,
disable_private_keys: true,
descriptors: true,
load_on_startup: false,
} as any);
expect(createWalletResult.name).toBe(btcAddrRegtest);
expect(createWalletResult.warning).toBeFalsy();

// descriptor wallets, if legacy wallet import fails
const info = await bitcoinRpcClient.getdescriptorinfo({
descriptor: btcDescriptor,
});
const request = { label: btcAddrRegtest, desc: info.descriptor, timestamp: 'now' };
const importDescriptorRes: { success: boolean }[] = await bitcoinRpcClient.rpc(
'importdescriptors',
{ requests: [request] },
btcAddrRegtest
);
expect(importDescriptorRes[0].success).toBe(true);
const btcWalletAddrs = await bitcoinRpcClient.getaddressesbylabel({
label: btcAddrRegtest,
});
expect(Object.keys(btcWalletAddrs)).toEqual([btcAddrRegtest]);
});

test('prepare', async () => {
await standByForPoxCycle();

try {
// legacy wallets
await testEnv.bitcoinRpcClient.importaddress({
address: btcAddrRegtest,
label: btcAddrRegtest,
});
const btcWalletAddrs = await testEnv.bitcoinRpcClient.getaddressesbylabel({
label: btcAddrRegtest,
});
expect(Object.keys(btcWalletAddrs)).toContain(btcAddrRegtest);
} catch (e) {
// descriptor wallets, if legacy wallet import fails
await withDescriptorWallet(async walletName => {
const info = await testEnv.bitcoinRpcClient.getdescriptorinfo({
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
descriptor: btcDescriptor!,
});
const request = { label: btcAddrRegtest, desc: info.descriptor, timestamp: 'now' };
await testEnv.bitcoinRpcClient.rpc(
'importdescriptors',
{ requests: [request] },
walletName
);
});
}

poxInfo = await testEnv.client.getPox();

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

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

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

let txs = await withDescriptorWallet(
async walletName =>
(await testEnv.bitcoinRpcClient.listtransactions(
{
label: btcAddrRegtest,
include_watchonly: true,
},
btcDescriptor ? walletName : undefined
)) as {
address: string;
category: string;
amount: number;
blockhash: string;
blockheight: number;
}[]
let txs: {
address: string;
category: string;
amount: number;
blockhash: string;
blockheight: number;
}[] = await bitcoinRpcClient.listtransactions(
{
label: btcAddrRegtest,
include_watchonly: true,
},
btcAddrRegtest
);
txs = txs.filter(r => r.address === btcAddrRegtest);
expect(txs.length).toBe(1);
expect(txs[0].category).toBe('receive');
expect(txs[0].blockhash).toBe(hexToBuffer(firstReward.burn_block_hash).toString('hex'));
const sats = new bignumber(txs[0].amount).shiftedBy(8).toString();

expect(txs.length).toBeGreaterThan(0);

const firstTx = txs.sort((a, b) => a.blockheight - b.blockheight)[0];
expect(firstTx.category).toBe('receive');
expect(firstTx.blockhash).toBe(hexToBuffer(firstReward.burn_block_hash).toString('hex'));
const sats = new bignumber(firstTx.amount).shiftedBy(8).toString();
expect(sats).toBe(firstReward.reward_amount);
});

test('BTC stacking reward received', async () => {
const received = await withDescriptorWallet(
async walletName =>
(await testEnv.bitcoinRpcClient.getreceivedbyaddress(
{
address: btcAddrRegtest,
minconf: 0,
},
btcDescriptor ? walletName : undefined
)) as number
const received: number = await bitcoinRpcClient.getreceivedbyaddress(
{
address: btcAddrRegtest,
minconf: 0,
},
btcAddrRegtest
);
expect(received).toBeGreaterThan(0);
});

afterAll(async () => {
// after: unload descriptor wallet
await bitcoinRpcClient.unloadwallet({ wallet_name: btcAddrRegtest });
});
}
);

Expand Down Expand Up @@ -300,7 +317,7 @@ function P2SH_P2WPKH() {
btcAddrDecoded,
btcAddrRegtest,
btcPubKey,
btcDescriptor: undefined,
btcDescriptor: `sh(wpkh(${btcPubKey}))`,
};
}

Expand Down Expand Up @@ -336,7 +353,7 @@ function P2WSH() {
btcAddrDecoded,
btcAddrRegtest,
btcPubKey,
btcDescriptor: undefined,
btcDescriptor: `wsh(multi(1,${btcPubKey}))`,
};
}

Expand Down Expand Up @@ -369,7 +386,7 @@ function P2WPKH() {
btcAddrDecoded,
btcAddrRegtest,
btcPubKey,
btcDescriptor: undefined,
btcDescriptor: `wpkh(${btcPubKey})`,
};
}

Expand Down Expand Up @@ -408,25 +425,3 @@ function P2TR() {
btcDescriptor: `tr(${btcPubKey})`,
};
}

// helper
async function withDescriptorWallet<R>(fn: (walletName: string) => Promise<R> | R): Promise<R> {
// before: load or create descriptor wallet
try {
await testEnv.bitcoinRpcClient.loadwallet({ filename: 'descriptor-wallet' });
} catch (e) {
await testEnv.bitcoinRpcClient.createwallet({
wallet_name: 'descriptor-wallet',
disable_private_keys: true,
descriptors: true,
load_on_startup: false,
} as any);
}

const res = await fn('descriptor-wallet');

// after: unload descriptor walletl
await testEnv.bitcoinRpcClient.unloadwallet({ wallet_name: 'descriptor-wallet' });

return res;
}
23 changes: 14 additions & 9 deletions src/tests-2.5/pox-4-delegate-aggregation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,12 @@ describe('PoX-4 - Delegate aggregation increase operations', () => {
});

test('Import testing accounts to bitcoind', async () => {
// register delegate accounts to bitcoind wallet
// TODO: only one of these (delegatee ?) should be required..
for (const account of [delegatorAccount, delegateeAccount]) {
await testEnv.bitcoinRpcClient.importprivkey({
privkey: account.wif,
label: account.btcAddr,
rescan: false,
});
}
// register delegatee account to bitcoind wallet
await testEnv.bitcoinRpcClient.importaddress({
address: delegateeAccount.btcAddr,
label: delegateeAccount.btcAddr,
rescan: false,
});
});

test('Seed delegate accounts', async () => {
Expand Down Expand Up @@ -446,4 +443,12 @@ describe('PoX-4 - Delegate aggregation increase operations', () => {
expect(BigInt(apiBalance.locked)).toBe(BigInt(BigInt(coreBalanceInfo.locked)));
expect(apiBalance.burnchain_unlock_height).toBe(coreBalanceInfo.unlock_height);
});

test('BTC stacking reward received', async () => {
const received: number = await testEnv.bitcoinRpcClient.getreceivedbyaddress({
address: delegateeAccount.btcAddr,
minconf: 0,
});
expect(received).toBeGreaterThan(0);
});
});
10 changes: 0 additions & 10 deletions src/tests-2.5/pox-4-delegate-revoked-stacking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,6 @@ describe('PoX-4 - Delegate Revoked Stacking', () => {
STACKER = accountFromKey(delegateeKey);
});

test('Import testing accounts to bitcoind', async () => {
for (const account of [POOL, STACKER]) {
await testEnv.bitcoinRpcClient.importprivkey({
privkey: account.wif,
label: account.btcAddr,
rescan: false,
});
}
});

test('Seed delegate accounts', async () => {
poxInfo = await testEnv.client.getPox();

Expand Down
23 changes: 14 additions & 9 deletions src/tests-2.5/pox-4-delegate-stacking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,12 @@ describe('PoX-4 - Delegate Stacking operations', () => {
});

test('Import testing accounts to bitcoind', async () => {
// register delegate accounts to bitcoind wallet
// TODO: only one of these (delegatee ?) should be required..
for (const account of [delegatorAccount, delegateeAccount]) {
await testEnv.bitcoinRpcClient.importprivkey({
privkey: account.wif,
label: account.btcAddr,
rescan: false,
});
}
// register delegatee account to bitcoind wallet
await testEnv.bitcoinRpcClient.importaddress({
address: delegateeAccount.btcAddr,
label: delegateeAccount.btcAddr,
rescan: false,
});
});

test('Seed delegate accounts', async () => {
Expand Down Expand Up @@ -449,4 +446,12 @@ describe('PoX-4 - Delegate Stacking operations', () => {
expect(BigInt(apiBalance.locked)).toBe(BigInt(BigInt(coreBalanceInfo.locked)));
expect(apiBalance.burnchain_unlock_height).toBe(coreBalanceInfo.unlock_height);
});

test('BTC stacking reward received', async () => {
const received: number = await testEnv.bitcoinRpcClient.getreceivedbyaddress({
address: delegateeAccount.btcAddr,
minconf: 0,
});
expect(received).toBeGreaterThan(0);
});
});
2 changes: 1 addition & 1 deletion stacks-blockchain/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Pointed to stacks-blockchain `2.1.0.0.0` git tag
FROM --platform=linux/amd64 hirosystems/stacks-api-e2e:stacks3.0-204ab4c as build
FROM --platform=linux/amd64 hirosystems/stacks-api-e2e:stacks3.0-1d675fd as build

FROM --platform=linux/amd64 debian:bookworm

Expand Down
Loading