signature work. script function renames. add wallet.fillTX/tx.fill.
This commit is contained in:
parent
6f86ca2d02
commit
b77314dd0f
@ -743,11 +743,11 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
if (!script.isKey(key))
|
if (!script.isKey(key))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!script.isSig(sig))
|
if (!script.isSignature(sig))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (flags.strictder !== false) {
|
if (flags.strictder !== false) {
|
||||||
if (!script.isValidSig(sig))
|
if (!script.isValidSignature(sig))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -815,11 +815,11 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
for (i = 0, j = 0; i < m && j < n; i++) {
|
for (i = 0, j = 0; i < m && j < n; i++) {
|
||||||
sig = stack.pop();
|
sig = stack.pop();
|
||||||
|
|
||||||
if (!script.isSig(sig))
|
if (!script.isSignature(sig))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (flags.strictder !== false) {
|
if (flags.strictder !== false) {
|
||||||
if (!script.isValidSig(sig))
|
if (!script.isValidSignature(sig))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1193,7 +1193,7 @@ script.isPubkeyInput = function isPubkeyInput(s, key, tx, i) {
|
|||||||
if (s.length !== 1 || !Array.isArray(s[0]))
|
if (s.length !== 1 || !Array.isArray(s[0]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!script.isSig(s[0]))
|
if (!script.isSignature(s[0]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Execute the script against our key's
|
// Execute the script against our key's
|
||||||
@ -1211,7 +1211,7 @@ script.isPubkeyhashInput = function isPubkeyhashInput(s, key) {
|
|||||||
if (s.length !== 2 || !Array.isArray(s[0]) || !Array.isArray(s[1]))
|
if (s.length !== 2 || !Array.isArray(s[0]) || !Array.isArray(s[1]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!script.isSig(s[0]))
|
if (!script.isSignature(s[0]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!script.isKey(s[1]))
|
if (!script.isKey(s[1]))
|
||||||
@ -1240,7 +1240,7 @@ script.isMultisigInput = function isMultisigInput(s, keys, tx, i) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (i = 1; i < s.length; i++) {
|
for (i = 1; i < s.length; i++) {
|
||||||
if (!script.isSig(s[i]))
|
if (!script.isSignature(s[i]))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1411,7 +1411,7 @@ script.isKey = function isKey(key) {
|
|||||||
return key.length >= 33 && key.length <= 65;
|
return key.length >= 33 && key.length <= 65;
|
||||||
};
|
};
|
||||||
|
|
||||||
script.isSig = function isSig(sig, allowZero) {
|
script.isSignature = function isSignature(sig, allowZero) {
|
||||||
if (!utils.isBuffer(sig))
|
if (!utils.isBuffer(sig))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -1432,7 +1432,7 @@ script.isSig = function isSig(sig, allowZero) {
|
|||||||
*
|
*
|
||||||
* This function is consensus-critical since BIP66.
|
* This function is consensus-critical since BIP66.
|
||||||
*/
|
*/
|
||||||
script.isValidSig = function isValidSig(sig, allowZero) {
|
script.isValidSignature = function isValidSignature(sig, allowZero) {
|
||||||
var lenR, lenS;
|
var lenR, lenS;
|
||||||
|
|
||||||
if (!utils.isBuffer(sig))
|
if (!utils.isBuffer(sig))
|
||||||
|
|||||||
136
lib/bcoin/tx.js
136
lib/bcoin/tx.js
@ -158,7 +158,7 @@ TX.prototype._inputIndex = function _inputIndex(hash, index) {
|
|||||||
|
|
||||||
// Build the scriptSigs for inputs, excluding the signatures
|
// Build the scriptSigs for inputs, excluding the signatures
|
||||||
TX.prototype.scriptInput = function scriptInput(index, pub, redeem) {
|
TX.prototype.scriptInput = function scriptInput(index, pub, redeem) {
|
||||||
var input, s, standard, n, i;
|
var input, s, n, i;
|
||||||
|
|
||||||
if (typeof index !== 'number')
|
if (typeof index !== 'number')
|
||||||
index = this.inputs.indexOf(index);
|
index = this.inputs.indexOf(index);
|
||||||
@ -167,6 +167,9 @@ TX.prototype.scriptInput = function scriptInput(index, pub, redeem) {
|
|||||||
input = this.inputs[index];
|
input = this.inputs[index];
|
||||||
assert(input);
|
assert(input);
|
||||||
|
|
||||||
|
// We should have previous outputs by now.
|
||||||
|
assert(input.out.tx);
|
||||||
|
|
||||||
// Get the previous output's subscript
|
// Get the previous output's subscript
|
||||||
s = input.out.tx.getSubscript(input.out.index);
|
s = input.out.tx.getSubscript(input.out.index);
|
||||||
|
|
||||||
@ -194,10 +197,13 @@ TX.prototype.scriptInput = function scriptInput(index, pub, redeem) {
|
|||||||
// but we create n signature slots so we can order
|
// but we create n signature slots so we can order
|
||||||
// the signatures properly.
|
// the signatures properly.
|
||||||
input.script = [ [] ];
|
input.script = [ [] ];
|
||||||
|
|
||||||
|
// Grab `n` value (number of keys).
|
||||||
n = s[s.length - 2];
|
n = s[s.length - 2];
|
||||||
// If using pushdata instead of OP_1-16:
|
|
||||||
if (Array.isArray(n))
|
if (Array.isArray(n))
|
||||||
n = n[0] || 0;
|
n = n[0] || 0;
|
||||||
|
|
||||||
|
// Fill script with `n` signature slots.
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
input.script[i + 1] = [];
|
input.script[i + 1] = [];
|
||||||
}
|
}
|
||||||
@ -212,7 +218,7 @@ TX.prototype.scriptInput = function scriptInput(index, pub, redeem) {
|
|||||||
// Sign the now-built scriptSigs
|
// Sign the now-built scriptSigs
|
||||||
TX.prototype.signInput = function signInput(index, key, type) {
|
TX.prototype.signInput = function signInput(index, key, type) {
|
||||||
var input, s, hash, signature;
|
var input, s, hash, signature;
|
||||||
var len, redeem, m, keys, pub, pubn, ki, signatures, i;
|
var len, redeem, m, n, keys, pub, pubn, ki, signatures, i;
|
||||||
|
|
||||||
if (typeof index !== 'number')
|
if (typeof index !== 'number')
|
||||||
index = this.inputs.indexOf(index);
|
index = this.inputs.indexOf(index);
|
||||||
@ -227,6 +233,9 @@ TX.prototype.signInput = function signInput(index, key, type) {
|
|||||||
input = this.inputs[index];
|
input = this.inputs[index];
|
||||||
assert(input);
|
assert(input);
|
||||||
|
|
||||||
|
// We should have previous outputs by now.
|
||||||
|
assert(input.out.tx);
|
||||||
|
|
||||||
// Get the previous output's subscript
|
// Get the previous output's subscript
|
||||||
s = input.out.tx.getSubscript(input.out.index);
|
s = input.out.tx.getSubscript(input.out.index);
|
||||||
|
|
||||||
@ -256,19 +265,56 @@ TX.prototype.signInput = function signInput(index, key, type) {
|
|||||||
len--;
|
len--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add signatures.
|
||||||
if (bcoin.script.isPubkey(s)) {
|
if (bcoin.script.isPubkey(s)) {
|
||||||
// P2PK
|
// P2PK
|
||||||
input.script[0] = signature;
|
if (Array.isArray(input.script[0]) && !input.script[0].length)
|
||||||
|
input.script[0] = signature;
|
||||||
|
return true;
|
||||||
} else if (bcoin.script.isPubkeyhash(s)) {
|
} else if (bcoin.script.isPubkeyhash(s)) {
|
||||||
// P2PKH
|
// P2PKH
|
||||||
input.script[0] = signature;
|
if (Array.isArray(input.script[0]) && !input.script[0].length)
|
||||||
|
input.script[0] = signature;
|
||||||
|
return true;
|
||||||
} else if (bcoin.script.isMultisig(s)) {
|
} else if (bcoin.script.isMultisig(s)) {
|
||||||
// Multisig
|
// Multisig
|
||||||
|
|
||||||
|
// Grab `m` value (number of sigs required).
|
||||||
m = s[0];
|
m = s[0];
|
||||||
// If using pushdata instead of OP_1-16:
|
|
||||||
if (Array.isArray(m))
|
if (Array.isArray(m))
|
||||||
m = m[0] || 0;
|
m = m[0] || 0;
|
||||||
|
|
||||||
|
// Grab `n` value (number of keys).
|
||||||
|
n = s[s.length - 2];
|
||||||
|
if (Array.isArray(m))
|
||||||
|
n = n[0] || 0;
|
||||||
|
|
||||||
|
// Something is very wrong here. Abort.
|
||||||
|
if (m < 1 || m > 15 || n < m || n > 15 || len - 1 > n)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Count the number of current signatures.
|
||||||
|
signatures = 0;
|
||||||
|
for (i = 1; i < len; i++) {
|
||||||
|
if (Array.isArray(input.script[i]) && input.script[i].length)
|
||||||
|
signatures++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signatures are already finalized.
|
||||||
|
if (signatures === m && len - 1 === m)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// This can happen in a case where another
|
||||||
|
// implementation adds signatures willy-nilly
|
||||||
|
// or by `m`. Add some signature slots for
|
||||||
|
// us to use.
|
||||||
|
while (len - 1 < n) {
|
||||||
|
input.script.splice(len, 0, []);
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab the redeem script's keys to figure
|
||||||
|
// out where our key should go.
|
||||||
keys = s.slice(1, -2);
|
keys = s.slice(1, -2);
|
||||||
pub = key.getPublic(true, 'array');
|
pub = key.getPublic(true, 'array');
|
||||||
pubn = key.getPublic(false, 'array');
|
pubn = key.getPublic(false, 'array');
|
||||||
@ -280,39 +326,57 @@ TX.prototype.signInput = function signInput(index, key, type) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public key is not in the prev_out script
|
// Our public key is not in the prev_out
|
||||||
|
// script. We tried to sign a transaction
|
||||||
|
// that is not redeemable by us.
|
||||||
if (ki === keys.length)
|
if (ki === keys.length)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// No signature slot available
|
// Offset key index by one to turn it into
|
||||||
if (ki + 1 > len - 1)
|
// "sig index". Accounts for OP_0 byte at
|
||||||
return;
|
// the start.
|
||||||
|
ki++;
|
||||||
|
|
||||||
// Add our signature to the correct slot
|
// Add our signature to the correct slot
|
||||||
// and count the total number of signatures.
|
// and increment the total number of
|
||||||
signatures = 0;
|
// signatures.
|
||||||
for (i = 1; i < len; i++) {
|
if (ki < len && signatures < m) {
|
||||||
if (Array.isArray(input.script[i]) && input.script[i].length) {
|
if (Array.isArray(input.script[ki]) && !input.script[ki].length) {
|
||||||
signatures++;
|
input.script[ki] = signature;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i - 1 === ki) {
|
|
||||||
if (signatures >= m)
|
|
||||||
continue;
|
|
||||||
input.script[i] = signature;
|
|
||||||
signatures++;
|
signatures++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// All signatures added. Finalize by removing empty slots.
|
// All signatures added. Finalize.
|
||||||
if (signatures >= m) {
|
if (signatures >= m) {
|
||||||
|
// Remove empty slots left over.
|
||||||
for (i = len - 1; i >= 1; i--) {
|
for (i = len - 1; i >= 1; i--) {
|
||||||
if (Array.isArray(input.script[i]) && !input.script[i].length)
|
if (Array.isArray(input.script[i]) && !input.script[i].length) {
|
||||||
input.script.splice(i, 1);
|
input.script.splice(i, 1);
|
||||||
|
len--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove signatures which are not required.
|
||||||
|
// If just using bcoin for signing, this
|
||||||
|
// should never happen except with dealing
|
||||||
|
// with implementations that potentially
|
||||||
|
// handle signature slots differently.
|
||||||
|
while (signatures > m) {
|
||||||
|
input.script.splice(len - 1, 1);
|
||||||
|
signatures--;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity checks.
|
||||||
|
assert.equal(signatures, m);
|
||||||
|
assert.equal(len - 1, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return signatures === m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
TX.prototype.scriptSig = function scriptSig(index, key, pub, redeem, type) {
|
TX.prototype.scriptSig = function scriptSig(index, key, pub, redeem, type) {
|
||||||
@ -857,6 +921,30 @@ TX.prototype.funds = function funds(side) {
|
|||||||
return acc;
|
return acc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TX.prototype.fill = function fill(txs) {
|
||||||
|
var inputs;
|
||||||
|
|
||||||
|
if (txs instanceof bcoin.txPool)
|
||||||
|
txs = txs._all;
|
||||||
|
else if (txs instanceof bcoin.wallet)
|
||||||
|
txs = txs.tx._all;
|
||||||
|
|
||||||
|
if (Array.isArray(txs)) {
|
||||||
|
txs = txs.reduce(function(out, tx) {
|
||||||
|
out[tx.hash('hex')] = tx;
|
||||||
|
return out;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
inputs = this.inputs.filter(function(input) {
|
||||||
|
if (!input.out.tx && txs[input.out.hash])
|
||||||
|
input.out.tx = txs[input.out.hash];
|
||||||
|
return !!input.out.tx;
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
return inputs.length === this.inputs.length;
|
||||||
|
};
|
||||||
|
|
||||||
// Used for postVerify/ContextualBlockCheck and miner isFinalTx call.
|
// Used for postVerify/ContextualBlockCheck and miner isFinalTx call.
|
||||||
// BIP113 will require that time-locked transactions have nLockTime set to
|
// BIP113 will require that time-locked transactions have nLockTime set to
|
||||||
// less than the median time of the previous block they're contained in.
|
// less than the median time of the previous block they're contained in.
|
||||||
|
|||||||
@ -242,7 +242,7 @@ Wallet.prototype.getPrivateKey = function getPrivateKey(enc) {
|
|||||||
return priv;
|
return priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.getScript = function getScript(enc) {
|
Wallet.prototype.getScript = function getScript() {
|
||||||
if (this.redeem)
|
if (this.redeem)
|
||||||
return this.redeem.slice();
|
return this.redeem.slice();
|
||||||
return bcoin.script.encode(bcoin.script.redeem(this.keys, this.m, this.n));
|
return bcoin.script.encode(bcoin.script.redeem(this.keys, this.m, this.n));
|
||||||
@ -448,6 +448,10 @@ Wallet.prototype.fillUnspent = function fillUnspent(tx, changeAddress) {
|
|||||||
return tx.fillUnspent(this.unspent(), changeAddress);
|
return tx.fillUnspent(this.unspent(), changeAddress);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Wallet.prototype.fillTX = function fillTX(tx) {
|
||||||
|
return tx.fill(this);
|
||||||
|
};
|
||||||
|
|
||||||
Wallet.prototype.scriptInputs = function scriptInputs(tx) {
|
Wallet.prototype.scriptInputs = function scriptInputs(tx) {
|
||||||
var pub = this.getPublicKey();
|
var pub = this.getPublicKey();
|
||||||
var redeem = this.getScript();
|
var redeem = this.getScript();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user