correct segwit signing.
This commit is contained in:
parent
3fcc7d5b07
commit
0e3aa32677
@ -699,8 +699,10 @@ Chain.prototype._checkInputs = function _checkInputs(block, prev, flags, callbac
|
||||
utils.debug('Block has invalid inputs: %s (%s/%d)',
|
||||
block.rhash, tx.rhash, j);
|
||||
utils.debug(input);
|
||||
utils.debug('Signature Hash: %s',
|
||||
utils.toHex(tx.signatureHash(j, input.output.script, 'all')));
|
||||
utils.debug('Signature Hash v0: %s',
|
||||
utils.toHex(tx.signatureHash(j, input.output.script, 'all', 0)));
|
||||
utils.debug('Signature Hash v1: %s',
|
||||
utils.toHex(tx.signatureHash(j, input.output.script, 'all', 1)));
|
||||
utils.debug('Raw Script: %s',
|
||||
utils.toHex(input.output.script._raw || []));
|
||||
utils.debug('Reserialized Script: %s',
|
||||
|
||||
@ -305,7 +305,7 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) {
|
||||
return true;
|
||||
};
|
||||
|
||||
MTX.prototype.createSignature = function createSignature(index, prev, key, type) {
|
||||
MTX.prototype.createSignature = function createSignature(index, prev, key, type, version) {
|
||||
var prev, hash, signature;
|
||||
|
||||
if (typeof index !== 'number')
|
||||
@ -319,7 +319,7 @@ MTX.prototype.createSignature = function createSignature(index, prev, key, type)
|
||||
|
||||
// Get the hash of the current tx, minus the other
|
||||
// inputs, plus the sighash type.
|
||||
hash = this.signatureHash(index, prev, type);
|
||||
hash = this.signatureHash(index, prev, type, version);
|
||||
|
||||
// Sign the transaction with our one input
|
||||
signature = bcoin.script.sign(hash, key, type);
|
||||
@ -332,7 +332,7 @@ MTX.prototype.createSignature = function createSignature(index, prev, key, type)
|
||||
|
||||
MTX.prototype.signInput = function signInput(index, addr, type) {
|
||||
var input, prev, signature, ki, signatures, i;
|
||||
var len, m, n, keys, vector, dummy;
|
||||
var len, m, n, keys, vector, dummy, version;
|
||||
|
||||
if (typeof index !== 'number')
|
||||
index = this.inputs.indexOf(index);
|
||||
@ -350,6 +350,7 @@ MTX.prototype.signInput = function signInput(index, addr, type) {
|
||||
vector = input.script;
|
||||
len = vector.length;
|
||||
dummy = 0;
|
||||
version = 0;
|
||||
|
||||
// We need to grab the redeem script when
|
||||
// signing p2sh transactions.
|
||||
@ -369,15 +370,17 @@ MTX.prototype.signInput = function signInput(index, addr, type) {
|
||||
vector = input.witness;
|
||||
len = vector.length - 1;
|
||||
dummy = new Buffer([]);
|
||||
version = 1;
|
||||
} else if (bcoin.script.isWitnessPubkeyhash(prev)) {
|
||||
prev = bcoin.script.createPubkeyhash(prev[1]);
|
||||
vector = input.witness;
|
||||
len = vector.length;
|
||||
dummy = new Buffer([]);
|
||||
version = 1;
|
||||
}
|
||||
|
||||
// Create our signature.
|
||||
signature = this.createSignature(index, prev, addr.key, type);
|
||||
signature = this.createSignature(index, prev, addr.key, type, version);
|
||||
|
||||
// Add signatures.
|
||||
if (bcoin.script.isPubkey(prev)) {
|
||||
|
||||
@ -303,14 +303,14 @@ script.verify = function verify(input, witness, output, tx, i, flags) {
|
||||
}
|
||||
|
||||
// Execute the input script
|
||||
script.execute(input, stack, tx, i, flags);
|
||||
script.execute(input, stack, tx, i, flags, 0);
|
||||
|
||||
// Copy the stack for P2SH
|
||||
if (flags & constants.flags.VERIFY_P2SH)
|
||||
copy = stack.slice();
|
||||
|
||||
// Execute the previous output script
|
||||
res = script.execute(output, stack, tx, i, flags);
|
||||
res = script.execute(output, stack, tx, i, flags, 0);
|
||||
|
||||
// Verify the script did not fail as well as the stack values
|
||||
if (!res || stack.length === 0 || !script.bool(stack.pop()))
|
||||
@ -354,7 +354,7 @@ script.verify = function verify(input, witness, output, tx, i, flags) {
|
||||
redeem = script.decode(raw);
|
||||
|
||||
// Execute the redeem script
|
||||
res = script.execute(redeem, stack, tx, i, flags);
|
||||
res = script.execute(redeem, stack, tx, i, flags, 0);
|
||||
|
||||
// Verify the script did not fail as well as the stack values
|
||||
if (!res || stack.length === 0 || !script.bool(stack.pop()))
|
||||
@ -465,7 +465,7 @@ script.verifyProgram = function verifyProgram(witness, output, tx, i, flags) {
|
||||
utils.debug(bcoin.script.format(stack));
|
||||
utils.debug(bcoin.script.format(redeem));
|
||||
|
||||
res = script.execute(redeem, stack, tx, i, flags);
|
||||
res = script.execute(redeem, stack, tx, i, flags, 1);
|
||||
|
||||
utils.debug(bcoin.script.format(stack));
|
||||
|
||||
@ -581,7 +581,7 @@ script._next = function _next(to, s, pc) {
|
||||
return -1;
|
||||
};
|
||||
|
||||
script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
||||
script.execute = function execute(data, stack, tx, index, flags, version, recurse) {
|
||||
var s = data.slice();
|
||||
|
||||
if (flags == null)
|
||||
@ -1053,7 +1053,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
||||
subscript = script.getSubscript(data, lastSep);
|
||||
script.removeData(subscript, sig);
|
||||
|
||||
hash = tx.signatureHash(index, subscript, type);
|
||||
hash = tx.signatureHash(index, subscript, type, version);
|
||||
|
||||
res = script.checksig(hash, sig, key, flags);
|
||||
if (o === 'checksigverify') {
|
||||
@ -1112,7 +1112,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
||||
|
||||
type = sig[sig.length - 1];
|
||||
|
||||
hash = tx.signatureHash(index, subscript, type);
|
||||
hash = tx.signatureHash(index, subscript, type, version);
|
||||
|
||||
res = false;
|
||||
for (; !res && j < n; j++)
|
||||
@ -1215,7 +1215,9 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
||||
if (res)
|
||||
return false;
|
||||
|
||||
res = script.execute(evalScript, stack, tx, index, flags, recurse);
|
||||
res = script.execute(
|
||||
evalScript, stack, tx, index, flags, version, recurse);
|
||||
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
|
||||
102
lib/bcoin/tx.js
102
lib/bcoin/tx.js
@ -212,7 +212,15 @@ TX.prototype.getSubscript = function getSubscript(index) {
|
||||
return bcoin.script.getSubscript(script);
|
||||
};
|
||||
|
||||
TX.prototype.signatureHash = function signatureHash(index, s, type) {
|
||||
TX.prototype.signatureHash = function signatureHash(index, s, type, version) {
|
||||
assert(version >= 0 && version <= 1);
|
||||
if (version === 0)
|
||||
return this.signatureHashV0(index, s, type);
|
||||
if (version === 1)
|
||||
return this.signatureHashV1(index, s, type);
|
||||
};
|
||||
|
||||
TX.prototype.signatureHashV0 = function signatureHashV0(index, s, type) {
|
||||
var copy = this.clone();
|
||||
var i, msg, hash;
|
||||
|
||||
@ -288,6 +296,98 @@ TX.prototype.signatureHash = function signatureHash(index, s, type) {
|
||||
return hash;
|
||||
};
|
||||
|
||||
TX.prototype.signatureHashV1 = function signatureHashV1(index, s, type) {
|
||||
var i, msg, hash, hashPrevouts, hashSequence, hashOutputs;
|
||||
var size, outputs, output, off, prev;
|
||||
|
||||
if (typeof index !== 'number')
|
||||
index = this.inputs.indexOf(index);
|
||||
|
||||
if (typeof type === 'string')
|
||||
type = constants.hashType[type];
|
||||
|
||||
assert(index >= 0 && index < this.inputs.length)
|
||||
assert(Array.isArray(s));
|
||||
|
||||
if (!(type & constants.hashType.anyonecanpay)) {
|
||||
hashPrevouts = new Buffer(36 * this.inputs.length);
|
||||
off = 0;
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
prev = this.inputs[i].prevout;
|
||||
off += utils.copy(new Buffer(prev.hash, 'hex'), hashPrevouts, off);
|
||||
off += utils.writeU32(hashPrevouts, prev.index, off);
|
||||
}
|
||||
hashPrevouts = utils.dsha256(hashPrevouts);
|
||||
} else {
|
||||
hashPrevouts = new Buffer(32);
|
||||
hashPrevouts.fill(0);
|
||||
}
|
||||
|
||||
if (!(type & constants.hashType.anyonecanpay)
|
||||
&& (type & 0x1f) !== constants.hashType.single
|
||||
&& (type & 0x1f) !== constants.hashType.none) {
|
||||
hashSequence = new Buffer(4 * this.inputs.length);
|
||||
off = 0;
|
||||
for (i = 0; i < this.inputs.length; i++)
|
||||
off += utils.writeU32(hashSequence, this.inputs[i].sequence, off);
|
||||
hashSequence = utils.dsha256(hashSequence);
|
||||
} else {
|
||||
hashSequence = new Buffer(32);
|
||||
hashSequence.fill(0);
|
||||
}
|
||||
|
||||
if ((type & 0x1f) !== constants.hashType.single
|
||||
&& (type & 0x1f) !== constants.hashType.none) {
|
||||
size = 0;
|
||||
outputs = [];
|
||||
for (i = 0; i < this.outputs.length; i++) {
|
||||
output = bcoin.protocol.framer.output(this.outputs[i]);
|
||||
size += output.length;
|
||||
outputs.push(output);
|
||||
}
|
||||
hashOutputs = new Buffer(size);
|
||||
off = 0;
|
||||
for (i = 0; i < outputs.length; i++)
|
||||
off += utils.copy(outputs[i], hashOutputs, off);
|
||||
hashOutputs = utils.dsha256(hashOutputs);
|
||||
} else if ((type & 0x1f) === constants.hashType.single && index < this.outputs.length) {
|
||||
hashOutputs = bcoin.protocol.framer.output(this.outputs[index]);
|
||||
hashOutputs = utils.dsha256(hashOutputs);
|
||||
} else {
|
||||
hashOutputs = new Buffer(32);
|
||||
hashOutputs.fill(0);
|
||||
}
|
||||
|
||||
s = bcoin.script.encode(s);
|
||||
|
||||
msg = new Buffer(
|
||||
4 + 32 + 32 + 36
|
||||
+ utils.sizeIntv(s.length)
|
||||
+ s.length
|
||||
+ 8 + 4 + 32 + 4 + 4);
|
||||
|
||||
off = 0;
|
||||
off += utils.write32(msg, this.version, off);
|
||||
off += utils.copy(hashPrevouts, msg, off);
|
||||
off += utils.copy(hashSequence, msg, off);
|
||||
off += utils.copy(new Buffer(this.inputs[index].prevout.hash, 'hex'), msg, off);
|
||||
off += utils.writeU32(msg, this.inputs[index].prevout.index, off);
|
||||
assert(off === 4 + 32 + 32 + 36);
|
||||
off += utils.writeIntv(msg, s.length, off);
|
||||
off += utils.copy(s, msg, off);
|
||||
off += utils.write64(msg, this.inputs[index].output.value, off);
|
||||
off += utils.writeU32(msg, this.inputs[index].sequence, off);
|
||||
off += utils.copy(hashOutputs, msg, off);
|
||||
off += utils.writeU32(msg, this.locktime, off);
|
||||
assert(off === msg.length - 4);
|
||||
off += utils.writeU32(msg, type, off);
|
||||
assert(off === msg.length);
|
||||
|
||||
hash = utils.dsha256(msg);
|
||||
|
||||
return hash;
|
||||
};
|
||||
|
||||
TX.prototype.normalizedHash = function normalizedHash(enc, force) {
|
||||
var copy = this.clone();
|
||||
var i;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user