Merge pull request #712 from maraoz/refactor/script
Refactor Script and other small stuff
This commit is contained in:
commit
0a0895a987
7
index.js
7
index.js
|
@ -23,6 +23,7 @@ bitcore.util = {};
|
||||||
bitcore.util.bitcoin = require('./lib/util/bitcoin');
|
bitcore.util.bitcoin = require('./lib/util/bitcoin');
|
||||||
bitcore.util.buffer = require('./lib/util/buffer');
|
bitcore.util.buffer = require('./lib/util/buffer');
|
||||||
bitcore.util.js = require('./lib/util/js');
|
bitcore.util.js = require('./lib/util/js');
|
||||||
|
bitcore.util.preconditions = require('./lib/util/preconditions');
|
||||||
|
|
||||||
// transport
|
// transport
|
||||||
bitcore.transport = {};
|
bitcore.transport = {};
|
||||||
|
@ -55,11 +56,5 @@ bitcore.deps.bs58 = require('bs58');
|
||||||
bitcore.deps.Buffer = Buffer;
|
bitcore.deps.Buffer = Buffer;
|
||||||
bitcore.deps.elliptic = require('elliptic');
|
bitcore.deps.elliptic = require('elliptic');
|
||||||
|
|
||||||
//bitcore.scriptexec = require('lib/scriptexec');
|
|
||||||
//bitcore.tx = require('lib/tx');
|
|
||||||
//bitcore.txpartial = require('lib/txpartial');
|
|
||||||
|
|
||||||
//bitcore.bip70 = require('lib/bip70');
|
|
||||||
|
|
||||||
// Internal usage, exposed for testing/advanced tweaking
|
// Internal usage, exposed for testing/advanced tweaking
|
||||||
bitcore._HDKeyCache = require('./lib/hdkeycache');
|
bitcore._HDKeyCache = require('./lib/hdkeycache');
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
|
var $ = require('./util/preconditions');
|
||||||
|
|
||||||
function Opcode(num) {
|
function Opcode(num) {
|
||||||
if (!(this instanceof Opcode)) {
|
if (!(this instanceof Opcode)) {
|
||||||
|
@ -19,11 +20,13 @@ function Opcode(num) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Opcode.prototype.set = function(obj) {
|
Opcode.prototype.set = function(obj) {
|
||||||
|
$.checkArgument(_.isObject(obj));
|
||||||
this.num = typeof obj.num !== 'undefined' ? obj.num : this.num;
|
this.num = typeof obj.num !== 'undefined' ? obj.num : this.num;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
Opcode.prototype.fromNumber = function(num) {
|
Opcode.prototype.fromNumber = function(num) {
|
||||||
|
$.checkArgument(_.isNumber(num));
|
||||||
this.num = num;
|
this.num = num;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
@ -33,9 +36,11 @@ Opcode.prototype.toNumber = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
Opcode.prototype.fromString = function(str) {
|
Opcode.prototype.fromString = function(str) {
|
||||||
|
$.checkArgument(_.isString(str));
|
||||||
var num = Opcode.map[str];
|
var num = Opcode.map[str];
|
||||||
if (typeof num === 'undefined')
|
if (typeof num === 'undefined') {
|
||||||
throw new Error('Invalid opcodestr');
|
throw new Error('Invalid opcodestr');
|
||||||
|
}
|
||||||
this.num = num;
|
this.num = num;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
@ -49,9 +54,7 @@ Opcode.prototype.toString = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
Opcode.smallInt = function(n) {
|
Opcode.smallInt = function(n) {
|
||||||
if (!(n >= 0 && n <= 16)) {
|
$.checkArgument(n >= 0 && n <= 16, 'Invalid Argument: n must be between 0 and 16');
|
||||||
throw new Error('Invalid Argument: n must be between 0 and 16');
|
|
||||||
}
|
|
||||||
if (n === 0) {
|
if (n === 0) {
|
||||||
return Opcode('OP_0');
|
return Opcode('OP_0');
|
||||||
}
|
}
|
||||||
|
|
141
lib/script.js
141
lib/script.js
|
@ -55,14 +55,14 @@ Script.fromBuffer = function(buffer) {
|
||||||
var opcodenum = br.readUInt8();
|
var opcodenum = br.readUInt8();
|
||||||
|
|
||||||
var len, buf;
|
var len, buf;
|
||||||
if (opcodenum > 0 && opcodenum < Opcode.map.OP_PUSHDATA1) {
|
if (opcodenum > 0 && opcodenum < Opcode.OP_PUSHDATA1) {
|
||||||
len = opcodenum;
|
len = opcodenum;
|
||||||
script.chunks.push({
|
script.chunks.push({
|
||||||
buf: br.read(len),
|
buf: br.read(len),
|
||||||
len: len,
|
len: len,
|
||||||
opcodenum: opcodenum
|
opcodenum: opcodenum
|
||||||
});
|
});
|
||||||
} else if (opcodenum === Opcode.map.OP_PUSHDATA1) {
|
} else if (opcodenum === Opcode.OP_PUSHDATA1) {
|
||||||
len = br.readUInt8();
|
len = br.readUInt8();
|
||||||
buf = br.read(len);
|
buf = br.read(len);
|
||||||
script.chunks.push({
|
script.chunks.push({
|
||||||
|
@ -70,7 +70,7 @@ Script.fromBuffer = function(buffer) {
|
||||||
len: len,
|
len: len,
|
||||||
opcodenum: opcodenum
|
opcodenum: opcodenum
|
||||||
});
|
});
|
||||||
} else if (opcodenum === Opcode.map.OP_PUSHDATA2) {
|
} else if (opcodenum === Opcode.OP_PUSHDATA2) {
|
||||||
len = br.readUInt16LE();
|
len = br.readUInt16LE();
|
||||||
buf = br.read(len);
|
buf = br.read(len);
|
||||||
script.chunks.push({
|
script.chunks.push({
|
||||||
|
@ -78,7 +78,7 @@ Script.fromBuffer = function(buffer) {
|
||||||
len: len,
|
len: len,
|
||||||
opcodenum: opcodenum
|
opcodenum: opcodenum
|
||||||
});
|
});
|
||||||
} else if (opcodenum === Opcode.map.OP_PUSHDATA4) {
|
} else if (opcodenum === Opcode.OP_PUSHDATA4) {
|
||||||
len = br.readUInt32LE();
|
len = br.readUInt32LE();
|
||||||
buf = br.read(len);
|
buf = br.read(len);
|
||||||
script.chunks.push({
|
script.chunks.push({
|
||||||
|
@ -87,7 +87,9 @@ Script.fromBuffer = function(buffer) {
|
||||||
opcodenum: opcodenum
|
opcodenum: opcodenum
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
script.chunks.push(opcodenum);
|
script.chunks.push({
|
||||||
|
opcodenum: opcodenum
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,22 +101,18 @@ Script.prototype.toBuffer = function() {
|
||||||
|
|
||||||
for (var i = 0; i < this.chunks.length; i++) {
|
for (var i = 0; i < this.chunks.length; i++) {
|
||||||
var chunk = this.chunks[i];
|
var chunk = this.chunks[i];
|
||||||
var opcodenum;
|
var opcodenum = chunk.opcodenum;
|
||||||
if (typeof chunk === 'number') {
|
bw.writeUInt8(chunk.opcodenum);
|
||||||
opcodenum = chunk;
|
if (chunk.buf) {
|
||||||
bw.writeUInt8(opcodenum);
|
if (opcodenum < Opcode.OP_PUSHDATA1) {
|
||||||
} else {
|
|
||||||
opcodenum = chunk.opcodenum;
|
|
||||||
bw.writeUInt8(chunk.opcodenum);
|
|
||||||
if (opcodenum < Opcode.map.OP_PUSHDATA1) {
|
|
||||||
bw.write(chunk.buf);
|
bw.write(chunk.buf);
|
||||||
} else if (opcodenum === Opcode.map.OP_PUSHDATA1) {
|
} else if (opcodenum === Opcode.OP_PUSHDATA1) {
|
||||||
bw.writeUInt8(chunk.len);
|
bw.writeUInt8(chunk.len);
|
||||||
bw.write(chunk.buf);
|
bw.write(chunk.buf);
|
||||||
} else if (opcodenum === Opcode.map.OP_PUSHDATA2) {
|
} else if (opcodenum === Opcode.OP_PUSHDATA2) {
|
||||||
bw.writeUInt16LE(chunk.len);
|
bw.writeUInt16LE(chunk.len);
|
||||||
bw.write(chunk.buf);
|
bw.write(chunk.buf);
|
||||||
} else if (opcodenum === Opcode.map.OP_PUSHDATA4) {
|
} else if (opcodenum === Opcode.OP_PUSHDATA4) {
|
||||||
bw.writeUInt32LE(chunk.len);
|
bw.writeUInt32LE(chunk.len);
|
||||||
bw.write(chunk.buf);
|
bw.write(chunk.buf);
|
||||||
}
|
}
|
||||||
|
@ -140,7 +138,7 @@ Script.fromString = function(str) {
|
||||||
|
|
||||||
if (typeof opcodenum === 'undefined') {
|
if (typeof opcodenum === 'undefined') {
|
||||||
opcodenum = parseInt(token);
|
opcodenum = parseInt(token);
|
||||||
if (opcodenum > 0 && opcodenum < Opcode.map.OP_PUSHDATA1) {
|
if (opcodenum > 0 && opcodenum < Opcode.OP_PUSHDATA1) {
|
||||||
script.chunks.push({
|
script.chunks.push({
|
||||||
buf: new Buffer(tokens[i + 1].slice(2), 'hex'),
|
buf: new Buffer(tokens[i + 1].slice(2), 'hex'),
|
||||||
len: opcodenum,
|
len: opcodenum,
|
||||||
|
@ -150,9 +148,9 @@ Script.fromString = function(str) {
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Invalid script: ' + JSON.stringify(str));
|
throw new Error('Invalid script: ' + JSON.stringify(str));
|
||||||
}
|
}
|
||||||
} else if (opcodenum === Opcode.map.OP_PUSHDATA1 ||
|
} else if (opcodenum === Opcode.OP_PUSHDATA1 ||
|
||||||
opcodenum === Opcode.map.OP_PUSHDATA2 ||
|
opcodenum === Opcode.OP_PUSHDATA2 ||
|
||||||
opcodenum === Opcode.map.OP_PUSHDATA4) {
|
opcodenum === Opcode.OP_PUSHDATA4) {
|
||||||
if (tokens[i + 2].slice(0, 2) !== '0x') {
|
if (tokens[i + 2].slice(0, 2) !== '0x') {
|
||||||
throw new Error('Pushdata data must start with 0x');
|
throw new Error('Pushdata data must start with 0x');
|
||||||
}
|
}
|
||||||
|
@ -163,7 +161,9 @@ Script.fromString = function(str) {
|
||||||
});
|
});
|
||||||
i = i + 3;
|
i = i + 3;
|
||||||
} else {
|
} else {
|
||||||
script.chunks.push(opcodenum);
|
script.chunks.push({
|
||||||
|
opcodenum: opcodenum
|
||||||
|
});
|
||||||
i = i + 1;
|
i = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,23 +175,25 @@ Script.prototype.toString = function() {
|
||||||
|
|
||||||
for (var i = 0; i < this.chunks.length; i++) {
|
for (var i = 0; i < this.chunks.length; i++) {
|
||||||
var chunk = this.chunks[i];
|
var chunk = this.chunks[i];
|
||||||
var opcodenum;
|
var opcodenum = chunk.opcodenum;
|
||||||
if (typeof chunk === 'number') {
|
if (!chunk.buf) {
|
||||||
opcodenum = chunk;
|
if (typeof Opcode.reverseMap[opcodenum] !== 'undefined') {
|
||||||
str = str + Opcode(opcodenum).toString() + ' ';
|
str = str + ' ' + Opcode(opcodenum).toString();
|
||||||
} else {
|
} else {
|
||||||
opcodenum = chunk.opcodenum;
|
str = str + ' ' + '0x' + opcodenum.toString(16);
|
||||||
if (opcodenum === Opcode.map.OP_PUSHDATA1 ||
|
|
||||||
opcodenum === Opcode.map.OP_PUSHDATA2 ||
|
|
||||||
opcodenum === Opcode.map.OP_PUSHDATA4) {
|
|
||||||
str = str + Opcode(opcodenum).toString() + ' ';
|
|
||||||
}
|
}
|
||||||
str = str + chunk.len + ' ';
|
} else {
|
||||||
str = str + '0x' + chunk.buf.toString('hex') + ' ';
|
if (opcodenum === Opcode.OP_PUSHDATA1 ||
|
||||||
|
opcodenum === Opcode.OP_PUSHDATA2 ||
|
||||||
|
opcodenum === Opcode.OP_PUSHDATA4) {
|
||||||
|
str = str + ' ' + Opcode(opcodenum).toString();
|
||||||
|
}
|
||||||
|
str = str + ' ' + chunk.len;
|
||||||
|
str = str + ' ' + '0x' + chunk.buf.toString('hex');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return str.substr(0, str.length - 1);
|
return str.substr(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
// script classification methods
|
// script classification methods
|
||||||
|
@ -200,23 +202,23 @@ Script.prototype.toString = function() {
|
||||||
* @returns true if this is a pay to pubkey hash output script
|
* @returns true if this is a pay to pubkey hash output script
|
||||||
*/
|
*/
|
||||||
Script.prototype.isPublicKeyHashOut = function() {
|
Script.prototype.isPublicKeyHashOut = function() {
|
||||||
return this.chunks[0] === Opcode('OP_DUP').toNumber() &&
|
return !!(this.chunks.length === 5 &&
|
||||||
this.chunks[1] === Opcode('OP_HASH160').toNumber() &&
|
this.chunks[0].opcodenum === Opcode.OP_DUP &&
|
||||||
|
this.chunks[1].opcodenum === Opcode.OP_HASH160 &&
|
||||||
this.chunks[2].buf &&
|
this.chunks[2].buf &&
|
||||||
this.chunks[3] === Opcode('OP_EQUALVERIFY').toNumber() &&
|
this.chunks[3].opcodenum === Opcode.OP_EQUALVERIFY &&
|
||||||
this.chunks[4] === Opcode('OP_CHECKSIG').toNumber();
|
this.chunks[4].opcodenum === Opcode.OP_CHECKSIG);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns true if this is a pay to public key hash input script
|
* @returns true if this is a pay to public key hash input script
|
||||||
*/
|
*/
|
||||||
Script.prototype.isPublicKeyHashIn = function() {
|
Script.prototype.isPublicKeyHashIn = function() {
|
||||||
return !!(this.chunks.length === 2 &&
|
return this.chunks.length === 2 &&
|
||||||
this.chunks[0].buf &&
|
this.chunks[0].buf &&
|
||||||
this.chunks[0].buf.length >= 0x47 &&
|
this.chunks[0].buf.length >= 0x47 &&
|
||||||
this.chunks[0].buf.length <= 0x49 &&
|
this.chunks[0].buf.length <= 0x49 &&
|
||||||
this.chunks[1].buf &&
|
PublicKey.isValid(this.chunks[1].buf);
|
||||||
PublicKey.isValid(this.chunks[1].buf));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -226,7 +228,7 @@ Script.prototype.isPublicKeyOut = function() {
|
||||||
return this.chunks.length === 2 &&
|
return this.chunks.length === 2 &&
|
||||||
bufferUtil.isBuffer(this.chunks[0].buf) &&
|
bufferUtil.isBuffer(this.chunks[0].buf) &&
|
||||||
PublicKey.isValid(this.chunks[0].buf) &&
|
PublicKey.isValid(this.chunks[0].buf) &&
|
||||||
this.chunks[1] === Opcode('OP_CHECKSIG').toNumber();
|
this.chunks[1].opcodenum === Opcode.OP_CHECKSIG;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -244,10 +246,10 @@ Script.prototype.isPublicKeyIn = function() {
|
||||||
*/
|
*/
|
||||||
Script.prototype.isScriptHashOut = function() {
|
Script.prototype.isScriptHashOut = function() {
|
||||||
return this.chunks.length === 3 &&
|
return this.chunks.length === 3 &&
|
||||||
this.chunks[0] === Opcode('OP_HASH160').toNumber() &&
|
this.chunks[0].opcodenum === Opcode.OP_HASH160 &&
|
||||||
this.chunks[1].buf &&
|
this.chunks[1].buf &&
|
||||||
this.chunks[1].buf.length === 20 &&
|
this.chunks[1].buf.length === 20 &&
|
||||||
this.chunks[2] === Opcode('OP_EQUAL').toNumber();
|
this.chunks[2].opcodenum === Opcode.OP_EQUAL;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -276,20 +278,21 @@ Script.prototype.isScriptHashIn = function() {
|
||||||
*/
|
*/
|
||||||
Script.prototype.isMultisigOut = function() {
|
Script.prototype.isMultisigOut = function() {
|
||||||
return (this.chunks.length > 3 &&
|
return (this.chunks.length > 3 &&
|
||||||
Opcode.isSmallIntOp(this.chunks[0]) &&
|
Opcode.isSmallIntOp(this.chunks[0].opcodenum) &&
|
||||||
this.chunks.slice(1, this.chunks.length - 2).every(function(obj) {
|
this.chunks.slice(1, this.chunks.length - 2).every(function(obj) {
|
||||||
return obj.buf && bufferUtil.isBuffer(obj.buf);
|
return obj.buf && bufferUtil.isBuffer(obj.buf);
|
||||||
}) &&
|
}) &&
|
||||||
Opcode.isSmallIntOp(this.chunks[this.chunks.length - 2]) &&
|
Opcode.isSmallIntOp(this.chunks[this.chunks.length - 2].opcodenum) &&
|
||||||
this.chunks[this.chunks.length - 1] === Opcode.map.OP_CHECKMULTISIG);
|
this.chunks[this.chunks.length - 1].opcodenum === Opcode.OP_CHECKMULTISIG);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns true if this is a mutlsig input script
|
* @returns true if this is a multisig input script
|
||||||
*/
|
*/
|
||||||
Script.prototype.isMultisigIn = function() {
|
Script.prototype.isMultisigIn = function() {
|
||||||
return this.chunks[0] === 0 &&
|
return this.chunks.length >= 2 &&
|
||||||
|
this.chunks[0].opcodenum === 0 &&
|
||||||
this.chunks.slice(1, this.chunks.length).every(function(obj) {
|
this.chunks.slice(1, this.chunks.length).every(function(obj) {
|
||||||
return obj.buf &&
|
return obj.buf &&
|
||||||
bufferUtil.isBuffer(obj.buf) &&
|
bufferUtil.isBuffer(obj.buf) &&
|
||||||
|
@ -301,12 +304,13 @@ Script.prototype.isMultisigIn = function() {
|
||||||
* @returns true if this is an OP_RETURN data script
|
* @returns true if this is an OP_RETURN data script
|
||||||
*/
|
*/
|
||||||
Script.prototype.isDataOut = function() {
|
Script.prototype.isDataOut = function() {
|
||||||
return (this.chunks[0] === Opcode('OP_RETURN').toNumber() &&
|
return this.chunks.length >= 1 &&
|
||||||
|
this.chunks[0].opcodenum === Opcode.OP_RETURN &&
|
||||||
(this.chunks.length === 1 ||
|
(this.chunks.length === 1 ||
|
||||||
(this.chunks.length === 2 &&
|
(this.chunks.length === 2 &&
|
||||||
this.chunks[1].buf &&
|
this.chunks[1].buf &&
|
||||||
this.chunks[1].buf.length <= 40 &&
|
this.chunks[1].buf.length <= 40 &&
|
||||||
this.chunks[1].length === this.chunks.len)));
|
this.chunks[1].length === this.chunks.len));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -315,8 +319,7 @@ Script.prototype.isDataOut = function() {
|
||||||
*/
|
*/
|
||||||
Script.prototype.isPushOnly = function() {
|
Script.prototype.isPushOnly = function() {
|
||||||
return _.every(this.chunks, function(chunk) {
|
return _.every(this.chunks, function(chunk) {
|
||||||
var opcodenum = chunk.opcodenum;
|
return chunk.opcodenum <= Opcode.OP_16;
|
||||||
return !_.isUndefined(opcodenum) || chunk <= Opcode.map.OP_16;
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -424,7 +427,9 @@ Script.prototype._addOpcode = function(opcode, prepend) {
|
||||||
} else {
|
} else {
|
||||||
op = Opcode(opcode).toNumber();
|
op = Opcode(opcode).toNumber();
|
||||||
}
|
}
|
||||||
this._insertAtPosition(op, prepend);
|
this._insertAtPosition({
|
||||||
|
opcodenum: op
|
||||||
|
}, prepend);
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -433,14 +438,14 @@ Script.prototype._addBuffer = function(buf, prepend) {
|
||||||
var len = buf.length;
|
var len = buf.length;
|
||||||
if (len === 0) {
|
if (len === 0) {
|
||||||
return;
|
return;
|
||||||
} else if (len > 0 && len < Opcode.map.OP_PUSHDATA1) {
|
} else if (len > 0 && len < Opcode.OP_PUSHDATA1) {
|
||||||
opcodenum = len;
|
opcodenum = len;
|
||||||
} else if (len < Math.pow(2, 8)) {
|
} else if (len < Math.pow(2, 8)) {
|
||||||
opcodenum = Opcode.map.OP_PUSHDATA1;
|
opcodenum = Opcode.OP_PUSHDATA1;
|
||||||
} else if (len < Math.pow(2, 16)) {
|
} else if (len < Math.pow(2, 16)) {
|
||||||
opcodenum = Opcode.map.OP_PUSHDATA2;
|
opcodenum = Opcode.OP_PUSHDATA2;
|
||||||
} else if (len < Math.pow(2, 32)) {
|
} else if (len < Math.pow(2, 32)) {
|
||||||
opcodenum = Opcode.map.OP_PUSHDATA4;
|
opcodenum = Opcode.OP_PUSHDATA4;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('You can\'t push that much data');
|
throw new Error('You can\'t push that much data');
|
||||||
}
|
}
|
||||||
|
@ -455,7 +460,7 @@ Script.prototype._addBuffer = function(buf, prepend) {
|
||||||
Script.prototype.removeCodeseparators = function() {
|
Script.prototype.removeCodeseparators = function() {
|
||||||
var chunks = [];
|
var chunks = [];
|
||||||
for (var i = 0; i < this.chunks.length; i++) {
|
for (var i = 0; i < this.chunks.length; i++) {
|
||||||
if (this.chunks[i] !== Opcode.OP_CODESEPARATOR) {
|
if (this.chunks[i].opcodenum !== Opcode.OP_CODESEPARATOR) {
|
||||||
chunks.push(this.chunks[i]);
|
chunks.push(this.chunks[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -489,7 +494,7 @@ Script.buildMultisigOut = function(pubkeys, m, opts) {
|
||||||
s.add(pubkey.toBuffer());
|
s.add(pubkey.toBuffer());
|
||||||
}
|
}
|
||||||
s.add(Opcode.smallInt(pubkeys.length));
|
s.add(Opcode.smallInt(pubkeys.length));
|
||||||
s.add(Opcode('OP_CHECKMULTISIG'));
|
s.add(Opcode.OP_CHECKMULTISIG);
|
||||||
return s;
|
return s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -505,11 +510,11 @@ Script.buildPublicKeyHashOut = function(to) {
|
||||||
to = new Address(to);
|
to = new Address(to);
|
||||||
}
|
}
|
||||||
var s = new Script();
|
var s = new Script();
|
||||||
s.add(Opcode('OP_DUP'))
|
s.add(Opcode.OP_DUP)
|
||||||
.add(Opcode('OP_HASH160'))
|
.add(Opcode.OP_HASH160)
|
||||||
.add(to.hashBuffer)
|
.add(to.hashBuffer)
|
||||||
.add(Opcode('OP_EQUALVERIFY'))
|
.add(Opcode.OP_EQUALVERIFY)
|
||||||
.add(Opcode('OP_CHECKSIG'));
|
.add(Opcode.OP_CHECKSIG);
|
||||||
return s;
|
return s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -520,7 +525,7 @@ Script.buildPublicKeyHashOut = function(to) {
|
||||||
Script.buildPublicKeyOut = function(pubkey) {
|
Script.buildPublicKeyOut = function(pubkey) {
|
||||||
var s = new Script();
|
var s = new Script();
|
||||||
s.add(pubkey.toBuffer())
|
s.add(pubkey.toBuffer())
|
||||||
.add(Opcode('OP_CHECKSIG'));
|
.add(Opcode.OP_CHECKSIG);
|
||||||
return s;
|
return s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -533,7 +538,7 @@ Script.buildDataOut = function(data) {
|
||||||
data = new Buffer(data);
|
data = new Buffer(data);
|
||||||
}
|
}
|
||||||
var s = new Script();
|
var s = new Script();
|
||||||
s.add(Opcode('OP_RETURN'))
|
s.add(Opcode.OP_RETURN)
|
||||||
.add(data);
|
.add(data);
|
||||||
return s;
|
return s;
|
||||||
};
|
};
|
||||||
|
@ -544,9 +549,9 @@ Script.buildDataOut = function(data) {
|
||||||
*/
|
*/
|
||||||
Script.buildScriptHashOut = function(script) {
|
Script.buildScriptHashOut = function(script) {
|
||||||
var s = new Script();
|
var s = new Script();
|
||||||
s.add(Opcode('OP_HASH160'))
|
s.add(Opcode.OP_HASH160)
|
||||||
.add(Hash.sha256ripemd160(script.toBuffer()))
|
.add(Hash.sha256ripemd160(script.toBuffer()))
|
||||||
.add(Opcode('OP_EQUAL'));
|
.add(Opcode.OP_EQUAL);
|
||||||
return s;
|
return s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -25,52 +25,61 @@ describe('Opcode', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#fromNumber', function() {
|
describe('#fromNumber', function() {
|
||||||
|
|
||||||
it('should work for 0', function() {
|
it('should work for 0', function() {
|
||||||
Opcode().fromNumber(0).num.should.equal(0);
|
Opcode().fromNumber(0).num.should.equal(0);
|
||||||
});
|
});
|
||||||
|
it('should fail for non-number', function() {
|
||||||
|
Opcode().fromNumber.bind(null, 'a string').should.throw('Invalid Argument');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#set', function() {
|
||||||
|
it('should work for object', function() {
|
||||||
|
Opcode().set({
|
||||||
|
num: 42
|
||||||
|
}).num.should.equal(42);
|
||||||
|
});
|
||||||
|
it('should fail for non-object', function() {
|
||||||
|
Opcode().set.bind(null, 'non-object').should.throw('Invalid Argument');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#toNumber', function() {
|
describe('#toNumber', function() {
|
||||||
|
|
||||||
it('should work for 0', function() {
|
it('should work for 0', function() {
|
||||||
Opcode().fromNumber(0).toNumber().should.equal(0);
|
Opcode().fromNumber(0).toNumber().should.equal(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#fromString', function() {
|
describe('#fromString', function() {
|
||||||
|
|
||||||
it('should work for OP_0', function() {
|
it('should work for OP_0', function() {
|
||||||
Opcode().fromString('OP_0').num.should.equal(0);
|
Opcode().fromString('OP_0').num.should.equal(0);
|
||||||
});
|
});
|
||||||
|
it('should fail for invalid string', function() {
|
||||||
|
Opcode().fromString.bind(null, 'OP_SATOSHI').should.throw('Invalid opcodestr');
|
||||||
|
Opcode().fromString.bind(null, 'BANANA').should.throw('Invalid opcodestr');
|
||||||
|
});
|
||||||
|
it('should fail for non-string', function() {
|
||||||
|
Opcode().fromString.bind(null, 123).should.throw('Invalid Argument');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#toString', function() {
|
describe('#toString', function() {
|
||||||
|
|
||||||
it('should work for OP_0', function() {
|
it('should work for OP_0', function() {
|
||||||
Opcode().fromString('OP_0').toString().should.equal('OP_0');
|
Opcode().fromString('OP_0').toString().should.equal('OP_0');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('@map', function() {
|
describe('@map', function() {
|
||||||
|
|
||||||
it('should have a map containing 116 elements', function() {
|
it('should have a map containing 116 elements', function() {
|
||||||
_.size(Opcode.map).should.equal(116);
|
_.size(Opcode.map).should.equal(116);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('@reverseMap', function() {
|
describe('@reverseMap', function() {
|
||||||
|
|
||||||
it('should exist and have op 185', function() {
|
it('should exist and have op 185', function() {
|
||||||
should.exist(Opcode.reverseMap);
|
should.exist(Opcode.reverseMap);
|
||||||
Opcode.reverseMap[185].should.equal('OP_NOP10');
|
Opcode.reverseMap[185].should.equal('OP_NOP10');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
var smallints = [
|
var smallints = [
|
||||||
Opcode('OP_0'),
|
Opcode('OP_0'),
|
||||||
|
|
|
@ -22,7 +22,7 @@ describe('Script', function() {
|
||||||
buf[0] = Opcode('OP_0').toNumber();
|
buf[0] = Opcode('OP_0').toNumber();
|
||||||
var script = Script.fromBuffer(buf);
|
var script = Script.fromBuffer(buf);
|
||||||
script.chunks.length.should.equal(1);
|
script.chunks.length.should.equal(1);
|
||||||
script.chunks[0].should.equal(buf[0]);
|
script.chunks[0].opcodenum.should.equal(buf[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should parse this buffer containing another OP code', function() {
|
it('should parse this buffer containing another OP code', function() {
|
||||||
|
@ -30,7 +30,7 @@ describe('Script', function() {
|
||||||
buf[0] = Opcode('OP_CHECKMULTISIG').toNumber();
|
buf[0] = Opcode('OP_CHECKMULTISIG').toNumber();
|
||||||
var script = Script.fromBuffer(buf);
|
var script = Script.fromBuffer(buf);
|
||||||
script.chunks.length.should.equal(1);
|
script.chunks.length.should.equal(1);
|
||||||
script.chunks[0].should.equal(buf[0]);
|
script.chunks[0].opcodenum.should.equal(buf[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should parse this buffer containing three bytes of data', function() {
|
it('should parse this buffer containing three bytes of data', function() {
|
||||||
|
@ -75,9 +75,9 @@ describe('Script', function() {
|
||||||
buf[buf.length - 1] = Opcode('OP_0').toNumber();
|
buf[buf.length - 1] = Opcode('OP_0').toNumber();
|
||||||
var script = Script.fromBuffer(buf);
|
var script = Script.fromBuffer(buf);
|
||||||
script.chunks.length.should.equal(3);
|
script.chunks.length.should.equal(3);
|
||||||
script.chunks[0].should.equal(buf[0]);
|
script.chunks[0].opcodenum.should.equal(buf[0]);
|
||||||
script.chunks[1].buf.toString('hex').should.equal('010203');
|
script.chunks[1].buf.toString('hex').should.equal('010203');
|
||||||
script.chunks[2].should.equal(buf[buf.length - 1]);
|
script.chunks[2].opcodenum.should.equal(buf[buf.length - 1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -89,7 +89,7 @@ describe('Script', function() {
|
||||||
buf[0] = Opcode('OP_0').toNumber();
|
buf[0] = Opcode('OP_0').toNumber();
|
||||||
var script = Script.fromBuffer(buf);
|
var script = Script.fromBuffer(buf);
|
||||||
script.chunks.length.should.equal(1);
|
script.chunks.length.should.equal(1);
|
||||||
script.chunks[0].should.equal(buf[0]);
|
script.chunks[0].opcodenum.should.equal(buf[0]);
|
||||||
script.toBuffer().toString('hex').should.equal(buf.toString('hex'));
|
script.toBuffer().toString('hex').should.equal(buf.toString('hex'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ describe('Script', function() {
|
||||||
buf[0] = Opcode('OP_CHECKMULTISIG').toNumber();
|
buf[0] = Opcode('OP_CHECKMULTISIG').toNumber();
|
||||||
var script = Script.fromBuffer(buf);
|
var script = Script.fromBuffer(buf);
|
||||||
script.chunks.length.should.equal(1);
|
script.chunks.length.should.equal(1);
|
||||||
script.chunks[0].should.equal(buf[0]);
|
script.chunks[0].opcodenum.should.equal(buf[0]);
|
||||||
script.toBuffer().toString('hex').should.equal(buf.toString('hex'));
|
script.toBuffer().toString('hex').should.equal(buf.toString('hex'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -148,9 +148,9 @@ describe('Script', function() {
|
||||||
buf[buf.length - 1] = Opcode('OP_0').toNumber();
|
buf[buf.length - 1] = Opcode('OP_0').toNumber();
|
||||||
var script = Script.fromBuffer(buf);
|
var script = Script.fromBuffer(buf);
|
||||||
script.chunks.length.should.equal(3);
|
script.chunks.length.should.equal(3);
|
||||||
script.chunks[0].should.equal(buf[0]);
|
script.chunks[0].opcodenum.should.equal(buf[0]);
|
||||||
script.chunks[1].buf.toString('hex').should.equal('010203');
|
script.chunks[1].buf.toString('hex').should.equal('010203');
|
||||||
script.chunks[2].should.equal(buf[buf.length - 1]);
|
script.chunks[2].opcodenum.should.equal(buf[buf.length - 1]);
|
||||||
script.toBuffer().toString('hex').should.equal(buf.toString('hex'));
|
script.toBuffer().toString('hex').should.equal(buf.toString('hex'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -182,9 +182,9 @@ describe('Script', function() {
|
||||||
buf[buf.length - 1] = Opcode('OP_0').toNumber();
|
buf[buf.length - 1] = Opcode('OP_0').toNumber();
|
||||||
var script = Script.fromBuffer(buf);
|
var script = Script.fromBuffer(buf);
|
||||||
script.chunks.length.should.equal(3);
|
script.chunks.length.should.equal(3);
|
||||||
script.chunks[0].should.equal(buf[0]);
|
script.chunks[0].opcodenum.should.equal(buf[0]);
|
||||||
script.chunks[1].buf.toString('hex').should.equal('010203');
|
script.chunks[1].buf.toString('hex').should.equal('010203');
|
||||||
script.chunks[2].should.equal(buf[buf.length - 1]);
|
script.chunks[2].opcodenum.should.equal(buf[buf.length - 1]);
|
||||||
script.toString().toString('hex').should.equal('OP_0 OP_PUSHDATA4 3 0x010203 OP_0');
|
script.toString().toString('hex').should.equal('OP_0 OP_PUSHDATA4 3 0x010203 OP_0');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -242,31 +242,6 @@ describe('Script', function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#isScripthashIn', function() {
|
|
||||||
|
|
||||||
it('should identify this known scripthashin', function() {
|
|
||||||
Script('OP_0 73 0x30460221008ca148504190c10eea7f5f9c283c719a37be58c3ad617928011a1bb9570901d2022100ced371a23e86af6f55ff4ce705c57d2721a09c4d192ca39d82c4239825f75a9801 72 0x30450220357011fd3b3ad2b8f2f2d01e05dc6108b51d2a245b4ef40c112d6004596f0475022100a8208c93a39e0c366b983f9a80bfaf89237fcd64ca543568badd2d18ee2e1d7501 OP_PUSHDATA1 105 0x5221024c02dff2f0b8263a562a69ec875b2c95ffad860f428acf2f9e8c6492bd067d362103546324a1351a6b601c623b463e33b6103ca444707d5b278ece1692f1aa7724a42103b1ad3b328429450069cc3f9fa80d537ee66ba1120e93f3f185a5bf686fb51e0a53ae').isScriptHashIn().should.equal(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should identify this known non-scripthashin', function() {
|
|
||||||
Script('20 0000000000000000000000000000000000000000 OP_CHECKSIG').isScriptHashIn().should.equal(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('#isScripthashOut', function() {
|
|
||||||
|
|
||||||
it('should identify this known pubkeyhashout as pubkeyhashout', function() {
|
|
||||||
Script('OP_HASH160 20 0x0000000000000000000000000000000000000000 OP_EQUAL').isScriptHashOut().should.equal(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should identify these known non-pubkeyhashout as not pubkeyhashout', function() {
|
|
||||||
Script('OP_HASH160 20 0x0000000000000000000000000000000000000000 OP_EQUAL OP_EQUAL').isScriptHashOut().should.equal(false);
|
|
||||||
Script('OP_HASH160 21 0x000000000000000000000000000000000000000000 OP_EQUAL').isScriptHashOut().should.equal(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('#isMultisigOut', function() {
|
describe('#isMultisigOut', function() {
|
||||||
it('should identify known multisig out 1', function() {
|
it('should identify known multisig out 1', function() {
|
||||||
Script('OP_2 21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 OP_2 OP_CHECKMULTISIG').isMultisigOut().should.equal(true);
|
Script('OP_2 21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 OP_2 OP_CHECKMULTISIG').isMultisigOut().should.equal(true);
|
||||||
|
@ -301,6 +276,32 @@ describe('Script', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#isScriptHashIn', function() {
|
||||||
|
it('should identify this known scripthashin', function() {
|
||||||
|
var sstr = 'OP_0 73 0x30460221008ca148504190c10eea7f5f9c283c719a37be58c3ad617928011a1bb9570901d2022100ced371a23e86af6f55ff4ce705c57d2721a09c4d192ca39d82c4239825f75a9801 72 0x30450220357011fd3b3ad2b8f2f2d01e05dc6108b51d2a245b4ef40c112d6004596f0475022100a8208c93a39e0c366b983f9a80bfaf89237fcd64ca543568badd2d18ee2e1d7501 OP_PUSHDATA1 105 0x5221024c02dff2f0b8263a562a69ec875b2c95ffad860f428acf2f9e8c6492bd067d362103546324a1351a6b601c623b463e33b6103ca444707d5b278ece1692f1aa7724a42103b1ad3b328429450069cc3f9fa80d537ee66ba1120e93f3f185a5bf686fb51e0a53ae';
|
||||||
|
var s = Script(sstr);
|
||||||
|
s.toString().should.equal(sstr);
|
||||||
|
s.isScriptHashIn().should.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should identify this known non-scripthashin', function() {
|
||||||
|
Script('20 0000000000000000000000000000000000000000 OP_CHECKSIG').isScriptHashIn().should.equal(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#isScripthashOut', function() {
|
||||||
|
|
||||||
|
it('should identify this known pubkeyhashout as pubkeyhashout', function() {
|
||||||
|
Script('OP_HASH160 20 0x0000000000000000000000000000000000000000 OP_EQUAL').isScriptHashOut().should.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should identify these known non-pubkeyhashout as not pubkeyhashout', function() {
|
||||||
|
Script('OP_HASH160 20 0x0000000000000000000000000000000000000000 OP_EQUAL OP_EQUAL').isScriptHashOut().should.equal(false);
|
||||||
|
Script('OP_HASH160 21 0x000000000000000000000000000000000000000000 OP_EQUAL').isScriptHashOut().should.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
describe('#isPushOnly', function() {
|
describe('#isPushOnly', function() {
|
||||||
it('should know these scripts are or aren\'t push only', function() {
|
it('should know these scripts are or aren\'t push only', function() {
|
||||||
Script('OP_NOP 1 0x01').isPushOnly().should.equal(false);
|
Script('OP_NOP 1 0x01').isPushOnly().should.equal(false);
|
||||||
|
|
|
@ -2,9 +2,10 @@
|
||||||
|
|
||||||
var should = require('chai').should();
|
var should = require('chai').should();
|
||||||
|
|
||||||
var errors = require('../../lib/errors');
|
var bitcore = require('../..');
|
||||||
var $ = require('../../lib/util/preconditions');
|
var errors = bitcore.errors;
|
||||||
var PrivateKey = require('../../lib/privatekey');
|
var $ = bitcore.util.preconditions;
|
||||||
|
var PrivateKey = bitcore.PrivateKey;
|
||||||
|
|
||||||
describe('preconditions', function() {
|
describe('preconditions', function() {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue