mtx: refactor templating.
This commit is contained in:
parent
e8f2c3321c
commit
0db8677139
@ -601,6 +601,17 @@ KeyRing.prototype.ownOutput = function ownOutput(tx, index) {
|
||||
return addressMap[hash] === true;
|
||||
};
|
||||
|
||||
KeyRing.prototype.getRedeem = function(hash) {
|
||||
if (this.program && utils.equal(hash, this.programHash))
|
||||
return this.program;
|
||||
|
||||
if (this.script && utils.equal(hash, this.scriptHash160))
|
||||
return this.script;
|
||||
|
||||
if (this.script && utils.equal(hash, this.scriptHash256))
|
||||
return this.script;
|
||||
};
|
||||
|
||||
/**
|
||||
* Build input scripts templates for a transaction (does not
|
||||
* sign, only creates signature slots). Only builds scripts
|
||||
|
||||
176
lib/bcoin/mtx.js
176
lib/bcoin/mtx.js
@ -218,7 +218,7 @@ MTX.prototype.addOutput = function addOutput(options, value) {
|
||||
*/
|
||||
|
||||
MTX.prototype.scriptInput = function scriptInput(index, ring) {
|
||||
var input, prev, n, i, vector, redeemScript, witnessScript;
|
||||
var input, prev, redeem;
|
||||
|
||||
// Get the input
|
||||
input = this.inputs[index];
|
||||
@ -248,57 +248,82 @@ MTX.prototype.scriptInput = function scriptInput(index, ring) {
|
||||
// with segwit: figuring out where the redeem script and witness
|
||||
// redeem scripts go.
|
||||
if (prev.isScripthash()) {
|
||||
if (ring.program && utils.equal(prev.get(1), ring.programHash)) {
|
||||
// Witness program nested in regular P2SH.
|
||||
redeemScript = ring.program.toRaw();
|
||||
vector = input.witness;
|
||||
if (ring.program.isWitnessScripthash()) {
|
||||
// P2WSH nested within pay-to-scripthash
|
||||
// (it had to be this complicated, didn't it?)
|
||||
witnessScript = ring.script.toRaw();
|
||||
prev = ring.script;
|
||||
} else if (ring.program.isWitnessPubkeyhash()) {
|
||||
// P2WPKH nested within pay-to-scripthash.
|
||||
prev = Script.fromPubkeyhash(ring.keyHash);
|
||||
} else {
|
||||
assert(false, 'Unknown program.');
|
||||
redeem = ring.getRedeem(prev.get(1));
|
||||
|
||||
if (!redeem)
|
||||
return false;
|
||||
|
||||
// Witness program nested in regular P2SH.
|
||||
if (redeem.isProgram()) {
|
||||
// P2WSH nested within pay-to-scripthash.
|
||||
if (redeem.isWitnessScripthash()) {
|
||||
prev = ring.getRedeem(redeem.get(1));
|
||||
if (!prev)
|
||||
return false;
|
||||
this.scriptVector(prev, input.witness, ring);
|
||||
input.witness.push(prev.toRaw());
|
||||
input.script.push(redeem.toRaw());
|
||||
input.script.compile();
|
||||
return true;
|
||||
}
|
||||
} else if (ring.script && utils.equal(prev.get(1), ring.scriptHash160)) {
|
||||
// Regular P2SH.
|
||||
redeemScript = ring.script.toRaw();
|
||||
vector = input.script;
|
||||
prev = ring.script;
|
||||
} else {
|
||||
|
||||
// P2WPKH nested within pay-to-scripthash.
|
||||
if (redeem.isWitnessPubkeyhash()) {
|
||||
prev = Script.fromPubkeyhash(ring.keyHash);
|
||||
this.scriptVector(prev, input.witness, ring);
|
||||
input.script.push(redeem.toRaw());
|
||||
input.script.compile();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Unknown witness program.
|
||||
return false;
|
||||
}
|
||||
} else if (prev.isProgram()) {
|
||||
// Witness program.
|
||||
vector = input.witness;
|
||||
|
||||
if (prev.isWitnessScripthash()) {
|
||||
// Bare P2WSH.
|
||||
if (!ring.script || !utils.equal(prev.get(1), ring.scriptHash256))
|
||||
return false;
|
||||
|
||||
witnessScript = ring.script.toRaw();
|
||||
prev = ring.script;
|
||||
} else if (prev.isWitnessPubkeyhash()) {
|
||||
// Bare P2WPKH.
|
||||
if (!utils.equal(prev.get(1), ring.keyHash))
|
||||
return false;
|
||||
|
||||
prev = Script.fromPubkeyhash(prev.get(1));
|
||||
} else {
|
||||
// Bare... who knows?
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Wow, a normal output! Praise be to Jengus and Gord.
|
||||
vector = input.script;
|
||||
// Regular P2SH.
|
||||
this.scriptVector(redeem, input.script, ring);
|
||||
input.script.push(redeem.toRaw());
|
||||
input.script.compile();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Witness program.
|
||||
if (prev.isProgram()) {
|
||||
// Bare P2WSH.
|
||||
if (prev.isWitnessScripthash()) {
|
||||
redeem = ring.getRedeem(prev.get(1));
|
||||
|
||||
if (!redeem)
|
||||
return false;
|
||||
|
||||
this.scriptVector(redeem, input.witness, ring);
|
||||
input.witness.push(redeem.toRaw());
|
||||
input.script.compile();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Bare P2WPKH.
|
||||
if (prev.isWitnessPubkeyhash()) {
|
||||
prev = Script.fromPubkeyhash(prev.get(1));
|
||||
this.scriptVector(prev, input.witness, ring);
|
||||
input.script.compile();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Bare... who knows?
|
||||
return false;
|
||||
}
|
||||
|
||||
// Wow, a normal output! Praise be to Jengus and Gord.
|
||||
this.scriptVector(prev, input.script, ring);
|
||||
return true;
|
||||
};
|
||||
|
||||
MTX.prototype.scriptVector = function scriptVector(prev, vector, ring) {
|
||||
var i, n;
|
||||
|
||||
// P2PK
|
||||
if (prev.isPubkey()) {
|
||||
// P2PK
|
||||
if (!utils.equal(prev.get(1), ring.publicKey))
|
||||
return false;
|
||||
|
||||
@ -307,8 +332,12 @@ MTX.prototype.scriptInput = function scriptInput(index, ring) {
|
||||
return true;
|
||||
|
||||
vector.set(0, opcodes.OP_0);
|
||||
} else if (prev.isPubkeyhash()) {
|
||||
// P2PKH
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// P2PKH
|
||||
if (prev.isPubkeyhash()) {
|
||||
if (!utils.equal(prev.get(2), ring.keyHash))
|
||||
return false;
|
||||
|
||||
@ -318,8 +347,12 @@ MTX.prototype.scriptInput = function scriptInput(index, ring) {
|
||||
|
||||
vector.set(0, opcodes.OP_0);
|
||||
vector.set(1, ring.publicKey);
|
||||
} else if (prev.isMultisig()) {
|
||||
// Multisig
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Multisig
|
||||
if (prev.isMultisig()) {
|
||||
if (prev.indexOf(ring.publicKey) === -1)
|
||||
return false;
|
||||
|
||||
@ -338,41 +371,28 @@ MTX.prototype.scriptInput = function scriptInput(index, ring) {
|
||||
// Fill script with `n` signature slots.
|
||||
for (i = 0; i < n; i++)
|
||||
vector.set(i + 1, opcodes.OP_0);
|
||||
} else {
|
||||
if (prev.indexOf(ring.publicKey) === -1)
|
||||
return false;
|
||||
|
||||
// Already has a script template (at least)
|
||||
if (vector.length !== 0)
|
||||
return true;
|
||||
|
||||
// Likely a non-standard scripthash multisig
|
||||
// input. Determine n value by counting keys.
|
||||
// Also, only allow nonstandard types for
|
||||
// scripthash.
|
||||
vector.set(0, opcodes.OP_0);
|
||||
|
||||
// Fill script with `n` signature slots.
|
||||
for (i = 0; i < prev.length; i++) {
|
||||
if (Script.isKey(prev.get(i)))
|
||||
vector.set(i + 1, opcodes.OP_0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// P2SH requires the redeem
|
||||
// script after signatures.
|
||||
if (redeemScript)
|
||||
input.script.push(redeemScript);
|
||||
if (prev.indexOf(ring.publicKey) === -1)
|
||||
return false;
|
||||
|
||||
// P2WSH requires the witness
|
||||
// script after signatures.
|
||||
if (witnessScript)
|
||||
input.witness.push(witnessScript);
|
||||
// Already has a script template (at least)
|
||||
if (vector.length !== 0)
|
||||
return true;
|
||||
|
||||
input.script.compile();
|
||||
input.witness.compile();
|
||||
// Likely a non-standard scripthash multisig
|
||||
// input. Determine n value by counting keys.
|
||||
// Also, only allow nonstandard types for
|
||||
// scripthash.
|
||||
vector.set(0, opcodes.OP_0);
|
||||
|
||||
return true;
|
||||
// Fill script with `n` signature slots.
|
||||
for (i = 0; i < prev.length; i++) {
|
||||
if (Script.isKey(prev.get(i)))
|
||||
vector.set(i + 1, opcodes.OP_0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user