primitives: cloning and assertions.
This commit is contained in:
parent
58da4be8fa
commit
a53b2c0eef
@ -791,7 +791,7 @@ RPC.prototype._txToJSON = function _txToJSON(tx, entry) {
|
||||
if (tx.isCoinbase()) {
|
||||
out.coinbase = input.script.toJSON();
|
||||
} else {
|
||||
out.txid = input.prevout.rhash();
|
||||
out.txid = input.prevout.txid();
|
||||
out.vout = input.prevout.index;
|
||||
out.scriptSig = {
|
||||
asm: input.script.toASM(),
|
||||
@ -3381,7 +3381,7 @@ RPC.prototype.listlockunspent = co(function* listlockunspent(args) {
|
||||
for (i = 0; i < outpoints.length; i++) {
|
||||
outpoint = outpoints[i];
|
||||
out.push({
|
||||
txid: outpoint.rhash(),
|
||||
txid: outpoint.txid(),
|
||||
vout: outpoint.index
|
||||
});
|
||||
}
|
||||
@ -3749,7 +3749,7 @@ RPC.prototype.listunspent = co(function* listunspent(args) {
|
||||
ring = yield wallet.getKey(hash);
|
||||
|
||||
out.push({
|
||||
txid: coin.rhash(),
|
||||
txid: coin.txid(),
|
||||
vout: coin.index,
|
||||
address: address ? address.toBase58(this.network) : null,
|
||||
account: ring ? ring.name : undefined,
|
||||
|
||||
@ -62,17 +62,21 @@ Coin.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(options, 'Coin data is required.');
|
||||
|
||||
if (options.version != null) {
|
||||
assert(util.isUInt32(options.version));
|
||||
assert(util.isUInt32(options.version), 'Version must be a uint32.');
|
||||
this.version = options.version;
|
||||
}
|
||||
|
||||
if (options.height != null) {
|
||||
assert(options.height === -1 || util.isUInt32(options.height));
|
||||
this.height = options.height;
|
||||
if (options.height !== -1) {
|
||||
assert(util.isUInt32(options.height), 'Height must be a uint32.');
|
||||
this.height = options.height;
|
||||
} else {
|
||||
this.height = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.value != null) {
|
||||
assert(util.isUInt53(options.value));
|
||||
assert(util.isUInt53(options.value), 'Value must be a uint53.');
|
||||
this.value = options.value;
|
||||
}
|
||||
|
||||
@ -80,17 +84,18 @@ Coin.prototype.fromOptions = function fromOptions(options) {
|
||||
this.script.fromOptions(options.script);
|
||||
|
||||
if (options.coinbase != null) {
|
||||
assert(typeof options.coinbase === 'boolean');
|
||||
assert(typeof options.coinbase === 'boolean',
|
||||
'Coinbase must be a boolean.');
|
||||
this.coinbase = options.coinbase;
|
||||
}
|
||||
|
||||
if (options.hash != null) {
|
||||
assert(typeof options.hash === 'string');
|
||||
assert(typeof options.hash === 'string', 'Hash must be a string.');
|
||||
this.hash = options.hash;
|
||||
}
|
||||
|
||||
if (options.index != null) {
|
||||
assert(util.isUInt32(options.index));
|
||||
assert(util.isUInt32(options.index), 'Index must be a uint32.');
|
||||
this.index = options.index;
|
||||
}
|
||||
|
||||
@ -107,6 +112,16 @@ Coin.fromOptions = function fromOptions(options) {
|
||||
return new Coin().fromOptions(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Clone the coin.
|
||||
* @private
|
||||
* @returns {Coin}
|
||||
*/
|
||||
|
||||
Coin.prototype.clone = function clone() {
|
||||
assert(false, 'Coins are not cloneable.');
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate number of confirmations since coin was created.
|
||||
* @param {Number?} height - Current chain height. Network
|
||||
@ -172,6 +187,15 @@ Coin.prototype.rhash = function rhash() {
|
||||
return util.revHex(this.hash);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get little-endian hash.
|
||||
* @returns {Hash}
|
||||
*/
|
||||
|
||||
Coin.prototype.txid = function txid() {
|
||||
return this.rhash();
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert the coin to a more user-friendly object.
|
||||
* @returns {Object}
|
||||
@ -239,20 +263,25 @@ Coin.prototype.getJSON = function getJSON(network, minimal) {
|
||||
|
||||
Coin.prototype.fromJSON = function fromJSON(json) {
|
||||
assert(json, 'Coin data required.');
|
||||
assert(util.isNumber(json.version));
|
||||
assert(util.isNumber(json.height));
|
||||
assert(typeof json.value === 'string');
|
||||
assert(typeof json.coinbase === 'boolean');
|
||||
assert(!json.hash || typeof json.hash === 'string');
|
||||
assert(!json.index || util.isNumber(json.index));
|
||||
assert(util.isUInt32(json.version), 'Version must be a uint32.');
|
||||
assert(json.height === -1 || util.isUInt32(json.height),
|
||||
'Height must be a uint32.');
|
||||
assert(typeof json.value === 'string', 'Value must be a string.');
|
||||
assert(typeof json.coinbase === 'boolean', 'Coinbase must be a boolean.');
|
||||
|
||||
this.version = json.version;
|
||||
this.height = json.height;
|
||||
this.value = Amount.value(json.value);
|
||||
this.script.fromJSON(json.script);
|
||||
this.coinbase = json.coinbase;
|
||||
this.hash = json.hash ? util.revHex(json.hash) : encoding.NULL_HASH;
|
||||
this.index = json.index != null ? json.index : 0;
|
||||
|
||||
if (json.hash != null) {
|
||||
assert(typeof json.hash === 'string', 'Hash must be a string.');
|
||||
assert(json.hash.length === 64, 'Hash must be a string.');
|
||||
assert(util.isUInt32(json.index), 'Index must be a uint32.');
|
||||
this.hash = util.revHex(json.hash);
|
||||
this.index = json.index;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
@ -365,9 +394,9 @@ Coin.fromRaw = function fromRaw(data, enc) {
|
||||
*/
|
||||
|
||||
Coin.prototype.fromTX = function fromTX(tx, index, height) {
|
||||
assert(util.isNumber(index));
|
||||
assert(index < tx.outputs.length);
|
||||
assert(typeof index === 'number');
|
||||
assert(typeof height === 'number');
|
||||
assert(index >= 0 && index < tx.outputs.length);
|
||||
this.version = tx.version;
|
||||
this.height = height;
|
||||
this.value = tx.outputs[index].value;
|
||||
|
||||
@ -48,7 +48,6 @@ function Input(options) {
|
||||
|
||||
Input.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(options, 'Input data is required.');
|
||||
assert(options.prevout);
|
||||
|
||||
this.prevout.fromOptions(options.prevout);
|
||||
|
||||
@ -56,7 +55,7 @@ Input.prototype.fromOptions = function fromOptions(options) {
|
||||
this.script.fromOptions(options.script);
|
||||
|
||||
if (options.sequence != null) {
|
||||
assert(util.isUInt32(options.sequence));
|
||||
assert(util.isUInt32(options.sequence), 'Sequence must be a uint32.');
|
||||
this.sequence = options.sequence;
|
||||
}
|
||||
|
||||
@ -76,6 +75,20 @@ Input.fromOptions = function fromOptions(options) {
|
||||
return new Input().fromOptions(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Clone the input.
|
||||
* @returns {Input}
|
||||
*/
|
||||
|
||||
Input.prototype.clone = function clone() {
|
||||
var input = new Input();
|
||||
input.prevout = this.prevout;
|
||||
input.script.inject(this.script);
|
||||
input.sequence = this.sequence;
|
||||
input.witness.inject(this.witness);
|
||||
return input;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the previous output script type as a string.
|
||||
* Will "guess" based on the input script and/or
|
||||
@ -300,7 +313,7 @@ Input.prototype.getJSON = function getJSON(network, coin) {
|
||||
|
||||
Input.prototype.fromJSON = function fromJSON(json) {
|
||||
assert(json, 'Input data is required.');
|
||||
assert(util.isUInt32(json.sequence));
|
||||
assert(util.isUInt32(json.sequence), 'Sequence must be a uint32.');
|
||||
this.prevout.fromJSON(json.prevout);
|
||||
this.script.fromJSON(json.script);
|
||||
this.witness.fromJSON(json.witness);
|
||||
@ -453,7 +466,7 @@ Input.fromCoin = function fromCoin(coin) {
|
||||
Input.prototype.fromTX = function fromTX(tx, index) {
|
||||
assert(tx);
|
||||
assert(typeof index === 'number');
|
||||
assert(index < tx.outputs.length);
|
||||
assert(index >= 0 && index < tx.outputs.length);
|
||||
this.prevout.hash = tx.hash('hex');
|
||||
this.prevout.index = index;
|
||||
return this;
|
||||
|
||||
@ -70,35 +70,40 @@ MTX.prototype.fromOptions = function fromOptions(options) {
|
||||
var i;
|
||||
|
||||
if (options.version != null) {
|
||||
assert(util.isUInt32(options.version));
|
||||
assert(util.isUInt32(options.version), 'Version must a be uint32.');
|
||||
this.version = options.version;
|
||||
}
|
||||
|
||||
if (options.flag != null) {
|
||||
assert(util.isUInt8(options.flag));
|
||||
assert(util.isUInt8(options.flag), 'Flag must be a uint8.');
|
||||
this.flag = options.flag;
|
||||
}
|
||||
|
||||
if (options.inputs) {
|
||||
assert(Array.isArray(options.inputs));
|
||||
assert(Array.isArray(options.inputs), 'Inputs must be an array.');
|
||||
for (i = 0; i < options.inputs.length; i++)
|
||||
this.addInput(options.inputs[i]);
|
||||
}
|
||||
|
||||
if (options.outputs) {
|
||||
assert(Array.isArray(options.outputs));
|
||||
assert(Array.isArray(options.outputs), 'Outputs must be an array.');
|
||||
for (i = 0; i < options.outputs.length; i++)
|
||||
this.addOutput(options.outputs[i]);
|
||||
}
|
||||
|
||||
if (options.locktime != null) {
|
||||
assert(util.isUInt32(options.locktime));
|
||||
assert(util.isUInt32(options.locktime), 'Locktime must be a uint32.');
|
||||
this.locktime = options.locktime;
|
||||
}
|
||||
|
||||
if (options.changeIndex != null) {
|
||||
assert(util.isNumber(options.changeIndex));
|
||||
this.changeIndex = options.changeIndex;
|
||||
if (options.changeIndex !== -1) {
|
||||
assert(util.isUInt32(options.changeIndex),
|
||||
'Change index must be a uint32.');
|
||||
this.changeIndex = options.changeIndex;
|
||||
} else {
|
||||
this.changeIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -115,12 +120,16 @@ MTX.fromOptions = function fromOptions(options) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Clone the transaction.
|
||||
* Clone the transaction. Note that
|
||||
* this will not carry over the view.
|
||||
* @returns {MTX}
|
||||
*/
|
||||
|
||||
MTX.prototype.clone = function clone() {
|
||||
return new MTX(this);
|
||||
var mtx = new MTX();
|
||||
mtx.inject(this);
|
||||
mtx.changeIndex = this.changeIndex;
|
||||
return mtx;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -211,8 +220,8 @@ MTX.prototype.addTX = function addTX(tx, index, height) {
|
||||
|
||||
/**
|
||||
* Add an output.
|
||||
* @param {Address|Script|Output|Object} options
|
||||
* @param {Amount?} value - Only needs to be present for non-output options.
|
||||
* @param {Address|Script|Output|Object} script - Script or output options.
|
||||
* @param {Amount?} value
|
||||
* @returns {Output}
|
||||
*
|
||||
* @example
|
||||
@ -222,24 +231,14 @@ MTX.prototype.addTX = function addTX(tx, index, height) {
|
||||
* mtx.addOutput(script, 100000);
|
||||
*/
|
||||
|
||||
MTX.prototype.addOutput = function addOutput(options, value) {
|
||||
MTX.prototype.addOutput = function addOutput(script, value) {
|
||||
var output;
|
||||
|
||||
if (typeof options === 'string')
|
||||
options = Address.fromBase58(options);
|
||||
|
||||
if (options instanceof Address)
|
||||
options = Script.fromAddress(options);
|
||||
|
||||
output = new Output();
|
||||
|
||||
if (options instanceof Script) {
|
||||
if (value != null) {
|
||||
assert(util.isUInt53(value), 'Value must be a uint53.');
|
||||
output.script.fromOptions(options);
|
||||
output.value = value;
|
||||
output = Output.fromScript(script, value);
|
||||
} else {
|
||||
output.fromOptions(options);
|
||||
assert(util.isUInt53(output.value), 'Value must be a uint53.');
|
||||
output = Output.fromOptions(script);
|
||||
}
|
||||
|
||||
this.outputs.push(output);
|
||||
@ -1404,7 +1403,7 @@ MTX.fromRaw = function fromRaw(data, enc) {
|
||||
*/
|
||||
|
||||
MTX.prototype.toTX = function toTX() {
|
||||
return new TX(this);
|
||||
return new TX().inject(this);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1414,7 +1413,7 @@ MTX.prototype.toTX = function toTX() {
|
||||
*/
|
||||
|
||||
MTX.fromTX = function fromTX(tx) {
|
||||
return new MTX(tx);
|
||||
return new MTX().inject(tx);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1834,8 +1833,8 @@ function sortRandom(a, b) {
|
||||
}
|
||||
|
||||
function sortInputs(a, b) {
|
||||
var ahash = a.prevout.rhash();
|
||||
var bhash = b.prevout.rhash();
|
||||
var ahash = a.prevout.txid();
|
||||
var bhash = b.prevout.txid();
|
||||
var cmp = util.strcmp(ahash, bhash);
|
||||
|
||||
if (cmp !== 0)
|
||||
|
||||
@ -26,8 +26,15 @@ function Outpoint(hash, index) {
|
||||
if (!(this instanceof Outpoint))
|
||||
return new Outpoint(hash, index);
|
||||
|
||||
this.hash = hash || encoding.NULL_HASH;
|
||||
this.index = index != null ? index : 0xffffffff;
|
||||
this.hash = encoding.NULL_HASH;
|
||||
this.index = 0xffffffff;
|
||||
|
||||
if (hash != null) {
|
||||
assert(typeof hash === 'string', 'Hash must be a string.');
|
||||
assert(util.isUInt32(index), 'Index must be a uint32.');
|
||||
this.hash = hash;
|
||||
this.index = index;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -37,8 +44,9 @@ function Outpoint(hash, index) {
|
||||
*/
|
||||
|
||||
Outpoint.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(typeof options.hash === 'string');
|
||||
assert(util.isNumber(options.index));
|
||||
assert(options, 'Outpoint data is required.');
|
||||
assert(typeof options.hash === 'string', 'Hash must be a string.');
|
||||
assert(util.isUInt32(options.index), 'Index must be a uint32.');
|
||||
this.hash = options.hash;
|
||||
this.index = options.index;
|
||||
return this;
|
||||
@ -73,6 +81,15 @@ Outpoint.prototype.rhash = function rhash() {
|
||||
return util.revHex(this.hash);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get little-endian hash.
|
||||
* @returns {Hash}
|
||||
*/
|
||||
|
||||
Outpoint.prototype.txid = function txid() {
|
||||
return this.rhash();
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize outpoint to a key
|
||||
* suitable for a hash table.
|
||||
@ -185,8 +202,9 @@ Outpoint.fromRaw = function fromRaw(data) {
|
||||
*/
|
||||
|
||||
Outpoint.prototype.fromJSON = function fromJSON(json) {
|
||||
assert(typeof json.hash === 'string');
|
||||
assert(util.isNumber(json.index));
|
||||
assert(json, 'Outpoint data is required.');
|
||||
assert(typeof json.hash === 'string', 'Hash must be a string.');
|
||||
assert(util.isUInt32(json.index), 'Index must be a uint32.');
|
||||
this.hash = util.revHex(json.hash);
|
||||
this.index = json.index;
|
||||
return this;
|
||||
@ -225,7 +243,8 @@ Outpoint.fromJSON = function fromJSON(json) {
|
||||
*/
|
||||
|
||||
Outpoint.prototype.fromTX = function fromTX(tx, index) {
|
||||
assert(util.isNumber(index));
|
||||
assert(tx);
|
||||
assert(typeof index === 'number');
|
||||
this.hash = tx.hash('hex');
|
||||
this.index = index;
|
||||
return this;
|
||||
|
||||
@ -11,6 +11,7 @@ var assert = require('assert');
|
||||
var util = require('../utils/util');
|
||||
var Amount = require('../btc/amount');
|
||||
var Network = require('../protocol/network');
|
||||
var Address = require('../primitives/address');
|
||||
var Script = require('../script/script');
|
||||
var StaticWriter = require('../utils/staticwriter');
|
||||
var BufferReader = require('../utils/reader');
|
||||
@ -47,7 +48,7 @@ Output.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(options, 'Output data is required.');
|
||||
|
||||
if (options.value) {
|
||||
assert(util.isInt53(options.value));
|
||||
assert(util.isUInt53(options.value), 'Value must be a uint53.');
|
||||
this.value = options.value;
|
||||
}
|
||||
|
||||
@ -70,6 +71,53 @@ Output.fromOptions = function fromOptions(options) {
|
||||
return new Output().fromOptions(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from script/value pair.
|
||||
* @private
|
||||
* @param {Script|Address} script
|
||||
* @param {Amount} value
|
||||
* @returns {Output}
|
||||
*/
|
||||
|
||||
Output.prototype.fromScript = function fromScript(script, value) {
|
||||
if (typeof script === 'string')
|
||||
script = Address.fromBase58(script);
|
||||
|
||||
if (script instanceof Address)
|
||||
script = Script.fromAddress(script);
|
||||
|
||||
assert(script instanceof Script, 'Script must be a Script.');
|
||||
assert(util.isUInt53(value), 'Value must be a uint53.');
|
||||
|
||||
this.script = script;
|
||||
this.value = value;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate output from script/value pair.
|
||||
* @param {Script|Address} script
|
||||
* @param {Amount} value
|
||||
* @returns {Output}
|
||||
*/
|
||||
|
||||
Output.fromScript = function fromScript(script, value) {
|
||||
return new Output().fromScript(script, value);
|
||||
};
|
||||
|
||||
/**
|
||||
* Clone the output.
|
||||
* @returns {Output}
|
||||
*/
|
||||
|
||||
Output.prototype.clone = function clone() {
|
||||
var output = new Output();
|
||||
output.value = this.value;
|
||||
output.script.inject(this.script);
|
||||
return output;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the script type as a string.
|
||||
* @returns {ScriptType} type
|
||||
@ -199,7 +247,8 @@ Output.prototype.isDust = function isDust(rate) {
|
||||
*/
|
||||
|
||||
Output.prototype.fromJSON = function fromJSON(json) {
|
||||
assert(typeof json.value === 'string');
|
||||
assert(json, 'Output data is required.');
|
||||
assert(typeof json.value === 'string', 'Value must be a string.');
|
||||
this.value = Amount.value(json.value);
|
||||
this.script.fromJSON(json.script);
|
||||
return this;
|
||||
|
||||
@ -94,29 +94,29 @@ TX.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(options, 'TX data is required.');
|
||||
|
||||
if (options.version != null) {
|
||||
assert(util.isUInt32(options.version));
|
||||
assert(util.isUInt32(options.version), 'Version must be a uint32.');
|
||||
this.version = options.version;
|
||||
}
|
||||
|
||||
if (options.flag != null) {
|
||||
assert(util.isUInt8(options.flag));
|
||||
assert(util.isUInt8(options.flag), 'Flag must be a uint8.');
|
||||
this.flag = options.flag;
|
||||
}
|
||||
|
||||
if (options.inputs) {
|
||||
assert(Array.isArray(options.inputs));
|
||||
assert(Array.isArray(options.inputs), 'Inputs must be an array.');
|
||||
for (i = 0; i < options.inputs.length; i++)
|
||||
this.inputs.push(new Input(options.inputs[i]));
|
||||
}
|
||||
|
||||
if (options.outputs) {
|
||||
assert(Array.isArray(options.outputs));
|
||||
assert(Array.isArray(options.outputs), 'Outputs must be an array.');
|
||||
for (i = 0; i < options.outputs.length; i++)
|
||||
this.outputs.push(new Output(options.outputs[i]));
|
||||
}
|
||||
|
||||
if (options.locktime != null) {
|
||||
assert(util.isUInt32(options.locktime));
|
||||
assert(util.isUInt32(options.locktime), 'Locktime must be a uint32.');
|
||||
this.locktime = options.locktime;
|
||||
}
|
||||
|
||||
@ -139,7 +139,36 @@ TX.fromOptions = function fromOptions(options) {
|
||||
*/
|
||||
|
||||
TX.prototype.clone = function clone() {
|
||||
return new TX(this);
|
||||
return new TX().inject(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from tx.
|
||||
* Used for cloning.
|
||||
* @private
|
||||
* @param {TX} tx
|
||||
* @returns {TX}
|
||||
*/
|
||||
|
||||
TX.prototype.inject = function inject(tx) {
|
||||
var i, input, output;
|
||||
|
||||
this.version = tx.version;
|
||||
this.flag = tx.flag;
|
||||
|
||||
for (i = 0; i < tx.inputs.length; i++) {
|
||||
input = tx.inputs[i];
|
||||
this.inputs.push(input.clone());
|
||||
}
|
||||
|
||||
for (i = 0; i < tx.outputs.length; i++) {
|
||||
output = tx.outputs[i];
|
||||
this.outputs.push(output.clone());
|
||||
}
|
||||
|
||||
this.locktime = tx.locktime;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -147,14 +147,14 @@ Script.prototype.fromOptions = function fromOptions(options) {
|
||||
if (options.raw) {
|
||||
if (!options.code)
|
||||
return this.fromRaw(options.raw);
|
||||
assert(Buffer.isBuffer(options.raw));
|
||||
assert(Buffer.isBuffer(options.raw), 'Raw must be a Buffer.');
|
||||
this.raw = options.raw;
|
||||
}
|
||||
|
||||
if (options.code) {
|
||||
if (!options.raw)
|
||||
return this.fromCode(options.code);
|
||||
assert(Array.isArray(options.code));
|
||||
assert(Array.isArray(options.code), 'Code must be an array.');
|
||||
this.code = options.code;
|
||||
}
|
||||
|
||||
@ -284,7 +284,21 @@ Script.fromCode = function fromCode(code) {
|
||||
*/
|
||||
|
||||
Script.prototype.clone = function clone() {
|
||||
return new Script(this.raw);
|
||||
return new Script().inject(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from script.
|
||||
* Used for cloning.
|
||||
* @private
|
||||
* @param {Script} script
|
||||
* @returns {Script}
|
||||
*/
|
||||
|
||||
Script.prototype.inject = function inject(script) {
|
||||
this.code = script.code.slice();
|
||||
this.raw = script.raw;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -388,7 +402,7 @@ Script.prototype.toJSON = function toJSON() {
|
||||
*/
|
||||
|
||||
Script.prototype.fromJSON = function fromJSON(json) {
|
||||
assert(typeof json === 'string');
|
||||
assert(typeof json === 'string', 'Code must be a string.');
|
||||
return this.fromRaw(new Buffer(json, 'hex'));
|
||||
};
|
||||
|
||||
@ -417,12 +431,14 @@ Script.prototype.getSubscript = function getSubscript(lastSep) {
|
||||
|
||||
for (i = lastSep; i < this.code.length; i++) {
|
||||
op = this.code[i];
|
||||
|
||||
if (op.value === -1)
|
||||
break;
|
||||
|
||||
code.push(op);
|
||||
}
|
||||
|
||||
return new Script(code);
|
||||
return Script.fromCode(code);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -434,21 +450,42 @@ Script.prototype.getSubscript = function getSubscript(lastSep) {
|
||||
*/
|
||||
|
||||
Script.prototype.removeSeparators = function removeSeparators() {
|
||||
var code = [];
|
||||
var i, op;
|
||||
var found = false;
|
||||
var i, op, code;
|
||||
|
||||
// Optimizing for the common case:
|
||||
// Check for any separators first.
|
||||
for (i = 0; i < this.code.length; i++) {
|
||||
op = this.code[i];
|
||||
|
||||
if (op.value === -1)
|
||||
break;
|
||||
|
||||
if (op.value === opcodes.OP_CODESEPARATOR) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return this.clone();
|
||||
|
||||
// Uncommon case: someone actually
|
||||
// has a code separator. Go through
|
||||
// and remove them all.
|
||||
code = [];
|
||||
|
||||
for (i = 0; i < this.code.length; i++) {
|
||||
op = this.code[i];
|
||||
|
||||
if (op.value === -1)
|
||||
break;
|
||||
|
||||
if (op.value !== opcodes.OP_CODESEPARATOR)
|
||||
code.push(op);
|
||||
}
|
||||
|
||||
if (code.length === this.code.length)
|
||||
return this.clone();
|
||||
|
||||
return new Script(code);
|
||||
return Script.fromCode(code);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -165,7 +165,20 @@ Witness.prototype.toASM = function toASM(decode) {
|
||||
*/
|
||||
|
||||
Witness.prototype.clone = function clone() {
|
||||
return new Witness(this.items.slice());
|
||||
return new Witness().inject(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from witness.
|
||||
* Used for cloning.
|
||||
* @private
|
||||
* @param {Witness} witness
|
||||
* @returns {Witness}
|
||||
*/
|
||||
|
||||
Witness.prototype.inject = function inject(witness) {
|
||||
this.items = witness.items.slice();
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -387,7 +400,7 @@ Witness.prototype.toJSON = function toJSON() {
|
||||
*/
|
||||
|
||||
Witness.prototype.fromJSON = function fromJSON(json) {
|
||||
assert(typeof json === 'string');
|
||||
assert(typeof json === 'string', 'Witness must be a string.');
|
||||
return this.fromRaw(new Buffer(json, 'hex'));
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user