mirror of
https://github.com/benjamin-wilson/public-pool.git
synced 2026-09-29 09:05:06 -07:00
Speed up template publication and share validation
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
import axios from 'axios';
|
||||
import * as bitcoinjs from 'bitcoinjs-lib';
|
||||
import { BehaviorSubject, firstValueFrom } from 'rxjs';
|
||||
|
||||
import { MiningJob } from '../src/models/MiningJob';
|
||||
import { IBlockTemplate } from '../src/models/bitcoin-rpc/IBlockTemplate';
|
||||
import { createSubsidyOnlyBlockTemplate } from '../src/services/subsidy-only-template.factory';
|
||||
import { StratumV1JobsService } from '../src/services/stratum-v1-jobs.service';
|
||||
|
||||
const describeRegtest = process.env.RUN_BITCOIN_REGTEST_INTEGRATION === 'true'
|
||||
? describe
|
||||
: describe.skip;
|
||||
|
||||
describeRegtest('Bitcoin Core regtest block proposals', () => {
|
||||
const rpcUrl = process.env.BITCOIN_REGTEST_RPC_URL ?? 'http://127.0.0.1:28332';
|
||||
const rpcUser = process.env.BITCOIN_REGTEST_RPC_USER ?? 'bitcoin';
|
||||
const rpcPassword = process.env.BITCOIN_REGTEST_RPC_PASSWORD ?? 'bitcoin';
|
||||
let rpcId = 0;
|
||||
|
||||
it('accepts reconstructed subsidy-only and full jobs in proposal mode', async () => {
|
||||
const authoritative = await rpc<IBlockTemplate>('getblocktemplate', [{
|
||||
mode: 'template',
|
||||
rules: ['segwit'],
|
||||
capabilities: ['proposal'],
|
||||
}]);
|
||||
const empty = createSubsidyOnlyBlockTemplate({
|
||||
authoritativeTemplate: authoritative,
|
||||
network: 'regtest',
|
||||
payoutMode: 'solo',
|
||||
});
|
||||
|
||||
const emptyBlock = await reconstruct(empty);
|
||||
const fullBlock = await reconstruct({
|
||||
...authoritative,
|
||||
payoutMode: 'solo',
|
||||
jobType: 'full',
|
||||
forceCleanJobs: true,
|
||||
});
|
||||
|
||||
expect(emptyBlock.transactions).toHaveLength(1);
|
||||
expect(fullBlock.transactions).toHaveLength(authoritative.transactions.length + 1);
|
||||
await expect(propose(emptyBlock)).resolves.toBeNull();
|
||||
await expect(propose(fullBlock)).resolves.toBeNull();
|
||||
});
|
||||
|
||||
async function reconstruct(template: IBlockTemplate): Promise<bitcoinjs.Block> {
|
||||
const source = new BehaviorSubject(template);
|
||||
const jobs = new StratumV1JobsService({
|
||||
newBlockTemplate$: source.asObservable(),
|
||||
miningInfo: { blocks: template.height - 1 },
|
||||
} as any);
|
||||
const jobTemplate = await firstValueFrom(jobs.newMiningJob$);
|
||||
const payoutAddress = bitcoinjs.payments.p2wpkh({
|
||||
hash: Buffer.alloc(20, 1),
|
||||
network: bitcoinjs.networks.regtest,
|
||||
}).address!;
|
||||
const job = new MiningJob(
|
||||
bitcoinjs.networks.regtest,
|
||||
'1',
|
||||
[{ address: payoutAddress, percent: 100 }],
|
||||
jobTemplate,
|
||||
);
|
||||
return job.copyAndUpdateBlock(
|
||||
jobTemplate,
|
||||
0,
|
||||
0,
|
||||
'01020304',
|
||||
'05060708090a0b0c',
|
||||
Math.max(template.mintime, template.curtime, Math.floor(Date.now() / 1000)),
|
||||
);
|
||||
}
|
||||
|
||||
async function propose(block: bitcoinjs.Block): Promise<string | null> {
|
||||
return rpc<string | null>('getblocktemplate', [{
|
||||
mode: 'proposal',
|
||||
data: block.toHex(false),
|
||||
rules: ['segwit'],
|
||||
}]);
|
||||
}
|
||||
|
||||
async function rpc<T>(method: string, params: unknown[]): Promise<T> {
|
||||
const response = await axios.post(rpcUrl, {
|
||||
jsonrpc: '1.0',
|
||||
id: ++rpcId,
|
||||
method,
|
||||
params,
|
||||
}, {
|
||||
auth: { username: rpcUser, password: rpcPassword },
|
||||
timeout: 30_000,
|
||||
});
|
||||
if (response.data.error != null) {
|
||||
throw new Error(response.data.error.message ?? JSON.stringify(response.data.error));
|
||||
}
|
||||
return response.data.result as T;
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user