test: add some new functions to test/util/common.
This commit is contained in:
parent
c522c79c58
commit
5a751d9ba7
@ -5,7 +5,7 @@ const StaticWriter = require('../lib/utils/staticwriter');
|
|||||||
const common = require('../test/util/common');
|
const common = require('../test/util/common');
|
||||||
const bench = require('./bench');
|
const bench = require('./bench');
|
||||||
|
|
||||||
const {tx} = common.parseTX('data/tx5.hex');
|
const {tx} = common.parseTX('tx5');
|
||||||
|
|
||||||
{
|
{
|
||||||
const end = bench('serialize (static-writer)');
|
const end = bench('serialize (static-writer)');
|
||||||
|
|||||||
@ -4,7 +4,7 @@ const Coins = require('../lib/coins/coins');
|
|||||||
const common = require('../test/util/common');
|
const common = require('../test/util/common');
|
||||||
const bench = require('./bench');
|
const bench = require('./bench');
|
||||||
|
|
||||||
const {tx} = common.parseTX('data/tx5.hex');
|
const {tx} = common.parseTX('tx5');
|
||||||
const coins = Coins.fromTX(tx, 1);
|
const coins = Coins.fromTX(tx, 1);
|
||||||
const raw = coins.toRaw();
|
const raw = coins.toRaw();
|
||||||
|
|
||||||
|
|||||||
@ -19,11 +19,11 @@ const undo = common.parseUndo(undoRaw);
|
|||||||
|
|
||||||
const btx = {
|
const btx = {
|
||||||
tx: block.txs[397],
|
tx: block.txs[397],
|
||||||
view: common.applyUndo(block, undo)
|
view: common.applyBlockUndo(block, undo)
|
||||||
};
|
};
|
||||||
|
|
||||||
const tx3 = common.parseTX('data/tx3.hex');
|
const tx3 = common.parseTX('tx3');
|
||||||
const tx5 = common.parseTX('data/tx5.hex');
|
const tx5 = common.parseTX('tx5');
|
||||||
const raw = tx5.tx.toRaw();
|
const raw = tx5.tx.toRaw();
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@ -7,7 +7,7 @@ const common = require('../test/util/common');
|
|||||||
|
|
||||||
const SNAPSHOT = `${__dirname}/../dump.heapsnapshot`;
|
const SNAPSHOT = `${__dirname}/../dump.heapsnapshot`;
|
||||||
|
|
||||||
const {tx, view} = common.parseTX('data/tx4.hex');
|
const {tx, view} = common.parseTX('tx4');
|
||||||
const coins = Coins.fromTX(tx, 0);
|
const coins = Coins.fromTX(tx, 0);
|
||||||
const entry = MempoolEntry.fromTX(tx, view, 1000000);
|
const entry = MempoolEntry.fromTX(tx, view, 1000000);
|
||||||
|
|
||||||
|
|||||||
@ -139,7 +139,7 @@ describe('Block', function() {
|
|||||||
it('should verify a historical block', () => {
|
it('should verify a historical block', () => {
|
||||||
const block = Block.fromRaw(block300025);
|
const block = Block.fromRaw(block300025);
|
||||||
const undo = common.parseUndo(undo300025);
|
const undo = common.parseUndo(undo300025);
|
||||||
const view = common.applyUndo(block, undo);
|
const view = common.applyBlockUndo(block, undo);
|
||||||
const flags = Script.flags.VERIFY_P2SH | Script.flags.VERIFY_DERSIG;
|
const flags = Script.flags.VERIFY_P2SH | Script.flags.VERIFY_DERSIG;
|
||||||
const height = 300025;
|
const height = 300025;
|
||||||
|
|
||||||
@ -361,7 +361,7 @@ describe('Block', function() {
|
|||||||
it('should count sigops for block 928927 (testnet)', () => {
|
it('should count sigops for block 928927 (testnet)', () => {
|
||||||
const block = Block.fromRaw(block928927);
|
const block = Block.fromRaw(block928927);
|
||||||
const undo = common.parseUndo(undo928927);
|
const undo = common.parseUndo(undo928927);
|
||||||
const view = common.applyUndo(block, undo);
|
const view = common.applyBlockUndo(block, undo);
|
||||||
const flags = Script.flags.VERIFY_P2SH | Script.flags.VERIFY_WITNESS;
|
const flags = Script.flags.VERIFY_P2SH | Script.flags.VERIFY_WITNESS;
|
||||||
|
|
||||||
let sigops = 0;
|
let sigops = 0;
|
||||||
@ -375,7 +375,7 @@ describe('Block', function() {
|
|||||||
it('should count sigops for block 928828 (testnet)', () => {
|
it('should count sigops for block 928828 (testnet)', () => {
|
||||||
const block = Block.fromRaw(block928828);
|
const block = Block.fromRaw(block928828);
|
||||||
const undo = common.parseUndo(undo928828);
|
const undo = common.parseUndo(undo928828);
|
||||||
const view = common.applyUndo(block, undo);
|
const view = common.applyBlockUndo(block, undo);
|
||||||
const flags = Script.flags.VERIFY_P2SH | Script.flags.VERIFY_WITNESS;
|
const flags = Script.flags.VERIFY_P2SH | Script.flags.VERIFY_WITNESS;
|
||||||
|
|
||||||
let sigops = 0;
|
let sigops = 0;
|
||||||
@ -389,7 +389,7 @@ describe('Block', function() {
|
|||||||
it('should count sigops for block 1087400 (testnet)', () => {
|
it('should count sigops for block 1087400 (testnet)', () => {
|
||||||
const block = Block.fromRaw(block1087400);
|
const block = Block.fromRaw(block1087400);
|
||||||
const undo = common.parseUndo(undo1087400);
|
const undo = common.parseUndo(undo1087400);
|
||||||
const view = common.applyUndo(block, undo);
|
const view = common.applyBlockUndo(block, undo);
|
||||||
const flags = Script.flags.VERIFY_P2SH | Script.flags.VERIFY_WITNESS;
|
const flags = Script.flags.VERIFY_P2SH | Script.flags.VERIFY_WITNESS;
|
||||||
|
|
||||||
let sigops = 0;
|
let sigops = 0;
|
||||||
|
|||||||
@ -13,7 +13,7 @@ const StaticWriter = require('../lib/utils/staticwriter');
|
|||||||
const BufferReader = require('../lib/utils/reader');
|
const BufferReader = require('../lib/utils/reader');
|
||||||
const {parseTX} = require('./util/common');
|
const {parseTX} = require('./util/common');
|
||||||
|
|
||||||
const data = parseTX('data/tx1.hex');
|
const data = parseTX('tx1');
|
||||||
const tx1 = data.tx;
|
const tx1 = data.tx;
|
||||||
|
|
||||||
function reserialize(coin) {
|
function reserialize(coin) {
|
||||||
|
|||||||
@ -15,8 +15,8 @@ const packets = require('../lib/net/packets');
|
|||||||
const common = require('./util/common');
|
const common = require('./util/common');
|
||||||
const network = Network.get('main');
|
const network = Network.get('main');
|
||||||
|
|
||||||
const tx8 = common.parseTX('data/tx8.hex');
|
const tx8 = common.parseTX('tx8');
|
||||||
const tx9 = common.parseTX('data/tx9.hex');
|
const tx9 = common.parseTX('tx9');
|
||||||
|
|
||||||
describe('Protocol', function() {
|
describe('Protocol', function() {
|
||||||
const pkg = require('../lib/pkg');
|
const pkg = require('../lib/pkg');
|
||||||
@ -28,15 +28,20 @@ describe('Protocol', function() {
|
|||||||
framer = new Framer();
|
framer = new Framer();
|
||||||
});
|
});
|
||||||
|
|
||||||
function packetTest(command, payload, test) {
|
function packetTest(cmd, payload, test) {
|
||||||
it(`should encode/decode ${command}`, (cb) => {
|
it(`should encode/decode ${cmd}`, (cb) => {
|
||||||
const ver = Buffer.from(framer.packet(command, payload.toRaw()));
|
|
||||||
parser.once('packet', (packet) => {
|
parser.once('packet', (packet) => {
|
||||||
assert.strictEqual(packet.cmd, command);
|
try {
|
||||||
test(packet);
|
assert.strictEqual(packet.cmd, cmd);
|
||||||
|
test(packet);
|
||||||
|
} catch (e) {
|
||||||
|
cb(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
parser.feed(ver);
|
const raw = framer.packet(cmd, payload.toRaw());
|
||||||
|
parser.feed(raw);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,13 +23,13 @@ const validTests = require('./data/tx-valid.json');
|
|||||||
const invalidTests = require('./data/tx-invalid.json');
|
const invalidTests = require('./data/tx-invalid.json');
|
||||||
const sighashTests = require('./data/sighash-tests.json');
|
const sighashTests = require('./data/sighash-tests.json');
|
||||||
|
|
||||||
const tx1 = common.parseTX('data/tx1.hex');
|
const tx1 = common.parseTX('tx1');
|
||||||
const tx2 = common.parseTX('data/tx2.hex');
|
const tx2 = common.parseTX('tx2');
|
||||||
const tx3 = common.parseTX('data/tx3.hex');
|
const tx3 = common.parseTX('tx3');
|
||||||
const tx4 = common.parseTX('data/tx4.hex');
|
const tx4 = common.parseTX('tx4');
|
||||||
const tx5 = common.parseTX('data/tx5.hex');
|
const tx5 = common.parseTX('tx5');
|
||||||
const tx6 = common.parseTX('data/tx6.hex');
|
const tx6 = common.parseTX('tx6');
|
||||||
const tx7 = common.parseTX('data/tx7.hex');
|
const tx7 = common.parseTX('tx7');
|
||||||
|
|
||||||
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
|
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
|
||||||
const MAX_SAFE_ADDITION = 0xfffffffffffff;
|
const MAX_SAFE_ADDITION = 0xfffffffffffff;
|
||||||
|
|||||||
@ -2,22 +2,26 @@
|
|||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const fs = require('../../lib/utils/fs');
|
const fs = require('../../lib/utils/fs');
|
||||||
|
const Block = require('../../lib/primitives/block');
|
||||||
|
const MerkleBlock = require('../../lib/primitives/merkleblock');
|
||||||
|
const {CompactBlock} = require('../../lib/net/bip152');
|
||||||
const TX = require('../../lib/primitives/tx');
|
const TX = require('../../lib/primitives/tx');
|
||||||
const Output = require('../../lib/primitives/output');
|
const Output = require('../../lib/primitives/output');
|
||||||
const CoinView = require('../../lib/coins/coinview');
|
const CoinView = require('../../lib/coins/coinview');
|
||||||
const BufferReader = require('../../lib/utils/reader');
|
const BufferReader = require('../../lib/utils/reader');
|
||||||
|
const BufferWriter = require('../../lib/utils/writer');
|
||||||
|
|
||||||
exports.parseTX = function parseTX(file) {
|
exports.parseTX = function parseTX(name) {
|
||||||
const data = fs.readFileSync(`${__dirname}/../${file}`, 'utf8');
|
const data = fs.readFileSync(`${__dirname}/../data/${name}.hex`, 'utf8');
|
||||||
const parts = data.trim().split(/\n+/);
|
const parts = data.trim().split('\n');
|
||||||
const raw = parts[0];
|
const raw = Buffer.from(parts[0], 'hex');
|
||||||
const tx = TX.fromRaw(raw.trim(), 'hex');
|
const tx = TX.fromRaw(raw);
|
||||||
const view = new CoinView();
|
const view = new CoinView();
|
||||||
const txs = [tx];
|
const txs = [tx];
|
||||||
|
|
||||||
for (let i = 1; i < parts.length; i++) {
|
for (let i = 1; i < parts.length; i++) {
|
||||||
const raw = parts[i];
|
const raw = Buffer.from(parts[i], 'hex');
|
||||||
const prev = TX.fromRaw(raw.trim(), 'hex');
|
const prev = TX.fromRaw(raw);
|
||||||
view.addTX(prev, -1);
|
view.addTX(prev, -1);
|
||||||
txs.push(prev);
|
txs.push(prev);
|
||||||
}
|
}
|
||||||
@ -29,19 +33,87 @@ exports.parseTX = function parseTX(file) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.readBlock = function readBlock(name) {
|
||||||
|
const height = name.substring(5);
|
||||||
|
const blockFile = `${__dirname}/../data/block${height}.raw`;
|
||||||
|
|
||||||
|
if (!fs.existsSync(blockFile)) {
|
||||||
|
const raw = fs.readFileSync(`${__dirname}/../data/${name}.raw`);
|
||||||
|
const block = Block.fromRaw(raw);
|
||||||
|
const view = new CoinView();
|
||||||
|
return { raw, block, view };
|
||||||
|
}
|
||||||
|
|
||||||
|
const raw = fs.readFileSync(blockFile);
|
||||||
|
const block = Block.fromRaw(raw);
|
||||||
|
|
||||||
|
const undoFile = `${__dirname}/../data/undo${height}.raw`;
|
||||||
|
|
||||||
|
if (!fs.existsSync(undoFile)) {
|
||||||
|
const view = new CoinView();
|
||||||
|
return { raw, block, view };
|
||||||
|
}
|
||||||
|
|
||||||
|
const undoRaw = fs.readFileSync(undoFile);
|
||||||
|
const undo = exports.parseUndo(undoRaw);
|
||||||
|
const view = exports.applyBlockUndo(block, undo);
|
||||||
|
|
||||||
|
return { raw, block, view };
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.readMerkle = function readMerkle(name) {
|
||||||
|
const raw = fs.readFileSync(`${__dirname}/../data/${name}.raw`);
|
||||||
|
const block = MerkleBlock.fromRaw(raw);
|
||||||
|
return { raw, block };
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.readCompact = function readCompact(name) {
|
||||||
|
const raw = fs.readFileSync(`${__dirname}/../data/${name}.raw`);
|
||||||
|
const block = CompactBlock.fromRaw(raw);
|
||||||
|
return { raw, block };
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.readTX = function readTX(name) {
|
||||||
|
const index = name.substring(2);
|
||||||
|
const txFile = `${__dirname}/../data/tx${index}.raw`;
|
||||||
|
|
||||||
|
if (!fs.existsSync(txFile)) {
|
||||||
|
const raw = fs.readFileSync(`${__dirname}/../data/${name}.raw`);
|
||||||
|
const tx = TX.fromRaw(raw);
|
||||||
|
const view = new CoinView();
|
||||||
|
return { raw, tx, view };
|
||||||
|
}
|
||||||
|
|
||||||
|
const raw = fs.readFileSync(txFile);
|
||||||
|
const tx = TX.fromRaw(raw);
|
||||||
|
|
||||||
|
const undoFile = `${__dirname}/../data/utx${index}.raw`;
|
||||||
|
|
||||||
|
if (!fs.existsSync(undoFile)) {
|
||||||
|
const view = new CoinView();
|
||||||
|
return { raw, tx, view };
|
||||||
|
}
|
||||||
|
|
||||||
|
const undoRaw = fs.readFileSync(undoFile);
|
||||||
|
const undo = exports.parseUndo(undoRaw);
|
||||||
|
const view = exports.applyTXUndo(tx, undo);
|
||||||
|
|
||||||
|
return { raw, tx, view };
|
||||||
|
};
|
||||||
|
|
||||||
exports.parseUndo = function parseUndo(data) {
|
exports.parseUndo = function parseUndo(data) {
|
||||||
const br = new BufferReader(data);
|
const br = new BufferReader(data);
|
||||||
const undo = [];
|
const items = [];
|
||||||
|
|
||||||
while (br.left()) {
|
while (br.left()) {
|
||||||
const output = Output.fromReader(br);
|
const output = Output.fromReader(br);
|
||||||
undo.push(output);
|
items.push(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
return undo;
|
return items;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.applyUndo = function applyUndo(block, undo) {
|
exports.applyBlockUndo = function applyBlockUndo(block, undo) {
|
||||||
const view = new CoinView();
|
const view = new CoinView();
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
|
||||||
@ -57,3 +129,83 @@ exports.applyUndo = function applyUndo(block, undo) {
|
|||||||
|
|
||||||
return view;
|
return view;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.applyTXUndo = function applyTXUndo(tx, undo) {
|
||||||
|
const view = new CoinView();
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
for (const {prevout} of tx.inputs)
|
||||||
|
view.addOutput(prevout, undo[i++]);
|
||||||
|
|
||||||
|
assert(i === undo.length, 'Undo coins data inconsistency.');
|
||||||
|
|
||||||
|
return view;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.makeBlockUndo = function makeBlockUndo(block, view) {
|
||||||
|
const items = [];
|
||||||
|
|
||||||
|
for (const tx of block.txs) {
|
||||||
|
if (tx.isCoinbase())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (const {prevout} of tx.inputs) {
|
||||||
|
const coin = view.getOutput(prevout);
|
||||||
|
assert(coin);
|
||||||
|
items.push(coin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.makeTXUndo = function makeTXUndo(tx, view) {
|
||||||
|
const items = [];
|
||||||
|
|
||||||
|
for (const {prevout} of tx.inputs) {
|
||||||
|
const coin = view.getOutput(prevout);
|
||||||
|
assert(coin);
|
||||||
|
items.push(coin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.serializeUndo = function serializeUndo(items) {
|
||||||
|
const bw = new BufferWriter();
|
||||||
|
|
||||||
|
for (const item of items) {
|
||||||
|
bw.writeI64(item.value);
|
||||||
|
bw.writeVarBytes(item.script.toRaw());
|
||||||
|
}
|
||||||
|
|
||||||
|
return bw.render();
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.writeBlock = function writeBlock(name, block, view) {
|
||||||
|
const height = name.substring(5);
|
||||||
|
|
||||||
|
fs.writeFileSync(`${__dirname}/../data/block${height}.raw`, block.toRaw());
|
||||||
|
|
||||||
|
if (!view)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const undo = exports.makeBlockUndo(block, view);
|
||||||
|
const undoRaw = exports.serializeUndo(undo);
|
||||||
|
|
||||||
|
fs.writeFileSync(`${__dirname}/../data/undo${height}.raw`, undoRaw);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.writeTX = function writeTX(name, tx, view) {
|
||||||
|
const index = name.substring(2);
|
||||||
|
|
||||||
|
fs.writeFileSync(`${__dirname}/../data/tx${index}.raw`, tx.toRaw());
|
||||||
|
|
||||||
|
if (!view)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const undo = exports.makeTXUndo(tx, view);
|
||||||
|
const undoRaw = exports.serializeUndo(undo);
|
||||||
|
|
||||||
|
fs.writeFileSync(`${__dirname}/../data/utx${index}.raw`, undoRaw);
|
||||||
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user