169 lines
3.9 KiB
JavaScript
169 lines
3.9 KiB
JavaScript
'use strict';
|
|
|
|
var bitcore = require('bitcore');
|
|
var BufferReader = bitcore.encoding.BufferReader;
|
|
var BufferWriter = bitcore.encoding.BufferWriter;
|
|
var Hash = bitcore.crypto.Hash;
|
|
|
|
//TODO: use bitcore.Block
|
|
|
|
function Block(obj) {
|
|
/* jshint maxstatements: 25 */
|
|
if (!(this instanceof Block)) {
|
|
return new Block(obj);
|
|
}
|
|
|
|
this.version = obj.version || 1;
|
|
this.prevHash = obj.prevHash;
|
|
|
|
if (!obj.hasOwnProperty('prevHash')) {
|
|
throw new TypeError('"prevHash" is expected');
|
|
}
|
|
if (!obj.timestamp) {
|
|
throw new TypeError('"timestamp" is expected');
|
|
}
|
|
this.timestamp = obj.timestamp;
|
|
if (typeof this.timestamp === 'string') {
|
|
this.timestamp = new Date(obj.timestamp);
|
|
}
|
|
|
|
this.merkleRoot = obj.merkleRoot;
|
|
|
|
if (obj.data) {
|
|
if (!Buffer.isBuffer(obj.data)) {
|
|
throw new TypeError('"data" is expected to be a buffer');
|
|
}
|
|
this.data = obj.data;
|
|
} else {
|
|
this.data = new Buffer(0);
|
|
}
|
|
|
|
var hashProperty = {
|
|
configurable: false,
|
|
enumerable: true,
|
|
get: function() {
|
|
return this.getHash();
|
|
},
|
|
set: function() {}
|
|
};
|
|
|
|
Object.defineProperty(this, 'hash', hashProperty);
|
|
|
|
this.bits = obj.bits;
|
|
this.nonce = obj.nonce || 0;
|
|
|
|
return this;
|
|
}
|
|
|
|
Block.fromBuffer = function(buffer) {
|
|
var br = new BufferReader(buffer);
|
|
return Block.fromBufferReader(br);
|
|
};
|
|
|
|
Block.fromBufferReader = function(br) {
|
|
var obj = {};
|
|
obj.version = br.readUInt32LE();
|
|
obj.prevHash = BufferReader(br.read(32)).readReverse().toString('hex');
|
|
var nullHash = new Buffer(Array(32)).toString('hex');
|
|
if (obj.prevHash === nullHash) {
|
|
obj.prevHash = null;
|
|
}
|
|
obj.merkleRoot = BufferReader(br.read(32)).readReverse().toString('hex');
|
|
var timestamp = br.readUInt32LE();
|
|
obj.timestamp = new Date(timestamp * 1000);
|
|
obj.bits = br.readUInt32LE();
|
|
obj.nonce = br.readUInt32LE();
|
|
obj.data = br.readAll();
|
|
return new Block(obj);
|
|
};
|
|
|
|
Block.prototype.validate = function(chain, callback) {
|
|
// bitcoind does all validation
|
|
setImmediate(callback);
|
|
};
|
|
|
|
Block.prototype.headerToBuffer = function() {
|
|
var bw = new BufferWriter();
|
|
this.headerToBufferWriter(bw);
|
|
return bw.concat();
|
|
};
|
|
|
|
Block.prototype.headerToBufferWriter = function(bw) {
|
|
/* jshint maxstatements: 20 */
|
|
|
|
// version
|
|
bw.writeUInt32LE(this.version);
|
|
|
|
// prevhash
|
|
if (!this.prevHash) {
|
|
bw.write(new Buffer(Array(32)));
|
|
} else {
|
|
var prevHashBuffer = new Buffer(this.prevHash, 'hex');
|
|
prevHashBuffer = BufferReader(prevHashBuffer).readReverse();
|
|
if (prevHashBuffer.length !== 32) {
|
|
throw new Error('"prevHash" is expected to be 32 bytes');
|
|
}
|
|
bw.write(prevHashBuffer);
|
|
}
|
|
|
|
// merkleroot
|
|
if (!this.merkleRoot) {
|
|
bw.write(new Buffer(Array(32)));
|
|
} else {
|
|
var merkleRoot = new Buffer(this.merkleRoot, 'hex');
|
|
merkleRoot = BufferReader(merkleRoot).readReverse();
|
|
if (merkleRoot.length !== 32) {
|
|
throw new Error('"merkleRoot" is expected to be 32 bytes');
|
|
}
|
|
bw.write(merkleRoot);
|
|
}
|
|
|
|
// timestamp
|
|
bw.writeUInt32LE(Math.floor(this.timestamp.getTime() / 1000));
|
|
|
|
// bits
|
|
bw.writeUInt32LE(this.bits);
|
|
|
|
// nonce
|
|
bw.writeUInt32LE(this.nonce);
|
|
|
|
return bw;
|
|
|
|
};
|
|
|
|
Block.prototype.toObject = Block.prototype.toJSON = function() {
|
|
return {
|
|
hash: this.hash,
|
|
version: this.version,
|
|
prevHash: this.prevHash,
|
|
merkleRoot: this.merkleRoot,
|
|
timestamp: this.timestamp.toISOString(),
|
|
bits: this.bits,
|
|
nonce: this.nonce,
|
|
data: this.data.toString('hex')
|
|
};
|
|
};
|
|
|
|
Block.prototype.toBufferWriter = function(bw) {
|
|
// header
|
|
this.headerToBufferWriter(bw);
|
|
|
|
// transaction data
|
|
bw.write(this.data);
|
|
return bw;
|
|
};
|
|
|
|
Block.prototype.toBuffer = function() {
|
|
var bw = new BufferWriter();
|
|
this.toBufferWriter(bw);
|
|
return bw.concat();
|
|
};
|
|
|
|
Block.prototype.getHash = function() {
|
|
var hashBuffer = BufferReader(Hash.sha256sha256(this.headerToBuffer())).readReverse();
|
|
var hash = hashBuffer.toString('hex');
|
|
return hash;
|
|
};
|
|
|
|
module.exports = Block;
|