transaction improvements.

This commit is contained in:
Christopher Jeffrey 2016-01-10 03:23:29 -08:00
parent 0b7ca266ee
commit eb1a3ea6d2
10 changed files with 167 additions and 154 deletions

View File

@ -7,6 +7,7 @@
var bn = require('bn.js'); var bn = require('bn.js');
var bcoin = require('../bcoin'); var bcoin = require('../bcoin');
var utils = bcoin.utils; var utils = bcoin.utils;
var constants = bcoin.protocol.constants;
/** /**
* Input * Input
@ -180,6 +181,7 @@ Input.prototype.__defineGetter__('scriptaddr', function() {
// Schema and defaults for data object: // Schema and defaults for data object:
// { // {
// type: null, // type: null,
// subtype: null,
// side: 'input', // side: 'input',
// signatures: [], // signatures: [],
// keys: [], // keys: [],
@ -263,7 +265,7 @@ Input.getData = function getData(input) {
} else if (data.type === 'scripthash') { } else if (data.type === 'scripthash') {
// We work backwards here: scripthash is one of the few cases // We work backwards here: scripthash is one of the few cases
// where we get more data from the input than the output. // 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 }, out: { hash: input.out.hash, index: input.out.index },
script: input.script, script: input.script,
seq: input.seq seq: input.seq
@ -313,19 +315,16 @@ Input.getData = function getData(input) {
} }
if (bcoin.script.isScripthashInput(s)) { if (bcoin.script.isScripthashInput(s)) {
signature = sub.slice(1, -1);
redeem = sub[sub.length - 1]; redeem = sub[sub.length - 1];
hash = utils.ripesha(redeem); hash = utils.ripesha(redeem);
address = bcoin.wallet.hash2addr(hash, 'scripthash'); address = bcoin.wallet.hash2addr(hash, 'scripthash');
redeem = bcoin.script.decode(redeem); redeem = bcoin.script.decode(redeem);
data = bcoin.output.getData({ val = bcoin.input.getData(sub.slice(0, -1));
script: redeem, data = bcoin.output.getData(redeem);
value: new bn(0) return utils.merge(val, data, {
});
return utils.merge(data, {
type: 'scripthash', type: 'scripthash',
subtype: data.type,
side: 'input', side: 'input',
signatures: signature,
redeem: redeem, redeem: redeem,
scripthash: hash, scripthash: hash,
scriptaddress: address, scriptaddress: address,
@ -351,6 +350,7 @@ Input.prototype.inspect = function inspect() {
return { return {
type: this.type, type: this.type,
subtype: this.data.subtype,
address: this.address, address: this.address,
signatures: this.signatures.map(utils.toHex), signatures: this.signatures.map(utils.toHex),
keys: this.keys.map(utils.toHex), keys: this.keys.map(utils.toHex),
@ -358,6 +358,7 @@ Input.prototype.inspect = function inspect() {
lock: this.lock, lock: this.lock,
value: utils.btc(output.value), value: utils.btc(output.value),
script: bcoin.script.format(this.script)[0], script: bcoin.script.format(this.script)[0],
redeem: this.data.redeem ? bcoin.script.format(this.data.redeem)[0] : null,
seq: this.seq, seq: this.seq,
output: output output: output
}; };

View File

@ -147,6 +147,7 @@ Output.prototype.__defineGetter__('scriptaddr', function() {
// Schema and defaults for data object: // Schema and defaults for data object:
// { // {
// type: null, // type: null,
// subtype: null,
// side: 'output', // side: 'output',
// signatures: [], // signatures: [],
// keys: [], // keys: [],
@ -215,14 +216,13 @@ Output.getData = function getData(output) {
address = bcoin.wallet.hash2addr(hash); address = bcoin.wallet.hash2addr(hash);
return utils.merge(def, { return utils.merge(def, {
type: 'pubkeyhash', type: 'pubkeyhash',
side: 'output',
hashes: [hash], hashes: [hash],
addresses: [address] addresses: [address]
}); });
} }
keys = bcoin.script.isMultisig(s); if (bcoin.script.isMultisig(s)) {
if (keys) { keys = sub.slice(1, -2);
hash = keys.map(function(key) { hash = keys.map(function(key) {
return utils.ripesha(key); return utils.ripesha(key);
}); });
@ -272,9 +272,6 @@ Output.prototype.inspect = function inspect() {
keys: this.keys.map(utils.toHex), keys: this.keys.map(utils.toHex),
hashes: this.hashes.map(utils.toHex), hashes: this.hashes.map(utils.toHex),
addresses: this.addresses, addresses: this.addresses,
redeem: this.type === 'scripthash'
? bcoin.script.format(this.data.redeem)[0]
: null,
m: this.m, m: this.m,
n: this.n, n: this.n,
text: this.text, text: this.text,

View File

@ -47,7 +47,6 @@ Parser.prototype.feed = function feed(data) {
while (this.pendingTotal >= this.waiting) { while (this.pendingTotal >= this.waiting) {
// Concat chunks // Concat chunks
// chunk = new Array(this.waiting);
chunk = new Buffer(this.waiting); chunk = new Buffer(this.waiting);
i = 0; i = 0;
@ -55,7 +54,6 @@ Parser.prototype.feed = function feed(data) {
len = 0; len = 0;
for (; off < chunk.length; i++) { 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); len = this.pending[0].copy(chunk, off, 0, this.pending[0].length);
if (len === this.pending[0].length) if (len === this.pending[0].length)
this.pending.shift(); this.pending.shift();

View File

@ -150,6 +150,64 @@ script.encode = function encode(s) {
return res; 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) { script.subscript = function subscript(s, lastSep) {
var i, res; var i, res;
@ -179,7 +237,7 @@ script.subscript = function subscript(s, lastSep) {
return res; return res;
}; };
script.verify = function verify(hash, sig, pub) { script.checksig = function checksig(hash, sig, pub) {
var k; var k;
try { try {
@ -249,7 +307,7 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
var n, n1, n2, n3; var n, n1, n2, n3;
var res; var res;
var key, sig, type, subscript, hash; var key, sig, type, subscript, hash;
var keys, i, j, key, m; var keys, i, j, m;
var succ; var succ;
var lock, threshold; var lock, threshold;
var evalScript; var evalScript;
@ -700,7 +758,7 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
subscript = script.subscript(s, lastSep); subscript = script.subscript(s, lastSep);
hash = tx.subscriptHash(index, subscript, type); 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 (o === 'checksigverify') {
if (!res) if (!res)
return false; return false;
@ -763,13 +821,19 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
res = false; res = false;
for (; !res && j < n; j++) 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) if (res)
succ++; succ++;
} }
// Extra value // Extra value
if (stack.length < 1)
return false;
if (flags.verifynulldummy !== false) {
if (stack[stack.length - 1].length > 0)
return false;
}
stack.pop(); stack.pop();
// Too many signatures on stack // Too many signatures on stack
@ -866,20 +930,6 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
return true; 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) { script.redeem = function redeem(keys, m, n) {
if (keys.length !== n) if (keys.length !== n)
throw new Error(n + ' keys are required to generate redeem script'); 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); keys = utils.sortKeys(keys);
return [ m ].concat( return [m].concat(
keys, keys,
[ n, 'checkmultisig' ] [n, 'checkmultisig']
); );
}; };
@ -908,11 +958,8 @@ script.standard = function standard(s) {
}; };
script.isStandard = function isStandard(s) { script.isStandard = function isStandard(s) {
var m, n;
var type = script.standard(s); var type = script.standard(s);
var m, n;
if (!type)
return false;
if (type === 'multisig') { if (type === 'multisig') {
m = new bn(s[0]).toNumber(); m = new bn(s[0]).toNumber();
@ -982,7 +1029,7 @@ script.isPubkey = function isPubkey(s, key) {
if (key) if (key)
return utils.isEqual(s[0], key); return utils.isEqual(s[0], key);
return s[0]; return true;
}; };
script.isPubkeyhash = function isPubkeyhash(s, hash) { script.isPubkeyhash = function isPubkeyhash(s, hash) {
@ -1008,11 +1055,11 @@ script.isPubkeyhash = function isPubkeyhash(s, hash) {
if (hash) if (hash)
return utils.isEqual(s[2], hash); return utils.isEqual(s[2], hash);
return s[2]; return true;
}; };
script.isMultisig = function isMultisig(s, pubs) { script.isMultisig = function isMultisig(s, pubs) {
var m, n, keys, isArray, total; var m, n, keys, total;
s = script.subscript(s); s = script.subscript(s);
@ -1048,15 +1095,11 @@ script.isMultisig = function isMultisig(s, pubs) {
keys = s.slice(1, 1 + n); keys = s.slice(1, 1 + n);
isArray = keys.every(function(k) { if (!keys.every(Array.isArray))
return Array.isArray(k);
});
if (!isArray)
return false; return false;
if (!pubs) if (!pubs)
return keys; return true;
total = keys.filter(function(k) { total = keys.filter(function(k) {
return pubs.some(function(pub) { 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. // checksig script to see if this is our input.
// This will only work if the script verifies. // This will only work if the script verifies.
if (key) if (key)
return script.exec(s, [key, 'checksig'], tx, i); return script.verify(s, [key, 'checksig'], tx, i);
return true; return true;
}; };
@ -1153,10 +1196,10 @@ script.isPubkeyhashInput = function isPubkeyhashInput(s, key) {
if (key) if (key)
return utils.isEqual(s[1], 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; var i, res, o;
// We need to rule out scripthash // We need to rule out scripthash
@ -1180,40 +1223,58 @@ script.isMultisigInput = function isMultisigInput(s, pubs, tx, i) {
// Execute the script against our pubkeys' // Execute the script against our pubkeys'
// redeem script to see if this is our input. // redeem script to see if this is our input.
// This will only work if the script verifies. // This will only work if the script verifies.
if (pubs && pubs.length >= 2) { if (keys && keys.length >= 2) {
o = script.redeem(pubs, 2, pubs.length); o = script.redeem(keys, s.length - 1, keys.length);
return script.exec(s, o, tx, i); return script.verify(s, o, tx, i);
} }
return true; return true;
}; };
script.isScripthashInput = function isScripthashInput(s, redeem) { script.isScripthashInput = function isScripthashInput(s, data) {
var i, res, r, keys; var raw, redeem;
s = script.subscript(s); 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; 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; return false;
for (i = 1; i < s.length - 1; i++) { // P2SH redeem scripts can be nonstandard: make
if (!script.isSig(s[i])) // it easier for other functions to parse this.
return false; 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]; // Check data against last array in case
if (r[r.length - 1] !== constants.opcodes.checkmultisig) // a raw redeem script was passed in.
return false; if (data && utils.isEqual(data, raw))
return true;
if (redeem) // Test against all other script types
return utils.isEqual(redeem, r); return script.isPubkey(redeem, data)
|| script.isPubkeyhash(redeem, data)
keys = script.decode(r).slice(1, -2); || script.isMultisig(redeem, data);
return keys;
}; };
script.coinbaseBits = function coinbaseBits(s, block) { script.coinbaseBits = function coinbaseBits(s, block) {
@ -1526,7 +1587,7 @@ script.sigopsScripthash = function sigopsScripthash(s) {
}; };
script.args = function args(s) { script.args = function args(s) {
var type, pubs, m; var type, keys, m;
s = bcoin.script.subscript(s); s = bcoin.script.subscript(s);
@ -1542,11 +1603,11 @@ script.args = function args(s) {
return 2; return 2;
if (type === 'multisig') { if (type === 'multisig') {
pubs = bcoin.script.isMultisig(s); keys = bcoin.script.isMultisig(s);
if (!pub) if (!pub)
return -1; return -1;
m = new bn(s[0]).toNumber(); m = new bn(s[0]).toNumber();
if (pubs.length < 1 || m < 1) if (keys.length < 1 || m < 1)
return -1; return -1;
return m + 1; return m + 1;
} }

View File

@ -123,7 +123,6 @@ TXPool.prototype.add = function add(tx, noWrite) {
// signature checking code to ownInput for p2sh and p2pk, // signature checking code to ownInput for p2sh and p2pk,
// we could in theory use ownInput here (and down below) // we could in theory use ownInput here (and down below)
// instead. // instead.
// if (this._wallet.ownInput(input.out.tx, input.out.index))
if (input.out.tx) { if (input.out.tx) {
if (!this._wallet.ownOutput(input.out.tx, input.out.index)) if (!this._wallet.ownOutput(input.out.tx, input.out.index))
continue; continue;

View File

@ -596,8 +596,11 @@ TX.prototype.verify = function verify(index, force, flags) {
if (this.inputs.length === 0) if (this.inputs.length === 0)
return false; return false;
if (!flags)
flags = {};
return this.inputs.every(function(input, i) { return this.inputs.every(function(input, i) {
var stack, prev, push, res, redeem; var output;
if (index != null && index !== i) if (index != null && index !== i)
return true; return true;
@ -605,41 +608,16 @@ TX.prototype.verify = function verify(index, force, flags) {
if (!input.out.tx) if (!input.out.tx)
return false; 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); assert.equal(input.out.tx.hash('hex'), input.out.hash);
// Transaction cannot reference itself // Transaction cannot reference itself
if (input.out.tx.hash('hex') === this.hash('hex')) if (input.out.tx.hash('hex') === this.hash('hex'))
return false; return false;
assert(input.out.tx.outputs.length > input.out.index); return bcoin.script.verify(input.script, output.script, this, i, flags);
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;
}, this); }, this);
}; };
@ -660,7 +638,7 @@ TX.prototype.maxSize = function maxSize() {
// Add size for signatures and public keys // Add size for signatures and public keys
copy.inputs.forEach(function(input, i) { copy.inputs.forEach(function(input, i) {
var s, m, n, script, redeem; var s, m, n;
// 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);
@ -694,34 +672,16 @@ TX.prototype.maxSize = function maxSize() {
} }
if (bcoin.script.isScripthash(s)) { 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 // Multisig
// Empty byte // Empty byte
size += 1; size += 1;
// Signature + len // Signature + len
size += 74 * m; size += 74 * 15;
// Redeem script // Redeem script
// m byte // m byte
size += 1; size += 1;
// 1 byte length + 65 byte pubkey // 1 byte length + 65 byte pubkey
size += 66 * n; size += 66 * 15;
// n byte // n byte
size += 1; size += 1;
// checkmultisig byte // checkmultisig byte
@ -848,7 +808,7 @@ TX.prototype._recalculateFee = function recalculateFee() {
output = this.outputs[this.outputs.length - 1]; 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 newFee = Math.ceil(byteSize / 1024) * TX.fee;
var currentFee = this.getFee().toNumber(); var currentFee = this.getFee().toNumber();

View File

@ -366,8 +366,10 @@ utils.array2utf8 = function array2utf8(arr) {
}; };
utils.copy = function copy(src, dst, off, force) { 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); return src.copy(dst, off, 0, src.length);
}
var len = src.length; var len = src.length;
var i = 0; var i = 0;

View File

@ -405,7 +405,7 @@ Wallet.prototype.ownInput = function ownInput(tx, index) {
if (bcoin.script.isPubkeyhashInput(input.script, key)) if (bcoin.script.isPubkeyhashInput(input.script, key))
return true; return true;
// if (bcoin.script.isMultisigInput(input.script, key, tx, i)) // if (bcoin.script.isMultisigInput(input.script, keys, tx, i))
// return true; // return true;
if (bcoin.script.isScripthashInput(input.script, redeem)) if (bcoin.script.isScripthashInput(input.script, redeem))
@ -449,10 +449,9 @@ Wallet.prototype.fillUnspent = function fillUnspent(tx, changeAddress) {
return tx.fillUnspent(this.unspent(), changeAddress); return tx.fillUnspent(this.unspent(), changeAddress);
}; };
Wallet.prototype.scriptInputs = function scriptInputs(tx, inputs) { Wallet.prototype.scriptInputs = function scriptInputs(tx) {
var pub = this.getFullPublicKey(); var pub = this.getFullPublicKey();
var inputs = tx.inputs;
inputs = inputs || tx.inputs;
inputs = inputs.filter(function(input, i) { inputs = inputs.filter(function(input, i) {
if (!input.out.tx && this.tx._all[input.out.hash]) if (!input.out.tx && this.tx._all[input.out.hash])
@ -470,14 +469,13 @@ Wallet.prototype.scriptInputs = function scriptInputs(tx, inputs) {
return inputs.length; return inputs.length;
}; };
Wallet.prototype.signInputs = function signInputs(tx, type, inputs) { Wallet.prototype.signInputs = function signInputs(tx, type) {
var key = this.key; var key = this.key;
var inputs = tx.inputs;
if (!type) if (!type)
type = 'all'; type = 'all';
inputs = inputs || tx.inputs;
inputs = inputs.filter(function(input, i) { inputs = inputs.filter(function(input, i) {
if (!input.out.tx && this.tx._all[input.out.hash]) if (!input.out.tx && this.tx._all[input.out.hash])
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; return inputs.length;
}; };
Wallet.prototype.sign = function sign(tx, type, inputs) { Wallet.prototype.sign = function sign(tx, type) {
if (!type) if (!type)
type = 'all'; type = 'all';
var pub = this.getFullPublicKey(); var pub = this.getFullPublicKey();
var key = this.key; var key = this.key;
var inputs = tx.inputs;
inputs = inputs || tx.inputs;
// Add signature script to each input // Add signature script to each input
inputs = inputs.filter(function(input, i) { inputs = inputs.filter(function(input, i) {
@ -623,11 +620,7 @@ Wallet.prototype.toJSON = function toJSON(encrypt) {
}; };
Wallet.fromJSON = function fromJSON(json, decrypt) { Wallet.fromJSON = function fromJSON(json, decrypt) {
var compressed, key, w; var priv, pub, xprivkey, multisig, compressed, key, w;
var priv = json.priv;
var pub = json.pub;
var xprivkey = json.xprivkey;
var multisig = json.multisig;
assert.equal(json.v, 2); assert.equal(json.v, 2);
assert.equal(json.type, 'wallet'); assert.equal(json.type, 'wallet');
@ -638,7 +631,8 @@ Wallet.fromJSON = function fromJSON(json, decrypt) {
if (json.encrypted && !decrypt) if (json.encrypted && !decrypt)
throw new Error('Cannot decrypt wallet'); throw new Error('Cannot decrypt wallet');
if (priv) { if (json.priv) {
priv = json.priv;
if (json.encrypted) if (json.encrypted)
priv = decrypt(priv); priv = decrypt(priv);
@ -656,20 +650,21 @@ Wallet.fromJSON = function fromJSON(json, decrypt) {
compressed = false; compressed = false;
} }
} else { } else {
pub = bcoin.utils.fromBase58(pub); pub = bcoin.utils.fromBase58(json.pub);
compressed = pub[0] !== 0x04; compressed = pub[0] !== 0x04;
} }
if (multisig) { if (json.multisig) {
multisig = { multisig = {
type: multisig.type, type: json.multisig.type,
keys: multisig.keys.map(utils.fromBase58), keys: json.multisig.keys.map(utils.fromBase58),
m: multisig.m, m: json.multisig.m,
n: multisig.n n: json.multisig.n
}; };
} }
if (xprivkey) { if (json.xprivkey) {
xprivkey = json.xprivkey;
if (json.encrypted) if (json.encrypted)
xprivkey = decrypt(xprivkey); xprivkey = decrypt(xprivkey);
priv = bcoin.hd.priv(xprivkey); priv = bcoin.hd.priv(xprivkey);

View File

@ -42,7 +42,7 @@ describe('Script', function() {
var hex = '6a28590c080112220a1b353930632e6f7267282a5f5e294f7665726c6179404f7261636c65103b1a010c' var hex = '6a28590c080112220a1b353930632e6f7267282a5f5e294f7665726c6179404f7261636c65103b1a010c'
var encoded = bcoin.utils.toArray(hex, 'hex') var encoded = bcoin.utils.toArray(hex, 'hex')
var decoded = bcoin.script.decode(encoded); var decoded = bcoin.script.decode(encoded);
assert(bcoin.script.isColored(decoded)) assert(bcoin.script.isNulldata(decoded))
}) })
it('should handle if statements correctly', function () { it('should handle if statements correctly', function () {

View File

@ -254,8 +254,8 @@ describe('Wallet', function() {
tx.input(unspent1[1]); tx.input(unspent1[1]);
tx.input(unspent1[2]); tx.input(unspent1[2]);
tx.input(unspent2[1]); tx.input(unspent2[1]);
assert.equal(w1.sign(tx, 'all', tx.inputs.slice(), 0), 2); assert.equal(w1.sign(tx, 'all', tx.inputs.slice()), 2);
assert.equal(w2.sign(tx, 'all', tx.inputs.slice(2), 2), 1); assert.equal(w2.sign(tx, 'all', tx.inputs.slice(2)), 1);
// Verify // Verify
assert.equal(tx.verify(), true); assert.equal(tx.verify(), true);