test: add net pool getheaders, tx, and merkleblock handler tests
This commit is contained in:
parent
357ad4c2c4
commit
fbe64cf4a2
301
test/net-test.js
301
test/net-test.js
@ -17,7 +17,10 @@ const Peer = require('../lib/net/peer');
|
||||
const Pool = require('../lib/net/pool');
|
||||
const InvItem = require('../lib/primitives/invitem');
|
||||
const Headers = require('../lib/primitives/headers');
|
||||
const MerkleBlock = require('../lib/primitives/merkleblock');
|
||||
const ChainEntry = require('../lib/blockchain/chainentry');
|
||||
const Network = require('../lib/protocol/network');
|
||||
const {VerifyError} = require('../lib/protocol/errors');
|
||||
const consensus = require('../lib/protocol/consensus');
|
||||
const util = require('../lib/utils/util');
|
||||
|
||||
@ -427,7 +430,7 @@ describe('Net', function() {
|
||||
check(pkt, true);
|
||||
});
|
||||
|
||||
it('sendheaders', () => {
|
||||
it('sendheaders (BIP130)', () => {
|
||||
const check = (pkt) => {
|
||||
assert.equal(pkt.cmd, 'sendheaders');
|
||||
assert.equal(pkt.type, packets.types.SENDHEADERS);
|
||||
@ -543,7 +546,7 @@ describe('Net', function() {
|
||||
check(pkt);
|
||||
});
|
||||
|
||||
it('mempool', () => {
|
||||
it('mempool (BIP35)', () => {
|
||||
const check = (pkt) => {
|
||||
assert.equal(pkt.cmd, 'mempool');
|
||||
assert.equal(pkt.type, packets.types.MEMPOOL);
|
||||
@ -555,7 +558,7 @@ describe('Net', function() {
|
||||
pkt = packets.MempoolPacket.fromRaw(pkt.toRaw());
|
||||
});
|
||||
|
||||
it('filterload', () => {
|
||||
it('filterload (BIP37)', () => {
|
||||
const check = (pkt) => {
|
||||
assert.equal(pkt.cmd, 'filterload');
|
||||
assert.equal(pkt.type, packets.types.FILTERLOAD);
|
||||
@ -574,7 +577,7 @@ describe('Net', function() {
|
||||
check(pkt);
|
||||
});
|
||||
|
||||
it('filteradd', () => {
|
||||
it('filteradd (BIP37)', () => {
|
||||
const check = (pkt) => {
|
||||
assert.equal(pkt.cmd, 'filteradd');
|
||||
assert.equal(pkt.type, packets.types.FILTERADD);
|
||||
@ -588,7 +591,7 @@ describe('Net', function() {
|
||||
check(pkt);
|
||||
});
|
||||
|
||||
it('filterclear', () => {
|
||||
it('filterclear (BIP37)', () => {
|
||||
const check = (pkt) => {
|
||||
assert.equal(pkt.cmd, 'filterclear');
|
||||
assert.equal(pkt.type, packets.types.FILTERCLEAR);
|
||||
@ -601,7 +604,7 @@ describe('Net', function() {
|
||||
check(pkt);
|
||||
});
|
||||
|
||||
it('merkleblock', () => {
|
||||
it('merkleblock (BIP37)', () => {
|
||||
const [block] = merkle300025.getBlock();
|
||||
|
||||
const check = (pkt) => {
|
||||
@ -618,7 +621,7 @@ describe('Net', function() {
|
||||
check(pkt);
|
||||
});
|
||||
|
||||
it('feefilter', () => {
|
||||
it('feefilter (BIP133)', () => {
|
||||
const check = (pkt) => {
|
||||
assert.equal(pkt.cmd, 'feefilter');
|
||||
assert.equal(pkt.type, packets.types.FEEFILTER);
|
||||
@ -633,7 +636,7 @@ describe('Net', function() {
|
||||
check(pkt);
|
||||
});
|
||||
|
||||
it('sendcmpct', () => {
|
||||
it('sendcmpct (BIP152)', () => {
|
||||
const check = (pkt, mode, version) => {
|
||||
assert.equal(pkt.cmd, 'sendcmpct');
|
||||
assert.equal(pkt.type, packets.types.SENDCMPCT);
|
||||
@ -655,7 +658,7 @@ describe('Net', function() {
|
||||
check(pkt, 1, 2);
|
||||
});
|
||||
|
||||
it('cmpctblock', () => {
|
||||
it('cmpctblock (BIP152)', () => {
|
||||
const [block] = block300025.getBlock();
|
||||
const [witnessBlock] = block482683.getBlock();
|
||||
|
||||
@ -690,7 +693,7 @@ describe('Net', function() {
|
||||
check(pkt, true, true);
|
||||
});
|
||||
|
||||
it('getblocktxn', () => {
|
||||
it('getblocktxn (BIP152)', () => {
|
||||
const check = (pkt) => {
|
||||
assert.equal(pkt.cmd, 'getblocktxn');
|
||||
assert.equal(pkt.type, packets.types.GETBLOCKTXN);
|
||||
@ -711,7 +714,7 @@ describe('Net', function() {
|
||||
check(pkt);
|
||||
});
|
||||
|
||||
it('blocktxn', () => {
|
||||
it('blocktxn (BIP152)', () => {
|
||||
const [block] = block482683.getBlock();
|
||||
|
||||
const tx = block.txs[9];
|
||||
@ -1101,7 +1104,7 @@ describe('Net', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleSendHeaders', function() {
|
||||
describe('handleSendHeaders (BIP130)', function() {
|
||||
it('will set prefer headers', async () => {
|
||||
const peer = Peer.fromOptions({});
|
||||
const pkt = new packets.SendHeadersPacket();
|
||||
@ -1110,7 +1113,7 @@ describe('Net', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleFilterLoad', function() {
|
||||
describe('handleFilterLoad (BIP37)', function() {
|
||||
it('will load spv filter', async () => {
|
||||
const peer = Peer.fromOptions({});
|
||||
const filter = new BloomFilter();
|
||||
@ -1138,7 +1141,7 @@ describe('Net', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleFilterAdd', function() {
|
||||
describe('handleFilterAdd (BIP37)', function() {
|
||||
it('will add to spv filter', async () => {
|
||||
const peer = Peer.fromOptions({});
|
||||
peer.spvFilter = BloomFilter.fromRate(
|
||||
@ -1181,7 +1184,7 @@ describe('Net', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleFilterClear', function() {
|
||||
describe('handleFilterClear (BIP37)', function() {
|
||||
it('will reset spv filter', async () => {
|
||||
const peer = Peer.fromOptions({});
|
||||
peer.spvFilter = BloomFilter.fromRate(
|
||||
@ -1210,7 +1213,7 @@ describe('Net', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleFeeFilter', function() {
|
||||
describe('handleFeeFilter (BIP133)', function() {
|
||||
it('will set fee rate', async () => {
|
||||
const peer = Peer.fromOptions({});
|
||||
const pkt = new packets.FeeFilterPacket(120000);
|
||||
@ -1237,7 +1240,7 @@ describe('Net', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleSendCmpct', function() {
|
||||
describe('handleSendCmpct (BIP152)', function() {
|
||||
it('will not set compact mode (already set)', async () => {
|
||||
const peer = Peer.fromOptions({});
|
||||
const pkt = new packets.SendCmpctPacket(1, 1);
|
||||
@ -1889,6 +1892,270 @@ describe('Net', function() {
|
||||
assert(called);
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleGetHeaders', function() {
|
||||
function mockHash(height) {
|
||||
const hash = Buffer.alloc(32, 0x00);
|
||||
hash.writeUInt32LE(height);
|
||||
return hash;
|
||||
}
|
||||
|
||||
const network = Network.get('regtest');
|
||||
let pool = null;
|
||||
|
||||
before(async () => {
|
||||
pool = new Pool({
|
||||
logger: Logger.global,
|
||||
chain: {
|
||||
network,
|
||||
options: {checkpoints: true},
|
||||
on: () => {},
|
||||
synced: true,
|
||||
findLocator: (locators) => {
|
||||
assert.bufferEqual(locators[0], mockHash(0));
|
||||
|
||||
return locators[0];
|
||||
},
|
||||
getNextHash: (hash) => {
|
||||
assert.bufferEqual(hash, mockHash(0));
|
||||
|
||||
return mockHash(1);
|
||||
},
|
||||
getEntry: (hash) => {
|
||||
assert.bufferEqual(hash, mockHash(1));
|
||||
|
||||
return new ChainEntry({
|
||||
version: 1,
|
||||
hash: mockHash(1),
|
||||
prevBlock: mockHash(0),
|
||||
merkleRoot: Buffer.alloc(32, 0x00),
|
||||
time: 1558629632,
|
||||
bits: 486604799,
|
||||
nonce: 10,
|
||||
height: 1
|
||||
});
|
||||
},
|
||||
getNext: (entry) => {
|
||||
const height = entry.height + 1;
|
||||
|
||||
return new ChainEntry({
|
||||
version: 1,
|
||||
hash: mockHash(height),
|
||||
prevBlock: entry.hash,
|
||||
merkleRoot: Buffer.alloc(32, 0x00),
|
||||
time: 1558629632,
|
||||
bits: 486604799,
|
||||
nonce: 10,
|
||||
height: height
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('will send max headers from chain', async () => {
|
||||
const peer = Peer.fromOptions(pool.options);
|
||||
peer.handshake = true;
|
||||
|
||||
const locators = [mockHash(0)];
|
||||
const stop = mockHash(7500);
|
||||
|
||||
const pkt = new packets.GetHeadersPacket(locators, stop);
|
||||
|
||||
let called = false;
|
||||
peer.send = (packet) => {
|
||||
assert.equal(packet.type, packets.types.HEADERS);
|
||||
assert.equal(packet.items.length, 2000);
|
||||
called = true;
|
||||
};
|
||||
|
||||
await pool.handleGetHeaders(peer, pkt);
|
||||
assert(called);
|
||||
});
|
||||
|
||||
it('will continue until stop point', async () => {
|
||||
const peer = Peer.fromOptions(pool.options);
|
||||
peer.handshake = true;
|
||||
|
||||
const locators = [mockHash(0)];
|
||||
const stop = mockHash(1500);
|
||||
|
||||
const pkt = new packets.GetHeadersPacket(locators, stop);
|
||||
|
||||
let called = false;
|
||||
peer.send = (packet) => {
|
||||
assert.equal(packet.type, packets.types.HEADERS);
|
||||
assert.equal(packet.items.length, 1500);
|
||||
assert.bufferEqual(packet.items[0].hash(), mockHash(1));
|
||||
assert.bufferEqual(packet.items[1499].hash(), mockHash(1500));
|
||||
called = true;
|
||||
};
|
||||
|
||||
await pool.handleGetHeaders(peer, pkt);
|
||||
assert(called);
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleTX', function() {
|
||||
const [block] = block300025.getBlock();
|
||||
|
||||
const network = Network.get('regtest');
|
||||
|
||||
it('will destroy if unrequested', async () => {
|
||||
const pool = new Pool({
|
||||
logger: Logger.global,
|
||||
chain: {network, options: {checkpoints: true}, on: () => {}}
|
||||
});
|
||||
|
||||
const peer = Peer.fromOptions(pool.options);
|
||||
|
||||
pool.resolveTX = (_peer, hash) => {
|
||||
assert.strictEqual(_peer, peer);
|
||||
assert.bufferEqual(hash, block.txs[10].hash());
|
||||
return false;
|
||||
};
|
||||
|
||||
let called = false;
|
||||
peer.destroy = () => {
|
||||
called = true;
|
||||
};
|
||||
|
||||
const pkt = new packets.TXPacket(block.txs[10]);
|
||||
|
||||
await pool.handleTX(peer, pkt);
|
||||
assert(called);
|
||||
});
|
||||
|
||||
it('will add tx to mempool', async () => {
|
||||
let added = false;
|
||||
|
||||
const pool = new Pool({
|
||||
logger: Logger.global,
|
||||
chain: {
|
||||
network,
|
||||
options: {
|
||||
checkpoints: true
|
||||
},
|
||||
on: () => {}
|
||||
}
|
||||
});
|
||||
|
||||
const peer = Peer.fromOptions(pool.options);
|
||||
|
||||
pool.resolveTX = () => true;
|
||||
pool.mempool = {
|
||||
addTX: (tx, id) => {
|
||||
assert.strictEqual(tx, block.txs[10]);
|
||||
assert.equal(id, peer.id);
|
||||
added = true;
|
||||
return false;
|
||||
},
|
||||
on: () => {}
|
||||
};
|
||||
|
||||
const pkt = new packets.TXPacket(block.txs[10]);
|
||||
|
||||
await pool.handleTX(peer, pkt);
|
||||
assert(added);
|
||||
});
|
||||
|
||||
it('will increase ban if invalid', async () => {
|
||||
const pool = new Pool({
|
||||
logger: Logger.global,
|
||||
chain: {
|
||||
network,
|
||||
options: {
|
||||
checkpoints: true
|
||||
},
|
||||
on: () => {}
|
||||
},
|
||||
mempool: {
|
||||
addTX: (tx) => {
|
||||
throw new VerifyError(tx, 'invalid', 'test-reason', 10);
|
||||
},
|
||||
on: () => {}
|
||||
}
|
||||
});
|
||||
|
||||
const peer = Peer.fromOptions(pool.options);
|
||||
|
||||
let increaseBan = false;
|
||||
peer.increaseBan = (score) => {
|
||||
assert.equal(score, 10);
|
||||
increaseBan = true;
|
||||
};
|
||||
|
||||
let send = false;
|
||||
peer.send = (packet) => {
|
||||
assert.equal(packet.type, packets.types.REJECT);
|
||||
send = true;
|
||||
};
|
||||
|
||||
pool.resolveTX = () => true;
|
||||
|
||||
const pkt = new packets.TXPacket(block.txs[10]);
|
||||
|
||||
await pool.handleTX(peer, pkt);
|
||||
assert(increaseBan);
|
||||
assert(send);
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleMerkleBlock/handleTX (BIP37)', function() {
|
||||
const network = Network.get('regtest');
|
||||
|
||||
it('will add block w/ merkle block and txs', async () => {
|
||||
const [block] = block300025.getBlock();
|
||||
|
||||
const pool = new Pool({
|
||||
logger: Logger.global,
|
||||
chain: {
|
||||
network,
|
||||
options: {
|
||||
checkpoints: true,
|
||||
spv: true
|
||||
},
|
||||
on: () => {}
|
||||
},
|
||||
spv: true
|
||||
});
|
||||
pool.syncing = true;
|
||||
|
||||
const filter = BloomFilter.fromRate(20000, 0.001,
|
||||
BloomFilter.flags.ALL);
|
||||
filter.add(block.txs[10].hash());
|
||||
filter.add(block.txs[12].hash());
|
||||
|
||||
// Serialize the block as the txs are not included
|
||||
// over the network, however the txs are included in
|
||||
// the data structure.
|
||||
const merkle = MerkleBlock.fromRaw(block.toMerkle(filter).toRaw());
|
||||
|
||||
const blkpkt = new packets.MerkleBlockPacket(merkle);
|
||||
const tx1pkt = new packets.TXPacket(block.txs[10]);
|
||||
const tx2pkt = new packets.TXPacket(block.txs[12]);
|
||||
|
||||
const peer = Peer.fromOptions(pool.options);
|
||||
peer.blockMap.set(block.hash(), Date.now());
|
||||
|
||||
let called = false;
|
||||
|
||||
pool._addBlock = (_peer, _block, flags) => {
|
||||
assert.strictEqual(_peer, peer);
|
||||
assert.bufferEqual(_block.hash(), block.hash());
|
||||
assert.equal(_block.txs.length, 2);
|
||||
assert.strictEqual(_block.txs[0], block.txs[10]);
|
||||
assert.strictEqual(_block.txs[1], block.txs[12]);
|
||||
called = true;
|
||||
};
|
||||
|
||||
await pool.handleMerkleBlock(peer, blkpkt);
|
||||
await pool.handleTX(peer, tx1pkt);
|
||||
await pool.handleTX(peer, tx2pkt);
|
||||
|
||||
assert(called);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Framer', function() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user