2014-11-20 13:19:48 -08:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
var bitcore = require('..');
|
2014-12-06 12:43:31 -08:00
|
|
|
var BN = require('../lib/crypto/bn');
|
2014-11-21 08:26:30 -08:00
|
|
|
var BufferReader = bitcore.encoding.BufferReader;
|
2014-12-19 11:36:57 -08:00
|
|
|
var BufferWriter = bitcore.encoding.BufferWriter;
|
2014-12-06 12:43:31 -08:00
|
|
|
var BlockHeader = bitcore.BlockHeader;
|
2014-11-20 13:19:48 -08:00
|
|
|
var Block = bitcore.Block;
|
2014-12-06 12:43:31 -08:00
|
|
|
var chai = require('chai');
|
|
|
|
var fs = require('fs');
|
|
|
|
var should = chai.should();
|
2014-11-20 13:19:48 -08:00
|
|
|
var Transaction = bitcore.Transaction;
|
2014-12-06 12:43:31 -08:00
|
|
|
|
|
|
|
// https://test-insight.bitpay.com/block/000000000b99b16390660d79fcc138d2ad0c89a0d044c4201a02bdf1f61ffa11
|
|
|
|
var dataRawBlockBuffer = fs.readFileSync('test/data/blk86756-testnet.dat');
|
|
|
|
var dataRawBlockBinary = fs.readFileSync('test/data/blk86756-testnet.dat', 'binary');
|
|
|
|
var dataJson = fs.readFileSync('test/data/blk86756-testnet.json').toString();
|
|
|
|
var data = require('./data/blk86756-testnet');
|
2015-01-09 13:50:24 -08:00
|
|
|
var dataBlocks = require('./data/bitcoind/blocks');
|
2014-09-16 18:42:11 -07:00
|
|
|
|
|
|
|
describe('Block', function() {
|
2014-12-06 12:43:31 -08:00
|
|
|
|
|
|
|
var blockhex = data.blockhex;
|
2014-09-16 18:42:11 -07:00
|
|
|
var blockbuf = new Buffer(blockhex, 'hex');
|
2014-12-06 12:43:31 -08:00
|
|
|
var bh = BlockHeader.fromBuffer(new Buffer(data.blockheaderhex, 'hex'));
|
|
|
|
var txs = [];
|
2015-04-28 11:17:41 -07:00
|
|
|
JSON.parse(dataJson).transactions.forEach(function(tx) {
|
2014-12-06 12:43:31 -08:00
|
|
|
txs.push(new Transaction().fromJSON(tx));
|
|
|
|
});
|
|
|
|
var json = dataJson;
|
2014-09-16 18:42:11 -07:00
|
|
|
|
2015-01-16 20:23:02 -08:00
|
|
|
var genesishex = '0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000';
|
2014-09-19 17:08:44 -07:00
|
|
|
var genesisbuf = new Buffer(genesishex, 'hex');
|
|
|
|
var genesisidhex = '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f';
|
2015-04-28 11:17:41 -07:00
|
|
|
var blockOneHex = '010000006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e61bc6649ffff001d01e362990101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000';
|
|
|
|
var blockOneBuf = new Buffer(blockOneHex, 'hex');
|
|
|
|
var blockOneId = '00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048';
|
2014-09-19 17:08:44 -07:00
|
|
|
|
2014-09-22 13:07:39 -07:00
|
|
|
it('should make a new block', function() {
|
2014-12-06 12:43:31 -08:00
|
|
|
var b = Block(blockbuf);
|
|
|
|
b.toBuffer().toString('hex').should.equal(blockhex);
|
2014-09-22 13:07:39 -07:00
|
|
|
});
|
|
|
|
|
2014-12-06 12:43:31 -08:00
|
|
|
it('should not make an empty block', function() {
|
|
|
|
(function() {
|
2015-01-16 11:54:32 -08:00
|
|
|
return new Block();
|
2014-12-06 12:43:31 -08:00
|
|
|
}).should.throw('Unrecognized argument for Block');
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('#constructor', function() {
|
2014-09-16 18:42:11 -07:00
|
|
|
|
|
|
|
it('should set these known values', function() {
|
2014-12-06 12:43:31 -08:00
|
|
|
var b = new Block({
|
2014-12-16 15:16:05 -08:00
|
|
|
header: bh,
|
2015-01-16 11:54:32 -08:00
|
|
|
transactions: txs
|
2014-09-16 18:42:11 -07:00
|
|
|
});
|
2014-12-16 15:16:05 -08:00
|
|
|
should.exist(b.header);
|
2015-01-16 11:54:32 -08:00
|
|
|
should.exist(b.transactions);
|
2014-12-06 12:43:31 -08:00
|
|
|
});
|
|
|
|
|
2015-01-09 13:50:24 -08:00
|
|
|
it('should properly deserialize blocks', function() {
|
2015-04-28 11:17:41 -07:00
|
|
|
dataBlocks.forEach(function(block) {
|
2015-01-16 20:23:02 -08:00
|
|
|
var b = Block.fromBuffer(new Buffer(block.data, 'hex'));
|
2015-01-16 11:54:32 -08:00
|
|
|
b.transactions.length.should.equal(block.transactions);
|
2015-01-09 13:50:24 -08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2014-12-06 12:43:31 -08:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('#fromRawBlock', function() {
|
|
|
|
|
|
|
|
it('should instantiate from a raw block binary', function() {
|
|
|
|
var x = Block.fromRawBlock(dataRawBlockBinary);
|
2014-12-16 15:16:05 -08:00
|
|
|
x.header.version.should.equal(2);
|
2015-02-05 11:46:18 -08:00
|
|
|
new BN(x.header.bits).toString('hex').should.equal('1c3fffc0');
|
2014-12-06 12:43:31 -08:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should instantiate from raw block buffer', function() {
|
|
|
|
var x = Block.fromRawBlock(dataRawBlockBuffer);
|
2014-12-16 15:16:05 -08:00
|
|
|
x.header.version.should.equal(2);
|
2015-02-05 11:46:18 -08:00
|
|
|
new BN(x.header.bits).toString('hex').should.equal('1c3fffc0');
|
2014-12-06 12:43:31 -08:00
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('#fromJSON', function() {
|
|
|
|
|
|
|
|
it('should set these known values', function() {
|
|
|
|
var block = Block.fromJSON(json);
|
2014-12-16 15:16:05 -08:00
|
|
|
should.exist(block.header);
|
2015-01-16 11:54:32 -08:00
|
|
|
should.exist(block.transactions);
|
2014-09-18 17:52:02 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should set these known values', function() {
|
2014-12-06 12:43:31 -08:00
|
|
|
|
|
|
|
var block = Block(json);
|
2014-12-16 15:16:05 -08:00
|
|
|
should.exist(block.header);
|
2015-01-16 11:54:32 -08:00
|
|
|
should.exist(block.transactions);
|
2014-09-18 17:52:02 -07:00
|
|
|
});
|
2014-12-06 12:43:31 -08:00
|
|
|
|
2014-09-18 17:52:02 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('#toJSON', function() {
|
|
|
|
|
|
|
|
it('should recover these known values', function() {
|
2014-12-12 15:34:43 -08:00
|
|
|
var block = Block.fromJSON(json);
|
|
|
|
var b = JSON.parse(block.toJSON());
|
2014-12-16 15:16:05 -08:00
|
|
|
should.exist(b.header);
|
2015-01-16 11:54:32 -08:00
|
|
|
should.exist(b.transactions);
|
2014-12-06 12:43:31 -08:00
|
|
|
});
|
|
|
|
|
2014-09-16 18:42:11 -07:00
|
|
|
});
|
|
|
|
|
2014-12-11 22:01:14 -08:00
|
|
|
describe('#fromString/#toString', function() {
|
|
|
|
|
|
|
|
it('should output/input a block hex string', function() {
|
|
|
|
var b = Block.fromString(blockhex);
|
|
|
|
b.toString().should.equal(blockhex);
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
2014-09-16 18:42:11 -07:00
|
|
|
describe('#fromBuffer', function() {
|
2014-12-06 12:43:31 -08:00
|
|
|
|
2014-09-16 18:42:11 -07:00
|
|
|
it('should make a block from this known buffer', function() {
|
2014-12-06 12:43:31 -08:00
|
|
|
var block = Block.fromBuffer(blockbuf);
|
2014-09-16 18:42:11 -07:00
|
|
|
block.toBuffer().toString('hex').should.equal(blockhex);
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('#fromBufferReader', function() {
|
2014-12-06 12:43:31 -08:00
|
|
|
|
2014-09-16 18:42:11 -07:00
|
|
|
it('should make a block from this known buffer', function() {
|
2014-12-06 12:43:31 -08:00
|
|
|
var block = Block.fromBufferReader(BufferReader(blockbuf));
|
2014-09-16 18:42:11 -07:00
|
|
|
block.toBuffer().toString('hex').should.equal(blockhex);
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('#toBuffer', function() {
|
2014-12-06 12:43:31 -08:00
|
|
|
|
2014-09-16 18:42:11 -07:00
|
|
|
it('should recover a block from this known buffer', function() {
|
2014-12-06 12:43:31 -08:00
|
|
|
var block = Block.fromBuffer(blockbuf);
|
2014-09-16 18:42:11 -07:00
|
|
|
block.toBuffer().toString('hex').should.equal(blockhex);
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('#toBufferWriter', function() {
|
2014-12-06 12:43:31 -08:00
|
|
|
|
2014-09-16 18:42:11 -07:00
|
|
|
it('should recover a block from this known buffer', function() {
|
2014-12-06 12:43:31 -08:00
|
|
|
var block = Block.fromBuffer(blockbuf);
|
2014-09-16 18:42:11 -07:00
|
|
|
block.toBufferWriter().concat().toString('hex').should.equal(blockhex);
|
|
|
|
});
|
|
|
|
|
2014-12-19 11:36:57 -08:00
|
|
|
it('doesn\'t create a bufferWriter if one provided', function() {
|
|
|
|
var writer = new BufferWriter();
|
|
|
|
var block = Block.fromBuffer(blockbuf);
|
|
|
|
block.toBufferWriter(writer).should.equal(writer);
|
|
|
|
});
|
|
|
|
|
2014-09-16 18:42:11 -07:00
|
|
|
});
|
|
|
|
|
2015-04-28 12:42:56 -07:00
|
|
|
describe('#toObject', function() {
|
2015-04-28 11:17:41 -07:00
|
|
|
|
|
|
|
it('should recover a block from genesis block buffer', function() {
|
|
|
|
var block = Block.fromBuffer(blockOneBuf);
|
|
|
|
block.id.should.equal(blockOneId);
|
|
|
|
block.toObject().should.deep.equal({
|
|
|
|
header: {
|
|
|
|
version: 1,
|
|
|
|
prevHash: '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f',
|
|
|
|
merkleRoot: '0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098',
|
|
|
|
time: 1231469665,
|
|
|
|
bits: 486604799,
|
|
|
|
nonce: 2573394689
|
|
|
|
},
|
|
|
|
transactions: [{
|
|
|
|
version: 1,
|
|
|
|
inputs: [{
|
|
|
|
prevTxId: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
|
|
outputIndex: 4294967295,
|
|
|
|
sequenceNumber: 4294967295,
|
|
|
|
script: '4 0xffff001d 1 0x04'
|
|
|
|
}],
|
|
|
|
outputs: [{
|
|
|
|
satoshis: 5000000000,
|
|
|
|
script: '65 0x0496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be' +
|
|
|
|
'63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee OP_CHECKSIG'
|
|
|
|
}],
|
|
|
|
nLockTime: 0
|
|
|
|
}]
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-04-28 12:42:56 -07:00
|
|
|
it('roundtrips correctly', function() {
|
|
|
|
var block = Block.fromBuffer(blockOneBuf);
|
|
|
|
var obj = block.toObject();
|
|
|
|
var block2 = Block.fromObject(obj);
|
|
|
|
block2.toObject().should.deep.equal(block.toObject());
|
|
|
|
});
|
|
|
|
|
2015-04-28 11:17:41 -07:00
|
|
|
});
|
|
|
|
|
2014-12-10 10:09:37 -08:00
|
|
|
describe('#_getHash', function() {
|
2014-12-06 12:43:31 -08:00
|
|
|
|
2014-09-19 17:29:40 -07:00
|
|
|
it('should return the correct hash of the genesis block', function() {
|
2014-12-06 12:43:31 -08:00
|
|
|
var block = Block.fromBuffer(genesisbuf);
|
2014-09-19 17:29:40 -07:00
|
|
|
var blockhash = new Buffer(Array.apply([], new Buffer(genesisidhex, 'hex')).reverse());
|
2014-12-10 10:09:37 -08:00
|
|
|
block._getHash().toString('hex').should.equal(blockhash.toString('hex'));
|
2014-09-19 17:29:40 -07:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2014-09-19 17:08:44 -07:00
|
|
|
describe('#id', function() {
|
2014-12-06 12:43:31 -08:00
|
|
|
|
2014-09-19 17:08:44 -07:00
|
|
|
it('should return the correct id of the genesis block', function() {
|
2014-12-06 12:43:31 -08:00
|
|
|
var block = Block.fromBuffer(genesisbuf);
|
2014-12-10 10:09:37 -08:00
|
|
|
block.id.should.equal(genesisidhex);
|
|
|
|
});
|
|
|
|
it('"hash" should be the same as "id"', function() {
|
|
|
|
var block = Block.fromBuffer(genesisbuf);
|
|
|
|
block.id.should.equal(block.hash);
|
2014-09-19 17:08:44 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
2014-12-06 12:43:31 -08:00
|
|
|
describe('#inspect', function() {
|
|
|
|
|
|
|
|
it('should return the correct inspect of the genesis block', function() {
|
|
|
|
var block = Block.fromBuffer(genesisbuf);
|
2015-04-28 11:17:41 -07:00
|
|
|
block.inspect().should.equal('<Block ' + genesisidhex + '>');
|
2014-12-06 12:43:31 -08:00
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('#merkleRoot', function() {
|
|
|
|
|
|
|
|
it('should describe as valid merkle root', function() {
|
|
|
|
var x = Block.fromRawBlock(dataRawBlockBinary);
|
|
|
|
var valid = x.validMerkleRoot();
|
|
|
|
valid.should.equal(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should describe as invalid merkle root', function() {
|
|
|
|
var x = Block.fromRawBlock(dataRawBlockBinary);
|
2015-01-16 11:54:32 -08:00
|
|
|
x.transactions.push(new Transaction());
|
2014-12-06 12:43:31 -08:00
|
|
|
var valid = x.validMerkleRoot();
|
|
|
|
valid.should.equal(false);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should get a null hash merkle root', function() {
|
|
|
|
var x = Block.fromRawBlock(dataRawBlockBinary);
|
2015-01-16 11:54:32 -08:00
|
|
|
x.transactions = []; // empty the txs
|
2014-12-06 12:43:31 -08:00
|
|
|
var mr = x.getMerkleRoot();
|
|
|
|
mr.should.deep.equal(Block.Values.NULL_HASH);
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
2014-09-16 18:42:11 -07:00
|
|
|
});
|