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) { return bitcoind.getBlock(hash, function(err, block) {
if (err) return print(err.message); if (err) return print(err.message);
// print(block); print(block);
if (argv['get-tx'] && block.tx.length && block.tx[0].txid) { if (argv['get-tx'] && block.tx.length && block.tx[0].txid) {
var txid = 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 bitcoindjs = require('../build/Release/bitcoindjs.node');
var util = require('util'); var util = require('util');
var net = require('net'); var net = require('net');
var assert = require('assert');
var bn = require('bn.js'); 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 * Transaction
*/ */
@ -420,7 +498,7 @@ Transaction.prototype.toHex = function() {
}; };
Transaction.toHex = function(tx) { Transaction.toHex = function(tx) {
return new bn(Transaction.toBinary(tx)).toString('hex'); return Transaction.toBinary(tx).toString('hex');
}; };
Transaction.toBinary = function(tx) { Transaction.toBinary = function(tx) {
@ -470,7 +548,7 @@ Transaction.toBinary = function(tx) {
} }
off += utils.writeU32(p, tx.nLockTime || tx.locktime, off); off += utils.writeU32(p, tx.nLockTime || tx.locktime, off);
return p; return new Buffer(p);
}; };
Transaction.prototype.toBinary = function() { Transaction.prototype.toBinary = function() {
@ -644,6 +722,48 @@ utils.copy = function copy(src, dst, off, force) {
return i; 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() {}; utils.NOOP = function() {};
/** /**

View File

@ -126,6 +126,7 @@ NAN_METHOD(GetTx);
NAN_METHOD(PollBlocks); NAN_METHOD(PollBlocks);
NAN_METHOD(PollMempool); NAN_METHOD(PollMempool);
NAN_METHOD(BroadcastTx); NAN_METHOD(BroadcastTx);
NAN_METHOD(VerifyBlock);
static void static void
async_start_node_work(uv_work_t *req); async_start_node_work(uv_work_t *req);
@ -636,7 +637,7 @@ async_get_block_after(uv_work_t *req) {
NAN_METHOD(GetTx) { NAN_METHOD(GetTx) {
NanScope(); NanScope();
if (args.Length() < 2 if (args.Length() < 3
|| !args[0]->IsString() || !args[0]->IsString()
|| !args[1]->IsString() || !args[1]->IsString()
|| !args[2]->IsFunction()) { || !args[2]->IsFunction()) {
@ -1084,6 +1085,32 @@ async_broadcast_tx_after(uv_work_t *req) {
delete 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 * Conversions
*/ */
@ -1315,6 +1342,7 @@ init(Handle<Object> target) {
NODE_SET_METHOD(target, "pollBlocks", PollBlocks); NODE_SET_METHOD(target, "pollBlocks", PollBlocks);
NODE_SET_METHOD(target, "pollMempool", PollMempool); NODE_SET_METHOD(target, "pollMempool", PollMempool);
NODE_SET_METHOD(target, "broadcastTx", BroadcastTx); NODE_SET_METHOD(target, "broadcastTx", BroadcastTx);
NODE_SET_METHOD(target, "verifyBlock", VerifyBlock);
} }
NODE_MODULE(bitcoindjs, init) NODE_MODULE(bitcoindjs, init)