2023-06-27 17:42:04 -04:00
|
|
|
import fs from 'fs';
|
2023-07-02 20:05:30 -04:00
|
|
|
import { GbtGenerator, ThreadTransaction } from '../../../rust-gbt';
|
2023-06-27 17:42:04 -04:00
|
|
|
import path from 'path';
|
|
|
|
|
|
|
|
const baseline = require('./test-data/target-template.json');
|
|
|
|
const testVector = require('./test-data/test-data-ids.json');
|
|
|
|
const vectorUidMap: Map<number, string> = new Map(testVector.map(x => [x[0], x[1]]));
|
|
|
|
const vectorTxidMap: Map<string, number> = new Map(testVector.map(x => [x[1], x[0]]));
|
|
|
|
// Note that this test buffer is specially constructed
|
|
|
|
// such that uids are assigned in numerical txid order
|
|
|
|
// so that ties break the same way as in Core's implementation
|
2023-06-28 16:31:59 -04:00
|
|
|
const vectorBuffer: Buffer = fs.readFileSync(path.join(__dirname, './', './test-data/test-buffer.bin'));
|
2023-06-27 17:42:04 -04:00
|
|
|
|
|
|
|
describe('Rust GBT', () => {
|
|
|
|
test('should produce the same template as getBlockTemplate from Bitcoin Core', async () => {
|
|
|
|
const rustGbt = new GbtGenerator();
|
2023-06-28 16:31:59 -04:00
|
|
|
const mempool = mempoolFromArrayBuffer(vectorBuffer.buffer);
|
|
|
|
const result = await rustGbt.make(mempool);
|
2023-06-27 17:42:04 -04:00
|
|
|
|
|
|
|
const blocks: [string, number][][] = result.blocks.map(block => {
|
|
|
|
return block.map(uid => [vectorUidMap.get(uid) || 'missing', uid]);
|
|
|
|
});
|
|
|
|
const template = baseline.map(tx => [tx.txid, vectorTxidMap.get(tx.txid)]);
|
|
|
|
|
|
|
|
expect(blocks[0].length).toEqual(baseline.length);
|
|
|
|
expect(blocks[0]).toEqual(template);
|
|
|
|
});
|
|
|
|
});
|
2023-06-28 16:31:59 -04:00
|
|
|
|
2023-07-02 20:05:30 -04:00
|
|
|
function mempoolFromArrayBuffer(buf: ArrayBuffer): ThreadTransaction[] {
|
2023-06-28 16:31:59 -04:00
|
|
|
const view = new DataView(buf);
|
|
|
|
const count = view.getUint32(0, false);
|
2023-07-02 20:05:30 -04:00
|
|
|
const txs: ThreadTransaction[] = [];
|
2023-06-28 16:31:59 -04:00
|
|
|
let offset = 4;
|
|
|
|
for (let i = 0; i < count; i++) {
|
2023-07-02 20:05:30 -04:00
|
|
|
const uid = view.getUint32(offset, false);
|
|
|
|
const tx: ThreadTransaction = {
|
|
|
|
uid,
|
|
|
|
order: txidToOrdering(vectorUidMap.get(uid) as string),
|
2023-06-28 16:31:59 -04:00
|
|
|
fee: view.getFloat64(offset + 4, false),
|
|
|
|
weight: view.getUint32(offset + 12, false),
|
|
|
|
sigops: view.getUint32(offset + 16, false),
|
2023-07-02 20:05:30 -04:00
|
|
|
// feePerVsize: view.getFloat64(offset + 20, false),
|
2023-06-28 16:31:59 -04:00
|
|
|
effectiveFeePerVsize: view.getFloat64(offset + 28, false),
|
|
|
|
inputs: [],
|
|
|
|
};
|
|
|
|
const numInputs = view.getUint32(offset + 36, false);
|
|
|
|
offset += 40;
|
|
|
|
for (let j = 0; j < numInputs; j++) {
|
|
|
|
tx.inputs.push(view.getUint32(offset, false));
|
|
|
|
offset += 4;
|
|
|
|
}
|
|
|
|
txs.push(tx);
|
|
|
|
}
|
|
|
|
return txs;
|
|
|
|
}
|
2023-07-02 20:05:30 -04:00
|
|
|
|
|
|
|
function txidToOrdering(txid: string): number {
|
2023-07-03 11:55:43 -04:00
|
|
|
return (
|
|
|
|
((parseInt(txid.substring(62, 64), 16) << 24) |
|
|
|
|
(parseInt(txid.substring(60, 62), 16) << 16) |
|
|
|
|
(parseInt(txid.substring(58, 60), 16) << 8) |
|
|
|
|
parseInt(txid.substring(56, 58), 16)) >>>
|
|
|
|
0
|
|
|
|
);
|
2023-07-02 20:05:30 -04:00
|
|
|
}
|