tx: pass coins into scripting system.
This commit is contained in:
parent
d4b8afa747
commit
f7e50e3435
@ -217,19 +217,17 @@ MTX.prototype.addOutput = function addOutput(options, value) {
|
||||
* Build input script (or witness) templates (with
|
||||
* OP_0 in place of signatures).
|
||||
* @param {Number} index - Input index.
|
||||
* @param {Coin|Output} coin
|
||||
* @param {KeyRing} ring
|
||||
* @returns {Boolean} Whether the script was able to be built.
|
||||
*/
|
||||
|
||||
MTX.prototype.scriptInput = function scriptInput(index, ring) {
|
||||
MTX.prototype.scriptInput = function scriptInput(index, coin, ring) {
|
||||
var input = this.inputs[index];
|
||||
var prev, redeem;
|
||||
|
||||
assert(input, 'Input does not exist.');
|
||||
|
||||
// We should have previous outputs by now.
|
||||
if (!input.coin)
|
||||
return false;
|
||||
assert(coin, 'No coin passed.');
|
||||
|
||||
// Don't bother with any below calculation
|
||||
// if the output is already templated.
|
||||
@ -239,7 +237,7 @@ MTX.prototype.scriptInput = function scriptInput(index, ring) {
|
||||
}
|
||||
|
||||
// Get the previous output's script
|
||||
prev = input.coin.script;
|
||||
prev = coin.script;
|
||||
|
||||
// This is easily the hardest part about
|
||||
// building a transaction with segwit:
|
||||
@ -402,33 +400,32 @@ MTX.prototype.scriptVector = function scriptVector(prev, vector, ring) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
MTX.prototype.signInputAsync = function signInputAsync(index, ring, type) {
|
||||
return workerPool.signInput(this, index, ring, type);
|
||||
MTX.prototype.signInputAsync = function signInputAsync(index, coin, ring, type) {
|
||||
return workerPool.signInput(this, index, coin, ring, type);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sign an input.
|
||||
* @param {Number} index - Index of input being signed.
|
||||
* @param {Coin|Output} coin
|
||||
* @param {KeyRing} ring - Private key.
|
||||
* @param {SighashType} type
|
||||
* @returns {Boolean} Whether the input was able to be signed.
|
||||
*/
|
||||
|
||||
MTX.prototype.signInput = function signInput(index, ring, type) {
|
||||
MTX.prototype.signInput = function signInput(index, coin, ring, type) {
|
||||
var input = this.inputs[index];
|
||||
var version = 0;
|
||||
var redeem = false;
|
||||
var key = ring.privateKey;
|
||||
var prev, vector, sig, result;
|
||||
var prev, value, vector, sig, result;
|
||||
|
||||
assert(input, 'Input does not exist.');
|
||||
|
||||
// We should have previous outputs by now.
|
||||
if (!input.coin)
|
||||
return false;
|
||||
assert(coin, 'No coin passed.');
|
||||
|
||||
// Get the previous output's script
|
||||
prev = input.coin.script;
|
||||
prev = coin.script;
|
||||
value = coin.value;
|
||||
vector = input.script;
|
||||
|
||||
// Grab regular p2sh redeem script.
|
||||
@ -460,7 +457,7 @@ MTX.prototype.signInput = function signInput(index, ring, type) {
|
||||
}
|
||||
|
||||
// Create our signature.
|
||||
sig = this.signature(index, prev, key, type, version);
|
||||
sig = this.signature(index, prev, value, key, type, version);
|
||||
|
||||
if (redeem) {
|
||||
redeem = vector.pop();
|
||||
@ -618,88 +615,19 @@ MTX.prototype.signVector = function signVector(prev, vector, sig, ring) {
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Combine and sort multisig signatures for script.
|
||||
* Mimics bitcoind's behavior.
|
||||
* @param {Number} index
|
||||
* @param {Script} prev
|
||||
* @param {Witness|Script} vector
|
||||
* @param {Number} version
|
||||
* @param {Buffer} data
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
MTX.prototype.combine = function combine(index, prev, vector, version, data) {
|
||||
var m = prev.getSmall(0);
|
||||
var sigs = [];
|
||||
var map = {};
|
||||
var result = false;
|
||||
var i, j, sig, type, msg, key, pub, res;
|
||||
|
||||
if (data)
|
||||
sigs.push(data);
|
||||
|
||||
for (i = 1; i < vector.length; i++) {
|
||||
sig = vector.get(i);
|
||||
if (Script.isSignature(sig))
|
||||
sigs.push(sig);
|
||||
}
|
||||
|
||||
for (i = 0; i < sigs.length; i++) {
|
||||
sig = sigs[i];
|
||||
type = sig[sig.length - 1];
|
||||
|
||||
msg = this.signatureHash(index, prev, type, version);
|
||||
|
||||
for (j = 1; j < prev.length - 2; j++) {
|
||||
key = prev.get(j);
|
||||
pub = key.toString('hex');
|
||||
|
||||
if (map[pub])
|
||||
continue;
|
||||
|
||||
res = Script.checksig(msg, sig, key);
|
||||
|
||||
if (res) {
|
||||
map[pub] = sig;
|
||||
if (util.equal(sig, data))
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vector.clear();
|
||||
vector.push(opcodes.OP_0);
|
||||
|
||||
for (i = 1; i < prev.length - 2; i++) {
|
||||
key = prev.get(i);
|
||||
pub = key.toString('hex');
|
||||
sig = map[pub];
|
||||
if (sig)
|
||||
vector.push(sig);
|
||||
}
|
||||
|
||||
while (vector.length - 1 < m)
|
||||
vector.push(opcodes.OP_0);
|
||||
|
||||
vector.compile();
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a signature suitable for inserting into scriptSigs/witnesses.
|
||||
* @param {Number} index - Index of input being signed.
|
||||
* @param {Script} prev - Previous output script or redeem script
|
||||
* (in the case of witnesspubkeyhash, this should be the generated
|
||||
* p2pkh script).
|
||||
* @param {Amount} value - Previous output value.
|
||||
* @param {SighashType} type
|
||||
* @param {Number} version - Sighash version (0=legacy, 1=segwit).
|
||||
* @returns {Buffer} Signature in DER format.
|
||||
*/
|
||||
|
||||
MTX.prototype.signature = function signature(index, prev, key, type, version) {
|
||||
MTX.prototype.signature = function signature(index, prev, value, key, type, version) {
|
||||
var hash;
|
||||
|
||||
if (type == null)
|
||||
@ -710,7 +638,7 @@ MTX.prototype.signature = function signature(index, prev, key, type, version) {
|
||||
|
||||
// Get the hash of the current tx, minus the other
|
||||
// inputs, plus the sighash type.
|
||||
hash = this.signatureHash(index, prev, type, version);
|
||||
hash = this.signatureHash(index, prev, value, type, version);
|
||||
|
||||
// Sign the transaction with our one input
|
||||
return Script.sign(hash, key, type);
|
||||
@ -722,10 +650,19 @@ MTX.prototype.signature = function signature(index, prev, key, type, version) {
|
||||
*/
|
||||
|
||||
MTX.prototype.isSigned = function isSigned() {
|
||||
for (var i = 0; i < this.inputs.length; i++) {
|
||||
if (!this.isInputSigned(i))
|
||||
var i, input, coin;
|
||||
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
input = this.inputs[i];
|
||||
coin = input.coin;
|
||||
|
||||
if (!coin)
|
||||
return false;
|
||||
|
||||
if (!this.isInputSigned(i, coin))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
@ -735,19 +672,15 @@ MTX.prototype.isSigned = function isSigned() {
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
MTX.prototype.isInputSigned = function isInputSigned(index) {
|
||||
MTX.prototype.isInputSigned = function isInputSigned(index, coin) {
|
||||
var input = this.inputs[index];
|
||||
var prev, vector, redeem, result;
|
||||
|
||||
assert(input, 'Input does not exist.');
|
||||
|
||||
// We can't check for signatures unless
|
||||
// we have the previous output.
|
||||
if (!input.coin)
|
||||
return false;
|
||||
assert(coin, 'No coin passed.');
|
||||
|
||||
// Get the prevout's script
|
||||
prev = input.coin.script;
|
||||
prev = coin.script;
|
||||
|
||||
// Script length, needed for multisig
|
||||
vector = input.script;
|
||||
@ -839,7 +772,7 @@ MTX.prototype.isVectorSigned = function isVectorSigned(prev, vector) {
|
||||
|
||||
MTX.prototype.template = function template(ring) {
|
||||
var total = 0;
|
||||
var i;
|
||||
var i, input, coin;
|
||||
|
||||
if (Array.isArray(ring)) {
|
||||
for (i = 0; i < ring.length; i++)
|
||||
@ -848,11 +781,17 @@ MTX.prototype.template = function template(ring) {
|
||||
}
|
||||
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
if (!ring.ownInput(this, i))
|
||||
input = this.inputs[i];
|
||||
coin = input.coin;
|
||||
|
||||
if (!coin)
|
||||
continue;
|
||||
|
||||
if (!ring.ownOutput(coin))
|
||||
continue;
|
||||
|
||||
// Build script for input
|
||||
if (!this.scriptInput(i, ring))
|
||||
if (!this.scriptInput(i, coin, ring))
|
||||
continue;
|
||||
|
||||
total++;
|
||||
@ -871,7 +810,7 @@ MTX.prototype.template = function template(ring) {
|
||||
|
||||
MTX.prototype.sign = function sign(ring, type) {
|
||||
var total = 0;
|
||||
var i;
|
||||
var i, input, coin;
|
||||
|
||||
if (Array.isArray(ring)) {
|
||||
for (i = 0; i < ring.length; i++)
|
||||
@ -882,15 +821,21 @@ MTX.prototype.sign = function sign(ring, type) {
|
||||
assert(ring.privateKey, 'No private key available.');
|
||||
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
if (!ring.ownInput(this, i))
|
||||
input = this.inputs[i];
|
||||
coin = input.coin;
|
||||
|
||||
if (!coin)
|
||||
continue;
|
||||
|
||||
if (!ring.ownOutput(coin))
|
||||
continue;
|
||||
|
||||
// Build script for input
|
||||
if (!this.scriptInput(i, ring))
|
||||
if (!this.scriptInput(i, coin, ring))
|
||||
continue;
|
||||
|
||||
// Sign input
|
||||
if (!this.signInput(i, ring, type))
|
||||
if (!this.signInput(i, coin, ring, type))
|
||||
continue;
|
||||
|
||||
total++;
|
||||
|
||||
@ -460,12 +460,13 @@ TX.prototype.hasWitness = function hasWitness() {
|
||||
* @returns {Buffer} Signature hash.
|
||||
*/
|
||||
|
||||
TX.prototype.signatureHash = function signatureHash(index, prev, type, version) {
|
||||
TX.prototype.signatureHash = function signatureHash(index, prev, value, type, version) {
|
||||
if (typeof type === 'string')
|
||||
type = constants.hashType[type.toUpperCase()];
|
||||
|
||||
assert(index >= 0 && index < this.inputs.length);
|
||||
assert(prev instanceof Script);
|
||||
assert(typeof value === 'number');
|
||||
|
||||
// Traditional sighashing
|
||||
if (version === 0)
|
||||
@ -473,7 +474,7 @@ TX.prototype.signatureHash = function signatureHash(index, prev, type, version)
|
||||
|
||||
// Segwit sighashing
|
||||
if (version === 1)
|
||||
return this.signatureHashV1(index, prev, type);
|
||||
return this.signatureHashV1(index, prev, value, type);
|
||||
|
||||
assert(false, 'Unknown sighash version.');
|
||||
};
|
||||
@ -599,7 +600,7 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) {
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, type) {
|
||||
TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, value, type) {
|
||||
var i, bw, input, output, prevouts, sequences, outputs;
|
||||
|
||||
if (!(type & constants.hashType.ANYONECANPAY)) {
|
||||
@ -678,7 +679,7 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, type) {
|
||||
bw.writeHash(input.prevout.hash);
|
||||
bw.writeU32(input.prevout.index);
|
||||
bw.writeVarBytes(prev.toRaw());
|
||||
bw.write64(input.coin.value);
|
||||
bw.write64(value);
|
||||
bw.writeU32(input.sequence);
|
||||
bw.writeBytes(outputs);
|
||||
bw.writeU32(this.locktime);
|
||||
@ -694,7 +695,7 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, type) {
|
||||
*/
|
||||
|
||||
TX.prototype.verify = function verify(flags) {
|
||||
var i;
|
||||
var i, input, coin;
|
||||
|
||||
if (this.inputs.length === 0)
|
||||
return false;
|
||||
@ -703,7 +704,13 @@ TX.prototype.verify = function verify(flags) {
|
||||
return true;
|
||||
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
if (!this.verifyInput(i, flags))
|
||||
input = this.inputs[i];
|
||||
coin = input.coin;
|
||||
|
||||
if (!coin)
|
||||
return false;
|
||||
|
||||
if (!this.verifyInput(i, coin, flags))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -714,25 +721,25 @@ TX.prototype.verify = function verify(flags) {
|
||||
* Verify a transaction input.
|
||||
* @param {Number} index - Index of output being
|
||||
* verified.
|
||||
* @param {Coin|Output} coin - Previous output.
|
||||
* @param {VerifyFlags} [flags=STANDARD_VERIFY_FLAGS]
|
||||
* @returns {Boolean} Whether the input is valid.
|
||||
*/
|
||||
|
||||
TX.prototype.verifyInput = function verifyInput(index, flags) {
|
||||
TX.prototype.verifyInput = function verifyInput(index, coin, flags) {
|
||||
var input = this.inputs[index];
|
||||
|
||||
assert(input, 'Input does not exist.');
|
||||
|
||||
if (!input.coin)
|
||||
return false;
|
||||
assert(coin, 'No coin passed.');
|
||||
|
||||
try {
|
||||
Script.verify(
|
||||
input.script,
|
||||
input.witness,
|
||||
input.coin.script,
|
||||
coin.script,
|
||||
this,
|
||||
index,
|
||||
coin.value,
|
||||
flags
|
||||
);
|
||||
} catch (e) {
|
||||
@ -766,14 +773,15 @@ TX.prototype.verifyAsync = co(function* verifyAsync(flags) {
|
||||
* Verify a transaction input asynchronously.
|
||||
* @param {Number} index - Index of output being
|
||||
* verified.
|
||||
* @param {Coin|Output} coin - Previous output.
|
||||
* @param {VerifyFlags} [flags=STANDARD_VERIFY_FLAGS]
|
||||
* @returns {Boolean} Whether the input is valid.
|
||||
*/
|
||||
|
||||
TX.prototype.verifyInputAsync = co(function* verifyInputAsync(index, flags) {
|
||||
TX.prototype.verifyInputAsync = co(function* verifyInputAsync(index, coin, flags) {
|
||||
var input = this.inputs[index];
|
||||
assert(input, 'Input does not exist.');
|
||||
return yield workerPool.verifyInput(this, index, flags);
|
||||
return yield workerPool.verifyInput(this, index, coin, flags);
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@ -309,7 +309,7 @@ Script.prototype.removeSeparators = function removeSeparators() {
|
||||
* @returns {Boolean} Whether the execution was successful.
|
||||
*/
|
||||
|
||||
Script.prototype.execute = function execute(stack, flags, tx, index, version) {
|
||||
Script.prototype.execute = function execute(stack, flags, tx, index, value, version) {
|
||||
var ip = 0;
|
||||
var lastSep = 0;
|
||||
var opCount = 0;
|
||||
@ -997,7 +997,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, version) {
|
||||
|
||||
if (sig.length > 0) {
|
||||
type = sig[sig.length - 1];
|
||||
hash = tx.signatureHash(index, subscript, type, version);
|
||||
hash = tx.signatureHash(index, subscript, value, type, version);
|
||||
res = Script.checksig(hash, sig, key, flags);
|
||||
}
|
||||
|
||||
@ -1076,7 +1076,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, version) {
|
||||
|
||||
if (sig.length > 0) {
|
||||
type = sig[sig.length - 1];
|
||||
hash = tx.signatureHash(index, subscript, type, version);
|
||||
hash = tx.signatureHash(index, subscript, value, type, version);
|
||||
|
||||
if (Script.checksig(hash, sig, key, flags)) {
|
||||
isig++;
|
||||
@ -3091,7 +3091,7 @@ Script.getSmall = function getSmall(op) {
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Script.verify = function verify(input, witness, output, tx, i, flags) {
|
||||
Script.verify = function verify(input, witness, output, tx, i, value, flags) {
|
||||
var stack, copy, raw, redeem, hadWitness;
|
||||
|
||||
if (flags == null)
|
||||
@ -3106,14 +3106,14 @@ Script.verify = function verify(input, witness, output, tx, i, flags) {
|
||||
stack = new Stack();
|
||||
|
||||
// Execute the input script
|
||||
input.execute(stack, flags, tx, i, 0);
|
||||
input.execute(stack, flags, tx, i, value, 0);
|
||||
|
||||
// Copy the stack for P2SH
|
||||
if (flags & constants.flags.VERIFY_P2SH)
|
||||
copy = stack.clone();
|
||||
|
||||
// Execute the previous output script.
|
||||
output.execute(stack, flags, tx, i, 0);
|
||||
output.execute(stack, flags, tx, i, value, 0);
|
||||
|
||||
// Verify the stack values.
|
||||
if (stack.length === 0 || !Script.bool(stack.top(-1)))
|
||||
@ -3127,7 +3127,7 @@ Script.verify = function verify(input, witness, output, tx, i, flags) {
|
||||
throw new ScriptError('WITNESS_MALLEATED');
|
||||
|
||||
// Verify the program in the output script.
|
||||
Script.verifyProgram(witness, output, flags, tx, i);
|
||||
Script.verifyProgram(witness, output, flags, tx, i, value);
|
||||
|
||||
// Force a cleanstack
|
||||
stack.length = 1;
|
||||
@ -3151,7 +3151,7 @@ Script.verify = function verify(input, witness, output, tx, i, flags) {
|
||||
redeem = new Script(raw);
|
||||
|
||||
// Execute the redeem script.
|
||||
redeem.execute(stack, flags, tx, i, 0);
|
||||
redeem.execute(stack, flags, tx, i, value, 0);
|
||||
|
||||
// Verify the the stack values.
|
||||
if (stack.length === 0 || !Script.bool(stack.top(-1)))
|
||||
@ -3165,7 +3165,7 @@ Script.verify = function verify(input, witness, output, tx, i, flags) {
|
||||
throw new ScriptError('WITNESS_MALLEATED_P2SH');
|
||||
|
||||
// Verify the program in the redeem script.
|
||||
Script.verifyProgram(witness, redeem, flags, tx, i);
|
||||
Script.verifyProgram(witness, redeem, flags, tx, i, value);
|
||||
|
||||
// Force a cleanstack.
|
||||
stack.length = 1;
|
||||
@ -3202,7 +3202,7 @@ Script.verify = function verify(input, witness, output, tx, i, flags) {
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i) {
|
||||
Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i, value) {
|
||||
var program = output.toProgram();
|
||||
var stack = witness.toStack();
|
||||
var j, witnessScript, redeem;
|
||||
@ -3252,7 +3252,7 @@ Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i) {
|
||||
}
|
||||
|
||||
// Verify the redeem script.
|
||||
redeem.execute(stack, flags, tx, i, 1);
|
||||
redeem.execute(stack, flags, tx, i, value, 1);
|
||||
|
||||
// Verify the stack values.
|
||||
if (stack.length !== 1 || !Script.bool(stack.top(-1)))
|
||||
@ -3273,7 +3273,7 @@ Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i) {
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i) {
|
||||
Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i, value) {
|
||||
var mastRoot = new BufferWriter();
|
||||
var scriptRoot = new BufferWriter();
|
||||
var scripts = new BufferWriter();
|
||||
@ -3388,7 +3388,7 @@ Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i) {
|
||||
}
|
||||
|
||||
output = new Script(scripts.render());
|
||||
output.execute(stack, flags, tx, i, 1);
|
||||
output.execute(stack, flags, tx, i, value, 1);
|
||||
|
||||
if (stack.length !== 0)
|
||||
throw new ScriptError('EVAL_FALSE');
|
||||
|
||||
@ -346,8 +346,7 @@ TXDB.prototype.verifyInputs = co(function* verifyInputs(tx, block) {
|
||||
|
||||
if (coin) {
|
||||
if (this.options.verify && tx.height === -1) {
|
||||
input.coin = coin;
|
||||
if (!(yield tx.verifyInputAsync(i, flags)))
|
||||
if (!(yield tx.verifyInputAsync(i, coin, flags)))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -366,8 +365,7 @@ TXDB.prototype.verifyInputs = co(function* verifyInputs(tx, block) {
|
||||
// of it.
|
||||
if (coin) {
|
||||
if (this.options.verify && tx.height === -1) {
|
||||
input.coin = coin;
|
||||
if (!(yield tx.verifyInputAsync(i, flags)))
|
||||
if (!(yield tx.verifyInputAsync(i, coin, flags)))
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
@ -480,10 +478,8 @@ TXDB.prototype.resolveOutputs = co(function* resolveOutputs(tx, block, resolved)
|
||||
assert(input.prevout.index === i);
|
||||
|
||||
// We can finally verify this input.
|
||||
if (this.options.verify && orphan.tx.height === -1) {
|
||||
input.coin = coin;
|
||||
valid = yield orphan.tx.verifyInputAsync(orphan.index, flags);
|
||||
}
|
||||
if (this.options.verify && orphan.tx.height === -1)
|
||||
valid = yield orphan.tx.verifyInputAsync(orphan.index, coin, flags);
|
||||
|
||||
// If it's valid and fully resolved,
|
||||
// we can resolve _its_ outputs.
|
||||
|
||||
@ -48,11 +48,11 @@ jobs._execute = function execute(p) {
|
||||
case packets.types.VERIFY:
|
||||
return jobs.verify(p.tx, p.flags);
|
||||
case packets.types.VERIFYINPUT:
|
||||
return jobs.verifyInput(p.tx, p.index, p.flags);
|
||||
return jobs.verifyInput(p.tx, p.index, p.coin, p.flags);
|
||||
case packets.types.SIGN:
|
||||
return jobs.sign(p.tx, p.rings, p.type);
|
||||
case packets.types.SIGNINPUT:
|
||||
return jobs.signInput(p.tx, p.index, p.rings, p.type);
|
||||
return jobs.signInput(p.tx, p.index, p.coin, p.ring, p.type);
|
||||
case packets.types.ECVERIFY:
|
||||
return jobs.ecVerify(p.msg, p.sig, p.key);
|
||||
case packets.types.ECSIGN:
|
||||
@ -84,12 +84,13 @@ jobs.verify = function verify(tx, flags) {
|
||||
* @see TX#verifyInput
|
||||
* @param {TX} tx
|
||||
* @param {Number} index
|
||||
* @param {Output} coin
|
||||
* @param {VerifyFlags} flags
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
jobs.verifyInput = function verifyInput(tx, index, flags) {
|
||||
var result = tx.verifyInput(index, flags);
|
||||
jobs.verifyInput = function verifyInput(tx, index, coin, flags) {
|
||||
var result = tx.verifyInput(index, coin, flags);
|
||||
return new packets.VerifyInputResultPacket(result);
|
||||
};
|
||||
|
||||
@ -111,12 +112,13 @@ jobs.sign = function sign(tx, ring, type) {
|
||||
* @see MTX#signInput
|
||||
* @param {MTX} tx
|
||||
* @param {Number} index
|
||||
* @param {Output} coin
|
||||
* @param {KeyRing} ring
|
||||
* @param {SighashType} type
|
||||
*/
|
||||
|
||||
jobs.signInput = function signInput(tx, index, ring, type) {
|
||||
var result = tx.signInput(tx, index, ring, type);
|
||||
jobs.signInput = function signInput(tx, index, coin, ring, type) {
|
||||
var result = tx.signInput(tx, index, coin, ring, type);
|
||||
return packets.SignInputResultPacket.fromTX(tx, index, result);
|
||||
};
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@ var BufferReader = require('../utils/reader');
|
||||
var Script = require('../script/script');
|
||||
var Witness = require('../script/witness');
|
||||
var Coin = require('../primitives/coin');
|
||||
var Output = require('../primitives/output');
|
||||
|
||||
/*
|
||||
* Constants
|
||||
@ -233,7 +234,7 @@ function SignPacket(tx, rings, type) {
|
||||
Packet.call(this);
|
||||
this.tx = tx || null;
|
||||
this.rings = rings || [];
|
||||
this.type = type != null ? type : null;
|
||||
this.type = type != null ? type : 1;
|
||||
}
|
||||
|
||||
util.inherits(SignPacket, Packet);
|
||||
@ -252,7 +253,7 @@ SignPacket.prototype.toWriter = function toWriter(bw) {
|
||||
ring.toWriter(bw);
|
||||
}
|
||||
|
||||
bw.write8(this.type != null ? this.type : -1);
|
||||
bw.writeU8(this.type);
|
||||
};
|
||||
|
||||
SignPacket.fromRaw = function fromRaw(MTX, KeyRing, data) {
|
||||
@ -269,10 +270,7 @@ SignPacket.fromRaw = function fromRaw(MTX, KeyRing, data) {
|
||||
packet.rings.push(ring);
|
||||
}
|
||||
|
||||
packet.type = br.read8();
|
||||
|
||||
if (packet.type === -1)
|
||||
packet.type = null;
|
||||
packet.type = br.readU8();
|
||||
|
||||
return packet;
|
||||
};
|
||||
@ -355,10 +353,11 @@ SignResultPacket.fromRaw = function fromRaw(data) {
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
function VerifyInputPacket(tx, index, flags) {
|
||||
function VerifyInputPacket(tx, index, coin, flags) {
|
||||
Packet.call(this);
|
||||
this.tx = tx || null;
|
||||
this.index = index;
|
||||
this.coin = coin || null;
|
||||
this.flags = flags != null ? flags : null;
|
||||
}
|
||||
|
||||
@ -367,8 +366,10 @@ util.inherits(VerifyInputPacket, Packet);
|
||||
VerifyInputPacket.prototype.cmd = packetTypes.VERIFYINPUT;
|
||||
|
||||
VerifyInputPacket.prototype.toWriter = function toWriter(bw) {
|
||||
frameTX(this.tx, bw);
|
||||
this.tx.toWriter(bw);
|
||||
bw.writeVarint(this.index);
|
||||
bw.writeVarint(this.coin.value);
|
||||
this.coin.script.toWriter(bw);
|
||||
bw.write32(this.flags != null ? this.flags : -1);
|
||||
};
|
||||
|
||||
@ -376,8 +377,13 @@ VerifyInputPacket.fromRaw = function fromRaw(TX, data) {
|
||||
var br = new BufferReader(data, true);
|
||||
var packet = new VerifyInputPacket();
|
||||
|
||||
packet.tx = parseTX(TX, br);
|
||||
packet.tx = TX.fromReader(br);
|
||||
packet.index = br.readVarint();
|
||||
|
||||
packet.coin = new Output();
|
||||
packet.coin.value = br.readVarint();
|
||||
packet.coin.script.fromReader(br);
|
||||
|
||||
packet.flags = br.read32();
|
||||
|
||||
if (packet.flags === -1)
|
||||
@ -416,12 +422,13 @@ VerifyInputResultPacket.fromRaw = function fromRaw(data) {
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
function SignInputPacket(tx, index, ring, type) {
|
||||
function SignInputPacket(tx, index, coin, ring, type) {
|
||||
Packet.call(this);
|
||||
this.tx = tx || null;
|
||||
this.index = index;
|
||||
this.coin = coin || null;
|
||||
this.ring = ring || null;
|
||||
this.type = type != null ? type : null;
|
||||
this.type = type != null ? type : 1;
|
||||
}
|
||||
|
||||
util.inherits(SignInputPacket, Packet);
|
||||
@ -429,48 +436,27 @@ util.inherits(SignInputPacket, Packet);
|
||||
SignInputPacket.prototype.cmd = packetTypes.SIGNINPUT;
|
||||
|
||||
SignInputPacket.prototype.toWriter = function toWriter(bw) {
|
||||
var input = this.tx.inputs[this.index];
|
||||
|
||||
assert(input);
|
||||
assert(input.coin);
|
||||
|
||||
this.tx.toWriter(bw);
|
||||
bw.writeVarint(this.index);
|
||||
|
||||
bw.writeVarint(input.coin.value);
|
||||
input.coin.script.toWriter(bw);
|
||||
|
||||
bw.writeVarint(this.coin.value);
|
||||
this.coin.script.toWriter(bw);
|
||||
this.ring.toWriter(bw);
|
||||
|
||||
bw.write8(this.type != null ? this.type : -1);
|
||||
bw.writeU8(this.type);
|
||||
};
|
||||
|
||||
SignInputPacket.fromRaw = function fromRaw(MTX, KeyRing, data) {
|
||||
var br = new BufferReader(data, true);
|
||||
var packet = new SignInputPacket();
|
||||
var coin = new Coin();
|
||||
var input;
|
||||
|
||||
packet.tx = parseTX(MTX, br);
|
||||
packet.tx = MTX.fromReader(br);
|
||||
packet.index = br.readVarint();
|
||||
|
||||
coin.value = br.readVarint();
|
||||
coin.script.fromReader(br);
|
||||
packet.coin = new Output();
|
||||
packet.coin.value = br.readVarint();
|
||||
packet.coin.script.fromReader(br);
|
||||
|
||||
packet.ring = KeyRing.fromReader(br);
|
||||
|
||||
packet.type = br.read8();
|
||||
|
||||
if (packet.type === -1)
|
||||
packet.type = null;
|
||||
|
||||
input = packet.tx.inputs[packet.index];
|
||||
assert(input);
|
||||
|
||||
coin.hash = input.prevout.hash;
|
||||
coin.index = input.prevout.index;
|
||||
|
||||
input.coin = coin;
|
||||
packet.type = br.readU8();
|
||||
|
||||
return packet;
|
||||
};
|
||||
|
||||
@ -297,12 +297,13 @@ WorkerPool.prototype.sign = co(function* sign(tx, ring, type) {
|
||||
* Execute the tx input verification job (default timeout).
|
||||
* @param {TX} tx
|
||||
* @param {Number} index
|
||||
* @param {Coin|Output} coin
|
||||
* @param {VerifyFlags} flags
|
||||
* @returns {Promise} - Returns Boolean.
|
||||
*/
|
||||
|
||||
WorkerPool.prototype.verifyInput = co(function* verifyInput(tx, index, flags) {
|
||||
var packet = new packets.VerifyInputPacket(tx, index, flags);
|
||||
WorkerPool.prototype.verifyInput = co(function* verifyInput(tx, index, coin, flags) {
|
||||
var packet = new packets.VerifyInputPacket(tx, index, coin, flags);
|
||||
var result = yield this.execute(packet, -1);
|
||||
return result.value;
|
||||
});
|
||||
@ -311,13 +312,14 @@ WorkerPool.prototype.verifyInput = co(function* verifyInput(tx, index, flags) {
|
||||
* Execute the tx input signing job (default timeout).
|
||||
* @param {MTX} tx
|
||||
* @param {Number} index
|
||||
* @param {Coin|Output} coin
|
||||
* @param {KeyRing} ring
|
||||
* @param {SighashType} type
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
WorkerPool.prototype.signInput = co(function* signInput(tx, index, ring, type) {
|
||||
var packet = new packets.SignInputPacket(tx, index, ring, type);
|
||||
WorkerPool.prototype.signInput = co(function* signInput(tx, index, coin, ring, type) {
|
||||
var packet = new packets.SignInputPacket(tx, index, coin, ring, type);
|
||||
var result = yield this.execute(packet, -1);
|
||||
result.inject(tx);
|
||||
return result.value;
|
||||
|
||||
@ -81,7 +81,7 @@ describe('Mempool', function() {
|
||||
|
||||
prev = new bcoin.script([kp.publicKey, opcodes.OP_CHECKSIG]);
|
||||
t1.addInput(dummy(prev));
|
||||
sig = t1.signature(0, prev, kp.privateKey, 'all', 0);
|
||||
sig = t1.signature(0, prev, t1.inputs[0].coin.value, kp.privateKey, 'all', 0);
|
||||
t1.inputs[0].script = new bcoin.script([sig]);
|
||||
|
||||
// balance: 51000
|
||||
@ -192,7 +192,7 @@ describe('Mempool', function() {
|
||||
|
||||
chain.tip.height = 200;
|
||||
|
||||
sig = tx.signature(0, prev, kp.privateKey, 'all', 0);
|
||||
sig = tx.signature(0, prev, tx.inputs[0].coin.value, kp.privateKey, 'all', 0);
|
||||
tx.inputs[0].script = new bcoin.script([sig]),
|
||||
|
||||
tx = tx.toTX();
|
||||
@ -217,7 +217,7 @@ describe('Mempool', function() {
|
||||
tx.setLocktime(200);
|
||||
chain.tip.height = 200 - 1;
|
||||
|
||||
sig = tx.signature(0, prev, kp.privateKey, 'all', 0);
|
||||
sig = tx.signature(0, prev, tx.inputs[0].coin.value, kp.privateKey, 'all', 0);
|
||||
tx.inputs[0].script = new bcoin.script([sig]),
|
||||
tx = tx.toTX();
|
||||
|
||||
@ -250,7 +250,7 @@ describe('Mempool', function() {
|
||||
|
||||
prevs = bcoin.script.fromPubkeyhash(kp.getKeyHash());
|
||||
|
||||
sig = tx.signature(0, prevs, kp.privateKey, 'all', 1);
|
||||
sig = tx.signature(0, prevs, tx.inputs[0].coin.value, kp.privateKey, 'all', 1);
|
||||
sig[sig.length - 1] = 0;
|
||||
tx.inputs[0].witness = new bcoin.witness([sig, kp.publicKey]);
|
||||
tx = tx.toTX();
|
||||
@ -279,7 +279,7 @@ describe('Mempool', function() {
|
||||
|
||||
tx.addInput(dummy(prev, prevHash));
|
||||
|
||||
sig = tx.signature(0, prev, kp.privateKey, 'all', 0);
|
||||
sig = tx.signature(0, prev, tx.inputs[0].coin.value, kp.privateKey, 'all', 0);
|
||||
tx.inputs[0].script = new bcoin.script([sig]);
|
||||
tx.inputs[0].witness.push(new Buffer(0));
|
||||
tx = tx.toTX();
|
||||
|
||||
@ -371,8 +371,9 @@ describe('Script', function() {
|
||||
delete output._address;
|
||||
}
|
||||
var err, res;
|
||||
var value = tx.inputs[0].coin.value;
|
||||
try {
|
||||
res = Script.verify(input, witness, output, tx, 0, flags);
|
||||
res = Script.verify(input, witness, output, tx, 0, value, flags);
|
||||
} catch (e) {
|
||||
err = e;
|
||||
}
|
||||
|
||||
@ -141,8 +141,9 @@ describe('TX', function() {
|
||||
});
|
||||
|
||||
it('should verify high S value with only DERSIG enabled' + suffix, function() {
|
||||
var coin = tx4.inputs[0].coin;
|
||||
clearCache(tx4, nocache);
|
||||
assert(tx4.verifyInput(0, constants.flags.VERIFY_P2SH | constants.flags.VERIFY_DERSIG));
|
||||
assert(tx4.verifyInput(0, coin, constants.flags.VERIFY_P2SH | constants.flags.VERIFY_DERSIG));
|
||||
});
|
||||
|
||||
it('should verify the coolest tx ever sent' + suffix, function() {
|
||||
@ -297,7 +298,7 @@ describe('TX', function() {
|
||||
hexType = '0' + hexType;
|
||||
it('should get signature hash of ' + data[4] + ' (' + hexType + ')' + suffix, function() {
|
||||
var subscript = script.getSubscript(0).removeSeparators();
|
||||
var hash = tx.signatureHash(index, subscript, type, 0).toString('hex');
|
||||
var hash = tx.signatureHash(index, subscript, 0, type, 0).toString('hex');
|
||||
assert.equal(hash, expected);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user