bitcoindjs.verifyBlock.

This commit is contained in:
Christopher Jeffrey 2014-09-26 11:23:21 -07:00
parent 4b6fceee37
commit 41c0cb5a4e
3 changed files with 152 additions and 4 deletions

View File

@ -69,7 +69,7 @@ function getBlocks(bitcoind) {
return bitcoind.getBlock(hash, function(err, block) {
if (err) return print(err.message);
// print(block);
print(block);
if (argv['get-tx'] && block.tx.length && block.tx[0].txid) {
var txid = block.tx[0].txid;

View File

@ -9,6 +9,7 @@ var EventEmitter = require('events').EventEmitter;
var bitcoindjs = require('../build/Release/bitcoindjs.node');
var util = require('util');
var net = require('net');
var assert = require('assert');
var bn = require('bn.js');
/**
@ -322,6 +323,83 @@ function Block(data) {
});
}
Block.prototype.verify = function() {
return this._verified = this._verified || bitcoindjs.verifyBlock(this.toHex());
};
Block.prototype.toBinary = function() {
return Block.toBinary(this);
};
Block.toBinary = function(block, type) {
var p = [];
var off = 0;
// version
off += utils.writeU32(p, block.nVersion || block.version, off);
// prev_block
utils.toArray(block.previousblockhash, 'hex').forEach(function(ch) {
p[off++] = ch;
});
// merkle_root
utils.toArray(block.merkleroot, 'hex').forEach(function(ch) {
p[off++] = ch;
});
// timestamp
off += utils.writeU32(p, block.time, off);
// bits
off += utils.writeU32(p, block.bits, off);
// nonce
off += utils.writeU32(p, block.nonce, off);
assert.equal(off, 80);
if (type === 'merkle') {
// txn_count
off += utils.writeU32(p, block.txn_count, off);
// hash count
off += utils.varint(p, block.hash_count, off);
// hashes
block.hashes.forEach(function(hash) {
utils.toArray(hash, 'hex').forEach(function(ch) {
p[off++] = ch;
});
});
// flag count
off += utils.varint(p, block.flags.length, off);
// flags
block.flags.forEach(function(flag) {
p[off++] = flag;
});
} else {
// txn_count
off += utils.varint(p, block.tx.length, off);
// txs
block.tx.forEach(function(tx) {
tx = bitcoin.tx(tx);
tx.toHex();
utils.toArray(tx.hex, 'hex').forEach(function(ch) {
p[off++] = ch;
});
});
}
return new Buffer(p);
};
Block.prototype.toHex = function() {
return this._hex = this._hex || Block.toHex(this);
};
Block.toHex = function(block) {
return Block.toBinary(block).toString('hex');
};
/**
* Transaction
*/
@ -420,7 +498,7 @@ Transaction.prototype.toHex = function() {
};
Transaction.toHex = function(tx) {
return new bn(Transaction.toBinary(tx)).toString('hex');
return Transaction.toBinary(tx).toString('hex');
};
Transaction.toBinary = function(tx) {
@ -470,7 +548,7 @@ Transaction.toBinary = function(tx) {
}
off += utils.writeU32(p, tx.nLockTime || tx.locktime, off);
return p;
return new Buffer(p);
};
Transaction.prototype.toBinary = function() {
@ -644,6 +722,48 @@ utils.copy = function copy(src, dst, off, force) {
return i;
};
function toArray(msg, enc) {
if (Array.isArray(msg))
return msg.slice();
if (!msg)
return [];
var res = [];
if (typeof msg === 'string') {
if (!enc) {
for (var i = 0; i < msg.length; i++) {
var c = msg.charCodeAt(i);
var hi = c >> 8;
var lo = c & 0xff;
if (hi)
res.push(hi, lo);
else
res.push(lo);
}
} else if (enc === 'hex') {
msg = msg.replace(/[^a-z0-9]+/ig, '');
if (msg.length % 2 !== 0)
msg = '0' + msg;
for (var i = 0; i < msg.length; i += 8) {
var slice = msg.slice(i, i + 8);
var num = parseInt(slice, 16);
if (slice.length === 8)
res.push((num >>> 24) & 0xff);
if (slice.length >= 6)
res.push((num >>> 16) & 0xff);
if (slice.length >= 4)
res.push((num >>> 8) & 0xff);
res.push(num & 0xff);
}
}
} else {
for (var i = 0; i < msg.length; i++)
res[i] = msg[i] | 0;
}
return res;
}
utils.toArray = toArray;
utils.NOOP = function() {};
/**

View File

@ -126,6 +126,7 @@ NAN_METHOD(GetTx);
NAN_METHOD(PollBlocks);
NAN_METHOD(PollMempool);
NAN_METHOD(BroadcastTx);
NAN_METHOD(VerifyBlock);
static void
async_start_node_work(uv_work_t *req);
@ -636,7 +637,7 @@ async_get_block_after(uv_work_t *req) {
NAN_METHOD(GetTx) {
NanScope();
if (args.Length() < 2
if (args.Length() < 3
|| !args[0]->IsString()
|| !args[1]->IsString()
|| !args[2]->IsFunction()) {
@ -1084,6 +1085,32 @@ async_broadcast_tx_after(uv_work_t *req) {
delete req;
}
/**
* VerifyBlock
*/
NAN_METHOD(VerifyBlock) {
NanScope();
if (args.Length() < 1 || !args[0]->IsString()) {
return NanThrowError(
"Usage: bitcoindjs.verifyBlock(blockHex)");
}
String::Utf8Value blockHex_(args[0]->ToString());
std::string blockHex = std::string(*blockHex_);
CBlock block;
CDataStream ssData(ParseHex(blockHex), SER_NETWORK, PROTOCOL_VERSION);
CTransaction tx;
ssData >> block;
CValidationState state;
bool valid = CheckBlock(block, state);
NanReturnValue(NanNew<Boolean>(valid));
}
/**
* Conversions
*/
@ -1315,6 +1342,7 @@ init(Handle<Object> target) {
NODE_SET_METHOD(target, "pollBlocks", PollBlocks);
NODE_SET_METHOD(target, "pollMempool", PollMempool);
NODE_SET_METHOD(target, "broadcastTx", BroadcastTx);
NODE_SET_METHOD(target, "verifyBlock", VerifyBlock);
}
NODE_MODULE(bitcoindjs, init)