Block: Added validation of proof of work, merkle tree and other interface changes. Closes #601

This commit is contained in:
Braydon Fuller 2014-12-06 15:43:31 -05:00
parent 5f4eb204b4
commit 5d1da9802c
11 changed files with 1280 additions and 235 deletions

View File

@ -96,7 +96,7 @@ gulp.task('browser', ['errors'], shell.task([
]));
gulp.task('browser-test', shell.task([
'find test/ -type f -name "*.js" | xargs ./node_modules/.bin/browserify -o browser/tests.js'
'find test/ -type f -name "*.js" | xargs ./node_modules/.bin/browserify -t brfs -o browser/tests.js'
]));
gulp.task('browser-all', ['errors'], function(callback) {

View File

@ -30,7 +30,7 @@ bitcore.errors = require('./lib/errors');
// main bitcoin library
bitcore.Address = require('./lib/address');
bitcore.Block = require('./lib/block');
bitcore.Blockheader = require('./lib/blockheader');
bitcore.BlockHeader = require('./lib/blockheader');
bitcore.HDPrivateKey = require('./lib/hdprivatekey.js');
bitcore.HDPublicKey = require('./lib/hdpublickey.js');
bitcore.Networks = require('./lib/networks');

View File

@ -1,56 +1,143 @@
'use strict';
var Hash = require('./crypto/hash');
var _ = require('lodash');
var BlockHeader = require('./blockheader');
var BN = require('./crypto/bn');
var bu = require('./util/buffer');
var BufferReader = require('./encoding/bufferreader');
var BufferWriter = require('./encoding/bufferwriter');
var Varint = require('./encoding/varint');
var Hash = require('./crypto/hash');
var ju = require('./util/js');
var Transaction = require('./transaction');
var Blockheader = require('./blockheader');
var Varint = require('./encoding/varint');
var Block = function Block(magicnum, blocksize, blockheader, txsvi, txs) {
if (!(this instanceof Block))
return new Block(magicnum, blocksize, blockheader, txsvi, txs);
if (typeof magicnum === 'number') {
this.set({
magicnum: magicnum,
blocksize: blocksize,
blockheader: blockheader,
txsvi: txsvi,
txs: txs
});
} else if (Buffer.isBuffer(magicnum)) {
var blockbuf = magicnum;
this.fromBuffer(blockbuf);
} else if (magicnum) {
var obj = magicnum;
/**
* Instantiate a Block from a Buffer, JSON object, or Object with
* the properties of the Block
*
* @param {*} - A Buffer, JSON string, or Object
* @returns {Block} - An instance of Block
* @constructor
*/
var Block = function Block(arg) {
if (!(this instanceof Block)) {
return new Block(arg);
}
};
Block.prototype.set = function(obj) {
this.magicnum = typeof obj.magicnum !== 'undefined' ? obj.magicnum : this.magicnum;
this.blocksize = typeof obj.blocksize !== 'undefined' ? obj.blocksize : this.blocksize;
this.blockheader = obj.blockheader || this.blockheader;
this.txsvi = obj.txsvi || this.txsvi;
this.txs = obj.txs || this.txs;
_.extend(this, Block._from(arg));
return this;
};
Block.prototype.fromJSON = function(json) {
/**
* @param {*} - A Buffer, JSON string or Object
* @returns {Object} - An object representing block data
* @throws {TypeError} - If the argument was not recognized
* @private
*/
Block._from = function _from(arg) {
var info = {};
if (bu.isBuffer(arg)) {
info = Block._fromBufferReader(BufferReader(arg));
} else if (ju.isValidJson(arg)) {
info = Block._fromJSON(arg);
} else if (_.isObject(arg)) {
info = {
magicnum: arg.magicnum,
blocksize: arg.blocksize,
blockheader: arg.blockheader,
txsvi: arg.txsvi,
txs: arg.txs
};
} else {
throw new TypeError('Unrecognized argument for Block');
}
return info;
};
/**
* @param {String|Object} - A JSON string or object
* @returns {Object} - An object representing block data
* @private
*/
Block._fromJSON = function _fromJSON(data) {
if (ju.isValidJson(data)) {
data = JSON.parse(data);
}
var txs = [];
json.txs.forEach(function(tx) {
data.txs.forEach(function(tx) {
txs.push(Transaction().fromJSON(tx));
});
this.set({
magicnum: json.magicnum,
blocksize: json.blocksize,
blockheader: Blockheader().fromJSON(json.blockheader),
txsvi: Varint().fromJSON(json.txsvi),
var info = {
magicnum: data.magicnum,
blocksize: data.blocksize,
blockheader: BlockHeader.fromJSON(data.blockheader),
txsvi: Varint().fromJSON(data.txsvi),
txs: txs
});
return this;
};
return info;
};
Block.prototype.toJSON = function() {
/**
* @param {String|Object} - A JSON string or object
* @returns {Block} - An instance of block
*/
Block.fromJSON = function fromJSON(json) {
var info = Block._fromJSON(json);
return new Block(info);
};
/**
* @param {BufferReader} - Block data
* @returns {Object} - An object representing the block data
* @private
*/
Block._fromBufferReader = function _fromBufferReader(br) {
var info = {};
info.magicnum = br.readUInt32LE();
info.blocksize = br.readUInt32LE();
info.blockheader = BlockHeader.fromBufferReader(br);
info.txsvi = Varint(br.readVarintBuf());
var txslen = info.txsvi.toNumber();
info.txs = [];
for (var i = 0; i < txslen; i++) {
info.txs.push(Transaction().fromBufferReader(br));
}
return info;
};
/**
* @param {BufferReader} - A buffer reader of the block
* @returns {Block} - An instance of block
*/
Block.fromBufferReader = function fromBufferReader(br) {
var info = Block._fromBufferReader(br);
return new Block(info);
};
/**
* @param {Buffer} - A buffer of the block
* @returns {Block} - An instance of block
*/
Block.fromBuffer = function fromBuffer(buf) {
return Block.fromBufferReader(BufferReader(buf));
};
/**
* @param {Binary} - Raw block binary data or buffer
* @returns {Block} - An instance of block
*/
Block.fromRawBlock = function fromRawBlock(data) {
if (!bu.isBuffer(data)) {
data = new Buffer(data, 'binary');
}
var br = BufferReader(data);
var info = Block._fromBufferReader(br);
return new Block(info);
};
/**
* @returns {Object} - A JSON object with the block properties
*/
Block.prototype.toJSON = function toJSON() {
var txs = [];
this.txs.forEach(function(tx) {
txs.push(tx.toJSON());
@ -64,30 +151,21 @@ Block.prototype.toJSON = function() {
};
};
Block.prototype.fromBuffer = function(buf) {
return this.fromBufferReader(BufferReader(buf));
};
Block.prototype.fromBufferReader = function(br) {
this.magicnum = br.readUInt32LE();
this.blocksize = br.readUInt32LE();
this.blockheader = Blockheader().fromBufferReader(br);
this.txsvi = Varint(br.readVarintBuf());
var txslen = this.txsvi.toNumber();
this.txs = [];
for (var i = 0; i < txslen; i++) {
this.txs.push(Transaction().fromBufferReader(br));
}
return this;
};
Block.prototype.toBuffer = function() {
/**
* @returns {Buffer} - A buffer of the block
*/
Block.prototype.toBuffer = function toBuffer() {
return this.toBufferWriter().concat();
};
Block.prototype.toBufferWriter = function(bw) {
if (!bw)
/**
* @param {BufferWriter} - An existing instance of BufferWriter
* @returns {BufferWriter} - An instance of BufferWriter representation of the Block
*/
Block.prototype.toBufferWriter = function toBufferWriter(bw) {
if (!bw) {
bw = new BufferWriter();
}
bw.writeUInt32LE(this.magicnum);
bw.writeUInt32LE(this.blocksize);
bw.write(this.blockheader.toBuffer());
@ -99,12 +177,93 @@ Block.prototype.toBufferWriter = function(bw) {
return bw;
};
Block.prototype.hash = function() {
return Hash.sha256sha256(this.blockheader.toBuffer());
/**
* Will iterate through each transaction and return an array of hashes
* @returns {Array} - An array with transaction hashes
*/
Block.prototype.getTransactionHashes = function getTransactionHashes() {
var hashes = [];
if (this.txs.length === 0) {
return [Block.Values.NULL_HASH];
}
for (var t = 0; t < this.txs.length; t++) {
hashes.push(this.txs[t].hash());
}
return hashes;
};
Block.prototype.id = function() {
return BufferReader(this.hash()).reverse().read();
/**
* Will build a merkle tree of all the transactions, ultimately arriving at
* a single point, the merkle root.
* @link https://en.bitcoin.it/wiki/Protocol_specification#Merkle_Trees
* @returns {Array} - An array with each level of the tree after the other.
*/
Block.prototype.getMerkleTree = function getMerkleTree() {
var tree = this.getTransactionHashes();
var j = 0;
for (var size = this.txs.length; size > 1; size = Math.floor((size + 1) / 2)) {
for (var i = 0; i < size; i += 2) {
var i2 = Math.min(i + 1, size - 1);
var buf = Buffer.concat([tree[j + i], tree[j + i2]]);
tree.push(Hash.sha256sha256(buf));
}
j += size;
}
return tree;
};
/**
* Calculates the merkleRoot from the transactions.
* @returns {Buffer} - A buffer of the merkle root hash
*/
Block.prototype.getMerkleRoot = function getMerkleRoot() {
var tree = this.getMerkleTree();
return tree[tree.length - 1];
};
/**
* Verifies that the transactions in the block match the blockheader merkle root
* @returns {Boolean} - If the merkle roots match
*/
Block.prototype.validMerkleRoot = function validMerkleRoot() {
var h = new BN(this.blockheader.merklerootbuf.toString('hex'), 'hex');
var c = new BN(this.getMerkleRoot().toString('hex'), 'hex');
if (h.cmp(c) !== 0) {
return false;
}
return true;
};
/**
* @returns {Buffer} - The little endian hash buffer of the header
*/
Block.prototype.hash = function hash() {
return this.blockheader.hash();
};
/**
* @returns {Buffer} - The big endian hash buffer of the header
*/
Block.prototype.id = function id() {
return this.blockheader.id();
};
/**
* @returns {String} - A string formated for the console
*/
Block.prototype.inspect = function inspect() {
return '<Block ' + this.id().toString('hex') + '>';
};
Block.Values = {
NULL_HASH: new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex')
};
module.exports = Block;

View File

@ -1,52 +1,138 @@
'use strict';
var _ = require('lodash');
var BN = require('./crypto/bn');
var bu = require('./util/buffer');
var BufferReader = require('./encoding/bufferreader');
var BufferWriter = require('./encoding/bufferwriter');
var Hash = require('./crypto/hash');
var ju = require('./util/js');
var Blockheader = function Blockheader(version, prevblockidbuf, merklerootbuf, time, bits, nonce) {
if (!(this instanceof Blockheader))
return new Blockheader(version, prevblockidbuf, merklerootbuf, time, bits, nonce);
if (typeof version === 'number') {
this.set({
version: version,
prevblockidbuf: prevblockidbuf,
merklerootbuf: merklerootbuf,
time: time,
bits: bits,
nonce: nonce
});
} else if (Buffer.isBuffer(version)) {
var bhbuf = version;
this.fromBuffer(bhbuf);
} else if (version) {
var obj = version;
this.set(obj);
/**
* Instantiate a BlockHeader from a Buffer, JSON object, or Object with
* the properties of the BlockHeader
*
* @param {*} - A Buffer, JSON string, or Object
* @returns {BlockHeader} - An instance of block header
* @constructor
*/
var BlockHeader = function BlockHeader(arg) {
if (!(this instanceof BlockHeader)) {
return new BlockHeader(arg);
}
};
Blockheader.prototype.set = function(obj) {
this.version = typeof obj.version !== 'undefined' ? obj.version : this.version;
this.prevblockidbuf = obj.prevblockidbuf || this.prevblockidbuf;
this.merklerootbuf = obj.merklerootbuf || this.merklerootbuf;
this.time = typeof obj.time !== 'undefined' ? obj.time : this.time;
this.bits = typeof obj.bits !== 'undefined' ? obj.bits : this.bits;
this.nonce = typeof obj.nonce !== 'undefined' ? obj.nonce : this.nonce;
_.extend(this, BlockHeader._from(arg));
return this;
};
Blockheader.prototype.fromJSON = function(json) {
this.set({
version: json.version,
prevblockidbuf: new Buffer(json.prevblockidbuf, 'hex'),
merklerootbuf: new Buffer(json.merklerootbuf, 'hex'),
time: json.time,
bits: json.bits,
nonce: json.nonce
});
return this;
/**
* @param {*} - A Buffer, JSON string or Object
* @returns {Object} - An object representing block header data
* @throws {TypeError} - If the argument was not recognized
* @private
*/
BlockHeader._from = function _from(arg) {
var info = {};
if (bu.isBuffer(arg)) {
info = BlockHeader._fromBufferReader(BufferReader(arg));
} else if (ju.isValidJson(arg)) {
info = BlockHeader._fromJSON(arg);
} else if (_.isObject(arg)) {
info = {
version: arg.version,
prevblockidbuf: arg.prevblockidbuf,
merklerootbuf: arg.merklerootbuf,
time: arg.time,
bits: arg.bits,
nonce: arg.nonce
};
} else {
throw new TypeError('Unrecognized argument for BlockHeader');
}
return info;
};
Blockheader.prototype.toJSON = function() {
/**
* @param {String|Object} - A JSON string or object
* @returns {Object} - An object representing block header data
* @private
*/
BlockHeader._fromJSON = function _fromJSON(data) {
if (ju.isValidJson(data)) {
data = JSON.parse(data);
}
var info = {
version: data.version,
prevblockidbuf: new Buffer(data.prevblockidbuf, 'hex'),
merklerootbuf: new Buffer(data.merklerootbuf, 'hex'),
time: data.time,
bits: data.bits,
nonce: data.nonce
};
return info;
};
/**
* @param {String|Object} - A JSON string or object
* @returns {BlockHeader} - An instance of block header
*/
BlockHeader.fromJSON = function fromJSON(json) {
var info = BlockHeader._fromJSON(json);
return new BlockHeader(info);
};
/**
* @param {Binary} - Raw block binary data or buffer
* @returns {BlockHeader} - An instance of block header
*/
BlockHeader.fromRawBlock = function fromRawBlock(data) {
if (!bu.isBuffer(data)) {
data = new Buffer(data, 'binary');
}
var br = BufferReader(data);
br.pos = BlockHeader.Constants.START_OF_HEADER;
var info = BlockHeader._fromBufferReader(br);
return new BlockHeader(info);
};
/**
* @param {Buffer} - A buffer of the block header
* @returns {BlockHeader} - An instance of block header
*/
BlockHeader.fromBuffer = function fromBuffer(buf) {
var info = BlockHeader._fromBufferReader(BufferReader(buf));
return new BlockHeader(info);
};
/**
* @param {BufferReader} - A BufferReader of the block header
* @returns {Object} - An object representing block header data
* @private
*/
BlockHeader._fromBufferReader = function _fromBufferReader(br) {
var info = {
version: br.readUInt32LE(),
prevblockidbuf: br.read(32),
merklerootbuf: br.read(32),
time: br.readUInt32LE(),
bits: br.readUInt32LE(),
nonce: br.readUInt32LE()
};
return info;
};
/**
* @param {BufferReader} - A BufferReader of the block header
* @returns {BlockHeader} - An instance of block header
*/
BlockHeader.fromBufferReader = function fromBufferReader(br) {
var info = BlockHeader._fromBufferReader(br);
return new BlockHeader(info);
};
/**
* @returns {Object} - A JSON object of the BlockHeader
*/
BlockHeader.prototype.toJSON = function toJSON() {
return {
version: this.version,
prevblockidbuf: this.prevblockidbuf.toString('hex'),
@ -57,27 +143,21 @@ Blockheader.prototype.toJSON = function() {
};
};
Blockheader.prototype.fromBuffer = function(buf) {
return this.fromBufferReader(BufferReader(buf));
};
Blockheader.prototype.fromBufferReader = function(br) {
this.version = br.readUInt32LE();
this.prevblockidbuf = br.read(32);
this.merklerootbuf = br.read(32);
this.time = br.readUInt32LE();
this.bits = br.readUInt32LE();
this.nonce = br.readUInt32LE();
return this;
};
Blockheader.prototype.toBuffer = function() {
/**
* @returns {Buffer} - A Buffer of the BlockHeader
*/
BlockHeader.prototype.toBuffer = function toBuffer() {
return this.toBufferWriter().concat();
};
Blockheader.prototype.toBufferWriter = function(bw) {
if (!bw)
/**
* @param {BufferWriter} - An existing instance BufferWriter
* @returns {BufferWriter} - An instance of BufferWriter representation of the BlockHeader
*/
BlockHeader.prototype.toBufferWriter = function toBufferWriter(bw) {
if (!bw) {
bw = new BufferWriter();
}
bw.writeUInt32LE(this.version);
bw.write(this.prevblockidbuf);
bw.write(this.merklerootbuf);
@ -87,4 +167,69 @@ Blockheader.prototype.toBufferWriter = function(bw) {
return bw;
};
module.exports = Blockheader;
/**
* @link https://en.bitcoin.it/wiki/Difficulty
* @returns {BN} - An instance of BN with the decoded difficulty bits
*/
BlockHeader.prototype.getTargetDifficulty = function getTargetDifficulty(info) {
var target = BN(this.bits & 0xffffff);
var mov = 8 * ((this.bits >>> 24) - 3);
while (mov-- > 0) {
target = target.mul(2);
}
return target;
};
/**
* @returns {Buffer} - The little endian hash buffer of the header
*/
BlockHeader.prototype.hash = function hash() {
var buf = this.toBuffer();
return Hash.sha256sha256(buf);
};
/**
* @returns {Buffer} - The big endian hash buffer of the header
*/
BlockHeader.prototype.id = function id() {
return BufferReader(this.hash()).reverse().read();
};
/**
* @returns {Boolean} - If timestamp is not too far in the future
*/
BlockHeader.prototype.validTimestamp = function validTimestamp() {
var currentTime = Math.round(new Date().getTime() / 1000);
if (this.time > currentTime + BlockHeader.Constants.MAX_TIME_OFFSET) {
return false;
}
return true;
};
/**
* @returns {Boolean} - If the proof-of-work hash satisfies the target difficulty
*/
BlockHeader.prototype.validProofOfWork = function validProofOfWork() {
var hash = this.id().toString('hex');
var pow = new BN(hash, 'hex');
var target = this.getTargetDifficulty();
if (pow.cmp(target) > 0) {
return false;
}
return true;
};
/**
* @returns {String} - A string formated for the console
*/
BlockHeader.prototype.inspect = function inspect() {
return '<BlockHeader ' + this.id().toString('hex') + '>';
};
BlockHeader.Constants = {
START_OF_HEADER: 8, // Start buffer position in raw block data
MAX_TIME_OFFSET: 2 * 60 * 60, // The max a timestamp can be in the future
LARGEST_HASH: new BN('10000000000000000000000000000000000000000000000000000000000000000', 'hex')
};
module.exports = BlockHeader;

View File

@ -83,6 +83,7 @@
"sha512": "=0.0.1"
},
"devDependencies": {
"brfs": "1.2.0",
"browserify": "~6.3.3",
"chai": "~1.10.0",
"closure-compiler-jar": "git://github.com/eordano/closure-compiler-jar.git",

View File

@ -1,138 +1,163 @@
'use strict';
var should = require('chai').should();
var bitcore = require('..');
var Varint = bitcore.encoding.Varint;
var BN = require('../lib/crypto/bn');
var BufferReader = bitcore.encoding.BufferReader;
var Blockheader = bitcore.Blockheader;
var BlockHeader = bitcore.BlockHeader;
var Block = bitcore.Block;
var chai = require('chai');
var fs = require('fs');
var should = chai.should();
var Transaction = bitcore.Transaction;
var Varint = bitcore.encoding.Varint;
// 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');
describe('Block', function() {
var txhex = '01000000029e8d016a7b0dc49a325922d05da1f916d1e4d4f0cb840c9727f3d22ce8d1363f000000008c493046022100e9318720bee5425378b4763b0427158b1051eec8b08442ce3fbfbf7b30202a44022100d4172239ebd701dae2fbaaccd9f038e7ca166707333427e3fb2a2865b19a7f27014104510c67f46d2cbb29476d1f0b794be4cb549ea59ab9cc1e731969a7bf5be95f7ad5e7f904e5ccf50a9dc1714df00fbeb794aa27aaff33260c1032d931a75c56f2ffffffffa3195e7a1ab665473ff717814f6881485dc8759bebe97e31c301ffe7933a656f020000008b48304502201c282f35f3e02a1f32d2089265ad4b561f07ea3c288169dedcf2f785e6065efa022100e8db18aadacb382eed13ee04708f00ba0a9c40e3b21cf91da8859d0f7d99e0c50141042b409e1ebbb43875be5edde9c452c82c01e3903d38fa4fd89f3887a52cb8aea9dc8aec7e2c9d5b3609c03eb16259a2537135a1bf0f9c5fbbcbdbaf83ba402442ffffffff02206b1000000000001976a91420bb5c3bfaef0231dc05190e7f1c8e22e098991e88acf0ca0100000000001976a9149e3e2d23973a04ec1b02be97c30ab9f2f27c3b2c88ac00000000';
var txbuf = new Buffer(txhex, 'hex');
var magicnum = 0xd9b4bef9;
var blocksize = 50;
var bhhex = '0100000005050505050505050505050505050505050505050505050505050505050505050909090909090909090909090909090909090909090909090909090909090909020000000300000004000000';
var bhbuf = new Buffer(bhhex, 'hex');
var bh = new Blockheader().fromBuffer(bhbuf);
var txsvi = new Varint(1);
var txs = [new Transaction().fromBuffer(txbuf)];
var block = new Block().set({
magicnum: magicnum,
blocksize: blocksize,
blockheader: bh,
txsvi: txsvi,
txs: txs
});
var blockhex = 'f9beb4d93200000001000000050505050505050505050505050505050505050505050505050505050505050509090909090909090909090909090909090909090909090909090909090909090200000003000000040000000101000000029e8d016a7b0dc49a325922d05da1f916d1e4d4f0cb840c9727f3d22ce8d1363f000000008c493046022100e9318720bee5425378b4763b0427158b1051eec8b08442ce3fbfbf7b30202a44022100d4172239ebd701dae2fbaaccd9f038e7ca166707333427e3fb2a2865b19a7f27014104510c67f46d2cbb29476d1f0b794be4cb549ea59ab9cc1e731969a7bf5be95f7ad5e7f904e5ccf50a9dc1714df00fbeb794aa27aaff33260c1032d931a75c56f2ffffffffa3195e7a1ab665473ff717814f6881485dc8759bebe97e31c301ffe7933a656f020000008b48304502201c282f35f3e02a1f32d2089265ad4b561f07ea3c288169dedcf2f785e6065efa022100e8db18aadacb382eed13ee04708f00ba0a9c40e3b21cf91da8859d0f7d99e0c50141042b409e1ebbb43875be5edde9c452c82c01e3903d38fa4fd89f3887a52cb8aea9dc8aec7e2c9d5b3609c03eb16259a2537135a1bf0f9c5fbbcbdbaf83ba402442ffffffff02206b1000000000001976a91420bb5c3bfaef0231dc05190e7f1c8e22e098991e88acf0ca0100000000001976a9149e3e2d23973a04ec1b02be97c30ab9f2f27c3b2c88ac00000000';
var magicnum = data.magicnum;
var blockhex = data.blockhex;
var blockbuf = new Buffer(blockhex, 'hex');
var blocksize = data.blocksize;
var bh = BlockHeader.fromBuffer(new Buffer(data.blockheaderhex, 'hex'));
var txsvi = Varint().fromNumber(data.txsvi);
var txs = [];
JSON.parse(dataJson).txs.forEach(function(tx){
txs.push(new Transaction().fromJSON(tx));
});
var json = dataJson;
var genesishex = 'f9beb4d91d0100000100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000';
var genesisbuf = new Buffer(genesishex, 'hex');
var genesisidhex = '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f';
it('should make a new block', function() {
var block = new Block();
should.exist(block);
block = Block();
should.exist(block);
block = Block(blockbuf);
block.toBuffer().toString('hex').should.equal(blockhex);
var b = Block(blockbuf);
b.toBuffer().toString('hex').should.equal(blockhex);
});
describe('#set', function() {
it('should not make an empty block', function() {
(function() {
var b = new Block();
}).should.throw('Unrecognized argument for Block');
});
describe('#constructor', function() {
it('should set these known values', function() {
var block = Block().set({
var b = new Block({
magicnum: magicnum,
blocksize: blocksize,
blockheader: bh,
txsvi: txsvi,
txs: txs
});
should.exist(block.magicnum);
should.exist(block.blocksize);
should.exist(block.blockheader);
should.exist(block.txsvi);
should.exist(block.txs);
should.exist(b.magicnum);
should.exist(b.blocksize);
should.exist(b.txsvi);
should.exist(b.blockheader);
should.exist(b.txs);
});
});
describe('#fromRawBlock', function() {
it('should instantiate from a raw block binary', function() {
var x = Block.fromRawBlock(dataRawBlockBinary);
x.blockheader.version.should.equal(2);
BN(x.blockheader.bits).toString('hex').should.equal('1c3fffc0');
});
it('should instantiate from raw block buffer', function() {
var x = Block.fromRawBlock(dataRawBlockBuffer);
x.blockheader.version.should.equal(2);
BN(x.blockheader.bits).toString('hex').should.equal('1c3fffc0');
});
});
describe('#fromJSON', function() {
it('should set these known values', function() {
var block = Block().set({
magicnum: magicnum,
blocksize: blocksize,
blockheader: bh.toJSON(),
txsvi: txsvi.toJSON(),
txs: [txs[0].toJSON()]
});
var block = Block.fromJSON(json);
should.exist(block.magicnum);
should.exist(block.blocksize);
should.exist(block.blockheader);
should.exist(block.txsvi);
should.exist(block.txs);
});
it('should set these known values', function() {
var block = Block(json);
should.exist(block.magicnum);
should.exist(block.blocksize);
should.exist(block.blockheader);
should.exist(block.txsvi);
should.exist(block.txs);
});
});
describe('#toJSON', function() {
it('should recover these known values', function() {
var json = block.toJSON();
should.exist(json.magicnum);
should.exist(json.blocksize);
should.exist(json.blockheader);
should.exist(json.txsvi);
should.exist(json.txs);
var block = Block(json);
var b = block.toJSON();
should.exist(b.magicnum);
should.exist(b.blocksize);
should.exist(b.blockheader);
should.exist(b.txsvi);
should.exist(b.txs);
});
});
describe('#fromBuffer', function() {
it('should make a block from this known buffer', function() {
var block = Block().fromBuffer(blockbuf);
var block = Block.fromBuffer(blockbuf);
block.toBuffer().toString('hex').should.equal(blockhex);
});
});
describe('#fromBufferReader', function() {
it('should make a block from this known buffer', function() {
var block = Block().fromBufferReader(BufferReader(blockbuf));
var block = Block.fromBufferReader(BufferReader(blockbuf));
block.toBuffer().toString('hex').should.equal(blockhex);
});
});
describe('#toBuffer', function() {
it('should recover a block from this known buffer', function() {
var block = Block().fromBuffer(blockbuf);
var block = Block.fromBuffer(blockbuf);
block.toBuffer().toString('hex').should.equal(blockhex);
});
});
describe('#toBufferWriter', function() {
it('should recover a block from this known buffer', function() {
var block = Block().fromBuffer(blockbuf);
var block = Block.fromBuffer(blockbuf);
block.toBufferWriter().concat().toString('hex').should.equal(blockhex);
});
});
describe('#hash', function() {
it('should return the correct hash of the genesis block', function() {
var block = Block().fromBuffer(genesisbuf);
var block = Block.fromBuffer(genesisbuf);
var blockhash = new Buffer(Array.apply([], new Buffer(genesisidhex, 'hex')).reverse());
block.hash().toString('hex').should.equal(blockhash.toString('hex'));
});
@ -140,12 +165,45 @@ describe('Block', function() {
});
describe('#id', function() {
it('should return the correct id of the genesis block', function() {
var block = Block().fromBuffer(genesisbuf);
var block = Block.fromBuffer(genesisbuf);
block.id().toString('hex').should.equal(genesisidhex);
});
});
describe('#inspect', function() {
it('should return the correct inspect of the genesis block', function() {
var block = Block.fromBuffer(genesisbuf);
block.inspect().should.equal('<Block '+genesisidhex+'>');
});
});
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);
x.txs.push(new Transaction());
var valid = x.validMerkleRoot();
valid.should.equal(false);
});
it('should get a null hash merkle root', function() {
var x = Block.fromRawBlock(dataRawBlockBinary);
x.txs = []; // empty the txs
var mr = x.getMerkleRoot();
mr.should.deep.equal(Block.Values.NULL_HASH);
});
});
});

View File

@ -1,22 +1,27 @@
'use strict';
var should = require('chai').should();
var bitcore = require('..');
var BN = require('../lib/crypto/bn');
var BufferReader = bitcore.encoding.BufferReader;
var Blockheader = bitcore.Blockheader;
var BlockHeader = bitcore.BlockHeader;
var fs = require('fs');
var should = require('chai').should();
describe('Blockheader', function() {
var bh = new Blockheader();
var version = 1;
var prevblockidbuf = new Buffer(32);
prevblockidbuf.fill(5);
var merklerootbuf = new Buffer(32);
merklerootbuf.fill(9);
var time = 2;
var bits = 3;
var nonce = 4;
bh.set({
// 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 dataRawId = '000000000b99b16390660d79fcc138d2ad0c89a0d044c4201a02bdf1f61ffa11';
var data = require('./data/blk86756-testnet');
describe('BlockHeader', function() {
var version = data.version;
var prevblockidbuf = new Buffer(data.prevblockidhex, 'hex');
var merklerootbuf = new Buffer(data.merkleroothex, 'hex');
var time = data.time;
var bits = data.bits;
var nonce = data.nonce;
var bh = new BlockHeader({
version: version,
prevblockidbuf: prevblockidbuf,
merklerootbuf: merklerootbuf,
@ -24,21 +29,23 @@ describe('Blockheader', function() {
bits: bits,
nonce: nonce
});
var bhhex = '0100000005050505050505050505050505050505050505050505050505050505050505050909090909090909090909090909090909090909090909090909090909090909020000000300000004000000';
var bhhex = data.blockheaderhex;
var bhbuf = new Buffer(bhhex, 'hex');
it('should make a new blockheader', function() {
var blockheader = new Blockheader();
should.exist(blockheader);
blockheader = Blockheader();
should.exist(blockheader);
Blockheader(bhbuf).toBuffer().toString('hex').should.equal(bhhex);
BlockHeader(bhbuf).toBuffer().toString('hex').should.equal(bhhex);
});
describe('#set', function() {
it('should not make an empty block', function() {
(function() {
BlockHeader();
}).should.throw('Unrecognized argument for BlockHeader');
});
describe('#constructor', function() {
it('should set all the variables', function() {
bh.set({
var bh = new BlockHeader({
version: version,
prevblockidbuf: prevblockidbuf,
merklerootbuf: merklerootbuf,
@ -59,7 +66,7 @@ describe('Blockheader', function() {
describe('#fromJSON', function() {
it('should set all the variables', function() {
var bh = Blockheader().fromJSON({
var bh = BlockHeader.fromJSON({
version: version,
prevblockidbuf: prevblockidbuf.toString('hex'),
merklerootbuf: merklerootbuf.toString('hex'),
@ -91,10 +98,34 @@ describe('Blockheader', function() {
});
describe('#fromJSON', function() {
it('should parse this known json string', function() {
var jsonString = JSON.stringify({
version: version,
prevblockidbuf: prevblockidbuf,
merklerootbuf: merklerootbuf,
time: time,
bits: bits,
nonce: nonce
});
var json = new BlockHeader(jsonString);
should.exist(json.version);
should.exist(json.prevblockidbuf);
should.exist(json.merklerootbuf);
should.exist(json.time);
should.exist(json.bits);
should.exist(json.nonce);
});
});
describe('#fromBuffer', function() {
it('should parse this known buffer', function() {
Blockheader().fromBuffer(bhbuf).toBuffer().toString('hex').should.equal(bhhex);
BlockHeader.fromBuffer(bhbuf).toBuffer().toString('hex').should.equal(bhhex);
});
});
@ -102,7 +133,7 @@ describe('Blockheader', function() {
describe('#fromBufferReader', function() {
it('should parse this known buffer', function() {
Blockheader().fromBufferReader(BufferReader(bhbuf)).toBuffer().toString('hex').should.equal(bhhex);
BlockHeader.fromBufferReader(BufferReader(bhbuf)).toBuffer().toString('hex').should.equal(bhhex);
});
});
@ -110,7 +141,7 @@ describe('Blockheader', function() {
describe('#toBuffer', function() {
it('should output this known buffer', function() {
Blockheader().fromBuffer(bhbuf).toBuffer().toString('hex').should.equal(bhhex);
BlockHeader.fromBuffer(bhbuf).toBuffer().toString('hex').should.equal(bhhex);
});
});
@ -118,7 +149,70 @@ describe('Blockheader', function() {
describe('#toBufferWriter', function() {
it('should output this known buffer', function() {
Blockheader().fromBuffer(bhbuf).toBufferWriter().concat().toString('hex').should.equal(bhhex);
BlockHeader.fromBuffer(bhbuf).toBufferWriter().concat().toString('hex').should.equal(bhhex);
});
});
describe('#inspect', function() {
it('should return the correct inspect of the genesis block', function() {
var block = BlockHeader.fromRawBlock(dataRawBlockBinary);
block.inspect().should.equal('<BlockHeader '+dataRawId+'>');
});
});
describe('#fromRawBlock', function() {
it('should instantiate from a raw block binary', function() {
var x = BlockHeader.fromRawBlock(dataRawBlockBinary);
x.version.should.equal(2);
BN(x.bits).toString('hex').should.equal('1c3fffc0');
});
it('should instantiate from raw block buffer', function() {
var x = BlockHeader.fromRawBlock(dataRawBlockBuffer);
x.version.should.equal(2);
BN(x.bits).toString('hex').should.equal('1c3fffc0');
});
});
describe('#validTimestamp', function() {
var x = BlockHeader.fromRawBlock(dataRawBlockBuffer);
it('should validate timpstamp as true', function() {
var valid = x.validTimestamp(x);
valid.should.equal(true);
});
it('should validate timestamp as false', function() {
x.time = Math.round(new Date().getTime() / 1000) + BlockHeader.Constants.MAX_TIME_OFFSET + 100;
var valid = x.validTimestamp(x);
valid.should.equal(false);
});
});
describe('#validProofOfWork', function() {
var x = BlockHeader.fromRawBlock(dataRawBlockBuffer);
it('should validate proof-of-work as true', function() {
var valid = x.validProofOfWork(x);
valid.should.equal(true);
});
it('should validate proof of work as false because incorrect proof of work', function() {
var nonce = x.nonce;
x.nonce = 0;
var valid = x.validProofOfWork(x);
valid.should.equal(false);
x.nonce = nonce;
});
});

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,600 @@
{
"magicnum": 118034699,
"blocksize": 8003,
"blockheader": {
"version": 2,
"prevblockidbuf": "4baaa9507c3b27908397ea7bc177a998e9f4fe38b9d5130be7b5353c00000000",
"merklerootbuf": "97fc4c97868288e984ff9f246f2c38510f5c37a3d5b41aae7004b01e2dd5e658",
"time": 1371410638,
"bits": 473956288,
"nonce": 3594009557
},
"txsvi": "16",
"txs": [{
"version": 1,
"txinsvi": "01",
"txins": [{
"txidbuf": "0000000000000000000000000000000000000000000000000000000000000000",
"txoutnum": 4294967295,
"scriptvi": "0b",
"script": "3 0xe45201 6 0x2f503253482f",
"seqnum": 4294967295
}],
"txoutsvi": "03",
"txouts": [{
"valuebn": "5001000000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0xee9a7590f91e04832054f0645bbf243c9fac8e22 OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "0",
"scriptvi": "43",
"script": "65 0x04ffd03de44a6e11b9917f3a29f9443283d9871c9d743ef30d5eddcd37094b64d1b3d8090496b53256786bf5c82932ec23c3b74d9f05a6f95a8b5529352656664b OP_CHECKSIG"
}, {
"valuebn": "0",
"scriptvi": "25",
"script": "36 0x58e99e66e2b90bd8b2a0e2bfcce91e1f09ee7621d95e9a728ca2372d45df3ded00000000"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "01",
"txins": [{
"txidbuf": "d6e149959b6248eee5a17c23a518e5e5e399e98f7d42a2833810f3baf1525acf",
"txoutnum": 0,
"scriptvi": "6b",
"script": "72 0x30450221009273f5d777408439a40c33ee96630a877d4f29af3f60f5c230e5254ee6f08f4302207975a64f43dc632f34479aa403b9956c484ad0c90a3c50d2e1b5037e1abb586f01 33 0x03449772f2c60c2f4e1f1f74cb6c521a48f12d51ea681b64c8fc074fd8108123f6",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "864185035",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x0487c481a671649e1db182ede98d093a335d6713 OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "2635964965",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x590ea00fa3a18281d3020e7ba0c3a1d6aea663c0 OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "2a24c5dfbdb9dc5e1eb5d38dc9e8c5f8643aee53fcb0d2e44a04924b55c65c6b",
"txoutnum": 0,
"scriptvi": "6a",
"script": "71 0x304402207aa649b3ba03eeac6c6fb88e74800ca418297f62da75c58284a0c5f6cdfa96b70220324eb99fecdb0eb8bd4eec05bec0f440f4c2132c1afbaa7aaf10f31d17d8ef0201 33 0x022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3c",
"seqnum": 4294967295
}, {
"txidbuf": "1186e9edc6526a3ab463d1f0123ae38e5593364d2f80de9d8031a48274b718ab",
"txoutnum": 0,
"scriptvi": "6c",
"script": "73 0x304602210084cd799ec732e95a08c9e1ef98e99e43767b6bc4eb6af6cf65ecdf2be6bc96ab022100da1d1c450d675d383b92095c2b9949d693b82b54ac81ba219fad98f8500589ad01 33 0x02b567c3f3442f71b6762404be7cc06ffd3b170d4cb98b90dab169187a07eb6786",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "2940000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x68340b9145127d2529dd7ebc3a4567d5579997ac OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "3010000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x3770e8980281b63351861a17881cecbfaaa5c74b OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "0f5000a056f91d03c489d7d1558f09c7bc330af3ca8e43706d5cb08fd6c60aad",
"txoutnum": 1,
"scriptvi": "6a",
"script": "71 0x304402201068b39118afc383bb1b7de9aa8fe02cddbd8be5d29cab99d5fff23a0cef5667022020d6cfb4712fc61c13c7ca26e32028cce3d68afea7957ab4bfc5ee03bf9615d401 33 0x03b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662",
"seqnum": 4294967295
}, {
"txidbuf": "08d4577f5634796567fb0cd50abd1886df3555f71847a1977ba5bc75195405a7",
"txoutnum": 1,
"scriptvi": "6a",
"script": "71 0x304402206728ade49cb5ec883e07d8acc6450e17b0e27b7f64c81143b4632eaded365e2e02202be3b4b723200de8c070b914d0050ead71d1418196a037f55f1a6dff4e45aee301 33 0x039e65fd2479d4edb0f3db6eecacdadcdc5ddd6d8ef518cf861466dfe1c21cc891",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "3650000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x9a704e2c99955f50694de60f93cdd449473678aa OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "3000000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0xdac91bdfe809346e9df5e753adaaef9336344bfc OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "fc85133b1e259f6deec25953bccfa75df61fd23a471553c80c043c2ea716a675",
"txoutnum": 0,
"scriptvi": "6a",
"script": "71 0x304402203da7beabc48687b746a7149679bd8982032816771b5634d1d651af59ce9fa86d0220198ea81d1a547e3493988dd94ffefff3b8fe030340886aa4ffc1b205532f0f9d01 33 0x03b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662",
"seqnum": 4294967295
}, {
"txidbuf": "04297137bc2c9f486713e4e4fab43134da153e0f8ee8e852554090d02f2605a5",
"txoutnum": 0,
"scriptvi": "6a",
"script": "71 0x304402206b729bfd4c132b673c9f1a66c645ed374338963f1e6a3b56229f72b4358f8077022023bea16c89d267313da6df152a976b36a36e1bbea738d698f0ce72ef315962df01 33 0x03ba341f7dd2401a2cd51682d418fd8a12b4d0b09acb8971f0671c2211366a8531",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "3700000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x4769612ee7c6e977df40a8cdfd837c85cc7a48f7 OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "3000000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0xdac91bdfe809346e9df5e753adaaef9336344bfc OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "1cb5734a303cefa1ace87b8cc386a573f1eed8370e14c0a830fd04249b7756a6",
"txoutnum": 0,
"scriptvi": "6a",
"script": "71 0x3044022059bbf19179b81fad8a15ba3dff94271d55d443da636dbaeba6ea0bb5901b8779022045417e208f41f8b37473caaf367a61ed21b31f1205605020de241e89b7ec0ca601 33 0x022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3c",
"seqnum": 4294967295
}, {
"txidbuf": "babb329d773e9101e127f7c1e95533fb384c79260789dc06fdf73296c9ef352d",
"txoutnum": 0,
"scriptvi": "6b",
"script": "72 0x30450220012c555e725f4eb0d767efdc07aec149c63522b06253e9d1ce6245b90c71951e022100edcce82ddd7e52a3b85bf9a4acc73a3b6df5c9b40fda36e8de09890860599ddf01 33 0x02b567c3f3442f71b6762404be7cc06ffd3b170d4cb98b90dab169187a07eb6786",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "3210000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x3770e8980281b63351861a17881cecbfaaa5c74b OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "2740000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0xe1144ff8ca0ac143b83ada244040bfe9c8d1d638 OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "9a494e6072106a040e279b4566f25fc35441a84f6228812142eb5515688832f5",
"txoutnum": 0,
"scriptvi": "6b",
"script": "72 0x3045022100b35809ba9abcea1ec143c7cd0a27845b3f5139a6bb52757c9e24d86319f8d16c022079f8381c5287af7e6488d6a589e73caf23c487bf355ac22b7c01cf58830110bf01 33 0x023d1c9bcd771cc12b60cce62e9b8196788dd365089b70d898d60917a174e16f6a",
"seqnum": 4294967295
}, {
"txidbuf": "ec7d5d39d4db41d7d9ba0653b6c9758f20cf89a4c2e60bb27645a966889fdfd6",
"txoutnum": 0,
"scriptvi": "6a",
"script": "71 0x3044022008848d34f2ca77f8bf79eb83b89ee8a24292d0c3936350a37f1522664e2e216002204ad05817044e18d0c26e89139b9fb98a21ceda2249a7cfa58f3ec420af9477c701 33 0x03af07092ed729d97d5e2ae9f8a295f1b2da268e7414ce3df9b374051d7647092b",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "3700000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0xb1b9b659297859bd310ba8ba6f95573c635b191a OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "3000000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x636c549bf6035b27cf3823f5482911ebb2bce5d0 OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "8c88435add45be7b1521756b8ee3bfc51558040c3922e11facff1d6cdc7fc841",
"txoutnum": 0,
"scriptvi": "6a",
"script": "71 0x304402201bf92a99fd85e09de43b9039801f387ad6ea996d71c02185019a18cd2691d68502204500ea82873501c25c5b1476f9cd75d70b2a34a4162470e3390f89ff6a58301101 33 0x022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3c",
"seqnum": 4294967295
}, {
"txidbuf": "bb1d138f7c9e8df06a87cd068fc303cb960c7b5670515a7759653fd3b71c6e7e",
"txoutnum": 0,
"scriptvi": "6b",
"script": "72 0x30450220277eb0e03b897cd20ac3bfa15af82ae2c1e75472ffce0482ce1594cd4536e83802210088164c46f3fc82ed3530b7552a1da6ecd2f690647485bb0fe1a706ae0f09d5b601 33 0x02718b695944b9e6f12db75e7dc7b77f023c8b9706405b62dac6e6c94dc1c7214e",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "1950000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0xe22f515855329b13602778a1d681295e485390b8 OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "3010000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x1882e6174c19c4a2ac6c7d807170e76cbc75160f OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "948a4df70264c816b3c65bb1315bc20df2ee12baaba580818ed232a59dbe3282",
"txoutnum": 0,
"scriptvi": "6b",
"script": "72 0x3045022100e96feaa777c517aa67498d51c52b7c177c18f7eb96c7ec109bcf4b7d1993245e02203d4f6dc06f4ac4ff947d81a45c9e53b12ee89e4223aa670eee2ca435157f605401 33 0x02690619097c609c03c8b82f7d289aac8a4d2fe36e5a41fc3701138deeeccd9807",
"seqnum": 4294967295
}, {
"txidbuf": "8dddf5d111131865b48f2b141f635ac6c41f14adc748ea0cd6087fd69b60d573",
"txoutnum": 0,
"scriptvi": "6b",
"script": "72 0x30450220588e7eb9477043dc7b7d9f554b5db44823d9b7108a73d224af8cb24b190ebc94022100deb2fd7cfbff5f7679a38a16c18075dc9eb705850054415eba27a0f769f94e8d01 33 0x02690619097c609c03c8b82f7d289aac8a4d2fe36e5a41fc3701138deeeccd9807",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "2740000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x7ff6d70c9f71e29f3b3b77e1acb0bae8d1af12d2 OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "3210000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x1c5b740011cff8324ed10c3e8f63f6261f36613a OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "7624f057be29a1d4d39112006d1a1acaca84b78f5e2323c3ae587365f91b6014",
"txoutnum": 0,
"scriptvi": "6a",
"script": "71 0x304402201bfc0a95285de492ca53fd2ab89b58cdb1d9d817d7c4ade64e31bb63ccf73b7802206d4f72973c9aa804d9a5c9b749a49aec579ab7875d30c1e0b9ab8d3d7b8041ad01 33 0x02926efc059307ca51862547d58b7a0c1749f0e27df6fbea550bbb291ef0a00bcb",
"seqnum": 4294967295
}, {
"txidbuf": "ed83ae0fa16dd5602ca174f1c845be1f1c370ce483925dda6e524e6f82b93bd8",
"txoutnum": 0,
"scriptvi": "6c",
"script": "73 0x30460221008de29b6fafdadc7a1430ff453c9cb4ea96f9186c1c43b9d1f243876c4d187c5a022100f03f8a8a43c39a619c03db80bedaf9111ee817a574edf912795b3bef85024d4601 33 0x02891fda8944ae461484abdc5898a94d666d8e54ed47f534218601c9a39e1058b8",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "3000000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0xfc9c507e2cf3563c63bf9ec7b38773c2a1e1c472 OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "3970000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x736d9e4703437b3f245cda14ab4ed2d52b0a622d OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "a34b87af6103eac5adaba08069aca7f19c6091f6b1f4b8ca788e54970cab2039",
"txoutnum": 1,
"scriptvi": "6b",
"script": "72 0x3045022049ce62033552a024ce0badb3d3c9db84af929c373b816dade2611563871e48840221009f80e97265ce861637468c98237a06df9c7482cc7c1739e1c36a8e85537c7f1601 33 0x032e68cde689f248f9dcce3f1b3b607400fd1275aa3d3a821ff81dd95a3645e20f",
"seqnum": 4294967295
}, {
"txidbuf": "a973c9f57b44c4f70b181311ba1ab60c3f3c20663a3127d3c418b9bb3b175ef4",
"txoutnum": 0,
"scriptvi": "6b",
"script": "72 0x304502204d5decc921dff956fbcfa1a574e43e0d17b9a49ee07f294b74f854f0dd7e0160022100d49781e18670f3372961dd5799d162071e13832fa9f15197c90d7b8ab8168e8d01 33 0x02690619097c609c03c8b82f7d289aac8a4d2fe36e5a41fc3701138deeeccd9807",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "2940000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0xcc0d9d6d476efe8205891836f40e00caf2fde492 OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "3010000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x3770e8980281b63351861a17881cecbfaaa5c74b OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "6904c207207b72a9671e78f8e1284ae13b7b60c51b352142c849d338e8f3e8f1",
"txoutnum": 1,
"scriptvi": "6a",
"script": "71 0x30440220740a2107c2d9be5f621822667b9cc34566511c0e6767de900f3b46fa0852d62302207cf2fcf969e48fce7ad43880bd3a7ee5658a421a3fb718e3fd824e22e4bac6ee01 33 0x02690619097c609c03c8b82f7d289aac8a4d2fe36e5a41fc3701138deeeccd9807",
"seqnum": 4294967295
}, {
"txidbuf": "a3693948981b6fab5aeb9df82b1fc8e3fdbfeff8d934ce0617f4a9be699e06e7",
"txoutnum": 1,
"scriptvi": "6c",
"script": "73 0x3046022100942e3ffd4522789f747b0c0d18a7228ba9f343294a34ffb0a53801b0d1626963022100eacf2ea0eef2c58e2666442bd331489dbda43adfd6d4809c2e71de38aff7fd9201 33 0x03de66ea9a044ee251ba8a6dfe1d68ee1c2e17acaf5d8b568a515ff37752b6ea0e",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "2940000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0xac64ed9c139e44fd8d1d9ad28d1d08fc8a8f70f8 OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "3010000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x3770e8980281b63351861a17881cecbfaaa5c74b OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "3b45e99dd007030fd8511434235b70a7d29041eb1e72d3cb2dda7d1e769ec13c",
"txoutnum": 0,
"scriptvi": "6b",
"script": "72 0x304502201c10c88a04850d9101b6cbcb51c28d9ca34f693fd918ba3c26775c5993cbdfc1022100e5d7708777b9592d709863859ce0f4d590f56acf5bb3655e119cac10d597c46301 33 0x03b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662",
"seqnum": 4294967295
}, {
"txidbuf": "87cc87cf0be7989073235f455fe6524324bfe8cba5f4ee3c2a59c46fec3bf14a",
"txoutnum": 1,
"scriptvi": "6b",
"script": "72 0x304502205cd5ea454979d705d4573d7b6f6a1bae22e5f146e0ccd14079a959a429bf69fc022100d88f05762b394621ec967546151b682f8103bed05b6d99b80adfadd626a721c501 33 0x03803aa78d28c40170231e0520fc38daa405140ed6e177c0747ce9d8d7dd6cdee4",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "3530000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0xbc1e95774ee2e36d2687714da14551132f0588b0 OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "3000000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x859819cb59368e07d4c95b5221fa4c466d666949 OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "7848ce7fbc4f3b3e56a778607e046aa2b2cf891cdba8b61186095d4931b44c72",
"txoutnum": 0,
"scriptvi": "6b",
"script": "72 0x3045022100850533f400465b01658b7dfcb05b3bae38a89344065f8321f69f7b1b2036446f0220663a629b5f2b1cf8748558ae71c8b49cda87e43347d4cbf4c84e3a79bc904a4901 33 0x03b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662",
"seqnum": 4294967295
}, {
"txidbuf": "0e33c08e14303d5660127f5d3792ca11c18321a276e71f53415af75a2319ee92",
"txoutnum": 1,
"scriptvi": "6b",
"script": "72 0x3045022020d4bbbc5c300aadbc52110f7aa971d77bcf567c91d288ed6af0a98fc8f75e74022100ea84ee6d3fbeb672e92ea993d27202fc9ecd33ba7494d8b064518649fc2c17dc01 33 0x036a91343ca1c973401accb1fb902336d2a7a1b4f670ff82d9acc5c380d6a627f0",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "3620000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x4cc35fc2651b5b3e4f22dfa9b6ebef0ca1797fb0 OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "3000000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x49452bed77744157799ba71fdb43efbd66968ad1 OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "2a6cc52c8804088ddbc164cfa01e4d9ee7e839c7a8f5d2f1b59b70a50d253f24",
"txoutnum": 0,
"scriptvi": "6b",
"script": "72 0x3045022100bd72079af0ba0965d01dc6de2502ceebe38fa94fcf9850140e7ce1e5ef29d3cc02207da0e0b881594a9bc8750143dfa41ce8255e14f24784a551d3d1c4a2acecc0a201 33 0x03b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662",
"seqnum": 4294967295
}, {
"txidbuf": "36262f4b7717eca333432cd9af776bb5ef4b29a2ea1b1cf877b49642db945c62",
"txoutnum": 1,
"scriptvi": "6b",
"script": "72 0x3045022100f074c81f476f50dad72d3d07cef668532bb2b0cc772b49abf67cafd476e4e41302201e36efd9eec72b2f5ff4eac4ffbbe0598c6185b63c6ba8e03737b708e731499401 33 0x022d7e055cd28a8b7ca2613687e9b5cd4ff4a959c54d74f49c12345d1d8f78b374",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "3000000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0xfc9c507e2cf3563c63bf9ec7b38773c2a1e1c472 OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "3750000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x5ab29618ded8892f8189ca3ce81bef83d3ddda16 OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "d724e595476277be4337bb8f39ca700b4f9df1bfb84089c4afd338e1079e9add",
"txoutnum": 1,
"scriptvi": "6b",
"script": "72 0x3045022100f775b297513593c1c6e461902ab6405c4c38ce3b37d9292fe074153b8c466c29022010ded748e9e7fb1fbb263b8f466e6a1352e05ddb8842a17f712478e3d9c1770401 33 0x023d1c9bcd771cc12b60cce62e9b8196788dd365089b70d898d60917a174e16f6a",
"seqnum": 4294967295
}, {
"txidbuf": "ff40fb739e2271f4aaa851dd46fcd1895ddd7a98850ef191ba3b50325c29a4ed",
"txoutnum": 1,
"scriptvi": "6b",
"script": "72 0x30450220686b1c5ecd7ea0e9078784f5ea0100035a962809fd1d0cf7a131604ecfb26f02022100ddf7b8874a375edfa4d0d7b93cfd214d0327e550add318f1a8a379cceae8dac601 33 0x0363c3fa31a5453a29f6cde46c9d77698fd8276cf9f511dd6e5d079a231fea568e",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "3940000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0xb0c1cda106bb5085bd9c0c9982773c7bd066fabc OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "3000000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x859819cb59368e07d4c95b5221fa4c466d666949 OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "a9b95beed9491639bc0d1bb833005cf45429ef9a50505f9b91f3c7588feb87ef",
"txoutnum": 1,
"scriptvi": "6c",
"script": "73 0x3046022100854bc0ee8b24e2b625798148fc505cb37464f72688456dc54b0c25c4dd564091022100c2863ab346c23157baaeb45e6d102e7354cc895ee0dd7b6ecdc77ab34bdd4d0f01 33 0x022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3c",
"seqnum": 4294967295
}, {
"txidbuf": "8eaaf0d722fe9deffbc6e9d543f406844c93d1dd1c073d739863c314d2adf4ef",
"txoutnum": 0,
"scriptvi": "6a",
"script": "71 0x304402203f28684b208f0f4bf87ca22544e59585a7807fcd5a2ec78fc93ce915e282335502201ab05402d3a2b2914dd955971fade92dc874e6441bc2383766ec8b4c56dca27501 33 0x0251a3bd043afe5cf46a40c4ce4caf3e917190583588634711507d6ef77acc438b",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "3010000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x1882e6174c19c4a2ac6c7d807170e76cbc75160f OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "2010000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0xb27f37b7cee282e7890f4f6df9b49574f35e8552 OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "fadecb6a5b1bd5f0688fc7dd049dadd956c30006e4dc57155f22c054c1550791",
"txoutnum": 0,
"scriptvi": "6b",
"script": "72 0x304502201dcb7d73d180cda9ddb192e50fcf5f0efaa5e680931f2bc25e58dd368d4b815f0221008149257f9394b01188aa84f92aec7374339076b408360767236a3af18718cddc01 33 0x032e68cde689f248f9dcce3f1b3b607400fd1275aa3d3a821ff81dd95a3645e20f",
"seqnum": 4294967295
}, {
"txidbuf": "569ed0585b1d5261fe5a1839e99c23d0cd3b82972526c5bb5b812ceb493facc3",
"txoutnum": 1,
"scriptvi": "6b",
"script": "72 0x304502205665ae2983ad6ec44220810a6f4c28d77dd518cc891eb9ed67503a756e97c477022100ab456b8a9c1f977623956943d8f1892c3bf84d8adefaa405606d3473f37fb8b401 33 0x02bbdf0772bbacab8eaba47d783d30fa401b08a0ecc4bccd49357171ac38791c0e",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "3010000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x1882e6174c19c4a2ac6c7d807170e76cbc75160f OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "1330000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0xa6a0900e3c77496dc68be8ee130a21b446b82665 OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "3d9d0df887b3621c3c884515d1a4c0a22e2bc4aa02300493cb568189847265db",
"txoutnum": 1,
"scriptvi": "6b",
"script": "72 0x3045022100af41bf6edc04de96ad8b0d0e0794a7055c9677f2616fcfc1b053f87ad5c60c0f02201ef5279534263776cca80957368791a362354d7a40f3f175874b909de2d7f9a101 33 0x022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3c",
"seqnum": 4294967295
}, {
"txidbuf": "70f6c965fcbae21ee712571b683b33e3b4d0e9c5d1fd685046db7176e3bf432e",
"txoutnum": 0,
"scriptvi": "6b",
"script": "72 0x3045022033da8150f9870e045581f5894366f57345946174b43b7f8c0f9b24f7afad395c022100e3db87d42b1050ea8f2e964a13eeae86cc57e771c4dfa29f7f055c74a39be3b801 33 0x0221f705f7d58ceea66122bcdc7220db0583d8ce1d7d948ed86007905268f55162",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "3010000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x1882e6174c19c4a2ac6c7d807170e76cbc75160f OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "2130000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x47830d334d04acd62668904b6fab06a90742e750 OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "2e48318fb557623da627d1c3f81ab34b99a87ce701440dfb907ad6a8691b51f2",
"txoutnum": 0,
"scriptvi": "6c",
"script": "73 0x3046022100d2733fcc63dd86bc4653d268f16e467e87a7be9e1d3f45cbeccb2423b7eb1c6c022100e3963622c12dab3e9c0c76a8ef13151114cb0f17abe6c29cca2fcbac264dfc9801 33 0x020ce8a0852e31812de6b8f2b2604d948cb06f8f7f404e70a19067cca01b5d0988",
"seqnum": 4294967295
}, {
"txidbuf": "675f09c92aa029f3283ee9a6b8bd6f022a1ea3bdccb1d33a09416ee9389e3ecb",
"txoutnum": 0,
"scriptvi": "6b",
"script": "72 0x304502202beb8d4ff142762f12f867a1686c2a523c55ff336b8ae3992ae1292019afeaf1022100a2e7edb9ffb29628540fd02b21c84abf1cc48d70c9f6adb39550b8aff572c65a01 33 0x03b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "3970000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x449c3ac7336a78f0c6401f51710949005d2c7ffa OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "3000000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x636c549bf6035b27cf3823f5482911ebb2bce5d0 OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "33232e2ce65e394a2c7e46519fae48b9b711b5152f764a4d6454bfc0552f275a",
"txoutnum": 0,
"scriptvi": "6c",
"script": "73 0x3046022100928f760eaabaed51bfc4db0188c84a6a19ef34a88786f2a25d8050c8356d858d022100c1a35c67f2c21b4837eaf73e195c74eb213bdaa4650fe77da072db9f84b90d0c01 33 0x022d9055b471959ea9385bf8c92788c45d836818d86833d91331cee37d8c15ee3c",
"seqnum": 4294967295
}, {
"txidbuf": "f7fc20459ede0aeba4e9224ac667212ff815c651ca4feaaf40880b9f9d82413a",
"txoutnum": 1,
"scriptvi": "6c",
"script": "73 0x3046022100c098dd6d9b20ed80de2d86d2c1bc9328b1c42f04b03c3767aec9d846d4538c9d0221009e32178215a499f22d8d3afe9f257159143c3d24f07371e0ef2de97d216e3b4201 33 0x02078d4050a314870bd68960765015e5f884e35c60b44e23e0f2d264b73aaca477",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "3210000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x1c5b740011cff8324ed10c3e8f63f6261f36613a OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "2740000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x7bdb65a92af2520836f77e5ebccc697d814149ce OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}, {
"version": 1,
"txinsvi": "02",
"txins": [{
"txidbuf": "dae9bc0142c15e33fe26a494d1233e80adf68b50a131f467eb13450caa56e43d",
"txoutnum": 0,
"scriptvi": "6c",
"script": "73 0x3046022100ecf03f0bafb0cf6e08ac80336565bf79b6bac800f546e9f953fb14df7bf239ac022100982e27f2f0b3f8569cef126c0c54a88b002f00d570106c74f5c4b314c960944201 33 0x03b3385ed65f34e06927d8835e86103c3de352dbdece5cb704f6899886a0334662",
"seqnum": 4294967295
}, {
"txidbuf": "6904c207207b72a9671e78f8e1284ae13b7b60c51b352142c849d338e8f3e8f1",
"txoutnum": 0,
"scriptvi": "6c",
"script": "73 0x3046022100febc4cdfbd5073ee756c9763b0e18009893b422e13c25e8f74ca97b84c0cf73f022100a85a6c10debf45e8ad00db28fce5fcb68404e9ac4b844f0ae1d59c0ef210d71401 33 0x03dc9adee9c23ca7a091b4eafc4dfef2ed07adf903dae568f345095321aa9c57e2",
"seqnum": 4294967295
}],
"txoutsvi": "02",
"txouts": [{
"valuebn": "3620000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0x67a341d7fe4de6a810c182ed27a09554e0b4405d OP_EQUALVERIFY OP_CHECKSIG"
}, {
"valuebn": "3000000",
"scriptvi": "19",
"script": "OP_DUP OP_HASH160 20 0xf7f1f64a590896dccfb869ced060f058007f388b OP_EQUALVERIFY OP_CHECKSIG"
}],
"nlocktime": 0
}]
}

View File

@ -1,27 +0,0 @@
'use strict';
if (process.browser || true) // no examples yet
return; //examples are loaded from files, which doesn't work in the browser
var should = require('chai').should();
var fs = require('fs');
describe('Examples', function() {
var filenames = fs.readdirSync(__dirname + '/../examples/');
filenames.forEach(function(filename) {
if (filename.slice(filename.length - 3) === '.js') {
describe(filename, function() {
it('should not throw any errors', function() {
(function() {
var save = console.log;
console.log = function() {};
require('../examples/' + filename);
console.log = save;
}).should.not.throw();
});
});
}
});
});