witness improvements.
This commit is contained in:
parent
30f4a0e7ec
commit
38ce14270a
@ -154,8 +154,8 @@ Block.prototype.__defineGetter__('commitmentHash', function() {
|
||||
|
||||
for (i = 0; i < coinbase.outputs.length; i++) {
|
||||
commitment = coinbase.outputs[i].script;
|
||||
if (bcoin.script.isCommitment(commitment)) {
|
||||
commitmentHash = bcoin.script.getCommitmentHash(commitment);
|
||||
if (commitment.isCommitment()) {
|
||||
commitmentHash = commitment.getCommitmentHash();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,11 +63,11 @@ Witness.prototype.isPubkeyhashInput = function isPubkeyhashInput(hash) {
|
||||
};
|
||||
|
||||
Witness.prototype.isMultisigInput = function isMultisigInput(keys) {
|
||||
return Script.isMultisigInput(this.items, keys);
|
||||
return Script.isMultisigInput(this.items, keys, true);
|
||||
};
|
||||
|
||||
Witness.prototype.isScripthashInput = function isScripthashInput(redeem) {
|
||||
return Script.isScripthashInput(this.items, redeem);
|
||||
return Script.isScripthashInput(this.items, redeem, true);
|
||||
};
|
||||
|
||||
Witness.prototype.getRedeem = function getRedeem() {
|
||||
@ -77,6 +77,53 @@ Witness.prototype.getRedeem = function getRedeem() {
|
||||
return this.redeem;
|
||||
};
|
||||
|
||||
Witness.fromString = function fromString(items) {
|
||||
var i, op;
|
||||
|
||||
items = items.trim().split(/\s+/);
|
||||
|
||||
// Remove OP_ prefixes and lowercase
|
||||
for (i = 0; i < items.length; i++) {
|
||||
op = items[i];
|
||||
if (typeof op === 'string') {
|
||||
op = op.toLowerCase();
|
||||
if (op.indexOf('op_') === 0)
|
||||
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') {
|
||||
op = new Buffer([0xff]);
|
||||
} else if (op === '0' || op === 'false') {
|
||||
op = new Buffer([]);
|
||||
} else if (op === 'true') {
|
||||
op = new Buffer([1]);
|
||||
} else if (+op >= 1 && +op <= 16) {
|
||||
op = new Buffer([+op]);
|
||||
} else if (constants.opcodes[op] == null) {
|
||||
if (op[0] === '[')
|
||||
op = op.slice(1, -1);
|
||||
if (op.indexOf('0x') === 0)
|
||||
op = op.substring(2);
|
||||
assert(utils.isHex(op), 'Non hex-string.');
|
||||
op = new Buffer(op, 'hex');
|
||||
} else {
|
||||
assert(false, 'Non-stack item in witness string.');
|
||||
}
|
||||
|
||||
items[i] = op;
|
||||
}
|
||||
|
||||
return new Witness(items);
|
||||
};
|
||||
|
||||
function Stack(items) {
|
||||
this.items = items || [];
|
||||
this.alt = [];
|
||||
@ -1360,10 +1407,10 @@ Script.prototype.getInputAddress = function getInputAddress(prev, isWitness) {
|
||||
isWitness ? 'witnesspubkeyhash' : 'pubkeyhash');
|
||||
}
|
||||
|
||||
if (this.isMultisigInput())
|
||||
if (this.isMultisigInput(null, isWitness))
|
||||
return;
|
||||
|
||||
if (this.isScripthashInput()) {
|
||||
if (this.isScripthashInput(null, isWitness)) {
|
||||
return bcoin.address.compileData(this.code[this.code.length - 1],
|
||||
isWitness ? 'witnessscripthash' : 'scripthash');
|
||||
}
|
||||
@ -1627,8 +1674,8 @@ Script.getInputType = function getInputType(code, prev, isWitness) {
|
||||
|
||||
type = (Script.isPubkeyInput(code) && 'pubkey')
|
||||
|| (Script.isPubkeyhashInput(code) && 'pubkeyhash')
|
||||
|| (Script.isMultisigInput(code) && 'multisig')
|
||||
|| (Script.isScripthashInput(code) && 'scripthash')
|
||||
|| (Script.isMultisigInput(code, null, isWitness) && 'multisig')
|
||||
|| (Script.isScripthashInput(code, null, isWitness) && 'scripthash')
|
||||
|| 'unknown';
|
||||
|
||||
if (isWitness) {
|
||||
@ -1684,21 +1731,26 @@ Script.prototype.isMultisigInput = function isMultisigInput(keys) {
|
||||
return Script.isMultisigInput(this.code, keys);
|
||||
};
|
||||
|
||||
Script.isMultisigInput = function isMultisigInput(code, keys) {
|
||||
Script.isMultisigInput = function isMultisigInput(code, keys, isWitness) {
|
||||
var i;
|
||||
|
||||
// We need to rule out scripthash because
|
||||
// it may look like multisig. This is
|
||||
// strange because it's technically a
|
||||
// recursive call.
|
||||
if (this.isScripthashInput())
|
||||
if (Script.isScripthashInput(null, isWitness))
|
||||
return false;
|
||||
|
||||
if (code.length < 3)
|
||||
return false;
|
||||
|
||||
if (code[0] !== 0 && !script.isDummy(code[0]))
|
||||
return false;
|
||||
if (isWitness) {
|
||||
if (!script.isDummy(code[0]))
|
||||
return false;
|
||||
} else {
|
||||
if (code[0] !== 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 1; i < code.length; i++) {
|
||||
if (!Script.isSignature(code[i]))
|
||||
@ -1714,7 +1766,7 @@ Script.prototype.isScripthashInput = function isScripthashInput(redeem) {
|
||||
return Script.isScripthashInput(this.code, redeem);
|
||||
};
|
||||
|
||||
Script.isScripthashInput = function isScripthashInput(code, redeem) {
|
||||
Script.isScripthashInput = function isScripthashInput(code, redeem, isWitness) {
|
||||
var raw;
|
||||
|
||||
// Grab the raw redeem script.
|
||||
@ -1722,9 +1774,13 @@ Script.isScripthashInput = function isScripthashInput(code, redeem) {
|
||||
|
||||
// Need at least one data element with
|
||||
// the redeem script. NOTE: NOT THE CASE FOR SEGWIT!
|
||||
// if (code.length < 2)
|
||||
if (code.length < 1)
|
||||
return false;
|
||||
if (isWitness) {
|
||||
if (code.length < 1)
|
||||
return false;
|
||||
} else {
|
||||
if (code.length < 2)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Last data element should be an array
|
||||
// for the redeem script.
|
||||
@ -2144,93 +2200,49 @@ Script.prototype.getArgs = function getArgs() {
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Witnesses aren't scripts, but we still
|
||||
// want to convert [0] to OP_0, [0xff] to 1negate, etc.
|
||||
Script.decodeWitness = function decodeWitness(witness) {
|
||||
var s = [];
|
||||
var chunk, i;
|
||||
|
||||
for (i = 0; i < witness.length; i++) {
|
||||
chunk = witness[i];
|
||||
|
||||
if (chunk.length <= 1) {
|
||||
if (chunk.length === 0)
|
||||
op = new Buffer([]);
|
||||
else if (chunk[0] >= 1 && chunk <= 16)
|
||||
op = chunk[0];
|
||||
else if (chunk[0] === 0xff)
|
||||
op = '1negate';
|
||||
}
|
||||
|
||||
s.push(op);
|
||||
}
|
||||
|
||||
return s;
|
||||
};
|
||||
|
||||
Script.encodeWitness = function encodeWitness(s) {
|
||||
var witness = [];
|
||||
var chunk, i;
|
||||
|
||||
for (i = 0; i < s.length; i++) {
|
||||
chunk = s[i];
|
||||
|
||||
if (chunk === 0)
|
||||
chunk = new Buffer([]);
|
||||
else if (chunk >= 1 && chunk <= 16)
|
||||
chunk = new Buffer([chunk]);
|
||||
else if (chunk === '1negate')
|
||||
chunk = new Buffer([0xff]);
|
||||
|
||||
assert(Buffer.isBuffer(chunk));
|
||||
|
||||
witness.push(chunk);
|
||||
}
|
||||
|
||||
return witness;
|
||||
};
|
||||
|
||||
Script.fromShittyString = function fromShittyString(s) {
|
||||
Script.fromString = function fromString(code) {
|
||||
var i, op;
|
||||
|
||||
s = s.split(/\s+/);
|
||||
code = code.trim().split(/\s+/);
|
||||
|
||||
// Remove OP_ prefixes and lowercase
|
||||
for (i = 0; i < s.length; i++) {
|
||||
op = s[i];
|
||||
for (i = 0; i < code.length; i++) {
|
||||
op = code[i];
|
||||
if (typeof op === 'string') {
|
||||
op = op.toLowerCase();
|
||||
if (op.indexOf('op_') === 0)
|
||||
op = op.slice(3);
|
||||
}
|
||||
s[i] = op;
|
||||
code[i] = op;
|
||||
}
|
||||
|
||||
// Convert OP_0 to array, convert OP_1-OP_16
|
||||
// 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 < s.length; i++) {
|
||||
op = s[i];
|
||||
for (i = 0; i < code.length; i++) {
|
||||
op = code[i];
|
||||
|
||||
if (op === '-1' || op === -1)
|
||||
if (op === '-1') {
|
||||
op = '1negate';
|
||||
else if (op === '0' || op === 0 || op === 'false')
|
||||
op = [];
|
||||
else if (op === 'true')
|
||||
} else if (op === '0' || op === 'false') {
|
||||
op = 0;
|
||||
} else if (op === 'true') {
|
||||
op = 1;
|
||||
else if (+op >= 1 && +op <= 16)
|
||||
} else if (+op >= 1 && +op <= 16) {
|
||||
op = +op;
|
||||
|
||||
if (typeof op === 'string' && constants.opcodes[op] == null) {
|
||||
} else if (constants.opcodes[op] == null) {
|
||||
if (op[0] === '[')
|
||||
op = op.slice(1, -1);
|
||||
if (op.indexOf('0x') === 0)
|
||||
op = op.substring(2);
|
||||
assert(utils.isHex(op), 'Non hex-string.');
|
||||
op = new Buffer(op, 'hex');
|
||||
}
|
||||
|
||||
s[i] = op;
|
||||
code[i] = op;
|
||||
}
|
||||
|
||||
return new Script(s);
|
||||
return new Script(code);
|
||||
};
|
||||
|
||||
Script.verify = function verify(input, witness, output, tx, i, flags) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user