witness improvements.

This commit is contained in:
Christopher Jeffrey 2016-03-14 20:53:17 -07:00
parent 30f4a0e7ec
commit 38ce14270a
2 changed files with 91 additions and 79 deletions

View File

@ -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;
}
}

View File

@ -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) {