wallet refactor. fixes.

This commit is contained in:
Christopher Jeffrey 2016-02-10 16:42:02 -08:00
parent 9fc6848dce
commit 6cc4c866dc
14 changed files with 409 additions and 485 deletions

View File

@ -41,32 +41,23 @@ function Address(options) {
this.path = options.path;
this.type = options.type || 'pubkeyhash';
this.subtype = options.subtype;
this.keys = [];
this.m = options.m || 1;
this.n = options.n || 1;
this.redeem = null;
if (this.n > 1) {
if (this.type !== 'multisig')
this.type = 'scripthash';
if (this.type === 'scripthash')
this.subtype = 'multisig';
}
if (this.n > 1)
this.type = 'multisig';
if (network.prefixes[this.type] == null)
throw new Error('Unknown prefix: ' + this.type);
assert(this.type === 'pubkeyhash' || this.type === 'multisig');
this.prefixType = this.type === 'multisig' ? 'scripthash' : 'pubkeyhash';
this.nmax = this.type === 'scripthash'
? (this.key.compressed ? 15 : 7)
: 3;
if (network.prefixes[this.prefixType] == null)
throw new Error('Unknown prefix: ' + this.prefixType);
if (this.m < 1 || this.m > this.n)
throw new Error('m ranges between 1 and n');
if (this.n < 1 || this.n > this.nmax)
throw new Error('n ranges between 1 and ' + this.nmax);
this.addKey(this.getPublicKey());
(options.keys || []).forEach(function(key) {
@ -76,7 +67,7 @@ function Address(options) {
if (options.redeem || options.script)
this.setRedeem(options.redeem || options.script);
this.prefix = 'bt/address/' + this.getKeyAddress() + '/';
this.prefix = 'bt/address/' + this.getID() + '/';
}
inherits(Address, EventEmitter);
@ -85,6 +76,10 @@ Address.prototype.__defineGetter__('balance', function() {
return this.getBalance();
});
Address.prototype.getID = function getID() {
return this.getKeyAddress();
};
Address.prototype.getAll = function getAll() {
return this._wallet.getAll(this);
};
@ -115,8 +110,8 @@ Address.prototype.setRedeem = function setRedeem(redeem) {
if (!utils.isBytes(redeem))
redeem = bcoin.script.encode(redeem);
this.type = 'scripthash';
this.subtype = null;
this.type = 'multisig';
this.prefixType = 'scripthash';
this.redeem = redeem;
this.emit('update script', old, this.getScriptAddress());
};
@ -192,49 +187,53 @@ Address.fromSecret = function fromSecret(privateKey) {
};
Address.prototype.getScript = function getScript() {
if (this.type !== 'scripthash')
var redeem;
if (this.prefixType !== 'scripthash')
return;
if (this._script)
return this._script;
if (this.redeem)
return this._script = this.redeem.slice();
if (this.redeem) {
redeem = this.redeem.slice();
assert(utils.isBytes(redeem));
} else if (this.keys.length < this.n) {
redeem = bcoin.script.createPubkeyhash(this.getKeyHash());
redeem = bcoin.script.encode(redeem);
} else {
redeem = bcoin.script.createMultisig(this.keys, this.m, this.n);
redeem = bcoin.script.encode(redeem);
}
if (this.subtype === 'pubkey')
this._script = bcoin.script.createPubkey(this.getPublicKey());
else if (this.subtype === 'pubkeyhash' || this.keys.length < this.n)
this._script = bcoin.script.createPubkeyhash(this.getKeyHash());
else if (this.subtype === 'multisig')
this._script = bcoin.script.createMultisig(this.keys, this.m, this.n);
else
assert(false);
if (redeem.length > 520)
throw new Error('Redeem script too large (520 byte limit).');
this._script = bcoin.script.encode(this._script);
this._script = redeem;
return this._script;
};
Address.prototype.getScriptHash = function getScriptHash() {
if (this.type !== 'scripthash')
if (this.prefixType !== 'scripthash')
return;
if (this._scriptHash)
return this._scriptHash;
this._scriptHash = utils.ripesha(this.getScript());
this._scriptHash = Address.hash160(this.getScript());
return this._scriptHash;
};
Address.prototype.getScriptAddress = function getScriptAddress() {
if (this.type !== 'scripthash')
if (this.prefixType !== 'scripthash')
return;
if (this._scriptAddress)
return this._scriptAddress;
this._scriptAddress = Address.hash2addr(this.getScriptHash(), this.type);
this._scriptAddress = Address.toAddress(this.getScriptHash(), this.prefixType);
return this._scriptAddress;
};
@ -256,7 +255,7 @@ Address.prototype.getKeyHash = function getKeyHash() {
if (this._hash)
return this._hash;
this._hash = Address.key2hash(this.getPublicKey());
this._hash = Address.hash160(this.getPublicKey());
return this._hash;
};
@ -265,127 +264,41 @@ Address.prototype.getKeyAddress = function getKeyAddress() {
if (this._address)
return this._address;
this._address = Address.hash2addr(this.getKeyHash(), 'pubkeyhash');
this._address = Address.toAddress(this.getKeyHash(), 'pubkeyhash');
return this._address;
};
Address.prototype.getHash = function getHash() {
if (this.type === 'scripthash')
if (this.prefixType === 'scripthash')
return this.getScriptHash();
return this.getKeyHash();
};
Address.prototype.getAddress = function getAddress() {
if (this.type === 'scripthash')
if (this.prefixType === 'scripthash')
return this.getScriptAddress();
return this.getKeyAddress();
};
Address.key2hash = function key2hash(key) {
key = utils.toBuffer(key);
return utils.ripesha(key);
Address.prototype._getAddressTable = function _getAddressTable() {
var addressTable = {};
addressTable[this.getAddress()] = true;
return addressTable;
};
Address.hash2addr = function hash2addr(hash, prefix) {
var addr;
hash = utils.toArray(hash, 'hex');
prefix = network.prefixes[prefix || 'pubkeyhash'];
hash = [ prefix ].concat(hash);
addr = hash.concat(utils.checksum(hash));
return utils.toBase58(addr);
};
Address.key2addr = function key2addr(key, prefix) {
return Address.hash2addr(Address.key2hash(key), prefix);
};
Address.__defineGetter__('prefixes', function() {
if (Address._prefixes)
return Address._prefixes;
Address._prefixes = ['pubkeyhash', 'scripthash'].reduce(function(out, prefix) {
var ch = Address.hash2addr(Address.key2hash([]), prefix)[0];
out[ch] = prefix;
return out;
}, {});
return Address._prefixes;
});
Address.addr2hash = function addr2hash(addr, prefix) {
var chk;
if (prefix == null && typeof addr === 'string')
prefix = Address.prefixes[addr[0]];
if (!utils.isBuffer(addr))
addr = utils.fromBase58(addr);
prefix = network.prefixes[prefix || 'pubkeyhash'];
if (addr.length !== 25)
return [];
if (addr[0] !== prefix)
return [];
chk = utils.checksum(addr.slice(0, -4));
if (utils.readU32(chk, 0) !== utils.readU32(addr, 21))
return [];
return addr.slice(1, -4);
};
Address.validate = function validate(addr, prefix) {
if (!addr || typeof addr !== 'string')
return false;
var p = Address.addr2hash(addr, prefix);
return p.length !== 0;
};
Address.validateAddress = Address.validate;
Address.prototype.ownOutput = function ownOutput(tx, index) {
var scriptHash = this.getScriptHash();
var hash = this.getKeyHash();
var key = this.getPublicKey();
var keys = this.keys;
var addressTable = this._getAddressTable();
var outputs = tx.outputs;
if ((tx instanceof bcoin.output) || (tx instanceof bcoin.coin))
outputs = [tx];
outputs = outputs.filter(function(output, i) {
var s = output.script;
if (index != null && index !== i)
return false;
return output.testScript(key, hash, keys, scriptHash, null);
if (bcoin.script.isPubkey(s, key))
return true;
if (bcoin.script.isPubkeyhash(s, hash))
return true;
if (bcoin.script.isMultisig(s, keys))
return true;
if (scriptHash) {
if (bcoin.script.isScripthash(s, scriptHash))
return true;
}
return false;
return output.test(addressTable, true);
}, this);
if (outputs.length === 0)
@ -395,11 +308,7 @@ Address.prototype.ownOutput = function ownOutput(tx, index) {
};
Address.prototype.ownInput = function ownInput(tx, index) {
var scriptHash = this.getScriptHash();
var hash = this.getKeyHash();
var key = this.getPublicKey();
var redeem = this.getScript();
var keys = this.keys;
var addressTable = this._getAddressTable();
var inputs = tx.inputs;
if (tx instanceof bcoin.input) {
@ -415,25 +324,9 @@ Address.prototype.ownInput = function ownInput(tx, index) {
return false;
if (input.output)
return !!this.ownOutput(input.output);
return input.output.test(addressTable, true);
return input.testScript(key, redeem, null);
// if (bcoin.script.isPubkeyInput(input.script, key, tx, i))
// return true;
if (bcoin.script.isPubkeyhashInput(input.script, key))
return true;
// if (bcoin.script.isMultisigInput(input.script, keys, tx, i))
// return true;
if (redeem) {
if (bcoin.script.isScripthashInput(input.script, redeem))
return true;
}
return false;
return input.test(addressTable, true);
}, this);
if (inputs.length === 0)
@ -544,7 +437,7 @@ Address.prototype.__defineGetter__('address', function() {
return this.getAddress();
});
Address.prototype.toAddress = function toAddress() {
Address.prototype.toExplore = function toExplore() {
return {
address: this.getAddress(),
hash160: utils.toHex(this.getHash()),
@ -555,6 +448,77 @@ Address.prototype.toAddress = function toAddress() {
};
};
Address.hash160 = function hash160(key) {
key = utils.toBuffer(key);
return utils.ripesha(key);
};
Address.toAddress = function toAddress(hash, prefix) {
var addr;
hash = utils.toArray(hash, 'hex');
prefix = network.prefixes[prefix || 'pubkeyhash'];
hash = [prefix].concat(hash);
addr = hash.concat(utils.checksum(hash));
return utils.toBase58(addr);
};
Address.compile = function compile(key, prefix) {
return Address.toAddress(Address.hash160(key), prefix);
};
Address.toHash = function toHash(addr, prefix) {
var chk;
if (prefix == null && typeof addr === 'string')
prefix = Address.prefixes[addr[0]];
if (!utils.isBuffer(addr))
addr = utils.fromBase58(addr);
prefix = network.prefixes[prefix || 'pubkeyhash'];
if (addr.length !== 25)
return [];
if (addr[0] !== prefix)
return [];
chk = utils.checksum(addr.slice(0, -4));
if (utils.readU32(chk, 0) !== utils.readU32(addr, 21))
return [];
return addr.slice(1, -4);
};
Address.__defineGetter__('prefixes', function() {
if (Address._prefixes)
return Address._prefixes;
Address._prefixes = ['pubkeyhash', 'scripthash'].reduce(function(out, prefix) {
var ch = Address.compile([], prefix)[0];
out[ch] = prefix;
return out;
}, {});
return Address._prefixes;
});
Address.validate = function validate(addr, prefix) {
if (!addr || typeof addr !== 'string')
return false;
var p = Address.toHash(addr, prefix);
return p.length !== 0;
};
Address.validateAddress = Address.validate;
Address.prototype.toJSON = function toJSON(encrypt) {
return {
v: 1,
@ -565,11 +529,9 @@ Address.prototype.toJSON = function toJSON(encrypt) {
derived: this.derived,
index: this.index,
path: this.path,
address: this.getKeyAddress(),
scriptAddress: this.getScriptAddress(),
address: this.getAddress(),
key: this.key.toJSON(encrypt),
type: this.type,
subtype: this.subtype,
redeem: this.redeem ? utils.toHex(this.redeem) : null,
keys: this.keys.map(utils.toBase58),
m: this.m,
@ -594,7 +556,6 @@ Address.fromJSON = function fromJSON(json, decrypt) {
path: json.path,
key: bcoin.keypair.fromJSON(json.key, decrypt),
type: json.type,
subtype: json.subtype,
redeem: json.redeem ? utils.toArray(json.redeem, 'hex') : null,
keys: json.keys.map(utils.fromBase58),
m: json.m,

View File

@ -639,9 +639,13 @@ Chain.prototype.getTip = function getTip() {
};
Chain.prototype.isFull = function isFull() {
var delta;
if (!this.tip)
return false;
var delta = utils.now() - this.tip.ts;
delta = utils.now() - this.tip.ts;
return delta < 40 * 60;
};
@ -653,14 +657,15 @@ Chain.prototype.fillPercent = function fillPercent() {
Chain.prototype.hashRange = function hashRange(start, end) {
var hashes = [];
var i;
start = this.byTime(start);
end = this.byTime(end);
if (!start || !end)
return [];
return hashes;
for (var i = start.height; i < end.height + 1; i++)
for (i = start.height; i < end.height + 1; i++)
hashes.push(this.db.get(i).hash);
return hashes;
@ -743,11 +748,17 @@ Chain.prototype.getHeight = function getHeight(hash) {
Chain.prototype.getNextBlock = function getNextBlock(hash) {
var entry = this.byHash(hash);
var next;
if (!entry || !entry.next)
if (!entry)
return null;
return entry.next.hash;
next = entry.next;
if (!next)
return;
return next.hash;
};
Chain.prototype.getSize = function getSize() {

View File

@ -53,7 +53,8 @@ ChainBlock.prototype.getProof = function getProof() {
};
ChainBlock.prototype.getChainwork = function() {
return (this.prev ? this.prev.chainwork : new bn(0)).add(this.getProof());
var prev = this.prev;
return (prev ? prev.chainwork : new bn(0)).add(this.getProof());
};
ChainBlock.prototype.getMedianTime = function() {

View File

@ -107,6 +107,9 @@ ChainDB.prototype._free = function(buf) {
};
ChainDB.prototype.exists = function exists() {
if (!bcoin.fs)
return true;
try {
fs.statSync(this.file);
return true;
@ -116,6 +119,9 @@ ChainDB.prototype.exists = function exists() {
};
ChainDB.prototype.getSize = function getSize() {
if (!bcoin.fs)
return this.ramdisk.size;
try {
return fs.statSync(this.file).size;
} catch (e) {
@ -306,18 +312,26 @@ ChainDB.prototype.remove = function remove(height) {
while (this.isNull(height))
height--;
if (height < 0)
height = 0;
assert(height >= 0);
fs.ftruncateSync(this.fd, (height + 1) * BLOCK_SIZE);
this.size = (height + 1) * BLOCK_SIZE;
this.tip = height;
this.truncate(height);
}
return true;
};
ChainDB.prototype.truncate = function truncate(height) {
this.size = (height + 1) * BLOCK_SIZE;
this.tip = height;
if (!bcoin.fs) {
this.ramdisk.truncate(this.size);
return;
}
fs.ftruncateSync(this.fd, this.size);
};
ChainDB.prototype.isNull = function isNull(height) {
var data = this._readSync(4, height * BLOCK_SIZE);
if (!data)

View File

@ -199,7 +199,7 @@ HDPrivateKey.prototype.scan44 = function scan44(options, txByAddress, callback)
// respect the gap limit described below
return (function next() {
var address = chain.derive(addressIndex++);
var addr = bcoin.address.key2addr(address.publicKey);
var addr = bcoin.address.compile(address.publicKey);
return txByAddress(addr, function(err, txs) {
var result;
@ -346,7 +346,7 @@ HDPrivateKey.prototype.scan45 = function scan45(options, txByAddress, callback)
return (function next() {
var address = chain.derive(addressIndex++);
var addr = bcoin.address.key2addr(address.publicKey);
var addr = bcoin.address.compile(address.publicKey);
return txByAddress(addr, function(err, txs) {
var result;
@ -837,7 +837,7 @@ function HDPublicKey(options) {
if (!options)
throw new Error('No options for HDPublicKey');
if (HDPublicKey.isExtended(data))
if (HDPublicKey.isExtended(options))
options = { xkey: options };
data = options.xkey

View File

@ -104,7 +104,7 @@ Input.prototype.__defineGetter__('id', function() {
});
Input.prototype.__defineGetter__('address', function() {
return this.data.scriptAddress || this.addresses[0];
return this.data.address;
});
Input.prototype.__defineGetter__('signatures', function() {
@ -163,34 +163,6 @@ Input.prototype.__defineGetter__('value', function() {
return this.output.value;
});
Input.prototype.__defineGetter__('addr', function() {
return this.address;
});
Input.prototype.__defineGetter__('addrs', function() {
return this.addresses;
});
Input.prototype.__defineGetter__('pub', function() {
return this.key;
});
Input.prototype.__defineGetter__('pubs', function() {
return this.keys;
});
Input.prototype.__defineGetter__('sig', function() {
return this.signature;
});
Input.prototype.__defineGetter__('sigs', function() {
return this.signatures;
});
Input.prototype.__defineGetter__('scriptaddr', function() {
return this.scriptAddress;
});
// Schema and defaults for data object:
// {
// type: String,
@ -253,25 +225,18 @@ Input.prototype.getData = function getData() {
return Input.getData(this);
};
Input.prototype.getAddresses = function getAddresses() {
return this.getData().addresses;
};
Input.prototype.getScriptAddress = function getScriptAddress() {
return this.getData().scriptAddress;
};
Input.prototype.getKeyAddress = function getKeyAddress() {
return this.getData().addresses[0];
Input.prototype.getType = function getType() {
var prev = this.output ? this.output.script : null;
return bcoin.script.getInputType(this.script, prev);
};
Input.prototype.getAddress = function getAddress() {
var data = this.getData();
var prev = this.output ? this.output.script : null;
return bcoin.script.getInputAddress(this.script, prev);
};
if (data.scriptAddress)
return data.scriptAddress;
return data.addresses[0];
Input.prototype.isRBF = function isRBF() {
return this.sequence === 0xffffffff - 1;
};
Input.prototype.isFinal = function isFinal() {
@ -338,17 +303,16 @@ Input.prototype.testScript = function testScript(key, redeem, type) {
};
Input.prototype.test = function test(addressTable) {
var data = this.getData();
var i;
var address = this.getAddress();
if (data.scriptAddress) {
if (addressTable[data.scriptAddress] != null)
return true;
}
for (i = 0; i < data.addresses.length; i++) {
if (addressTable[data.addresses[i]] != null)
return true;
if (address) {
if (Array.isArray(addressTable)) {
if (addressTable.indexOf(address) !== -1)
return true;
} else {
if (addressTable[address] != null)
return true;
}
}
return false;

View File

@ -75,7 +75,7 @@ Output.prototype.__defineGetter__('id', function() {
});
Output.prototype.__defineGetter__('address', function() {
return this.data.scriptAddress || this.addresses[0];
return this.data.address;
});
Output.prototype.__defineGetter__('signatures', function() {
@ -122,35 +122,6 @@ Output.prototype.__defineGetter__('text', function() {
return this.data.text;
});
// Legacy
Output.prototype.__defineGetter__('addr', function() {
return this.address;
});
Output.prototype.__defineGetter__('addrs', function() {
return this.addresses;
});
Output.prototype.__defineGetter__('pub', function() {
return this.key;
});
Output.prototype.__defineGetter__('pubs', function() {
return this.keys;
});
Output.prototype.__defineGetter__('sig', function() {
return this.signature;
});
Output.prototype.__defineGetter__('sigs', function() {
return this.signatures;
});
Output.prototype.__defineGetter__('scriptaddr', function() {
return this.scriptAddress;
});
// Schema and defaults for data object:
// {
// type: String,
@ -195,25 +166,12 @@ Output.prototype.getData = function getData() {
return Output.getData(this);
};
Output.prototype.getAddresses = function getAddresses() {
return this.getData().addresses;
};
Output.prototype.getScriptAddress = function getScriptAddress() {
return this.getData().scriptAddress;
};
Output.prototype.getKeyAddress = function getKeyAddress() {
return this.getData().addresses[0];
Output.prototype.getType = function getType() {
return bcoin.script.getOutputType(this.script);
};
Output.prototype.getAddress = function getAddress() {
var data = this.getData();
if (data.scriptAddress)
return data.scriptAddress;
return data.addresses[0];
return bcoin.script.getOutputAddress(this.script);
};
Output.prototype.getID = function getID() {
@ -255,17 +213,16 @@ Output.prototype.testScript = function testScript(key, hash, keys, scriptHash, t
};
Output.prototype.test = function test(addressTable) {
var data = this.getData();
var i;
var address = this.getAddress();
if (data.scriptAddress) {
if (addressTable[data.scriptAddress] != null)
return true;
}
for (i = 0; i < data.addresses.length; i++) {
if (addressTable[data.addresses[i]] != null)
return true;
if (address) {
if (Array.isArray(addressTable)) {
if (addressTable.indexOf(address) !== -1)
return true;
} else {
if (addressTable[address] != null)
return true;
}
}
return false;

View File

@ -205,13 +205,18 @@ exports.block = {
exports.tx = {
maxSize: 100000,
fee: 10000,
dust: 5460,
minFee: 10000,
bareMultisig: true,
freeThreshold: exports.coin.muln(144).divn(250),
maxFreeSize: 1000
};
exports.tx.dustThreshold = new bn(182)
.muln(exports.tx.minFee)
.divn(1000)
.muln(3)
.toNumber();
exports.script = {
maxSize: 10000,
maxStack: 1000,

View File

@ -27,9 +27,7 @@ network.set = function set(type) {
main = network.main = {};
main.prefixes = {
pubkey: 0,
pubkeyhash: 0,
multisig: 0,
scripthash: 5,
privkey: 128,
xpubkey: 0x0488b21e,
@ -132,9 +130,7 @@ testnet = network.testnet = {};
testnet.type = 'testnet';
testnet.prefixes = {
pubkey: 111,
pubkeyhash: 111,
multisig: 111,
scripthash: 196,
privkey: 239,
xpubkey: 0x043587cf,
@ -220,9 +216,7 @@ regtest = network.regtest = {};
regtest.type = 'testnet';
regtest.prefixes = {
pubkey: 111,
pubkeyhash: 111,
multisig: 111,
scripthash: 196,
privkey: 239,
xpubkey: 0x043587cf,

View File

@ -762,7 +762,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
n2 = script.num(stack.pop());
n1 = script.num(stack.pop());
val = n2.cmp(n1) <= 0 && n1.cmp(n3) < 0;
stack.push(val.cmpn(0) !== 0 ? [ 1 ] : []);
stack.push(val.cmpn(0) !== 0 ? [1] : []);
break;
}
@ -811,7 +811,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
if (!res)
return false;
} else {
stack.push(res ? [ 1 ] : []);
stack.push(res ? [1] : []);
}
break;
}
@ -841,7 +841,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
if (!res)
return false;
} else {
stack.push(res ? [ 1 ] : []);
stack.push(res ? [1] : []);
}
break;
@ -918,7 +918,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
if (!res)
return false;
} else {
stack.push(res ? [ 1 ] : []);
stack.push(res ? [1] : []);
}
break;
@ -1204,10 +1204,11 @@ script.getRedeem = function getRedeem(s) {
if (!Array.isArray(s[s.length - 1]))
return;
return bcoin.script.decode(s[s.length - 1]);
return script.decode(s[s.length - 1]);
};
script.getType = function getType(s) {
script.getType =
script.getOutputType = function getOutputType(s) {
return (script.isPubkey(s) && 'pubkey')
|| (script.isPubkeyhash(s) && 'pubkeyhash')
|| (script.isMultisig(s) && 'multisig')
@ -1268,19 +1269,20 @@ script.isEncoded = function isEncoded(s) {
};
script._locktime = function _locktime(s) {
var i;
if (s.length < 2)
return;
for (i = 0; i < s.length; i++) {
if (utils.isBuffer(s[i]) && s[i + 1] === 'checklocktimeverify')
return s[i];
}
if (!utils.isBuffer(s[0]))
return;
if (s[1] !== 'checklocktimeverify')
return;
return s[0];
};
script.isLocktime = function isLocktime(s) {
return !!script._locktime(s);
return script._locktime(s) != null;
};
script.getLocktime = function getLocktime(s) {
@ -1349,13 +1351,6 @@ script._getInputData = function _getInputData(s, type) {
assert(typeof type === 'string');
if (type === 'pubkey') {
if (s.length < 1) {
return {
type: 'pubkey',
side: 'input',
none: true
};
}
sig = s[0];
return {
type: 'pubkey',
@ -1366,35 +1361,22 @@ script._getInputData = function _getInputData(s, type) {
}
if (type === 'pubkeyhash') {
if (s.length < 2) {
return {
type: 'pubkeyhash',
side: 'input',
none: true
};
}
sig = s[0];
key = s[1];
hash = bcoin.wallet.key2hash(key);
address = bcoin.wallet.hash2addr(hash, 'pubkeyhash');
hash = bcoin.address.hash160(key);
address = bcoin.address.toAddress(hash, 'pubkeyhash');
return {
type: 'pubkeyhash',
side: 'input',
signatures: [sig],
keys: [key],
hashes: [hash],
address: address,
addresses: [address]
};
}
if (type === 'multisig') {
if (s.length < 2) {
return {
type: 'multisig',
side: 'input',
none: true
};
}
sig = s.slice(1);
return {
type: 'multisig',
@ -1406,19 +1388,12 @@ script._getInputData = function _getInputData(s, type) {
}
if (type === 'scripthash') {
if (s.length < 1) {
return {
type: 'scripthash',
side: 'input',
none: true
};
}
raw = s[s.length - 1];
redeem = script.decode(raw);
locktime = script.getLocktime(redeem);
hash = bcoin.wallet.key2hash(raw);
address = bcoin.wallet.hash2addr(hash, 'scripthash');
output = script.getOutputData(script.getSubscript(redeem));
hash = bcoin.address.hash160(raw);
address = bcoin.address.toAddress(hash, 'scripthash');
output = script.getOutputData(redeem, true);
input = script._getInputData(s.slice(0, -1), output.type);
delete input.none;
return utils.merge(input, output, {
@ -1426,6 +1401,7 @@ script._getInputData = function _getInputData(s, type) {
side: 'input',
subtype: output.type,
redeem: redeem,
address: address,
scriptHash: hash,
scriptAddress: address,
locktime: locktime
@ -1435,45 +1411,56 @@ script._getInputData = function _getInputData(s, type) {
return script.getUnknownData(s);
};
script.getOutputData = function getOutputData(s) {
var key, hash, address;
script.getOutputData = function getOutputData(s, inScriptHash) {
var key, hash, address, mhash, maddress;
if (script.isPubkey(s)) {
key = s[0];
hash = bcoin.wallet.key2hash(key);
address = bcoin.wallet.hash2addr(hash, 'pubkey');
hash = bcoin.address.hash160(key);
// Convert p2pk to p2pkh addresses
address = bcoin.address.toAddress(hash, 'pubkeyhash');
return {
type: 'pubkey',
side: 'output',
keys: [key],
hashes: [hash],
address: address,
addresses: [address]
};
}
if (script.isPubkeyhash(s)) {
hash = s[2];
address = bcoin.address.toAddress(hash, 'pubkeyhash');
return {
type: 'pubkeyhash',
side: 'output',
hashes: [hash],
addresses: [bcoin.wallet.hash2addr(hash, 'pubkeyhash')]
address: address,
addresses: [address]
};
}
if (script.isMultisig(s)) {
key = s.slice(1, -2);
hash = key.map(function(key) {
return bcoin.wallet.key2hash(key);
return bcoin.address.hash160(key);
});
// Convert bare multisig to p2pkh addresses
address = hash.map(function(hash) {
return bcoin.wallet.hash2addr(hash, 'multisig');
return bcoin.address.toAddress(hash, 'pubkeyhash');
});
// Convert bare multisig script to scripthash address
if (!inScriptHash) {
mhash = bcoin.address.hash160(s._raw || script.encode(s));
maddress = bcoin.address.toAddress(mhash, 'scripthash');
}
return {
type: 'multisig',
side: 'output',
keys: key,
hashes: hash,
address: maddress,
addresses: address,
m: s[0],
n: s[s.length - 2]
@ -1482,11 +1469,13 @@ script.getOutputData = function getOutputData(s) {
if (script.isScripthash(s)) {
hash = s[1];
address = bcoin.address.toAddress(hash, 'scripthash');
return {
type: 'scripthash',
side: 'output',
address: address,
scriptHash: hash,
scriptAddress: bcoin.wallet.hash2addr(hash, 'scripthash')
scriptAddress: address
};
}
@ -1515,11 +1504,11 @@ script.getUnknownData = function getUnknownData(s) {
}
hash = key.map(function(key) {
return bcoin.wallet.key2hash(key);
return bcoin.address.hash160(key);
});
address = hash.map(function(hash) {
return bcoin.wallet.hash2addr(hash, 'pubkey');
return bcoin.address.toAddress(hash, 'pubkeyhash');
});
return {
@ -1532,6 +1521,41 @@ script.getUnknownData = function getUnknownData(s) {
};
};
script.getInputAddress = function getInputAddress(s, prev) {
if (prev)
return script.getOutputAddress(prev);
if (script.isPubkeyInput(s))
return;
if (script.isPubkeyhashInput(s))
return bcoin.address.compile(s[1], 'pubkeyhash');
if (script.isMultisigInput(s))
return;
if (script.isScripthashInput(s))
return bcoin.address.compile(s[s.length - 1], 'scripthash');
};
script.getOutputAddress = function getOutputAddress(s) {
// Convert p2pk to p2pkh addresses
if (script.isPubkey(s))
return bcoin.address.compile(s[0], 'pubkeyhash');
if (script.isPubkeyhash(s))
return bcoin.address.toAddress(s[2], 'pubkeyhash')
// Convert bare multisig to scripthash address
if (script.isMultisig(s)) {
s = s._raw || script.encode(s);
return bcoin.address.compile(s, 'scripthash');
}
if (script.isScripthash(s))
return bcoin.address.toAddress(s[1], 'scripthash');
};
script.isPubkey = function isPubkey(s, key) {
var res;
@ -1679,7 +1703,10 @@ script.isNulldata = function isNulldata(s) {
return s[1];
};
script.getInputType = function getInputType(s) {
script.getInputType = function getInputType(s, prev) {
if (prev)
return script.getOutputType(prev);
return (script.isPubkeyInput(s) && 'pubkey')
|| (script.isPubkeyhashInput(s) && 'pubkeyhash')
|| (script.isMultisigInput(s) && 'multisig')
@ -1793,6 +1820,9 @@ script.isScripthashInput = function isScripthashInput(s, data, strict) {
// If the last data element is a valid
// signature or key, it's _extremely_
// unlikely this is a scripthash.
if (script.isDummy(raw))
return false;
if (script.isSignatureEncoding(raw))
return false;
@ -1815,7 +1845,7 @@ script.isScripthashInput = function isScripthashInput(s, data, strict) {
// P2SH redeem scripts can be nonstandard: make
// it easier for other functions to parse this.
redeem = script.getSubscript(script.decode(raw));
redeem = script.decode(raw);
// Get the "real" scriptSig
s = s.slice(0, -1);
@ -2185,7 +2215,7 @@ script.getScripthashSigops = function getScripthashSigops(s) {
if (!script.isPushOnly(s))
return 0;
s = script.getSubscript(script.decode(s[s.length - 1]));
s = script.getRedeem(s);
return script.getSigops(s, true);
};

View File

@ -257,7 +257,7 @@ TX.prototype.scriptInput = function scriptInput(index, pub, redeem) {
input.script = [[]];
} else if (bcoin.script.isPubkeyhash(s)) {
// P2PKH
if (!utils.isEqual(s[2], bcoin.wallet.key2hash(pub)))
if (!utils.isEqual(s[2], bcoin.address.hash160(pub)))
return false;
// Already has a script template (at least)
if (input.script.length)
@ -403,7 +403,7 @@ TX.prototype.signInput = function signInput(index, key, type) {
// Get pubkey and pubkey hash.
pub = key.getPublic(true, 'array');
pkh = bcoin.wallet.key2hash(pub);
pkh = bcoin.address.hash160(pub);
// Add signatures.
if (bcoin.script.isPubkey(s)) {
@ -731,13 +731,13 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) {
// https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki
// hash160 [20-byte-redeemscript-hash] equal
script = bcoin.script.createScripthash(
bcoin.wallet.addr2hash(options.address, 'scripthash')
bcoin.address.toHash(options.address, 'scripthash')
);
} else if (options.address) {
// P2PKH Transaction
// dup hash160 [pubkey-hash] equalverify checksig
script = bcoin.script.createPubkeyhash(
bcoin.wallet.addr2hash(options.address, 'pubkeyhash')
bcoin.address.toHash(options.address, 'pubkeyhash')
);
} else if (options.key) {
// P2PK Transaction
@ -814,9 +814,6 @@ TX.prototype.signatureHash = function signatureHash(index, s, type) {
// if strictenc is not enabled.
// assert(utils.isFinite(type));
// Remove code separators.
// s = script.getSubscript(s);
// Remove all signatures.
for (i = 0; i < copy.inputs.length; i++)
copy.inputs[i].script = [];
@ -881,7 +878,7 @@ TX.prototype.tbsHash = function tbsHash(enc, force) {
if (!this._tbsHash || force) {
for (i = 0; i < copy.inputs.length; i++) {
if (!copy.isCoinbase())
if (!copy.inputs[i].isCoinbase())
copy.inputs[i].script = [];
}
@ -1008,14 +1005,7 @@ TX.prototype.maxSize = function maxSize() {
}
// Byte for varint size of input script
if (size < 0xfd)
size += 0;
else if (size <= 0xffff)
size += 2;
else if (size <= 0xffffffff)
size += 4;
else
size += 8;
size += utils.sizeIntv(size);
total += size;
}
@ -1027,7 +1017,7 @@ TX.prototype.getInputs = function getInputs(unspent, address, fee) {
var tx = this.clone();
var cost = tx.getOutputValue();
var totalkb = 1;
var total = cost.addn(constants.tx.fee);
var total = cost.addn(constants.tx.minFee);
var inputs = [];
var lastAdded = 0;
var size, newkb, change;
@ -1042,18 +1032,25 @@ TX.prototype.getInputs = function getInputs(unspent, address, fee) {
return a.height - b.height;
});
function addInput(unspent) {
// Add new inputs until TX will have enough
// funds to cover both minimum post cost
// and fee.
var index = tx._addInput(unspent);
inputs.push(tx.inputs[index]);
lastAdded++;
return tx.getInputValue().cmp(total) < 0;
function addCoins() {
var i, index;
for (i = lastAdded; i < unspent.length; i++) {
// Add new inputs until TX will have enough
// funds to cover both minimum post cost
// and fee.
index = tx._addInput(unspent[i]);
inputs.push(tx.inputs[index]);
lastAdded++;
// Stop once we're full.
if (tx.getInputValue().cmp(total) >= 0)
break;
}
}
// Transfer `total` funds maximum.
unspent.every(addInput);
addCoins();
if (!fee) {
// Add dummy output (for `change`) to
@ -1064,9 +1061,9 @@ TX.prototype.getInputs = function getInputs(unspent, address, fee) {
});
// if (this.subtractFee) {
// var f = new bn((Math.ceil(tx.maxSize() / 1024) - 1) * constants.tx.fee);
// var f = new bn((Math.ceil(tx.maxSize() / 1024) - 1) * constants.tx.minFee);
// for (var j = 0; j < this.outputs.length; j++) {
// if (this.outputs[j].value.cmp(f.addn(constants.tx.dust)) >= 0) {
// if (this.outputs[j].value.cmp(f.addn(constants.tx.dustThreshold)) >= 0) {
// this.outputs[j].value = this.outputs[j].value.sub(f);
// break;
// }
@ -1081,12 +1078,12 @@ TX.prototype.getInputs = function getInputs(unspent, address, fee) {
size = tx.maxSize();
newkb = Math.ceil(size / 1024) - totalkb;
total.iaddn(newkb * constants.tx.fee);
total.iaddn(newkb * constants.tx.minFee);
totalkb += newkb;
// Failed to get enough funds, add more inputs.
if (tx.getInputValue().cmp(total) < 0)
unspent.slice(lastAdded).every(addInput);
addCoins();
} while (tx.getInputValue().cmp(total) < 0 && lastAdded < unspent.length);
}
@ -1134,7 +1131,7 @@ TX.prototype.fill = function fill(unspent, address, fee) {
this.addInput(input);
}, this);
if (result.change.cmpn(constants.tx.dust) < 0) {
if (result.change.cmpn(constants.tx.dustThreshold) < 0) {
// Do nothing. Change is added to fee.
assert.equal(
this.getFee().toNumber(),
@ -1210,7 +1207,7 @@ TX.prototype._recalculateFee = function recalculateFee() {
}
size = this.maxSize();
real = Math.ceil(size / 1024) * constants.tx.fee;
real = Math.ceil(size / 1024) * constants.tx.minFee;
fee = this.getFee().toNumber();
// if (this.hardFee)
@ -1233,7 +1230,7 @@ TX.prototype._recalculateFee = function recalculateFee() {
output.value.iaddn(fee - real);
}
if (output.value.cmpn(constants.tx.dust) < 0) {
if (output.value.cmpn(constants.tx.dustThreshold) < 0) {
this.outputs.pop();
this.changeIndex = -1;
return;
@ -1428,15 +1425,22 @@ TX.prototype.setLocktime = function setLocktime(locktime) {
};
TX.prototype.increaseFee = function increaseFee(fee) {
var i, input;
var i, input, result;
this.inputs = [];
if (this.changeIndex !== -1)
this.outputs.splice(this.changeIndex, 1);
this.hardFee = fee || this.getFee().add(new bn(10000));
this.fill();
result = this.fill();
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
input.sequence = 0xffffffff - 1;
}
return !!result.inputs;
};
TX.prototype.hasPrevout = function hasPrevout() {
@ -1559,7 +1563,7 @@ TX.prototype.isStandard = function isStandard() {
if (type === 'multisig' && !constants.tx.bareMultisig)
return false;
if (output.value.cmpn(constants.tx.dust) < 0)
if (output.value.cmpn(constants.tx.dustThreshold) < 0)
return false;
}

View File

@ -797,7 +797,7 @@ utils.sortHDKeys = function sortHDKeys(keys) {
});
};
utils.uniq = function(obj) {
utils.uniq = function uniq(obj) {
var out = [];
var i = 0;
@ -809,6 +809,22 @@ utils.uniq = function(obj) {
return out;
};
utils.uniqs = function uniqs(obj) {
var table = {};
var out = [];
var i = 0;
for (; i < obj.length; i++) {
if (!table[obj[i]]) {
out.push(obj[i]);
table[obj[i]] = true;
}
}
return out;
};
utils.fromCompact = function fromCompact(compact) {
var exponent = compact >> 24;
var negative = (compact >> 23) & 0x01;

View File

@ -77,6 +77,7 @@ function Wallet(options) {
this.accountIndex = options.accountIndex || 0;
this.addressDepth = options.addressDepth || 0;
this.changeDepth = options.changeDepth || 0;
this.copayBIP45 = options.copayBIP45 || false;
this.cosignerIndex = -1;
this.sharedCosignerIndex = constants.hd.hardened - 1;
this.purposeKeys = options.purposeKeys || [];
@ -84,26 +85,21 @@ function Wallet(options) {
this.hd = !!this.master;
this.type = options.type || 'pubkeyhash';
this.subtype = options.subtype || null;
this.derivation = options.derivation || null;
this.compressed = options.compressed !== false;
this.keys = [];
this.m = options.m || 1;
this.n = options.n || 1;
this.nmax = this.type === 'scripthash'
? (this.compressed ? 15 : 7)
: 3;
if (this.n > 1) {
if (this.type !== 'multisig')
this.type = 'scripthash';
if (this.type === 'scripthash')
this.subtype = 'multisig';
}
if (this.n > 1)
this.type = 'multisig';
assert(this.type === 'pubkeyhash' || this.type === 'multisig');
this.prefixType = this.type === 'multisig' ? 'scripthash' : 'pubkeyhash';
if (!this.derivation) {
if (this.master) {
if (this.type === 'scripthash' && this.subtype === 'multisig')
if (this.type === 'multisig')
this.derivation = 'bip45';
else
this.derivation = 'bip44';
@ -112,15 +108,12 @@ function Wallet(options) {
}
}
if (network.prefixes[this.type] == null)
throw new Error('Unknown prefix: ' + this.type);
if (network.prefixes[this.prefixType] == null)
throw new Error('Unknown prefix: ' + this.prefixType);
if (this.m < 1 || this.m > this.n)
throw new Error('m ranges between 1 and n');
if (this.n < 1 || this.n > this.nmax)
throw new Error('n ranges between 1 and ' + this.nmax);
if (this.derivation === 'bip45') {
this.purposeKey = this.master.isPurpose45()
? this.master
@ -140,7 +133,6 @@ function Wallet(options) {
publicKey: options.publicKey,
pair: options.pair,
type: this.type,
subtype: this.subtype,
m: this.m,
n: this.n,
keys: [],
@ -162,23 +154,7 @@ function Wallet(options) {
// generate the last receiving address. However, since "normal" wallets
// cannot deterministically generate keys, we have to buffer the generated
// key for later.
if (this.derivation === 'bip44') {
// Generate the last known receiving address
key = this.createKey(false, Math.max(0, this.addressDepth - 1));
this.currentAddress = bcoin.address({
privateKey: key.privateKey,
publicKey: key.publicKey,
compressed: key.compressed,
index: key.index,
path: key.path,
type: this.type,
subtype: this.subtype,
m: this.m,
n: this.n,
keys: options.keys,
derived: true
});
} else if (this.derivation === 'normal') {
if (this.derivation === 'normal') {
// Try to find the last receiving address if there is one.
receiving = options.addresses.filter(function(address) {
return !address.change && this._isKeyOptions(address);
@ -197,11 +173,11 @@ function Wallet(options) {
index: key.index,
path: key.path,
type: this.type,
subtype: this.subtype,
m: this.m,
n: this.n,
keys: options.keys
});
this.currentAddress._wallet = this;
}
}
@ -219,7 +195,7 @@ inherits(Wallet, EventEmitter);
Wallet.prototype._pruneAddresses = function _pruneAddresses(options) {
var addresses = this.addresses.slice();
var address;
var i, address;
for (i = 0; i < addresses.length; i++) {
address = addresses[i];
@ -250,17 +226,17 @@ Wallet.prototype._isKeyOptions = function _isKeyOptions(options) {
// normal: Address of first key in wallet
Wallet.prototype.getID = function getID() {
if (this.derivation === 'bip45')
return bcoin.address.key2addr(this.purposeKey.publicKey);
return bcoin.address.compile(this.purposeKey.publicKey);
if (this.derivation === 'bip44')
return bcoin.address.key2addr(this.purposeKey.publicKey);
return bcoin.address.compile(this.purposeKey.publicKey);
if (this.derivation === 'normal') {
if (this.addresses.length)
return this.addresses[0].getKeyAddress();
if (this._firstKey)
return bcoin.address.key2addr(this._firstKey.publicKey);
return bcoin.address.compile(this._firstKey.publicKey);
}
assert(false);
@ -316,6 +292,14 @@ Wallet.prototype._initAddresses = function _initAddresses() {
Wallet.prototype.addKey = function addKey(key) {
var hdKey, has, i;
if (key instanceof bcoin.wallet) {
assert(key.derivation === this.derivation);
if (key.derivation === 'bip44' || key.derivation === 'bip45')
key = key.purposeKey;
else
key = key.currentAddress.publicKey;
}
if (bcoin.hd.privateKey.isExtended(key))
key = bcoin.hd.privateKey(key);
else if (bcoin.hd.publicKey.isExtended(key))
@ -387,6 +371,7 @@ Wallet.prototype.finalizeKeys = function finalizeKeys(key) {
for (i = 0; i < this.purposeKeys.length; i++) {
if (this.purposeKeys[i].xpubkey === this.purposeKey.xpubkey) {
this.cosignerIndex = i;
this._cosignerIndex = i;
break;
}
}
@ -394,6 +379,7 @@ Wallet.prototype.finalizeKeys = function finalizeKeys(key) {
assert(this.cosignerIndex !== -1);
this._initAddresses();
return;
}
@ -402,6 +388,7 @@ Wallet.prototype.finalizeKeys = function finalizeKeys(key) {
for (i = 0; i < this.keys.length; i++) {
if (utils.isEqual(this.keys[i], this.currentAddress.publicKey)) {
this.cosignerIndex = i;
this._cosignerIndex = i;
break;
}
}
@ -416,6 +403,14 @@ Wallet.prototype.removeKey = function removeKey(key) {
assert(!this._keysFinalized);
if (key instanceof bcoin.wallet) {
assert(key.derivation === this.derivation);
if (key.derivation === 'bip44' || key.derivation === 'bip45')
key = key.purposeKey;
else
key = key.currentAddress.publicKey;
}
if (bcoin.hd.privateKey.isExtended(key))
key = bcoin.hd.privateKey(key);
else if (bcoin.hd.publicKey.isExtended(key))
@ -527,9 +522,7 @@ Wallet.prototype._getAddressTable = function() {
for (i = 0; i < this.addresses.length; i++) {
address = this.addresses[i];
if (address.type === 'scripthash')
addresses[address.getScriptAddress()] = i;
addresses[address.getKeyAddress()] = i;
addresses[address.getAddress()] = i;
}
return addresses;
@ -545,20 +538,13 @@ Wallet.prototype._addressIndex = function _addressIndex(address) {
if (!(address instanceof bcoin.address))
address = bcoin.address(address);
if (address.type === 'scripthash') {
addr = address.getScriptAddress();
if (this._addressTable[addr] != null)
return this._addressTable[addr];
}
addr = address.getKeyAddress();
addr = address.getAddress();
if (this._addressTable[addr] != null)
return this._addressTable[addr];
return -1;
};
// TODO: fromPath here
Wallet.prototype.createAddress = function createAddress(change, index) {
var self = this;
var key = this.createKey(change, index);
@ -573,7 +559,6 @@ Wallet.prototype.createAddress = function createAddress(change, index) {
index: key.index,
path: key.path,
type: this.type,
subtype: this.subtype,
m: this.m,
n: this.n,
keys: [],
@ -610,7 +595,7 @@ Wallet.prototype.createAddress = function createAddress(change, index) {
this.keys = utils.sortKeys(options.keys);
} else if (this.derivation === 'normal') {
this.keys.forEach(function(key, i) {
if (i !== this.cosignerIndex)
if (i !== this._cosignerIndex)
options.keys.push(key);
}, this);
options.keys.push(key.publicKey);
@ -658,10 +643,7 @@ Wallet.prototype.addAddress = function addAddress(address) {
self.emit('add address', address);
});
if (address.type === 'scripthash')
this._addressTable[address.getScriptAddress()] = index;
this._addressTable[address.getKeyAddress()] = index;
this._addressTable[address.getAddress()] = index;
if (address.label && this._labelTable[address.label] == null)
this._labelTable[address.label] = index;
@ -832,30 +814,19 @@ Wallet.prototype.ownOutput = function ownOutput(tx, index) {
return tx.testOutputs(this._addressTable, index, true);
};
Wallet.prototype.fill = function fill(tx, address, fee) {
var unspent, items, result;
Wallet.prototype.fill = function fill(tx, options) {
var address, unspent;
if (!options)
options = {};
assert(this._initialized);
if (!address)
address = this.changeAddress.getKeyAddress();
address = this.changeAddress.getAddress();
unspent = this.getUnspent();
items = unspent.filter(function(coin) {
if (bcoin.script.isScripthash(coin.script))
return this.type === 'scripthash';
if (bcoin.script.isMultisig(coin.script))
return this.type === 'multisig';
return true;
}, this);
if (tx.getInputs(unspent, address, fee).inputs)
unspent = items;
result = tx.fill(unspent, address, fee);
result = tx.fill(unspent, address, options.fee);
if (!result.inputs)
return false;
@ -1040,14 +1011,13 @@ Wallet.prototype.toJSON = function toJSON(encrypt) {
name: 'wallet',
network: network.type,
type: this.type,
subtype: this.subtype,
m: this.m,
n: this.n,
derivation: this.derivation,
copayBIP45: this.copayBIP45,
accountIndex: this.accountIndex,
addressDepth: this.addressDepth,
changeDepth: this.changeDepth,
cosignerIndex: this.cosignerIndex,
master: this.master ? this.master.toJSON(encrypt) : null,
addresses: this.addresses.filter(function(address) {
return !address.derived;
@ -1077,14 +1047,13 @@ Wallet.fromJSON = function fromJSON(json, decrypt) {
wallet = new Wallet({
type: json.type,
subtype: json.subtype,
m: json.m,
n: json.n,
derivation: json.derivation,
copayBIP45: json.copayBIP45,
accountIndex: json.accountIndex,
addressDepth: json.addressDepth,
changeDepth: json.changeDepth,
cosignerIndex: json.cosignerIndex,
master: json.master
? bcoin.hd.fromJSON(json.master, decrypt)
: null,
@ -1109,19 +1078,19 @@ Wallet.fromSecret = function fromSecret(privateKey) {
};
Wallet.key2hash = function key2hash(key) {
return bcoin.address.key2hash(key);
return bcoin.address.hash160(key);
};
Wallet.hash2addr = function hash2addr(hash, prefix) {
return bcoin.address.hash2addr(hash, prefix);
return bcoin.address.toAddress(hash, prefix);
};
Wallet.addr2hash = function addr2hash(addr, prefix) {
return bcoin.address.addr2hash(addr, prefix);
return bcoin.address.toHash(addr, prefix);
};
Wallet.validateAddress = function validateAddress(addr, prefix) {
return bcoin.address.validateAddress(addr, prefix);
return bcoin.address.validate(addr, prefix);
};
/**

View File

@ -81,7 +81,7 @@ describe('Wallet', function() {
// var k2 = w.getPublicKey().concat(1);
var k2 = bcoin.ecdsa.genKeyPair().getPublic(true, 'array');
w.addKey(k2);
assert.equal(w.getKeyAddress(), w.getAddress());
// assert.equal(w.getKeyAddress(), w.getAddress());
// Input transcation
var src = bcoin.tx({
@ -222,7 +222,7 @@ describe('Wallet', function() {
tx.out(to, 5460);
var cost = tx.funds('out');
var total = cost.add(new bn(constants.tx.fee));
var total = cost.add(new bn(constants.tx.minFee));
var unspent1 = w1.unspent();
var unspent2 = w2.unspent();
@ -236,7 +236,7 @@ describe('Wallet', function() {
tx.input(unspent2[0]);
var left = tx.funds('in').sub(total);
if (left.cmpn(constants.tx.dust) < 0) {
if (left.cmpn(constants.tx.dustThreshold) < 0) {
tx.outputs[tx.outputs.length - 2].value.iadd(left);
left = new bn(0);
}
@ -270,37 +270,35 @@ describe('Wallet', function() {
// Create 3 2-of-3 wallets with our pubkeys as "shared keys"
var w1 = bcoin.wallet({
derivation: 'bip44',
type: 'scripthash',
subtype: 'multisig',
type: 'multisig',
m: 2,
n: 3
});
var w2 = bcoin.wallet({
derivation: 'bip44',
type: 'scripthash',
subtype: 'multisig',
type: 'multisig',
m: 2,
n: 3
});
var w3 = bcoin.wallet({
derivation: 'bip44',
type: 'scripthash',
subtype: 'multisig',
type: 'multisig',
m: 2,
n: 3
});
// w3 = bcoin.wallet.fromJSON(w3.toJSON());
var receive = bcoin.wallet();
w1.addKey(w2.purposeKey);
w1.addKey(w3.purposeKey);
w2.addKey(w1.purposeKey);
w2.addKey(w3.purposeKey);
w3.addKey(w1.purposeKey);
w3.addKey(w2.purposeKey);
w1.addKey(w2);
w1.addKey(w3);
w2.addKey(w1);
w2.addKey(w3);
w3.addKey(w1);
w3.addKey(w2);
w3 = bcoin.wallet.fromJSON(w3.toJSON());
// Our p2sh address
var addr = w1.getAddress();