transaction improvements.
This commit is contained in:
parent
0b7ca266ee
commit
eb1a3ea6d2
@ -7,6 +7,7 @@
|
||||
var bn = require('bn.js');
|
||||
var bcoin = require('../bcoin');
|
||||
var utils = bcoin.utils;
|
||||
var constants = bcoin.protocol.constants;
|
||||
|
||||
/**
|
||||
* Input
|
||||
@ -180,6 +181,7 @@ Input.prototype.__defineGetter__('scriptaddr', function() {
|
||||
// Schema and defaults for data object:
|
||||
// {
|
||||
// type: null,
|
||||
// subtype: null,
|
||||
// side: 'input',
|
||||
// signatures: [],
|
||||
// keys: [],
|
||||
@ -263,7 +265,7 @@ Input.getData = function getData(input) {
|
||||
} else if (data.type === 'scripthash') {
|
||||
// We work backwards here: scripthash is one of the few cases
|
||||
// where we get more data from the input than the output.
|
||||
val = Input.getData({
|
||||
val = bcoin.input.getData({
|
||||
out: { hash: input.out.hash, index: input.out.index },
|
||||
script: input.script,
|
||||
seq: input.seq
|
||||
@ -313,19 +315,16 @@ Input.getData = function getData(input) {
|
||||
}
|
||||
|
||||
if (bcoin.script.isScripthashInput(s)) {
|
||||
signature = sub.slice(1, -1);
|
||||
redeem = sub[sub.length - 1];
|
||||
hash = utils.ripesha(redeem);
|
||||
address = bcoin.wallet.hash2addr(hash, 'scripthash');
|
||||
redeem = bcoin.script.decode(redeem);
|
||||
data = bcoin.output.getData({
|
||||
script: redeem,
|
||||
value: new bn(0)
|
||||
});
|
||||
return utils.merge(data, {
|
||||
val = bcoin.input.getData(sub.slice(0, -1));
|
||||
data = bcoin.output.getData(redeem);
|
||||
return utils.merge(val, data, {
|
||||
type: 'scripthash',
|
||||
subtype: data.type,
|
||||
side: 'input',
|
||||
signatures: signature,
|
||||
redeem: redeem,
|
||||
scripthash: hash,
|
||||
scriptaddress: address,
|
||||
@ -351,6 +350,7 @@ Input.prototype.inspect = function inspect() {
|
||||
|
||||
return {
|
||||
type: this.type,
|
||||
subtype: this.data.subtype,
|
||||
address: this.address,
|
||||
signatures: this.signatures.map(utils.toHex),
|
||||
keys: this.keys.map(utils.toHex),
|
||||
@ -358,6 +358,7 @@ Input.prototype.inspect = function inspect() {
|
||||
lock: this.lock,
|
||||
value: utils.btc(output.value),
|
||||
script: bcoin.script.format(this.script)[0],
|
||||
redeem: this.data.redeem ? bcoin.script.format(this.data.redeem)[0] : null,
|
||||
seq: this.seq,
|
||||
output: output
|
||||
};
|
||||
|
||||
@ -147,6 +147,7 @@ Output.prototype.__defineGetter__('scriptaddr', function() {
|
||||
// Schema and defaults for data object:
|
||||
// {
|
||||
// type: null,
|
||||
// subtype: null,
|
||||
// side: 'output',
|
||||
// signatures: [],
|
||||
// keys: [],
|
||||
@ -215,14 +216,13 @@ Output.getData = function getData(output) {
|
||||
address = bcoin.wallet.hash2addr(hash);
|
||||
return utils.merge(def, {
|
||||
type: 'pubkeyhash',
|
||||
side: 'output',
|
||||
hashes: [hash],
|
||||
addresses: [address]
|
||||
});
|
||||
}
|
||||
|
||||
keys = bcoin.script.isMultisig(s);
|
||||
if (keys) {
|
||||
if (bcoin.script.isMultisig(s)) {
|
||||
keys = sub.slice(1, -2);
|
||||
hash = keys.map(function(key) {
|
||||
return utils.ripesha(key);
|
||||
});
|
||||
@ -272,9 +272,6 @@ Output.prototype.inspect = function inspect() {
|
||||
keys: this.keys.map(utils.toHex),
|
||||
hashes: this.hashes.map(utils.toHex),
|
||||
addresses: this.addresses,
|
||||
redeem: this.type === 'scripthash'
|
||||
? bcoin.script.format(this.data.redeem)[0]
|
||||
: null,
|
||||
m: this.m,
|
||||
n: this.n,
|
||||
text: this.text,
|
||||
|
||||
@ -47,7 +47,6 @@ Parser.prototype.feed = function feed(data) {
|
||||
|
||||
while (this.pendingTotal >= this.waiting) {
|
||||
// Concat chunks
|
||||
// chunk = new Array(this.waiting);
|
||||
chunk = new Buffer(this.waiting);
|
||||
|
||||
i = 0;
|
||||
@ -55,7 +54,6 @@ Parser.prototype.feed = function feed(data) {
|
||||
len = 0;
|
||||
|
||||
for (; off < chunk.length; i++) {
|
||||
// len = utils.copy(this.pending[0], chunk, off);
|
||||
len = this.pending[0].copy(chunk, off, 0, this.pending[0].length);
|
||||
if (len === this.pending[0].length)
|
||||
this.pending.shift();
|
||||
|
||||
@ -150,6 +150,64 @@ script.encode = function encode(s) {
|
||||
return res;
|
||||
};
|
||||
|
||||
script.verify = function verify(input, output, tx, i, flags) {
|
||||
var copy, res, redeem;
|
||||
var stack = [];
|
||||
|
||||
if (!flags)
|
||||
flags = {};
|
||||
|
||||
// Execute the input script
|
||||
script.execute(input, stack, tx, i, flags);
|
||||
|
||||
// Copy the stack for P2SH
|
||||
if (flags.verifyp2sh !== false)
|
||||
copy = stack.slice();
|
||||
|
||||
// Execute the previous output script
|
||||
res = script.execute(output, stack, tx, i, flags);
|
||||
|
||||
// Verify the script did not fail as well as the stack values
|
||||
if (!res || stack.length === 0 || new bn(stack.pop()).cmpn(0) === 0)
|
||||
return false;
|
||||
|
||||
// If the script is P2SH, execute the real output script
|
||||
if (flags.verifyp2sh !== false && script.isScripthash(output)) {
|
||||
// P2SH can only have push ops in the scriptSig
|
||||
if (!script.pushOnly(input))
|
||||
return false;
|
||||
|
||||
// Reset the stack
|
||||
stack = copy;
|
||||
|
||||
// Stack should _never_ be empty at this point
|
||||
assert(stack.length !== 0);
|
||||
|
||||
// Grab the real redeem script
|
||||
redeem = stack.pop();
|
||||
|
||||
if (!Array.isArray(redeem))
|
||||
return false;
|
||||
|
||||
redeem = script.decode(redeem);
|
||||
|
||||
// Execute the redeem script
|
||||
res = script.execute(redeem, stack, tx, i, flags);
|
||||
|
||||
// Verify the script did not fail as well as the stack values
|
||||
if (!res || stack.length === 0 || new bn(stack.pop()).cmpn(0) === 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure there is nothing left on the stack
|
||||
if (flags.cleanstack !== false) {
|
||||
if (stack.length !== 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
script.subscript = function subscript(s, lastSep) {
|
||||
var i, res;
|
||||
|
||||
@ -179,7 +237,7 @@ script.subscript = function subscript(s, lastSep) {
|
||||
return res;
|
||||
};
|
||||
|
||||
script.verify = function verify(hash, sig, pub) {
|
||||
script.checksig = function checksig(hash, sig, pub) {
|
||||
var k;
|
||||
|
||||
try {
|
||||
@ -249,7 +307,7 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
||||
var n, n1, n2, n3;
|
||||
var res;
|
||||
var key, sig, type, subscript, hash;
|
||||
var keys, i, j, key, m;
|
||||
var keys, i, j, m;
|
||||
var succ;
|
||||
var lock, threshold;
|
||||
var evalScript;
|
||||
@ -700,7 +758,7 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
||||
subscript = script.subscript(s, lastSep);
|
||||
hash = tx.subscriptHash(index, subscript, type);
|
||||
|
||||
res = script.verify(hash, sig.slice(0, -1), key);
|
||||
res = script.checksig(hash, sig.slice(0, -1), key);
|
||||
if (o === 'checksigverify') {
|
||||
if (!res)
|
||||
return false;
|
||||
@ -763,13 +821,19 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
||||
|
||||
res = false;
|
||||
for (; !res && j < n; j++)
|
||||
res = script.verify(hash, sig.slice(0, -1), keys[j]);
|
||||
res = script.checksig(hash, sig.slice(0, -1), keys[j]);
|
||||
|
||||
if (res)
|
||||
succ++;
|
||||
}
|
||||
|
||||
// Extra value
|
||||
if (stack.length < 1)
|
||||
return false;
|
||||
if (flags.verifynulldummy !== false) {
|
||||
if (stack[stack.length - 1].length > 0)
|
||||
return false;
|
||||
}
|
||||
stack.pop();
|
||||
|
||||
// Too many signatures on stack
|
||||
@ -866,20 +930,6 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
||||
return true;
|
||||
};
|
||||
|
||||
script.exec = function exec(input, output, tx, i, flags) {
|
||||
var stack = [];
|
||||
var res;
|
||||
|
||||
script.execute(input, stack, tx, i, flags);
|
||||
|
||||
res = script.execute(output, stack, tx, i, flags);
|
||||
|
||||
if (!res || stack.length === 0 || new bn(stack.pop()).cmpn(0) === 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
script.redeem = function redeem(keys, m, n) {
|
||||
if (keys.length !== n)
|
||||
throw new Error(n + ' keys are required to generate redeem script');
|
||||
@ -892,9 +942,9 @@ script.redeem = function redeem(keys, m, n) {
|
||||
|
||||
keys = utils.sortKeys(keys);
|
||||
|
||||
return [ m ].concat(
|
||||
return [m].concat(
|
||||
keys,
|
||||
[ n, 'checkmultisig' ]
|
||||
[n, 'checkmultisig']
|
||||
);
|
||||
};
|
||||
|
||||
@ -908,11 +958,8 @@ script.standard = function standard(s) {
|
||||
};
|
||||
|
||||
script.isStandard = function isStandard(s) {
|
||||
var m, n;
|
||||
var type = script.standard(s);
|
||||
|
||||
if (!type)
|
||||
return false;
|
||||
var m, n;
|
||||
|
||||
if (type === 'multisig') {
|
||||
m = new bn(s[0]).toNumber();
|
||||
@ -982,7 +1029,7 @@ script.isPubkey = function isPubkey(s, key) {
|
||||
if (key)
|
||||
return utils.isEqual(s[0], key);
|
||||
|
||||
return s[0];
|
||||
return true;
|
||||
};
|
||||
|
||||
script.isPubkeyhash = function isPubkeyhash(s, hash) {
|
||||
@ -1008,11 +1055,11 @@ script.isPubkeyhash = function isPubkeyhash(s, hash) {
|
||||
if (hash)
|
||||
return utils.isEqual(s[2], hash);
|
||||
|
||||
return s[2];
|
||||
return true;
|
||||
};
|
||||
|
||||
script.isMultisig = function isMultisig(s, pubs) {
|
||||
var m, n, keys, isArray, total;
|
||||
var m, n, keys, total;
|
||||
|
||||
s = script.subscript(s);
|
||||
|
||||
@ -1048,15 +1095,11 @@ script.isMultisig = function isMultisig(s, pubs) {
|
||||
|
||||
keys = s.slice(1, 1 + n);
|
||||
|
||||
isArray = keys.every(function(k) {
|
||||
return Array.isArray(k);
|
||||
});
|
||||
|
||||
if (!isArray)
|
||||
if (!keys.every(Array.isArray))
|
||||
return false;
|
||||
|
||||
if (!pubs)
|
||||
return keys;
|
||||
return true;
|
||||
|
||||
total = keys.filter(function(k) {
|
||||
return pubs.some(function(pub) {
|
||||
@ -1133,7 +1176,7 @@ script.isPubkeyInput = function isPubkeyInput(s, key, tx, i) {
|
||||
// checksig script to see if this is our input.
|
||||
// This will only work if the script verifies.
|
||||
if (key)
|
||||
return script.exec(s, [key, 'checksig'], tx, i);
|
||||
return script.verify(s, [key, 'checksig'], tx, i);
|
||||
|
||||
return true;
|
||||
};
|
||||
@ -1153,10 +1196,10 @@ script.isPubkeyhashInput = function isPubkeyhashInput(s, key) {
|
||||
if (key)
|
||||
return utils.isEqual(s[1], key);
|
||||
|
||||
return s[1];
|
||||
return true;
|
||||
};
|
||||
|
||||
script.isMultisigInput = function isMultisigInput(s, pubs, tx, i) {
|
||||
script.isMultisigInput = function isMultisigInput(s, keys, tx, i) {
|
||||
var i, res, o;
|
||||
|
||||
// We need to rule out scripthash
|
||||
@ -1180,40 +1223,58 @@ script.isMultisigInput = function isMultisigInput(s, pubs, tx, i) {
|
||||
// Execute the script against our pubkeys'
|
||||
// redeem script to see if this is our input.
|
||||
// This will only work if the script verifies.
|
||||
if (pubs && pubs.length >= 2) {
|
||||
o = script.redeem(pubs, 2, pubs.length);
|
||||
return script.exec(s, o, tx, i);
|
||||
if (keys && keys.length >= 2) {
|
||||
o = script.redeem(keys, s.length - 1, keys.length);
|
||||
return script.verify(s, o, tx, i);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
script.isScripthashInput = function isScripthashInput(s, redeem) {
|
||||
var i, res, r, keys;
|
||||
script.isScripthashInput = function isScripthashInput(s, data) {
|
||||
var raw, redeem;
|
||||
|
||||
s = script.subscript(s);
|
||||
|
||||
if (s.length < 4)
|
||||
// Grab the raw redeem script.
|
||||
raw = s[s.length - 1];
|
||||
|
||||
// Need at least one data element with
|
||||
// the redeem script.
|
||||
if (s.length < 2)
|
||||
return false;
|
||||
|
||||
if (!Array.isArray(s[0]) || s[0].length !== 0)
|
||||
// Last data element should be an array
|
||||
// for the redeem script.
|
||||
if (!Array.isArray(raw))
|
||||
return false;
|
||||
|
||||
for (i = 1; i < s.length - 1; i++) {
|
||||
if (!script.isSig(s[i]))
|
||||
return false;
|
||||
// P2SH redeem scripts can be nonstandard: make
|
||||
// it easier for other functions to parse this.
|
||||
redeem = script.decode(raw);
|
||||
redeem = script.subscript(redeem);
|
||||
if (script.lockTime(redeem))
|
||||
redeem = redeem.slice(3);
|
||||
|
||||
// Get the "real" scriptSig
|
||||
s = s.slice(0, -1);
|
||||
|
||||
// Do some sanity checking on the inputs
|
||||
if (!script.isPubkeyInput(s)
|
||||
&& !script.isPubkeyhashInput(s)
|
||||
&& !script.isMultisigInput(s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
r = Array.isArray(s[s.length - 1]) && s[s.length - 1];
|
||||
if (r[r.length - 1] !== constants.opcodes.checkmultisig)
|
||||
return false;
|
||||
// Check data against last array in case
|
||||
// a raw redeem script was passed in.
|
||||
if (data && utils.isEqual(data, raw))
|
||||
return true;
|
||||
|
||||
if (redeem)
|
||||
return utils.isEqual(redeem, r);
|
||||
|
||||
keys = script.decode(r).slice(1, -2);
|
||||
|
||||
return keys;
|
||||
// Test against all other script types
|
||||
return script.isPubkey(redeem, data)
|
||||
|| script.isPubkeyhash(redeem, data)
|
||||
|| script.isMultisig(redeem, data);
|
||||
};
|
||||
|
||||
script.coinbaseBits = function coinbaseBits(s, block) {
|
||||
@ -1526,7 +1587,7 @@ script.sigopsScripthash = function sigopsScripthash(s) {
|
||||
};
|
||||
|
||||
script.args = function args(s) {
|
||||
var type, pubs, m;
|
||||
var type, keys, m;
|
||||
|
||||
s = bcoin.script.subscript(s);
|
||||
|
||||
@ -1542,11 +1603,11 @@ script.args = function args(s) {
|
||||
return 2;
|
||||
|
||||
if (type === 'multisig') {
|
||||
pubs = bcoin.script.isMultisig(s);
|
||||
keys = bcoin.script.isMultisig(s);
|
||||
if (!pub)
|
||||
return -1;
|
||||
m = new bn(s[0]).toNumber();
|
||||
if (pubs.length < 1 || m < 1)
|
||||
if (keys.length < 1 || m < 1)
|
||||
return -1;
|
||||
return m + 1;
|
||||
}
|
||||
|
||||
@ -123,7 +123,6 @@ TXPool.prototype.add = function add(tx, noWrite) {
|
||||
// signature checking code to ownInput for p2sh and p2pk,
|
||||
// we could in theory use ownInput here (and down below)
|
||||
// instead.
|
||||
// if (this._wallet.ownInput(input.out.tx, input.out.index))
|
||||
if (input.out.tx) {
|
||||
if (!this._wallet.ownOutput(input.out.tx, input.out.index))
|
||||
continue;
|
||||
|
||||
@ -596,8 +596,11 @@ TX.prototype.verify = function verify(index, force, flags) {
|
||||
if (this.inputs.length === 0)
|
||||
return false;
|
||||
|
||||
if (!flags)
|
||||
flags = {};
|
||||
|
||||
return this.inputs.every(function(input, i) {
|
||||
var stack, prev, push, res, redeem;
|
||||
var output;
|
||||
|
||||
if (index != null && index !== i)
|
||||
return true;
|
||||
@ -605,41 +608,16 @@ TX.prototype.verify = function verify(index, force, flags) {
|
||||
if (!input.out.tx)
|
||||
return false;
|
||||
|
||||
output = input.out.tx.outputs[input.out.index];
|
||||
|
||||
assert(input.out.tx.outputs.length > input.out.index);
|
||||
assert.equal(input.out.tx.hash('hex'), input.out.hash);
|
||||
|
||||
// Transaction cannot reference itself
|
||||
if (input.out.tx.hash('hex') === this.hash('hex'))
|
||||
return false;
|
||||
|
||||
assert(input.out.tx.outputs.length > input.out.index);
|
||||
|
||||
stack = [];
|
||||
prev = input.out.tx.outputs[input.out.index].script;
|
||||
|
||||
if (bcoin.script.isScripthash(prev)) {
|
||||
// P2SH transactions cannot have anything
|
||||
// other than pushdata ops in the scriptSig.
|
||||
if (!bcoin.script.pushOnly(input.script))
|
||||
return false;
|
||||
}
|
||||
|
||||
bcoin.script.execute(input.script, stack, this, i, flags);
|
||||
res = bcoin.script.execute(prev, stack, this, i, flags);
|
||||
|
||||
if (!res || stack.length === 0 || new bn(stack.pop()).cmpn(0) === 0)
|
||||
return false;
|
||||
|
||||
if (bcoin.script.isScripthash(prev)) {
|
||||
redeem = input.script[input.script.length - 1];
|
||||
if (!Array.isArray(redeem))
|
||||
return false;
|
||||
redeem = bcoin.script.decode(redeem);
|
||||
res = bcoin.script.execute(redeem, stack, this, i, flags);
|
||||
if (!res || stack.length === 0 || new bn(stack.pop()).cmpn(0) === 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return bcoin.script.verify(input.script, output.script, this, i, flags);
|
||||
}, this);
|
||||
};
|
||||
|
||||
@ -660,7 +638,7 @@ TX.prototype.maxSize = function maxSize() {
|
||||
|
||||
// Add size for signatures and public keys
|
||||
copy.inputs.forEach(function(input, i) {
|
||||
var s, m, n, script, redeem;
|
||||
var s, m, n;
|
||||
|
||||
// Get the previous output's subscript
|
||||
s = input.out.tx.getSubscript(input.out.index);
|
||||
@ -694,34 +672,16 @@ TX.prototype.maxSize = function maxSize() {
|
||||
}
|
||||
|
||||
if (bcoin.script.isScripthash(s)) {
|
||||
script = this.inputs[i].script;
|
||||
if (script.length) {
|
||||
redeem = bcoin.script.decode(script[script.length - 1]);
|
||||
m = redeem[0];
|
||||
n = redeem[redeem.length - 2];
|
||||
// If using pushdata instead of OP_1-16:
|
||||
if (Array.isArray(m))
|
||||
m = m[0] || 0;
|
||||
if (Array.isArray(n))
|
||||
n = n[0] || 0;
|
||||
} else {
|
||||
// May end up in a higher fee if we
|
||||
// do not have the redeem script available.
|
||||
m = 15;
|
||||
n = 15;
|
||||
}
|
||||
assert(m >= 1 && m <= n);
|
||||
assert(n >= 1 && n <= 15);
|
||||
// Multisig
|
||||
// Empty byte
|
||||
size += 1;
|
||||
// Signature + len
|
||||
size += 74 * m;
|
||||
size += 74 * 15;
|
||||
// Redeem script
|
||||
// m byte
|
||||
size += 1;
|
||||
// 1 byte length + 65 byte pubkey
|
||||
size += 66 * n;
|
||||
size += 66 * 15;
|
||||
// n byte
|
||||
size += 1;
|
||||
// checkmultisig byte
|
||||
@ -848,7 +808,7 @@ TX.prototype._recalculateFee = function recalculateFee() {
|
||||
output = this.outputs[this.outputs.length - 1];
|
||||
}
|
||||
|
||||
var byteSize = this.maxSize();
|
||||
var byteSize = this.render().length;
|
||||
var newFee = Math.ceil(byteSize / 1024) * TX.fee;
|
||||
var currentFee = this.getFee().toNumber();
|
||||
|
||||
|
||||
@ -366,8 +366,10 @@ utils.array2utf8 = function array2utf8(arr) {
|
||||
};
|
||||
|
||||
utils.copy = function copy(src, dst, off, force) {
|
||||
if (Buffer.isBuffer(src) && Buffer.isBuffer(dst) && !force)
|
||||
if (Buffer.isBuffer(src) && Buffer.isBuffer(dst)) {
|
||||
assert(!force);
|
||||
return src.copy(dst, off, 0, src.length);
|
||||
}
|
||||
|
||||
var len = src.length;
|
||||
var i = 0;
|
||||
|
||||
@ -405,7 +405,7 @@ Wallet.prototype.ownInput = function ownInput(tx, index) {
|
||||
if (bcoin.script.isPubkeyhashInput(input.script, key))
|
||||
return true;
|
||||
|
||||
// if (bcoin.script.isMultisigInput(input.script, key, tx, i))
|
||||
// if (bcoin.script.isMultisigInput(input.script, keys, tx, i))
|
||||
// return true;
|
||||
|
||||
if (bcoin.script.isScripthashInput(input.script, redeem))
|
||||
@ -449,10 +449,9 @@ Wallet.prototype.fillUnspent = function fillUnspent(tx, changeAddress) {
|
||||
return tx.fillUnspent(this.unspent(), changeAddress);
|
||||
};
|
||||
|
||||
Wallet.prototype.scriptInputs = function scriptInputs(tx, inputs) {
|
||||
Wallet.prototype.scriptInputs = function scriptInputs(tx) {
|
||||
var pub = this.getFullPublicKey();
|
||||
|
||||
inputs = inputs || tx.inputs;
|
||||
var inputs = tx.inputs;
|
||||
|
||||
inputs = inputs.filter(function(input, i) {
|
||||
if (!input.out.tx && this.tx._all[input.out.hash])
|
||||
@ -470,14 +469,13 @@ Wallet.prototype.scriptInputs = function scriptInputs(tx, inputs) {
|
||||
return inputs.length;
|
||||
};
|
||||
|
||||
Wallet.prototype.signInputs = function signInputs(tx, type, inputs) {
|
||||
Wallet.prototype.signInputs = function signInputs(tx, type) {
|
||||
var key = this.key;
|
||||
var inputs = tx.inputs;
|
||||
|
||||
if (!type)
|
||||
type = 'all';
|
||||
|
||||
inputs = inputs || tx.inputs;
|
||||
|
||||
inputs = inputs.filter(function(input, i) {
|
||||
if (!input.out.tx && this.tx._all[input.out.hash])
|
||||
input.out.tx = this.tx._all[input.out.hash];
|
||||
@ -493,14 +491,13 @@ Wallet.prototype.signInputs = function signInputs(tx, type, inputs) {
|
||||
return inputs.length;
|
||||
};
|
||||
|
||||
Wallet.prototype.sign = function sign(tx, type, inputs) {
|
||||
Wallet.prototype.sign = function sign(tx, type) {
|
||||
if (!type)
|
||||
type = 'all';
|
||||
|
||||
var pub = this.getFullPublicKey();
|
||||
var key = this.key;
|
||||
|
||||
inputs = inputs || tx.inputs;
|
||||
var inputs = tx.inputs;
|
||||
|
||||
// Add signature script to each input
|
||||
inputs = inputs.filter(function(input, i) {
|
||||
@ -623,11 +620,7 @@ Wallet.prototype.toJSON = function toJSON(encrypt) {
|
||||
};
|
||||
|
||||
Wallet.fromJSON = function fromJSON(json, decrypt) {
|
||||
var compressed, key, w;
|
||||
var priv = json.priv;
|
||||
var pub = json.pub;
|
||||
var xprivkey = json.xprivkey;
|
||||
var multisig = json.multisig;
|
||||
var priv, pub, xprivkey, multisig, compressed, key, w;
|
||||
|
||||
assert.equal(json.v, 2);
|
||||
assert.equal(json.type, 'wallet');
|
||||
@ -638,7 +631,8 @@ Wallet.fromJSON = function fromJSON(json, decrypt) {
|
||||
if (json.encrypted && !decrypt)
|
||||
throw new Error('Cannot decrypt wallet');
|
||||
|
||||
if (priv) {
|
||||
if (json.priv) {
|
||||
priv = json.priv;
|
||||
if (json.encrypted)
|
||||
priv = decrypt(priv);
|
||||
|
||||
@ -656,20 +650,21 @@ Wallet.fromJSON = function fromJSON(json, decrypt) {
|
||||
compressed = false;
|
||||
}
|
||||
} else {
|
||||
pub = bcoin.utils.fromBase58(pub);
|
||||
pub = bcoin.utils.fromBase58(json.pub);
|
||||
compressed = pub[0] !== 0x04;
|
||||
}
|
||||
|
||||
if (multisig) {
|
||||
if (json.multisig) {
|
||||
multisig = {
|
||||
type: multisig.type,
|
||||
keys: multisig.keys.map(utils.fromBase58),
|
||||
m: multisig.m,
|
||||
n: multisig.n
|
||||
type: json.multisig.type,
|
||||
keys: json.multisig.keys.map(utils.fromBase58),
|
||||
m: json.multisig.m,
|
||||
n: json.multisig.n
|
||||
};
|
||||
}
|
||||
|
||||
if (xprivkey) {
|
||||
if (json.xprivkey) {
|
||||
xprivkey = json.xprivkey;
|
||||
if (json.encrypted)
|
||||
xprivkey = decrypt(xprivkey);
|
||||
priv = bcoin.hd.priv(xprivkey);
|
||||
|
||||
@ -42,7 +42,7 @@ describe('Script', function() {
|
||||
var hex = '6a28590c080112220a1b353930632e6f7267282a5f5e294f7665726c6179404f7261636c65103b1a010c'
|
||||
var encoded = bcoin.utils.toArray(hex, 'hex')
|
||||
var decoded = bcoin.script.decode(encoded);
|
||||
assert(bcoin.script.isColored(decoded))
|
||||
assert(bcoin.script.isNulldata(decoded))
|
||||
})
|
||||
|
||||
it('should handle if statements correctly', function () {
|
||||
|
||||
@ -254,8 +254,8 @@ describe('Wallet', function() {
|
||||
tx.input(unspent1[1]);
|
||||
tx.input(unspent1[2]);
|
||||
tx.input(unspent2[1]);
|
||||
assert.equal(w1.sign(tx, 'all', tx.inputs.slice(), 0), 2);
|
||||
assert.equal(w2.sign(tx, 'all', tx.inputs.slice(2), 2), 1);
|
||||
assert.equal(w1.sign(tx, 'all', tx.inputs.slice()), 2);
|
||||
assert.equal(w2.sign(tx, 'all', tx.inputs.slice(2)), 1);
|
||||
|
||||
// Verify
|
||||
assert.equal(tx.verify(), true);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user