2013-07-09 11:45:52 -07:00
|
|
|
require('classtool');
|
|
|
|
|
|
|
|
function spec(b) {
|
2013-07-09 14:45:21 -07:00
|
|
|
var config = b.config || require('./config');
|
2013-10-31 09:40:06 -07:00
|
|
|
var log = b.log || require('./util/log');
|
2013-07-09 14:45:21 -07:00
|
|
|
|
2014-02-18 08:17:23 -08:00
|
|
|
var Opcode = b.Opcode || require('./Opcode').class();
|
|
|
|
var buffertools = b.buffertools || require('buffertools');
|
2013-07-09 11:45:52 -07:00
|
|
|
|
|
|
|
// Make opcodes available as pseudo-constants
|
|
|
|
for (var i in Opcode.map) {
|
|
|
|
eval(i + " = " + Opcode.map[i] + ";");
|
|
|
|
}
|
|
|
|
|
2013-07-09 14:45:21 -07:00
|
|
|
var util = b.util || require('./util/util');
|
|
|
|
var Parser = b.Parser || require('./util/BinaryParser').class();
|
2013-07-09 11:45:52 -07:00
|
|
|
var Put = b.Put || require('bufferput');
|
|
|
|
|
2013-08-16 13:38:28 -07:00
|
|
|
var TX_UNKNOWN = 0;
|
|
|
|
var TX_PUBKEY = 1;
|
|
|
|
var TX_PUBKEYHASH = 2;
|
|
|
|
var TX_MULTISIG = 3;
|
|
|
|
var TX_SCRIPTHASH = 4;
|
|
|
|
|
2013-10-31 09:40:06 -07:00
|
|
|
var TX_TYPES = [
|
|
|
|
'unknown',
|
|
|
|
'pubkey',
|
|
|
|
'pubkeyhash',
|
|
|
|
'multisig',
|
|
|
|
'scripthash'
|
|
|
|
];
|
2013-08-16 13:38:28 -07:00
|
|
|
|
2013-07-09 11:45:52 -07:00
|
|
|
function Script(buffer) {
|
|
|
|
if(buffer) {
|
|
|
|
this.buffer = buffer;
|
|
|
|
} else {
|
2013-07-09 14:45:21 -07:00
|
|
|
this.buffer = util.EMPTY_BUFFER;
|
2013-07-09 11:45:52 -07:00
|
|
|
}
|
|
|
|
this.chunks = [];
|
|
|
|
this.parse();
|
|
|
|
};
|
|
|
|
this.class = Script;
|
|
|
|
|
2013-12-18 15:16:19 -08:00
|
|
|
Script.TX_UNKNOWN=TX_UNKNOWN;
|
|
|
|
Script.TX_PUBKEY=TX_PUBKEY;
|
|
|
|
Script.TX_PUBKEYHASH=TX_PUBKEYHASH;
|
|
|
|
Script.TX_MULTISIG=TX_MULTISIG;
|
|
|
|
Script.TX_SCRIPTHASH=TX_SCRIPTHASH;
|
2013-12-10 09:54:11 -08:00
|
|
|
|
2013-07-09 11:45:52 -07:00
|
|
|
Script.prototype.parse = function () {
|
|
|
|
this.chunks = [];
|
|
|
|
|
|
|
|
var parser = new Parser(this.buffer);
|
|
|
|
while (!parser.eof()) {
|
|
|
|
var opcode = parser.word8();
|
|
|
|
|
|
|
|
var len;
|
|
|
|
if (opcode > 0 && opcode < OP_PUSHDATA1) {
|
|
|
|
// Read some bytes of data, opcode value is the length of data
|
|
|
|
this.chunks.push(parser.buffer(opcode));
|
|
|
|
} else if (opcode == OP_PUSHDATA1) {
|
|
|
|
len = parser.word8();
|
|
|
|
this.chunks.push(parser.buffer(len));
|
|
|
|
} else if (opcode == OP_PUSHDATA2) {
|
|
|
|
len = parser.word16le();
|
|
|
|
this.chunks.push(parser.buffer(len));
|
|
|
|
} else if (opcode == OP_PUSHDATA4) {
|
|
|
|
len = parser.word32le();
|
|
|
|
this.chunks.push(parser.buffer(len));
|
|
|
|
} else {
|
|
|
|
this.chunks.push(opcode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-08-21 05:29:06 -07:00
|
|
|
Script.prototype.isPushOnly = function ()
|
|
|
|
{
|
|
|
|
for (var i = 0; i < this.chunks.length; i++)
|
|
|
|
if (!Buffer.isBuffer(this.chunks[i]))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
2013-08-16 13:38:28 -07:00
|
|
|
Script.prototype.isP2SH = function ()
|
2013-07-09 11:45:52 -07:00
|
|
|
{
|
2013-08-16 13:38:28 -07:00
|
|
|
return (this.chunks.length == 3 &&
|
2014-01-16 01:21:35 -08:00
|
|
|
this.chunks[0] == OP_HASH160 &&
|
|
|
|
Buffer.isBuffer(this.chunks[1]) &&
|
|
|
|
this.chunks[1].length == 20 &&
|
|
|
|
this.chunks[2] == OP_EQUAL);
|
2013-07-09 11:45:52 -07:00
|
|
|
};
|
|
|
|
|
2013-08-16 13:38:28 -07:00
|
|
|
Script.prototype.isPubkey = function ()
|
2013-07-09 11:45:52 -07:00
|
|
|
{
|
2013-08-16 13:38:28 -07:00
|
|
|
return (this.chunks.length == 2 &&
|
2014-01-16 01:21:35 -08:00
|
|
|
Buffer.isBuffer(this.chunks[0]) &&
|
|
|
|
this.chunks[1] == OP_CHECKSIG);
|
2013-08-16 13:38:28 -07:00
|
|
|
};
|
2013-07-09 11:45:52 -07:00
|
|
|
|
2013-08-16 13:38:28 -07:00
|
|
|
Script.prototype.isPubkeyHash = function ()
|
|
|
|
{
|
|
|
|
return (this.chunks.length == 5 &&
|
2014-01-16 01:21:35 -08:00
|
|
|
this.chunks[0] == OP_DUP &&
|
|
|
|
this.chunks[1] == OP_HASH160 &&
|
|
|
|
Buffer.isBuffer(this.chunks[2]) &&
|
|
|
|
this.chunks[2].length == 20 &&
|
|
|
|
this.chunks[3] == OP_EQUALVERIFY &&
|
|
|
|
this.chunks[4] == OP_CHECKSIG);
|
2013-08-16 13:38:28 -07:00
|
|
|
};
|
2013-07-09 11:45:52 -07:00
|
|
|
|
2013-08-16 13:38:28 -07:00
|
|
|
function isSmallIntOp(opcode)
|
|
|
|
{
|
|
|
|
return ((opcode == OP_0) ||
|
2014-01-16 01:21:35 -08:00
|
|
|
((opcode >= OP_1) && (opcode <= OP_16)));
|
2013-08-16 13:38:28 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
Script.prototype.isMultiSig = function ()
|
|
|
|
{
|
|
|
|
return (this.chunks.length > 3 &&
|
2014-01-16 01:21:35 -08:00
|
|
|
isSmallIntOp(this.chunks[0]) &&
|
|
|
|
isSmallIntOp(this.chunks[this.chunks.length-2]) &&
|
|
|
|
this.chunks[this.chunks.length-1] == OP_CHECKMULTISIG);
|
2013-08-16 13:38:28 -07:00
|
|
|
};
|
|
|
|
|
2014-01-15 19:16:45 -08:00
|
|
|
Script.prototype.finishedMultiSig = function()
|
|
|
|
{
|
|
|
|
var nsigs = 0;
|
|
|
|
for (var i = 0; i < this.chunks.length-1; i++)
|
|
|
|
if (this.chunks[i] !== 0)
|
|
|
|
nsigs++;
|
|
|
|
|
|
|
|
var serializedScript = this.chunks[this.chunks.length-1];
|
|
|
|
var script = new Script(serializedScript);
|
|
|
|
var nreq = script.chunks[0] - 80; //see OP_2-OP_16
|
|
|
|
|
|
|
|
if (nsigs == nreq)
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Script.prototype.removePlaceHolders = function()
|
|
|
|
{
|
|
|
|
var chunks = [];
|
|
|
|
for (var i in this.chunks)
|
|
|
|
{
|
2014-02-21 11:48:27 -08:00
|
|
|
if (this.chunks.hasOwnProperty(i)) {
|
|
|
|
var chunk = this.chunks[i];
|
|
|
|
if (chunk != 0)
|
|
|
|
chunks.push(chunk);
|
|
|
|
}
|
2014-01-15 19:16:45 -08:00
|
|
|
}
|
|
|
|
this.chunks = chunks;
|
|
|
|
this.updateBuffer();
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
Script.prototype.prependOp0 = function()
|
|
|
|
{
|
|
|
|
var chunks = [0];
|
2014-02-21 11:48:27 -08:00
|
|
|
for (i in this.chunks) {
|
|
|
|
if (this.chunks.hasOwnProperty(i)) {
|
|
|
|
chunks.push(this.chunks[i]);
|
|
|
|
}
|
|
|
|
}
|
2014-01-15 19:16:45 -08:00
|
|
|
this.chunks = chunks;
|
|
|
|
this.updateBuffer();
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2013-08-16 13:38:28 -07:00
|
|
|
// is this a script form we know?
|
|
|
|
Script.prototype.classify = function ()
|
|
|
|
{
|
2014-01-16 01:21:35 -08:00
|
|
|
if (this.isPubkeyHash())
|
|
|
|
return TX_PUBKEYHASH;
|
|
|
|
if (this.isP2SH())
|
|
|
|
return TX_SCRIPTHASH;
|
|
|
|
if (this.isMultiSig())
|
|
|
|
return TX_MULTISIG;
|
|
|
|
if (this.isPubkey())
|
|
|
|
return TX_PUBKEY;
|
|
|
|
return TX_UNKNOWN;
|
2013-08-16 13:38:28 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
// extract useful data items from known scripts
|
|
|
|
Script.prototype.capture = function ()
|
|
|
|
{
|
2014-01-16 01:21:35 -08:00
|
|
|
var txType = this.classify();
|
|
|
|
var res = [];
|
|
|
|
switch (txType) {
|
|
|
|
case TX_PUBKEY:
|
|
|
|
res.push(this.chunks[0]);
|
|
|
|
break;
|
|
|
|
case TX_PUBKEYHASH:
|
|
|
|
res.push(this.chunks[2]);
|
|
|
|
break;
|
|
|
|
case TX_MULTISIG:
|
|
|
|
for (var i = 1; i < (this.chunks.length - 2); i++)
|
|
|
|
res.push(this.chunks[i]);
|
|
|
|
break;
|
|
|
|
case TX_SCRIPTHASH:
|
|
|
|
res.push(this.chunks[1]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TX_UNKNOWN:
|
|
|
|
default:
|
|
|
|
// do nothing
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
2013-08-16 13:38:28 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
// return first extracted data item from script
|
|
|
|
Script.prototype.captureOne = function ()
|
|
|
|
{
|
2014-01-16 01:21:35 -08:00
|
|
|
var arr = this.capture();
|
|
|
|
return arr[0];
|
2013-08-16 13:38:28 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
Script.prototype.getOutType = function ()
|
|
|
|
{
|
2013-10-31 09:40:06 -07:00
|
|
|
var txType = this.classify();
|
|
|
|
switch (txType) {
|
2014-01-16 01:21:35 -08:00
|
|
|
case TX_PUBKEY: return 'Pubkey';
|
|
|
|
case TX_PUBKEYHASH: return 'Address';
|
|
|
|
default: return 'Strange';
|
2013-10-31 09:40:06 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Script.prototype.getRawOutType = function() {
|
|
|
|
return TX_TYPES[this.classify()];
|
2013-07-09 11:45:52 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
Script.prototype.simpleOutHash = function ()
|
|
|
|
{
|
|
|
|
switch (this.getOutType()) {
|
|
|
|
case 'Address':
|
|
|
|
return this.chunks[2];
|
|
|
|
case 'Pubkey':
|
2013-07-09 14:45:21 -07:00
|
|
|
return util.sha256ripe160(this.chunks[0]);
|
2013-07-09 11:45:52 -07:00
|
|
|
default:
|
2013-07-09 14:45:21 -07:00
|
|
|
log.debug("Encountered non-standard scriptPubKey");
|
|
|
|
log.debug("Strange script was: " + this.toString());
|
2013-07-09 11:45:52 -07:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Script.prototype.getInType = function ()
|
|
|
|
{
|
|
|
|
if (this.chunks.length == 1) {
|
|
|
|
// Direct IP to IP transactions only have the public key in their scriptSig.
|
|
|
|
return 'Pubkey';
|
|
|
|
} else if (this.chunks.length == 2 &&
|
|
|
|
Buffer.isBuffer(this.chunks[0]) &&
|
|
|
|
Buffer.isBuffer(this.chunks[1])) {
|
|
|
|
return 'Address';
|
|
|
|
} else {
|
|
|
|
return 'Strange';
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Script.prototype.simpleInPubKey = function ()
|
|
|
|
{
|
|
|
|
switch (this.getInType()) {
|
|
|
|
case 'Address':
|
|
|
|
return this.chunks[1];
|
|
|
|
case 'Pubkey':
|
|
|
|
return null;
|
|
|
|
default:
|
2013-07-09 14:45:21 -07:00
|
|
|
log.debug("Encountered non-standard scriptSig");
|
|
|
|
log.debug("Strange script was: " + this.toString());
|
2013-07-09 11:45:52 -07:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Script.prototype.getBuffer = function ()
|
|
|
|
{
|
|
|
|
return this.buffer;
|
|
|
|
};
|
|
|
|
|
|
|
|
Script.prototype.getStringContent = function (truncate, maxEl)
|
|
|
|
{
|
|
|
|
if (truncate === null) {
|
|
|
|
truncate = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ("undefined" === typeof maxEl) {
|
|
|
|
maxEl = 15;
|
|
|
|
}
|
|
|
|
|
|
|
|
var script = '';
|
|
|
|
for (var i = 0, l = this.chunks.length; i < l; i++) {
|
|
|
|
var chunk = this.chunks[i];
|
|
|
|
|
|
|
|
if (i > 0) {
|
|
|
|
script += " ";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Buffer.isBuffer(chunk)) {
|
2013-07-09 14:45:21 -07:00
|
|
|
script += "0x"+util.formatBuffer(chunk, truncate ? null : 0);
|
2013-07-09 11:45:52 -07:00
|
|
|
} else {
|
|
|
|
script += Opcode.reverseMap[chunk];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (maxEl && i > maxEl) {
|
|
|
|
script += " ...";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return script;
|
|
|
|
};
|
|
|
|
|
|
|
|
Script.prototype.toString = function (truncate, maxEl)
|
|
|
|
{
|
|
|
|
var script = "<Script ";
|
|
|
|
script += this.getStringContent(truncate, maxEl);
|
|
|
|
script += ">";
|
|
|
|
return script;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Script.prototype.writeOp = function (opcode)
|
|
|
|
{
|
2013-08-15 19:40:07 -07:00
|
|
|
var buf = Buffer(this.buffer.length + 1);
|
|
|
|
this.buffer.copy(buf);
|
|
|
|
buf.writeUInt8(opcode, this.buffer.length);
|
|
|
|
|
|
|
|
this.buffer = buf;
|
2013-07-09 11:45:52 -07:00
|
|
|
|
|
|
|
this.chunks.push(opcode);
|
|
|
|
};
|
|
|
|
|
2013-08-15 19:40:07 -07:00
|
|
|
Script.prototype.writeN = function (n)
|
2013-07-09 11:45:52 -07:00
|
|
|
{
|
2013-08-15 19:40:07 -07:00
|
|
|
if (n < 0 || n > 16)
|
|
|
|
throw new Error("writeN: out of range value " + n);
|
|
|
|
|
|
|
|
if (n == 0)
|
|
|
|
this.writeOp(OP_0);
|
|
|
|
else
|
|
|
|
this.writeOp(OP_1 + n - 1);
|
|
|
|
};
|
|
|
|
|
|
|
|
function prefixSize(data_length)
|
|
|
|
{
|
|
|
|
if (data_length < OP_PUSHDATA1) {
|
|
|
|
return 1;
|
|
|
|
} else if (data_length <= 0xff) {
|
|
|
|
return 1 + 1;
|
|
|
|
} else if (data_length <= 0xffff) {
|
|
|
|
return 1 + 2;
|
2013-07-09 11:45:52 -07:00
|
|
|
} else {
|
2013-08-15 19:40:07 -07:00
|
|
|
return 1 + 4;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
function encodeLen(data_length) {
|
|
|
|
var buf = undefined;
|
|
|
|
if (data_length < OP_PUSHDATA1) {
|
|
|
|
buf = new Buffer(1);
|
|
|
|
buf.writeUInt8(data_length, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (data_length <= 0xff) {
|
|
|
|
buf = new Buffer(1 + 1);
|
|
|
|
buf.writeUInt8(OP_PUSHDATA1, 0);
|
|
|
|
buf.writeUInt8(data_length, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (data_length <= 0xffff) {
|
|
|
|
buf = new Buffer(1 + 2);
|
|
|
|
buf.writeUInt8(OP_PUSHDATA2, 0);
|
|
|
|
buf.writeUInt16LE(data_length, 1);
|
2013-07-09 11:45:52 -07:00
|
|
|
}
|
2013-08-15 19:40:07 -07:00
|
|
|
|
|
|
|
else {
|
|
|
|
buf = new Buffer(1 + 4);
|
|
|
|
buf.writeUInt8(OP_PUSHDATA4, 0);
|
|
|
|
buf.writeUInt32LE(data_length, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
};
|
|
|
|
|
|
|
|
Script.prototype.writeBytes = function (data)
|
|
|
|
{
|
|
|
|
var newSize = this.buffer.length + prefixSize(data.length) + data.length;
|
2014-02-18 11:03:29 -08:00
|
|
|
this.buffer = Buffer.concat([this.buffer, encodeLen(data.length), data]);
|
2013-07-09 11:45:52 -07:00
|
|
|
this.chunks.push(data);
|
|
|
|
};
|
|
|
|
|
|
|
|
Script.prototype.updateBuffer = function ()
|
|
|
|
{
|
|
|
|
this.buffer = Script.chunksToBuffer(this.chunks);
|
|
|
|
};
|
|
|
|
|
|
|
|
Script.prototype.findAndDelete = function (chunk)
|
|
|
|
{
|
|
|
|
var dirty = false;
|
|
|
|
if (Buffer.isBuffer(chunk)) {
|
|
|
|
for (var i = 0, l = this.chunks.length; i < l; i++) {
|
|
|
|
if (Buffer.isBuffer(this.chunks[i]) &&
|
2014-02-18 08:17:23 -08:00
|
|
|
buffertools.compare(this.chunks[i], chunk) === 0) {
|
2013-07-09 11:45:52 -07:00
|
|
|
this.chunks.splice(i, 1);
|
|
|
|
dirty = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if ("number" === typeof chunk) {
|
|
|
|
for (var i = 0, l = this.chunks.length; i < l; i++) {
|
|
|
|
if (this.chunks[i] === chunk) {
|
|
|
|
this.chunks.splice(i, 1);
|
|
|
|
dirty = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
throw new Error("Invalid chunk datatype.");
|
|
|
|
}
|
|
|
|
if (dirty) {
|
|
|
|
this.updateBuffer();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a simple OP_CHECKSIG with pubkey output script.
|
|
|
|
*
|
|
|
|
* These are used for coinbase transactions and at some point were used for
|
|
|
|
* IP-based transactions as well.
|
|
|
|
*/
|
|
|
|
Script.createPubKeyOut = function (pubkey) {
|
|
|
|
var script = new Script();
|
|
|
|
script.writeBytes(pubkey);
|
|
|
|
script.writeOp(OP_CHECKSIG);
|
|
|
|
return script;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a standard txout script.
|
|
|
|
*/
|
|
|
|
Script.createPubKeyHashOut = function (pubKeyHash) {
|
|
|
|
var script = new Script();
|
|
|
|
script.writeOp(OP_DUP);
|
|
|
|
script.writeOp(OP_HASH160);
|
|
|
|
script.writeBytes(pubKeyHash);
|
|
|
|
script.writeOp(OP_EQUALVERIFY);
|
|
|
|
script.writeOp(OP_CHECKSIG);
|
|
|
|
return script;
|
|
|
|
};
|
|
|
|
|
2013-08-15 19:40:07 -07:00
|
|
|
Script.createMultisig = function(n_required, keys) {
|
|
|
|
var script = new Script();
|
|
|
|
script.writeN(n_required);
|
|
|
|
keys.forEach(function(key) {
|
2014-01-16 01:21:35 -08:00
|
|
|
script.writeBytes(key);
|
2013-08-15 19:40:07 -07:00
|
|
|
});
|
|
|
|
script.writeN(keys.length);
|
|
|
|
script.writeOp(OP_CHECKMULTISIG);
|
|
|
|
return script;
|
|
|
|
};
|
|
|
|
|
|
|
|
Script.createP2SH = function(scriptHash) {
|
|
|
|
var script = new Script();
|
|
|
|
script.writeOp(OP_HASH160);
|
|
|
|
script.writeBytes(scriptHash);
|
|
|
|
script.writeOp(OP_EQUAL);
|
|
|
|
return script;
|
|
|
|
};
|
|
|
|
|
2013-07-09 11:45:52 -07:00
|
|
|
Script.fromTestData = function (testData) {
|
|
|
|
testData = testData.map(function (chunk) {
|
|
|
|
if ("string" === typeof chunk) {
|
|
|
|
return new Buffer(chunk, 'hex');
|
|
|
|
} else {
|
|
|
|
return chunk;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
var script = new Script();
|
|
|
|
script.chunks = testData;
|
|
|
|
script.updateBuffer();
|
|
|
|
return script;
|
|
|
|
};
|
|
|
|
|
|
|
|
Script.fromChunks = function (chunks) {
|
|
|
|
var script = new Script();
|
|
|
|
script.chunks = chunks;
|
|
|
|
script.updateBuffer();
|
|
|
|
return script;
|
|
|
|
};
|
|
|
|
|
|
|
|
Script.chunksToBuffer = function (chunks) {
|
2014-01-06 12:25:12 -08:00
|
|
|
var buf = new Put();
|
2014-02-21 11:48:27 -08:00
|
|
|
|
2013-07-09 11:45:52 -07:00
|
|
|
for (var i = 0, l = chunks.length; i < l; i++) {
|
|
|
|
var data = chunks[i];
|
|
|
|
if (Buffer.isBuffer(data)) {
|
|
|
|
if (data.length < OP_PUSHDATA1) {
|
|
|
|
buf.word8(data.length);
|
|
|
|
} else if (data.length <= 0xff) {
|
|
|
|
buf.word8(OP_PUSHDATA1);
|
|
|
|
buf.word8(data.length);
|
|
|
|
} else if (data.length <= 0xffff) {
|
|
|
|
buf.word8(OP_PUSHDATA2);
|
|
|
|
buf.word16le(data.length);
|
|
|
|
} else {
|
|
|
|
buf.word8(OP_PUSHDATA4);
|
|
|
|
buf.word32le(data.length);
|
|
|
|
}
|
|
|
|
buf.put(data);
|
|
|
|
} else if ("number" === typeof data) {
|
|
|
|
buf.word8(data);
|
|
|
|
} else {
|
|
|
|
throw new Error("Script.chunksToBuffer(): Invalid chunk datatype");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return buf.buffer();
|
|
|
|
};
|
|
|
|
|
|
|
|
return Script;
|
|
|
|
};
|
|
|
|
module.defineClass(spec);
|
|
|
|
|