script parsing.
This commit is contained in:
parent
caf52c0579
commit
00e7fcc1ad
@ -42,7 +42,7 @@ function Coin(tx, index) {
|
|||||||
this.version = options.version;
|
this.version = options.version;
|
||||||
this.height = options.height;
|
this.height = options.height;
|
||||||
this.value = options.value;
|
this.value = options.value;
|
||||||
this.script = options.script;
|
this.script = bcoin.script(options.script);
|
||||||
this.coinbase = options.coinbase;
|
this.coinbase = options.coinbase;
|
||||||
this.hash = options.hash;
|
this.hash = options.hash;
|
||||||
this.index = options.index;
|
this.index = options.index;
|
||||||
@ -117,7 +117,7 @@ Coin.prototype.toJSON = function toJSON() {
|
|||||||
version: this.version,
|
version: this.version,
|
||||||
height: this.height,
|
height: this.height,
|
||||||
value: utils.btc(this.value),
|
value: utils.btc(this.value),
|
||||||
script: utils.toHex(this.script.encode()),
|
script: utils.toHex(bcoin.protocol.framer(this.script)),
|
||||||
coinbase: this.coinbase,
|
coinbase: this.coinbase,
|
||||||
hash: this.hash ? utils.revHex(this.hash) : null,
|
hash: this.hash ? utils.revHex(this.hash) : null,
|
||||||
index: this.index
|
index: this.index
|
||||||
|
|||||||
@ -21,9 +21,9 @@ function Input(options, tx) {
|
|||||||
assert(typeof options.script !== 'string');
|
assert(typeof options.script !== 'string');
|
||||||
|
|
||||||
this.prevout = options.prevout;
|
this.prevout = options.prevout;
|
||||||
this.script = options.script || new bcoin.script([]);
|
this.script = bcoin.script(options.script);
|
||||||
this.sequence = options.sequence == null ? 0xffffffff : options.sequence;
|
this.sequence = options.sequence == null ? 0xffffffff : options.sequence;
|
||||||
this.witness = options.witness || new bcoin.script.witness([]);
|
this.witness = bcoin.script.witness(options.witness);
|
||||||
this._mutable = !tx || (tx instanceof bcoin.mtx);
|
this._mutable = !tx || (tx instanceof bcoin.mtx);
|
||||||
|
|
||||||
if (options.coin)
|
if (options.coin)
|
||||||
@ -205,8 +205,8 @@ Input.prototype.toJSON = function toJSON() {
|
|||||||
index: this.prevout.index
|
index: this.prevout.index
|
||||||
},
|
},
|
||||||
coin: this.coin ? this.coin.toJSON() : null,
|
coin: this.coin ? this.coin.toJSON() : null,
|
||||||
script: utils.toHex(this.script.encode()),
|
script: utils.toHex(bcoin.protocol.framer.script(this.script)),
|
||||||
witness: utils.toHex(this.witness.encode()),
|
witness: utils.toHex(bcoin.protocol.framer.witness(this.witness)),
|
||||||
sequence: this.sequence
|
sequence: this.sequence
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -218,8 +218,8 @@ Input._fromJSON = function _fromJSON(json) {
|
|||||||
index: json.prevout.index
|
index: json.prevout.index
|
||||||
},
|
},
|
||||||
coin: json.coin ? bcoin.coin._fromJSON(json.coin) : null,
|
coin: json.coin ? bcoin.coin._fromJSON(json.coin) : null,
|
||||||
script: new bcoin.script(new Buffer(json.script, 'hex')),
|
script: bcoin.protocol.parser.parseScript(new Buffer(json.script, 'hex')),
|
||||||
witness: new bcoin.script.witness(new Buffer(json.witness, 'hex')),
|
witness: bcoin.protocol.parser.parseWitness(new Buffer(json.witness, 'hex')),
|
||||||
sequence: json.sequence
|
sequence: json.sequence
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -140,10 +140,10 @@ MTX.prototype.addInput = function addInput(options, index) {
|
|||||||
|
|
||||||
input = bcoin.input(options, this);
|
input = bcoin.input(options, this);
|
||||||
|
|
||||||
if (options.script)
|
if (options.script instanceof bcoin.script)
|
||||||
input.script = options.script.clone();
|
input.script = options.script.clone();
|
||||||
|
|
||||||
if (options.witness)
|
if (options.witness instanceof bcoin.script.witness)
|
||||||
input.witness = options.witness.clone();
|
input.witness = options.witness.clone();
|
||||||
|
|
||||||
this.inputs.push(input);
|
this.inputs.push(input);
|
||||||
@ -666,8 +666,10 @@ MTX.prototype.scriptOutput = function scriptOutput(index, options) {
|
|||||||
output = this.outputs[index];
|
output = this.outputs[index];
|
||||||
assert(output);
|
assert(output);
|
||||||
|
|
||||||
if (options.script)
|
if (options.script instanceof bcoin.script)
|
||||||
output.script = options.script.clone();
|
output.script = options.script.clone();
|
||||||
|
else if (options.script)
|
||||||
|
output.script = bcoin.script(options.script);
|
||||||
else
|
else
|
||||||
output.script = Script.createOutputScript(options);
|
output.script = Script.createOutputScript(options);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -29,7 +29,7 @@ function Output(options, tx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.value = utils.satoshi(value || new bn(0));
|
this.value = utils.satoshi(value || new bn(0));
|
||||||
this.script = options.script || new bcoin.script([]);
|
this.script = bcoin.script(options.script);
|
||||||
this._mutable = !tx || (tx instanceof bcoin.mtx);
|
this._mutable = !tx || (tx instanceof bcoin.mtx);
|
||||||
|
|
||||||
// For safety: do not allow usage of
|
// For safety: do not allow usage of
|
||||||
@ -114,7 +114,7 @@ Output.prototype.inspect = function inspect() {
|
|||||||
Output.prototype.toJSON = function toJSON() {
|
Output.prototype.toJSON = function toJSON() {
|
||||||
return {
|
return {
|
||||||
value: utils.btc(this.value),
|
value: utils.btc(this.value),
|
||||||
script: utils.toHex(this.script.encode())
|
script: utils.toHex(bcoin.protocol.framer.script(this.script))
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -335,7 +335,7 @@ Framer.utxo = function _utxo(coin, writer) {
|
|||||||
p.writeU32(coin.version);
|
p.writeU32(coin.version);
|
||||||
p.writeU32(height);
|
p.writeU32(height);
|
||||||
p.write64(coin.value);
|
p.write64(coin.value);
|
||||||
p.writeVarBytes(coin.script.encode());
|
Framer.script(coin.script, p);
|
||||||
|
|
||||||
if (!writer)
|
if (!writer)
|
||||||
p = p.render();
|
p = p.render();
|
||||||
@ -355,7 +355,7 @@ Framer.coin = function _coin(coin, extended, writer) {
|
|||||||
p.writeU32(coin.version);
|
p.writeU32(coin.version);
|
||||||
p.writeU32(height);
|
p.writeU32(height);
|
||||||
p.write64(coin.value);
|
p.write64(coin.value);
|
||||||
p.writeVarBytes(coin.script.encode());
|
Framer.script(coin.script, p);
|
||||||
p.writeU8(coin.coinbase ? 1 : 0);
|
p.writeU8(coin.coinbase ? 1 : 0);
|
||||||
|
|
||||||
if (extended) {
|
if (extended) {
|
||||||
@ -398,7 +398,7 @@ Framer.input = function _input(input, writer) {
|
|||||||
|
|
||||||
p.writeHash(input.prevout.hash);
|
p.writeHash(input.prevout.hash);
|
||||||
p.writeU32(input.prevout.index);
|
p.writeU32(input.prevout.index);
|
||||||
p.writeVarBytes(input.script.encode());
|
Framer.script(input.script, p);
|
||||||
p.writeU32(input.sequence);
|
p.writeU32(input.sequence);
|
||||||
|
|
||||||
if (!writer)
|
if (!writer)
|
||||||
@ -413,7 +413,7 @@ Framer.output = function _output(output, writer) {
|
|||||||
assert(output.value.byteLength() <= 8);
|
assert(output.value.byteLength() <= 8);
|
||||||
|
|
||||||
p.write64(output.value);
|
p.write64(output.value);
|
||||||
p.writeVarBytes(output.script.encode());
|
Framer.script(output.script, p);
|
||||||
|
|
||||||
if (!writer)
|
if (!writer)
|
||||||
p = p.render();
|
p = p.render();
|
||||||
@ -456,12 +456,28 @@ Framer.witnessTX = function _witnessTX(tx, writer) {
|
|||||||
return p;
|
return p;
|
||||||
};
|
};
|
||||||
|
|
||||||
Framer.witnessBlockSize = function witnessBlockSize(block) {
|
// Scripts require extra magic since they're
|
||||||
return Framer.witnessBlock(block, new BufferWriter())._witnessSize;
|
// so goddamn bizarre. Normally in an "encoded"
|
||||||
};
|
// script we don't include the varint size
|
||||||
|
// because scripthashes don't include them. This
|
||||||
|
// is why script.encode/decode is separate
|
||||||
|
// from the framer and parser.
|
||||||
|
Framer.script = function _script(script, writer) {
|
||||||
|
var data;
|
||||||
|
|
||||||
Framer.witnessTXSize = function witnessTXSize(tx) {
|
p = new BufferWriter(writer);
|
||||||
return Framer.witnessTXSize(tx, new BufferWriter())._witnessSize;
|
|
||||||
|
if (script.encode)
|
||||||
|
data = script.encode();
|
||||||
|
else
|
||||||
|
data = script.raw || bcoin.script.encode(script.code);
|
||||||
|
|
||||||
|
p.writeVarBytes(data);
|
||||||
|
|
||||||
|
if (!writer)
|
||||||
|
p = p.render();
|
||||||
|
|
||||||
|
return p;
|
||||||
};
|
};
|
||||||
|
|
||||||
Framer.witness = function _witness(witness, writer) {
|
Framer.witness = function _witness(witness, writer) {
|
||||||
@ -672,6 +688,54 @@ Framer.alert = function alert(data, writer) {
|
|||||||
return p;
|
return p;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Witness size
|
||||||
|
Framer.blockSizes = function blockSizes(block) {
|
||||||
|
var sizes = Framer.witnessBlock(block, new BufferWriter());
|
||||||
|
return {
|
||||||
|
size: sizes._size,
|
||||||
|
witnessSize: sizes._witnessSize
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Framer.txSizes = function txSizes(tx) {
|
||||||
|
var sizes = Framer.renderTX(tx, true, new BufferWriter());
|
||||||
|
return {
|
||||||
|
size: sizes._size,
|
||||||
|
witnessSize: sizes._witnessSize
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Size with witness (if present)
|
||||||
|
Framer.blockRealSize = function blockRealSize(block) {
|
||||||
|
return Framer.blockSizes(block).size;
|
||||||
|
};
|
||||||
|
|
||||||
|
Framer.txRealSize = function txRealSize(tx) {
|
||||||
|
return Framer.txSizes(tx).size;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Size without witness
|
||||||
|
Framer.blockSize = function blockSize(block) {
|
||||||
|
return Framer.block(block, new BufferWriter())._size;
|
||||||
|
};
|
||||||
|
|
||||||
|
Framer.txSize = function txSize(tx) {
|
||||||
|
return Framer.renderTX(tx, false, new BufferWriter())._size;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Virtual size
|
||||||
|
Framer.blockVsize = function blockVsize(block) {
|
||||||
|
var sizes = this.blockSizes(block);
|
||||||
|
var base = sizes.size - sizes.witnessSize;
|
||||||
|
return (base * 4 + sizes.witnessSize + 3) / 4 | 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Framer.txVsize = function txVsize(tx) {
|
||||||
|
var sizes = this.txSizes(tx);
|
||||||
|
var base = sizes.size - sizes.witnessSize;
|
||||||
|
return (base * 4 + sizes.witnessSize + 3) / 4 | 0;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -405,7 +405,7 @@ Parser.parseInput = function parseInput(p) {
|
|||||||
|
|
||||||
hash = p.readHash('hex');
|
hash = p.readHash('hex');
|
||||||
index = p.readU32();
|
index = p.readU32();
|
||||||
script = new bcoin.script(p.readVarBytes());
|
script = Parser.parseScript(p);
|
||||||
sequence = p.readU32();
|
sequence = p.readU32();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -413,6 +413,7 @@ Parser.parseInput = function parseInput(p) {
|
|||||||
hash: hash,
|
hash: hash,
|
||||||
index: index
|
index: index
|
||||||
},
|
},
|
||||||
|
coin: null,
|
||||||
script: script,
|
script: script,
|
||||||
sequence: sequence,
|
sequence: sequence,
|
||||||
_size: p.end()
|
_size: p.end()
|
||||||
@ -426,7 +427,7 @@ Parser.parseOutput = function parseOutput(p) {
|
|||||||
p.start();
|
p.start();
|
||||||
|
|
||||||
value = p.read64();
|
value = p.read64();
|
||||||
script = new bcoin.script(p.readVarBytes());
|
script = Parser.parseScript(p);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
value: value,
|
value: value,
|
||||||
@ -444,7 +445,7 @@ Parser.parseUTXO = function parseUTXO(p) {
|
|||||||
version = p.readU32();
|
version = p.readU32();
|
||||||
height = p.readU32();
|
height = p.readU32();
|
||||||
value = p.read64();
|
value = p.read64();
|
||||||
script = new bcoin.script(p.readVarBytes());
|
script = Parser.parseScript(p);
|
||||||
|
|
||||||
if (height === 0x7fffffff)
|
if (height === 0x7fffffff)
|
||||||
height = -1;
|
height = -1;
|
||||||
@ -467,7 +468,7 @@ Parser.parseCoin = function parseCoin(p, extended) {
|
|||||||
version = p.readU32();
|
version = p.readU32();
|
||||||
height = p.readU32();
|
height = p.readU32();
|
||||||
value = p.read64();
|
value = p.read64();
|
||||||
script = new bcoin.script(p.readVarBytes());
|
script = Parser.parseScript(p);
|
||||||
coinbase = p.readU8() === 1;
|
coinbase = p.readU8() === 1;
|
||||||
|
|
||||||
if (extended) {
|
if (extended) {
|
||||||
@ -510,7 +511,7 @@ Parser.parseTX = function parseTX(p) {
|
|||||||
tx = Parser.parseInput(p);
|
tx = Parser.parseInput(p);
|
||||||
|
|
||||||
txIn[i] = tx;
|
txIn[i] = tx;
|
||||||
txIn[i].witness = new bcoin.script.witness([]);
|
txIn[i].witness = { items: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
outCount = p.readVarint();
|
outCount = p.readVarint();
|
||||||
@ -611,9 +612,23 @@ Parser.parseWitnessTX = function parseWitnessTX(p) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Parser.parseScript = function parseScript(p) {
|
||||||
|
var data;
|
||||||
|
|
||||||
|
p = new BufferReader(p);
|
||||||
|
p.start();
|
||||||
|
data = p.readVarBytes();
|
||||||
|
|
||||||
|
return {
|
||||||
|
raw: data,
|
||||||
|
code: bcoin.script.decode(data),
|
||||||
|
_size: p.end()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
Parser.parseWitness = function parseWitness(p) {
|
Parser.parseWitness = function parseWitness(p) {
|
||||||
var items = [];
|
var items = [];
|
||||||
var witness, chunkCount, i;
|
var chunkCount, i;
|
||||||
|
|
||||||
p = new BufferReader(p);
|
p = new BufferReader(p);
|
||||||
p.start();
|
p.start();
|
||||||
@ -623,10 +638,10 @@ Parser.parseWitness = function parseWitness(p) {
|
|||||||
for (i = 0; i < chunkCount; i++)
|
for (i = 0; i < chunkCount; i++)
|
||||||
items.push(p.readVarBytes());
|
items.push(p.readVarBytes());
|
||||||
|
|
||||||
witness = new bcoin.script.witness(items);
|
return {
|
||||||
witness._size = p.end();
|
items: items,
|
||||||
|
_size: p.end()
|
||||||
return witness;
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.parseReject = function parseReject(p) {
|
Parser.parseReject = function parseReject(p) {
|
||||||
|
|||||||
@ -16,13 +16,19 @@ var STACK_FALSE = new Buffer([]);
|
|||||||
var STACK_NEGATE = new Buffer([0xff]);
|
var STACK_NEGATE = new Buffer([0xff]);
|
||||||
|
|
||||||
function Witness(items) {
|
function Witness(items) {
|
||||||
|
if (items instanceof Witness)
|
||||||
|
return items;
|
||||||
|
|
||||||
if (!(this instanceof Witness))
|
if (!(this instanceof Witness))
|
||||||
return new Witness(items);
|
return new Witness(items);
|
||||||
|
|
||||||
if (Buffer.isBuffer(items))
|
if (!items)
|
||||||
this.items = Witness.decode(items);
|
items = [];
|
||||||
else if (items)
|
|
||||||
this.items = items || [];
|
if (items.items)
|
||||||
|
items = items.items;
|
||||||
|
|
||||||
|
this.items = items || [];
|
||||||
|
|
||||||
this.redeem = null;
|
this.redeem = null;
|
||||||
}
|
}
|
||||||
@ -31,18 +37,6 @@ Witness.prototype.inspect = function inspect() {
|
|||||||
return Script.format(this.items);
|
return Script.format(this.items);
|
||||||
};
|
};
|
||||||
|
|
||||||
Witness.prototype.encode = function encode() {
|
|
||||||
return bcoin.protocol.framer.witness(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
Witness.encode = function encode(witness) {
|
|
||||||
return bcoin.protocol.framer.witness(witness);
|
|
||||||
};
|
|
||||||
|
|
||||||
Witness.decode = function decode(buf) {
|
|
||||||
return bcoin.protocol.parser.parseWitness(buf).items;
|
|
||||||
};
|
|
||||||
|
|
||||||
Witness.prototype.clone = function clone() {
|
Witness.prototype.clone = function clone() {
|
||||||
return new Witness(this.items.slice());
|
return new Witness(this.items.slice());
|
||||||
};
|
};
|
||||||
@ -91,19 +85,11 @@ Witness.fromString = function fromString(items) {
|
|||||||
|
|
||||||
items = items.trim().split(/\s+/);
|
items = items.trim().split(/\s+/);
|
||||||
|
|
||||||
// Remove OP_ prefixes and lowercase
|
|
||||||
for (i = 0; i < items.length; i++) {
|
for (i = 0; i < items.length; i++) {
|
||||||
op = items[i].toLowerCase();
|
op = items[i].toLowerCase();
|
||||||
|
|
||||||
if (op.indexOf('op_') === 0)
|
if (op.indexOf('op_') === 0)
|
||||||
op = op.slice(3);
|
op = op.slice(3);
|
||||||
items[i] = op;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert OP_FALSE to 0, convert OP_1-OP_16
|
|
||||||
// to number literals, convert -1 to OP_1NEGATE.
|
|
||||||
// Convert hex strings to arrays.
|
|
||||||
for (i = 0; i < items.length; i++) {
|
|
||||||
op = items[i];
|
|
||||||
|
|
||||||
if (op === '-1' || op === '1negate') {
|
if (op === '-1' || op === '1negate') {
|
||||||
op = STACK_NEGATE;
|
op = STACK_NEGATE;
|
||||||
@ -115,13 +101,12 @@ Witness.fromString = function fromString(items) {
|
|||||||
op = new Buffer([+op]);
|
op = new Buffer([+op]);
|
||||||
} else {
|
} else {
|
||||||
symbol = 'OP_' + op.toUpperCase();
|
symbol = 'OP_' + op.toUpperCase();
|
||||||
|
|
||||||
if (opcodes[symbol] == null) {
|
if (opcodes[symbol] == null) {
|
||||||
if (op[0] === '[')
|
if (op[0] === '[')
|
||||||
op = op.slice(1, -1);
|
op = op.slice(1, -1);
|
||||||
if (op.indexOf('0x') === 0)
|
if (op.indexOf('0x') === 0)
|
||||||
op = op.substring(2);
|
op = op.substring(2);
|
||||||
assert(utils.isHex(op), 'Non hex-string.');
|
assert(utils.isHex(op), 'Non-stack item in witness string.');
|
||||||
op = new Buffer(op, 'hex');
|
op = new Buffer(op, 'hex');
|
||||||
} else {
|
} else {
|
||||||
assert(false, 'Non-stack item in witness string.');
|
assert(false, 'Non-stack item in witness string.');
|
||||||
@ -445,6 +430,9 @@ Stack.isStack = function isStack(obj) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function Script(code) {
|
function Script(code) {
|
||||||
|
if (code instanceof Script)
|
||||||
|
return code;
|
||||||
|
|
||||||
if (!(this instanceof Script))
|
if (!(this instanceof Script))
|
||||||
return new Script(code);
|
return new Script(code);
|
||||||
|
|
||||||
@ -454,9 +442,16 @@ function Script(code) {
|
|||||||
} else {
|
} else {
|
||||||
if (!code)
|
if (!code)
|
||||||
code = [];
|
code = [];
|
||||||
assert(Array.isArray(code));
|
if (code.code) {
|
||||||
this.raw = null;
|
this.raw = code.raw || null;
|
||||||
this.code = code;
|
this.code = code.code;
|
||||||
|
if (!this.code)
|
||||||
|
this.code = Script.decode(this.raw);
|
||||||
|
} else {
|
||||||
|
assert(Array.isArray(code));
|
||||||
|
this.raw = null;
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.redeem = null;
|
this.redeem = null;
|
||||||
@ -2331,37 +2326,22 @@ Script.fromString = function fromString(code) {
|
|||||||
|
|
||||||
code = code.trim().split(/\s+/);
|
code = code.trim().split(/\s+/);
|
||||||
|
|
||||||
// Remove OP_ prefixes and lowercase
|
|
||||||
for (i = 0; i < code.length; i++) {
|
|
||||||
op = code[i].toLowerCase();
|
|
||||||
if (op.indexOf('op_') === 0)
|
|
||||||
op = op.slice(3);
|
|
||||||
code[i] = op;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert OP_FALSE to 0, convert OP_1-OP_16
|
|
||||||
// to number literals, convert -1 to OP_1NEGATE.
|
|
||||||
// Convert hex strings to arrays.
|
|
||||||
for (i = 0; i < code.length; i++) {
|
for (i = 0; i < code.length; i++) {
|
||||||
op = code[i];
|
op = code[i];
|
||||||
|
|
||||||
if (op === '-1')
|
if (op === '-1')
|
||||||
op = '1negate';
|
op = '1negate';
|
||||||
else if (op === '0' || op === 'false')
|
|
||||||
op = '0';
|
|
||||||
else if (op === 'true')
|
|
||||||
op = '1';
|
|
||||||
else if (+op >= 1 && +op <= 16)
|
|
||||||
op = +op + '';
|
|
||||||
|
|
||||||
symbol = 'OP_' + op.toUpperCase();
|
symbol = (op + '').toUpperCase();
|
||||||
|
if (symbol.indexOf('OP_') !== 0)
|
||||||
|
symbol = 'OP_' + op;
|
||||||
|
|
||||||
if (opcodes[symbol] == null) {
|
if (opcodes[symbol] == null) {
|
||||||
if (op[0] === '[')
|
if (op[0] === '[')
|
||||||
op = op.slice(1, -1);
|
op = op.slice(1, -1);
|
||||||
if (op.indexOf('0x') === 0)
|
if (op.indexOf('0x') === 0)
|
||||||
op = op.substring(2);
|
op = op.substring(2);
|
||||||
assert(utils.isHex(op), 'Non hex-string.');
|
assert(utils.isHex(op), 'Unknown opcode.');
|
||||||
op = new Buffer(op, 'hex');
|
op = new Buffer(op, 'hex');
|
||||||
code[i] = op;
|
code[i] = op;
|
||||||
continue;
|
continue;
|
||||||
@ -2404,7 +2384,7 @@ Script.toSmall = function toSmall(op) {
|
|||||||
|
|
||||||
Script.fromSymbolic = function fromSymbolic(items) {
|
Script.fromSymbolic = function fromSymbolic(items) {
|
||||||
var code = new Array(items.length);
|
var code = new Array(items.length);
|
||||||
var i, op, symbol;
|
var i, op;
|
||||||
|
|
||||||
for (i = 0; i < items.length; i++) {
|
for (i = 0; i < items.length; i++) {
|
||||||
op = items[i];
|
op = items[i];
|
||||||
@ -2414,24 +2394,16 @@ Script.fromSymbolic = function fromSymbolic(items) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
op = (op + '').toLowerCase();
|
|
||||||
if (op.indexOf('op_') === 0)
|
|
||||||
op = op.slice(3);
|
|
||||||
|
|
||||||
if (+op === -1)
|
if (+op === -1)
|
||||||
op = '1negate';
|
op = '1negate';
|
||||||
else if (+op === 0 || op === 'false')
|
|
||||||
op = '0';
|
|
||||||
else if (+op === 1 || op === 'true')
|
|
||||||
op = '1';
|
|
||||||
else if (+op >= 1 && +op <= 16)
|
|
||||||
op = +op + '';
|
|
||||||
|
|
||||||
symbol = 'OP_' + op.toUpperCase();
|
op = (op + '').toUpperCase();
|
||||||
|
if (op.indexOf('OP_') !== 0)
|
||||||
|
op = 'OP_' + op;
|
||||||
|
|
||||||
code[i] = opcodes[symbol];
|
assert(opcodes[op] != null, 'Unknown opcode.');
|
||||||
|
|
||||||
assert(code[i] != null, 'Unknown opcode.');
|
code[i] = opcodes[op];
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Script(code);
|
return new Script(code);
|
||||||
|
|||||||
@ -66,6 +66,52 @@ function TX(data, block, index) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TX.prototype.clone = function clone() {
|
||||||
|
var copy, i;
|
||||||
|
|
||||||
|
copy = {
|
||||||
|
version: this.version,
|
||||||
|
inputs: [],
|
||||||
|
outputs: [],
|
||||||
|
locktime: this.locktime,
|
||||||
|
flag: this.flag,
|
||||||
|
ts: this.ts,
|
||||||
|
block: this.block,
|
||||||
|
index: this.index,
|
||||||
|
height: this.height
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i = 0; i < this.inputs.length; i++) {
|
||||||
|
copy.inputs.push({
|
||||||
|
prevout: {
|
||||||
|
hash: this.inputs[i].prevout.hash,
|
||||||
|
index: this.inputs[i].prevout.index
|
||||||
|
},
|
||||||
|
coin: null,
|
||||||
|
script: {
|
||||||
|
code: this.inputs[i].script.code.slice(),
|
||||||
|
raw: this.inputs[i].script.raw
|
||||||
|
},
|
||||||
|
witness: {
|
||||||
|
items: this.inputs[i].witness.items.slice()
|
||||||
|
},
|
||||||
|
sequence: this.inputs[i].sequence
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < this.outputs.length; i++) {
|
||||||
|
copy.outputs.push({
|
||||||
|
value: this.outputs[i].value.clone(),
|
||||||
|
script: {
|
||||||
|
code: this.inputs[i].script.code.slice(),
|
||||||
|
raw: this.inputs[i].script.raw
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TX(copy);
|
||||||
|
};
|
||||||
|
|
||||||
TX.prototype.setBlock = function setBlock(block, index) {
|
TX.prototype.setBlock = function setBlock(block, index) {
|
||||||
this.ts = block.ts;
|
this.ts = block.ts;
|
||||||
this.block = block.hash('hex');
|
this.block = block.hash('hex');
|
||||||
@ -252,7 +298,7 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) {
|
|||||||
for (i = 0; i < copy.outputs.length; i++) {
|
for (i = 0; i < copy.outputs.length; i++) {
|
||||||
if (i !== index) {
|
if (i !== index) {
|
||||||
copy.outputs[i].script = new Script([]);
|
copy.outputs[i].script = new Script([]);
|
||||||
copy.outputs[i].value = new bn('ffffffffffffffff', 'hex');
|
copy.outputs[i].value = utils.U64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user