Merge pull request #1205 from maraoz/fix/block-parser
Fix block parsing
This commit is contained in:
commit
a11b916be7
@ -68,8 +68,8 @@ Block._fromJSON = function _fromJSON(data) {
|
|||||||
*/
|
*/
|
||||||
Block._fromObject = function _fromObject(data) {
|
Block._fromObject = function _fromObject(data) {
|
||||||
var transactions = [];
|
var transactions = [];
|
||||||
data.transactions.forEach(function(data) {
|
data.transactions.forEach(function(tx) {
|
||||||
transactions.push(Transaction().fromJSON(data));
|
transactions.push(Transaction().fromJSON(tx));
|
||||||
});
|
});
|
||||||
var info = {
|
var info = {
|
||||||
header: BlockHeader.fromObject(data.header),
|
header: BlockHeader.fromObject(data.header),
|
||||||
@ -118,6 +118,7 @@ Block._fromBufferReader = function _fromBufferReader(br) {
|
|||||||
* @returns {Block} - An instance of block
|
* @returns {Block} - An instance of block
|
||||||
*/
|
*/
|
||||||
Block.fromBufferReader = function fromBufferReader(br) {
|
Block.fromBufferReader = function fromBufferReader(br) {
|
||||||
|
$.checkArgument(br, 'br is required');
|
||||||
var info = Block._fromBufferReader(br);
|
var info = Block._fromBufferReader(br);
|
||||||
return new Block(info);
|
return new Block(info);
|
||||||
};
|
};
|
||||||
@ -127,7 +128,7 @@ Block.fromBufferReader = function fromBufferReader(br) {
|
|||||||
* @returns {Block} - An instance of block
|
* @returns {Block} - An instance of block
|
||||||
*/
|
*/
|
||||||
Block.fromBuffer = function fromBuffer(buf) {
|
Block.fromBuffer = function fromBuffer(buf) {
|
||||||
return Block.fromBufferReader(BufferReader(buf));
|
return Block.fromBufferReader(new BufferReader(buf));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -9,13 +9,22 @@ var BufferReader = function BufferReader(buf) {
|
|||||||
if (!(this instanceof BufferReader)) {
|
if (!(this instanceof BufferReader)) {
|
||||||
return new BufferReader(buf);
|
return new BufferReader(buf);
|
||||||
}
|
}
|
||||||
|
if (_.isUndefined(buf)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (Buffer.isBuffer(buf)) {
|
if (Buffer.isBuffer(buf)) {
|
||||||
this.set({
|
this.set({
|
||||||
buf: buf
|
buf: buf
|
||||||
});
|
});
|
||||||
} else if (buf) {
|
} else if (_.isString(buf)) {
|
||||||
|
this.set({
|
||||||
|
buf: new Buffer(buf, 'hex'),
|
||||||
|
});
|
||||||
|
} else if (_.isObject(buf)) {
|
||||||
var obj = buf;
|
var obj = buf;
|
||||||
this.set(obj);
|
this.set(obj);
|
||||||
|
} else {
|
||||||
|
throw new TypeError('Unrecognized argument for BufferReader');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -99,7 +99,7 @@ Script.fromBuffer = function(buffer) {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof RangeError) {
|
if (e instanceof RangeError) {
|
||||||
throw new errors.Script.InvalidBuffer(buffer);
|
throw new errors.Script.InvalidBuffer(buffer.toString('hex'));
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
@ -778,13 +778,6 @@ Script.prototype.toAddress = function(network) {
|
|||||||
return new Address(info);
|
return new Address(info);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {Script}
|
|
||||||
*/
|
|
||||||
Script.prototype.toScriptHashOut = function() {
|
|
||||||
return Script.buildScriptHashOut(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Analagous to bitcoind's FindAndDelete. Find and delete equivalent chunks,
|
* Analagous to bitcoind's FindAndDelete. Find and delete equivalent chunks,
|
||||||
* typically used with push data chunks. Note that this will find and delete
|
* typically used with push data chunks. Note that this will find and delete
|
||||||
|
|||||||
@ -30,6 +30,9 @@ Object.defineProperty(Input.prototype, 'script', {
|
|||||||
writeable: false,
|
writeable: false,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
get: function() {
|
get: function() {
|
||||||
|
if (this.isNull()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (!this._script) {
|
if (!this._script) {
|
||||||
this._script = new Script(this._scriptBuffer);
|
this._script = new Script(this._scriptBuffer);
|
||||||
}
|
}
|
||||||
@ -59,8 +62,12 @@ Input.prototype.toObject = function toObject() {
|
|||||||
prevTxId: this.prevTxId.toString('hex'),
|
prevTxId: this.prevTxId.toString('hex'),
|
||||||
outputIndex: this.outputIndex,
|
outputIndex: this.outputIndex,
|
||||||
sequenceNumber: this.sequenceNumber,
|
sequenceNumber: this.sequenceNumber,
|
||||||
script: this.script.toString(),
|
script: this._scriptBuffer.toString('hex'),
|
||||||
};
|
};
|
||||||
|
// add human readable form if input contains valid script
|
||||||
|
if (this.script) {
|
||||||
|
obj.scriptString = this.script.toString();
|
||||||
|
}
|
||||||
if (this.output) {
|
if (this.output) {
|
||||||
obj.output = this.output.toObject();
|
obj.output = this.output.toObject();
|
||||||
}
|
}
|
||||||
@ -88,6 +95,8 @@ Input.fromBufferReader = function(br) {
|
|||||||
input.outputIndex = br.readUInt32LE();
|
input.outputIndex = br.readUInt32LE();
|
||||||
input._scriptBuffer = br.readVarLengthBuffer();
|
input._scriptBuffer = br.readVarLengthBuffer();
|
||||||
input.sequenceNumber = br.readUInt32LE();
|
input.sequenceNumber = br.readUInt32LE();
|
||||||
|
// TODO: return different classes according to which input it is
|
||||||
|
// e.g: CoinbaseInput, PublicKeyHashInput, MultiSigScriptHashInput, etc.
|
||||||
return input;
|
return input;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -105,14 +114,19 @@ Input.prototype.toBufferWriter = function(writer) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Input.prototype.setScript = function(script) {
|
Input.prototype.setScript = function(script) {
|
||||||
|
this._script = null;
|
||||||
if (script instanceof Script) {
|
if (script instanceof Script) {
|
||||||
this._script = script;
|
this._script = script;
|
||||||
this._scriptBuffer = script.toBuffer();
|
this._scriptBuffer = script.toBuffer();
|
||||||
|
} else if (JSUtil.isHexa(script)) {
|
||||||
|
// hex string script
|
||||||
|
this._scriptBuffer = new Buffer(script, 'hex');
|
||||||
} else if (_.isString(script)) {
|
} else if (_.isString(script)) {
|
||||||
|
// human readable string script
|
||||||
this._script = new Script(script);
|
this._script = new Script(script);
|
||||||
this._scriptBuffer = this._script.toBuffer();
|
this._scriptBuffer = this._script.toBuffer();
|
||||||
} else if (BufferUtil.isBuffer(script)) {
|
} else if (BufferUtil.isBuffer(script)) {
|
||||||
this._script = null;
|
// buffer script
|
||||||
this._scriptBuffer = new buffer.Buffer(script);
|
this._scriptBuffer = new buffer.Buffer(script);
|
||||||
} else {
|
} else {
|
||||||
throw new TypeError('Invalid argument type: script');
|
throw new TypeError('Invalid argument type: script');
|
||||||
|
|||||||
@ -1017,7 +1017,7 @@ Transaction.prototype.verify = function() {
|
|||||||
|
|
||||||
var isCoinbase = this.isCoinbase();
|
var isCoinbase = this.isCoinbase();
|
||||||
if (isCoinbase) {
|
if (isCoinbase) {
|
||||||
var buf = this.inputs[0]._script.toBuffer();
|
var buf = this.inputs[0]._scriptBuffer;
|
||||||
if (buf.length < 2 || buf.length > 100) {
|
if (buf.length < 2 || buf.length > 100) {
|
||||||
return 'coinbase transaction script size invalid';
|
return 'coinbase transaction script size invalid';
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -21,6 +21,12 @@ describe('BufferReader', function() {
|
|||||||
should.exist(br);
|
should.exist(br);
|
||||||
Buffer.isBuffer(br.buf).should.equal(true);
|
Buffer.isBuffer(br.buf).should.equal(true);
|
||||||
});
|
});
|
||||||
|
it('should fail for invalid object', function() {
|
||||||
|
var fail = function() {
|
||||||
|
return new BufferReader(5);
|
||||||
|
};
|
||||||
|
fail.should.throw('Unrecognized argument for BufferReader');
|
||||||
|
});
|
||||||
|
|
||||||
describe('#set', function() {
|
describe('#set', function() {
|
||||||
|
|
||||||
|
|||||||
@ -196,9 +196,6 @@ describe('Interpreter', function() {
|
|||||||
var scriptPubkey = Script.fromBitcoindString(vector[1]);
|
var scriptPubkey = Script.fromBitcoindString(vector[1]);
|
||||||
var flags = getFlags(vector[2]);
|
var flags = getFlags(vector[2]);
|
||||||
|
|
||||||
//testToFromString(scriptSig);
|
|
||||||
//testToFromString(scriptPubkey);
|
|
||||||
|
|
||||||
var hashbuf = new Buffer(32);
|
var hashbuf = new Buffer(32);
|
||||||
hashbuf.fill(0);
|
hashbuf.fill(0);
|
||||||
var credtx = new Transaction();
|
var credtx = new Transaction();
|
||||||
@ -242,7 +239,8 @@ describe('Interpreter', function() {
|
|||||||
var fullScriptString = vector[0] + ' ' + vector[1];
|
var fullScriptString = vector[0] + ' ' + vector[1];
|
||||||
var comment = descstr ? (' (' + descstr + ')') : '';
|
var comment = descstr ? (' (' + descstr + ')') : '';
|
||||||
it('should pass script_' + (expected ? '' : 'in') + 'valid ' +
|
it('should pass script_' + (expected ? '' : 'in') + 'valid ' +
|
||||||
'vector #' + c + ': ' + fullScriptString + comment, function() {
|
'vector #' + c + ': ' + fullScriptString + comment,
|
||||||
|
function() {
|
||||||
testFixture(vector, expected);
|
testFixture(vector, expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -279,12 +277,15 @@ describe('Interpreter', function() {
|
|||||||
var tx = new Transaction(txhex);
|
var tx = new Transaction(txhex);
|
||||||
var allInputsVerified = true;
|
var allInputsVerified = true;
|
||||||
tx.inputs.forEach(function(txin, j) {
|
tx.inputs.forEach(function(txin, j) {
|
||||||
|
if (txin.isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
var scriptSig = txin.script;
|
var scriptSig = txin.script;
|
||||||
var txidhex = txin.prevTxId.toString('hex');
|
var txidhex = txin.prevTxId.toString('hex');
|
||||||
var txoutnum = txin.outputIndex;
|
var txoutnum = txin.outputIndex;
|
||||||
var scriptPubkey = map[txidhex + ':' + txoutnum];
|
var scriptPubkey = map[txidhex + ':' + txoutnum];
|
||||||
should.exist(scriptPubkey);
|
should.exist(scriptPubkey);
|
||||||
should.exist(scriptSig);
|
(scriptSig !== undefined).should.equal(true);
|
||||||
var interp = new Interpreter();
|
var interp = new Interpreter();
|
||||||
var verified = interp.verify(scriptSig, scriptPubkey, tx, j, flags);
|
var verified = interp.verify(scriptSig, scriptPubkey, tx, j, flags);
|
||||||
if (!verified) {
|
if (!verified) {
|
||||||
|
|||||||
@ -11,8 +11,6 @@ var Opcode = bitcore.Opcode;
|
|||||||
var PublicKey = bitcore.PublicKey;
|
var PublicKey = bitcore.PublicKey;
|
||||||
var Address = bitcore.Address;
|
var Address = bitcore.Address;
|
||||||
|
|
||||||
var script_valid = require('../data/bitcoind/script_valid');
|
|
||||||
|
|
||||||
describe('Script', function() {
|
describe('Script', function() {
|
||||||
|
|
||||||
it('should make a new script', function() {
|
it('should make a new script', function() {
|
||||||
@ -328,11 +326,16 @@ describe('Script', function() {
|
|||||||
|
|
||||||
describe('#isScripthashOut', function() {
|
describe('#isScripthashOut', function() {
|
||||||
|
|
||||||
it('should identify this known pubkeyhashout as pubkeyhashout', function() {
|
it('should identify this known p2shout as p2shout', function() {
|
||||||
Script('OP_HASH160 20 0x0000000000000000000000000000000000000000 OP_EQUAL').isScriptHashOut().should.equal(true);
|
Script('OP_HASH160 20 0x0000000000000000000000000000000000000000 OP_EQUAL').isScriptHashOut().should.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should identify these known non-pubkeyhashout as not pubkeyhashout', function() {
|
it('should identify result of .isScriptHashOut() as p2sh', function() {
|
||||||
|
Script('OP_DUP OP_HASH160 20 0x0000000000000000000000000000000000000000 OP_EQUALVERIFY OP_CHECKSIG')
|
||||||
|
.toScriptHashOut().isScriptHashOut().should.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should identify these known non-p2shout as not p2shout', function() {
|
||||||
Script('OP_HASH160 20 0x0000000000000000000000000000000000000000 OP_EQUAL OP_EQUAL').isScriptHashOut().should.equal(false);
|
Script('OP_HASH160 20 0x0000000000000000000000000000000000000000 OP_EQUAL OP_EQUAL').isScriptHashOut().should.equal(false);
|
||||||
Script('OP_HASH160 21 0x000000000000000000000000000000000000000000 OP_EQUAL').isScriptHashOut().should.equal(false);
|
Script('OP_HASH160 21 0x000000000000000000000000000000000000000000 OP_EQUAL').isScriptHashOut().should.equal(false);
|
||||||
});
|
});
|
||||||
@ -755,4 +758,5 @@ describe('Script', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -73,7 +73,6 @@ describe('Transaction.Input', function() {
|
|||||||
it('fromObject should work', function() {
|
it('fromObject should work', function() {
|
||||||
var input = Input.fromJSON(coinbaseJSON);
|
var input = Input.fromJSON(coinbaseJSON);
|
||||||
var obj = input.toObject();
|
var obj = input.toObject();
|
||||||
obj.script = new Buffer(obj.script, 'hex');
|
|
||||||
Input.fromObject(obj).should.deep.equal(input);
|
Input.fromObject(obj).should.deep.equal(input);
|
||||||
obj.script = 42;
|
obj.script = 42;
|
||||||
Input.fromObject.bind(null, obj).should.throw('Invalid argument type: script');
|
Input.fromObject.bind(null, obj).should.throw('Invalid argument type: script');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user