wallet refactor. fixes.
This commit is contained in:
parent
9fc6848dce
commit
6cc4c866dc
@ -41,32 +41,23 @@ function Address(options) {
|
|||||||
this.path = options.path;
|
this.path = options.path;
|
||||||
|
|
||||||
this.type = options.type || 'pubkeyhash';
|
this.type = options.type || 'pubkeyhash';
|
||||||
this.subtype = options.subtype;
|
|
||||||
this.keys = [];
|
this.keys = [];
|
||||||
this.m = options.m || 1;
|
this.m = options.m || 1;
|
||||||
this.n = options.n || 1;
|
this.n = options.n || 1;
|
||||||
this.redeem = null;
|
this.redeem = null;
|
||||||
|
|
||||||
if (this.n > 1) {
|
if (this.n > 1)
|
||||||
if (this.type !== 'multisig')
|
this.type = 'multisig';
|
||||||
this.type = 'scripthash';
|
|
||||||
if (this.type === 'scripthash')
|
|
||||||
this.subtype = 'multisig';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (network.prefixes[this.type] == null)
|
assert(this.type === 'pubkeyhash' || this.type === 'multisig');
|
||||||
throw new Error('Unknown prefix: ' + this.type);
|
this.prefixType = this.type === 'multisig' ? 'scripthash' : 'pubkeyhash';
|
||||||
|
|
||||||
this.nmax = this.type === 'scripthash'
|
if (network.prefixes[this.prefixType] == null)
|
||||||
? (this.key.compressed ? 15 : 7)
|
throw new Error('Unknown prefix: ' + this.prefixType);
|
||||||
: 3;
|
|
||||||
|
|
||||||
if (this.m < 1 || this.m > this.n)
|
if (this.m < 1 || this.m > this.n)
|
||||||
throw new Error('m ranges between 1 and 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());
|
this.addKey(this.getPublicKey());
|
||||||
|
|
||||||
(options.keys || []).forEach(function(key) {
|
(options.keys || []).forEach(function(key) {
|
||||||
@ -76,7 +67,7 @@ function Address(options) {
|
|||||||
if (options.redeem || options.script)
|
if (options.redeem || options.script)
|
||||||
this.setRedeem(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);
|
inherits(Address, EventEmitter);
|
||||||
@ -85,6 +76,10 @@ Address.prototype.__defineGetter__('balance', function() {
|
|||||||
return this.getBalance();
|
return this.getBalance();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Address.prototype.getID = function getID() {
|
||||||
|
return this.getKeyAddress();
|
||||||
|
};
|
||||||
|
|
||||||
Address.prototype.getAll = function getAll() {
|
Address.prototype.getAll = function getAll() {
|
||||||
return this._wallet.getAll(this);
|
return this._wallet.getAll(this);
|
||||||
};
|
};
|
||||||
@ -115,8 +110,8 @@ Address.prototype.setRedeem = function setRedeem(redeem) {
|
|||||||
if (!utils.isBytes(redeem))
|
if (!utils.isBytes(redeem))
|
||||||
redeem = bcoin.script.encode(redeem);
|
redeem = bcoin.script.encode(redeem);
|
||||||
|
|
||||||
this.type = 'scripthash';
|
this.type = 'multisig';
|
||||||
this.subtype = null;
|
this.prefixType = 'scripthash';
|
||||||
this.redeem = redeem;
|
this.redeem = redeem;
|
||||||
this.emit('update script', old, this.getScriptAddress());
|
this.emit('update script', old, this.getScriptAddress());
|
||||||
};
|
};
|
||||||
@ -192,49 +187,53 @@ Address.fromSecret = function fromSecret(privateKey) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.getScript = function getScript() {
|
Address.prototype.getScript = function getScript() {
|
||||||
if (this.type !== 'scripthash')
|
var redeem;
|
||||||
|
|
||||||
|
if (this.prefixType !== 'scripthash')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this._script)
|
if (this._script)
|
||||||
return this._script;
|
return this._script;
|
||||||
|
|
||||||
if (this.redeem)
|
if (this.redeem) {
|
||||||
return this._script = this.redeem.slice();
|
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')
|
if (redeem.length > 520)
|
||||||
this._script = bcoin.script.createPubkey(this.getPublicKey());
|
throw new Error('Redeem script too large (520 byte limit).');
|
||||||
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);
|
|
||||||
|
|
||||||
this._script = bcoin.script.encode(this._script);
|
this._script = redeem;
|
||||||
|
|
||||||
return this._script;
|
return this._script;
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.getScriptHash = function getScriptHash() {
|
Address.prototype.getScriptHash = function getScriptHash() {
|
||||||
if (this.type !== 'scripthash')
|
if (this.prefixType !== 'scripthash')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this._scriptHash)
|
if (this._scriptHash)
|
||||||
return this._scriptHash;
|
return this._scriptHash;
|
||||||
|
|
||||||
this._scriptHash = utils.ripesha(this.getScript());
|
this._scriptHash = Address.hash160(this.getScript());
|
||||||
|
|
||||||
return this._scriptHash;
|
return this._scriptHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.getScriptAddress = function getScriptAddress() {
|
Address.prototype.getScriptAddress = function getScriptAddress() {
|
||||||
if (this.type !== 'scripthash')
|
if (this.prefixType !== 'scripthash')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this._scriptAddress)
|
if (this._scriptAddress)
|
||||||
return this._scriptAddress;
|
return this._scriptAddress;
|
||||||
|
|
||||||
this._scriptAddress = Address.hash2addr(this.getScriptHash(), this.type);
|
this._scriptAddress = Address.toAddress(this.getScriptHash(), this.prefixType);
|
||||||
|
|
||||||
return this._scriptAddress;
|
return this._scriptAddress;
|
||||||
};
|
};
|
||||||
@ -256,7 +255,7 @@ Address.prototype.getKeyHash = function getKeyHash() {
|
|||||||
if (this._hash)
|
if (this._hash)
|
||||||
return this._hash;
|
return this._hash;
|
||||||
|
|
||||||
this._hash = Address.key2hash(this.getPublicKey());
|
this._hash = Address.hash160(this.getPublicKey());
|
||||||
|
|
||||||
return this._hash;
|
return this._hash;
|
||||||
};
|
};
|
||||||
@ -265,127 +264,41 @@ Address.prototype.getKeyAddress = function getKeyAddress() {
|
|||||||
if (this._address)
|
if (this._address)
|
||||||
return this._address;
|
return this._address;
|
||||||
|
|
||||||
this._address = Address.hash2addr(this.getKeyHash(), 'pubkeyhash');
|
this._address = Address.toAddress(this.getKeyHash(), 'pubkeyhash');
|
||||||
|
|
||||||
return this._address;
|
return this._address;
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.getHash = function getHash() {
|
Address.prototype.getHash = function getHash() {
|
||||||
if (this.type === 'scripthash')
|
if (this.prefixType === 'scripthash')
|
||||||
return this.getScriptHash();
|
return this.getScriptHash();
|
||||||
return this.getKeyHash();
|
return this.getKeyHash();
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.getAddress = function getAddress() {
|
Address.prototype.getAddress = function getAddress() {
|
||||||
if (this.type === 'scripthash')
|
if (this.prefixType === 'scripthash')
|
||||||
return this.getScriptAddress();
|
return this.getScriptAddress();
|
||||||
return this.getKeyAddress();
|
return this.getKeyAddress();
|
||||||
};
|
};
|
||||||
|
|
||||||
Address.key2hash = function key2hash(key) {
|
Address.prototype._getAddressTable = function _getAddressTable() {
|
||||||
key = utils.toBuffer(key);
|
var addressTable = {};
|
||||||
return utils.ripesha(key);
|
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) {
|
Address.prototype.ownOutput = function ownOutput(tx, index) {
|
||||||
var scriptHash = this.getScriptHash();
|
var addressTable = this._getAddressTable();
|
||||||
var hash = this.getKeyHash();
|
|
||||||
var key = this.getPublicKey();
|
|
||||||
var keys = this.keys;
|
|
||||||
var outputs = tx.outputs;
|
var outputs = tx.outputs;
|
||||||
|
|
||||||
if ((tx instanceof bcoin.output) || (tx instanceof bcoin.coin))
|
if ((tx instanceof bcoin.output) || (tx instanceof bcoin.coin))
|
||||||
outputs = [tx];
|
outputs = [tx];
|
||||||
|
|
||||||
outputs = outputs.filter(function(output, i) {
|
outputs = outputs.filter(function(output, i) {
|
||||||
var s = output.script;
|
|
||||||
|
|
||||||
if (index != null && index !== i)
|
if (index != null && index !== i)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return output.testScript(key, hash, keys, scriptHash, null);
|
return output.test(addressTable, true);
|
||||||
|
|
||||||
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;
|
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
if (outputs.length === 0)
|
if (outputs.length === 0)
|
||||||
@ -395,11 +308,7 @@ Address.prototype.ownOutput = function ownOutput(tx, index) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Address.prototype.ownInput = function ownInput(tx, index) {
|
Address.prototype.ownInput = function ownInput(tx, index) {
|
||||||
var scriptHash = this.getScriptHash();
|
var addressTable = this._getAddressTable();
|
||||||
var hash = this.getKeyHash();
|
|
||||||
var key = this.getPublicKey();
|
|
||||||
var redeem = this.getScript();
|
|
||||||
var keys = this.keys;
|
|
||||||
var inputs = tx.inputs;
|
var inputs = tx.inputs;
|
||||||
|
|
||||||
if (tx instanceof bcoin.input) {
|
if (tx instanceof bcoin.input) {
|
||||||
@ -415,25 +324,9 @@ Address.prototype.ownInput = function ownInput(tx, index) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (input.output)
|
if (input.output)
|
||||||
return !!this.ownOutput(input.output);
|
return input.output.test(addressTable, true);
|
||||||
|
|
||||||
return input.testScript(key, redeem, null);
|
return input.test(addressTable, true);
|
||||||
|
|
||||||
// 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;
|
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
if (inputs.length === 0)
|
if (inputs.length === 0)
|
||||||
@ -544,7 +437,7 @@ Address.prototype.__defineGetter__('address', function() {
|
|||||||
return this.getAddress();
|
return this.getAddress();
|
||||||
});
|
});
|
||||||
|
|
||||||
Address.prototype.toAddress = function toAddress() {
|
Address.prototype.toExplore = function toExplore() {
|
||||||
return {
|
return {
|
||||||
address: this.getAddress(),
|
address: this.getAddress(),
|
||||||
hash160: utils.toHex(this.getHash()),
|
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) {
|
Address.prototype.toJSON = function toJSON(encrypt) {
|
||||||
return {
|
return {
|
||||||
v: 1,
|
v: 1,
|
||||||
@ -565,11 +529,9 @@ Address.prototype.toJSON = function toJSON(encrypt) {
|
|||||||
derived: this.derived,
|
derived: this.derived,
|
||||||
index: this.index,
|
index: this.index,
|
||||||
path: this.path,
|
path: this.path,
|
||||||
address: this.getKeyAddress(),
|
address: this.getAddress(),
|
||||||
scriptAddress: this.getScriptAddress(),
|
|
||||||
key: this.key.toJSON(encrypt),
|
key: this.key.toJSON(encrypt),
|
||||||
type: this.type,
|
type: this.type,
|
||||||
subtype: this.subtype,
|
|
||||||
redeem: this.redeem ? utils.toHex(this.redeem) : null,
|
redeem: this.redeem ? utils.toHex(this.redeem) : null,
|
||||||
keys: this.keys.map(utils.toBase58),
|
keys: this.keys.map(utils.toBase58),
|
||||||
m: this.m,
|
m: this.m,
|
||||||
@ -594,7 +556,6 @@ Address.fromJSON = function fromJSON(json, decrypt) {
|
|||||||
path: json.path,
|
path: json.path,
|
||||||
key: bcoin.keypair.fromJSON(json.key, decrypt),
|
key: bcoin.keypair.fromJSON(json.key, decrypt),
|
||||||
type: json.type,
|
type: json.type,
|
||||||
subtype: json.subtype,
|
|
||||||
redeem: json.redeem ? utils.toArray(json.redeem, 'hex') : null,
|
redeem: json.redeem ? utils.toArray(json.redeem, 'hex') : null,
|
||||||
keys: json.keys.map(utils.fromBase58),
|
keys: json.keys.map(utils.fromBase58),
|
||||||
m: json.m,
|
m: json.m,
|
||||||
|
|||||||
@ -639,9 +639,13 @@ Chain.prototype.getTip = function getTip() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.isFull = function isFull() {
|
Chain.prototype.isFull = function isFull() {
|
||||||
|
var delta;
|
||||||
|
|
||||||
if (!this.tip)
|
if (!this.tip)
|
||||||
return false;
|
return false;
|
||||||
var delta = utils.now() - this.tip.ts;
|
|
||||||
|
delta = utils.now() - this.tip.ts;
|
||||||
|
|
||||||
return delta < 40 * 60;
|
return delta < 40 * 60;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -653,14 +657,15 @@ Chain.prototype.fillPercent = function fillPercent() {
|
|||||||
|
|
||||||
Chain.prototype.hashRange = function hashRange(start, end) {
|
Chain.prototype.hashRange = function hashRange(start, end) {
|
||||||
var hashes = [];
|
var hashes = [];
|
||||||
|
var i;
|
||||||
|
|
||||||
start = this.byTime(start);
|
start = this.byTime(start);
|
||||||
end = this.byTime(end);
|
end = this.byTime(end);
|
||||||
|
|
||||||
if (!start || !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);
|
hashes.push(this.db.get(i).hash);
|
||||||
|
|
||||||
return hashes;
|
return hashes;
|
||||||
@ -743,11 +748,17 @@ Chain.prototype.getHeight = function getHeight(hash) {
|
|||||||
|
|
||||||
Chain.prototype.getNextBlock = function getNextBlock(hash) {
|
Chain.prototype.getNextBlock = function getNextBlock(hash) {
|
||||||
var entry = this.byHash(hash);
|
var entry = this.byHash(hash);
|
||||||
|
var next;
|
||||||
|
|
||||||
if (!entry || !entry.next)
|
if (!entry)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return entry.next.hash;
|
next = entry.next;
|
||||||
|
|
||||||
|
if (!next)
|
||||||
|
return;
|
||||||
|
|
||||||
|
return next.hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.getSize = function getSize() {
|
Chain.prototype.getSize = function getSize() {
|
||||||
|
|||||||
@ -53,7 +53,8 @@ ChainBlock.prototype.getProof = function getProof() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ChainBlock.prototype.getChainwork = function() {
|
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() {
|
ChainBlock.prototype.getMedianTime = function() {
|
||||||
|
|||||||
@ -107,6 +107,9 @@ ChainDB.prototype._free = function(buf) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ChainDB.prototype.exists = function exists() {
|
ChainDB.prototype.exists = function exists() {
|
||||||
|
if (!bcoin.fs)
|
||||||
|
return true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fs.statSync(this.file);
|
fs.statSync(this.file);
|
||||||
return true;
|
return true;
|
||||||
@ -116,6 +119,9 @@ ChainDB.prototype.exists = function exists() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ChainDB.prototype.getSize = function getSize() {
|
ChainDB.prototype.getSize = function getSize() {
|
||||||
|
if (!bcoin.fs)
|
||||||
|
return this.ramdisk.size;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return fs.statSync(this.file).size;
|
return fs.statSync(this.file).size;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -306,18 +312,26 @@ ChainDB.prototype.remove = function remove(height) {
|
|||||||
while (this.isNull(height))
|
while (this.isNull(height))
|
||||||
height--;
|
height--;
|
||||||
|
|
||||||
if (height < 0)
|
assert(height >= 0);
|
||||||
height = 0;
|
|
||||||
|
|
||||||
fs.ftruncateSync(this.fd, (height + 1) * BLOCK_SIZE);
|
this.truncate(height);
|
||||||
|
|
||||||
this.size = (height + 1) * BLOCK_SIZE;
|
|
||||||
this.tip = height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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) {
|
ChainDB.prototype.isNull = function isNull(height) {
|
||||||
var data = this._readSync(4, height * BLOCK_SIZE);
|
var data = this._readSync(4, height * BLOCK_SIZE);
|
||||||
if (!data)
|
if (!data)
|
||||||
|
|||||||
@ -199,7 +199,7 @@ HDPrivateKey.prototype.scan44 = function scan44(options, txByAddress, callback)
|
|||||||
// respect the gap limit described below
|
// respect the gap limit described below
|
||||||
return (function next() {
|
return (function next() {
|
||||||
var address = chain.derive(addressIndex++);
|
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) {
|
return txByAddress(addr, function(err, txs) {
|
||||||
var result;
|
var result;
|
||||||
@ -346,7 +346,7 @@ HDPrivateKey.prototype.scan45 = function scan45(options, txByAddress, callback)
|
|||||||
|
|
||||||
return (function next() {
|
return (function next() {
|
||||||
var address = chain.derive(addressIndex++);
|
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) {
|
return txByAddress(addr, function(err, txs) {
|
||||||
var result;
|
var result;
|
||||||
@ -837,7 +837,7 @@ function HDPublicKey(options) {
|
|||||||
if (!options)
|
if (!options)
|
||||||
throw new Error('No options for HDPublicKey');
|
throw new Error('No options for HDPublicKey');
|
||||||
|
|
||||||
if (HDPublicKey.isExtended(data))
|
if (HDPublicKey.isExtended(options))
|
||||||
options = { xkey: options };
|
options = { xkey: options };
|
||||||
|
|
||||||
data = options.xkey
|
data = options.xkey
|
||||||
|
|||||||
@ -104,7 +104,7 @@ Input.prototype.__defineGetter__('id', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Input.prototype.__defineGetter__('address', function() {
|
Input.prototype.__defineGetter__('address', function() {
|
||||||
return this.data.scriptAddress || this.addresses[0];
|
return this.data.address;
|
||||||
});
|
});
|
||||||
|
|
||||||
Input.prototype.__defineGetter__('signatures', function() {
|
Input.prototype.__defineGetter__('signatures', function() {
|
||||||
@ -163,34 +163,6 @@ Input.prototype.__defineGetter__('value', function() {
|
|||||||
return this.output.value;
|
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:
|
// Schema and defaults for data object:
|
||||||
// {
|
// {
|
||||||
// type: String,
|
// type: String,
|
||||||
@ -253,25 +225,18 @@ Input.prototype.getData = function getData() {
|
|||||||
return Input.getData(this);
|
return Input.getData(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
Input.prototype.getAddresses = function getAddresses() {
|
Input.prototype.getType = function getType() {
|
||||||
return this.getData().addresses;
|
var prev = this.output ? this.output.script : null;
|
||||||
};
|
return bcoin.script.getInputType(this.script, prev);
|
||||||
|
|
||||||
Input.prototype.getScriptAddress = function getScriptAddress() {
|
|
||||||
return this.getData().scriptAddress;
|
|
||||||
};
|
|
||||||
|
|
||||||
Input.prototype.getKeyAddress = function getKeyAddress() {
|
|
||||||
return this.getData().addresses[0];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Input.prototype.getAddress = function getAddress() {
|
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)
|
Input.prototype.isRBF = function isRBF() {
|
||||||
return data.scriptAddress;
|
return this.sequence === 0xffffffff - 1;
|
||||||
|
|
||||||
return data.addresses[0];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Input.prototype.isFinal = function isFinal() {
|
Input.prototype.isFinal = function isFinal() {
|
||||||
@ -338,17 +303,16 @@ Input.prototype.testScript = function testScript(key, redeem, type) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Input.prototype.test = function test(addressTable) {
|
Input.prototype.test = function test(addressTable) {
|
||||||
var data = this.getData();
|
var address = this.getAddress();
|
||||||
var i;
|
|
||||||
|
|
||||||
if (data.scriptAddress) {
|
if (address) {
|
||||||
if (addressTable[data.scriptAddress] != null)
|
if (Array.isArray(addressTable)) {
|
||||||
return true;
|
if (addressTable.indexOf(address) !== -1)
|
||||||
}
|
return true;
|
||||||
|
} else {
|
||||||
for (i = 0; i < data.addresses.length; i++) {
|
if (addressTable[address] != null)
|
||||||
if (addressTable[data.addresses[i]] != null)
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -75,7 +75,7 @@ Output.prototype.__defineGetter__('id', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Output.prototype.__defineGetter__('address', function() {
|
Output.prototype.__defineGetter__('address', function() {
|
||||||
return this.data.scriptAddress || this.addresses[0];
|
return this.data.address;
|
||||||
});
|
});
|
||||||
|
|
||||||
Output.prototype.__defineGetter__('signatures', function() {
|
Output.prototype.__defineGetter__('signatures', function() {
|
||||||
@ -122,35 +122,6 @@ Output.prototype.__defineGetter__('text', function() {
|
|||||||
return this.data.text;
|
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:
|
// Schema and defaults for data object:
|
||||||
// {
|
// {
|
||||||
// type: String,
|
// type: String,
|
||||||
@ -195,25 +166,12 @@ Output.prototype.getData = function getData() {
|
|||||||
return Output.getData(this);
|
return Output.getData(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
Output.prototype.getAddresses = function getAddresses() {
|
Output.prototype.getType = function getType() {
|
||||||
return this.getData().addresses;
|
return bcoin.script.getOutputType(this.script);
|
||||||
};
|
|
||||||
|
|
||||||
Output.prototype.getScriptAddress = function getScriptAddress() {
|
|
||||||
return this.getData().scriptAddress;
|
|
||||||
};
|
|
||||||
|
|
||||||
Output.prototype.getKeyAddress = function getKeyAddress() {
|
|
||||||
return this.getData().addresses[0];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Output.prototype.getAddress = function getAddress() {
|
Output.prototype.getAddress = function getAddress() {
|
||||||
var data = this.getData();
|
return bcoin.script.getOutputAddress(this.script);
|
||||||
|
|
||||||
if (data.scriptAddress)
|
|
||||||
return data.scriptAddress;
|
|
||||||
|
|
||||||
return data.addresses[0];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Output.prototype.getID = function getID() {
|
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) {
|
Output.prototype.test = function test(addressTable) {
|
||||||
var data = this.getData();
|
var address = this.getAddress();
|
||||||
var i;
|
|
||||||
|
|
||||||
if (data.scriptAddress) {
|
if (address) {
|
||||||
if (addressTable[data.scriptAddress] != null)
|
if (Array.isArray(addressTable)) {
|
||||||
return true;
|
if (addressTable.indexOf(address) !== -1)
|
||||||
}
|
return true;
|
||||||
|
} else {
|
||||||
for (i = 0; i < data.addresses.length; i++) {
|
if (addressTable[address] != null)
|
||||||
if (addressTable[data.addresses[i]] != null)
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -205,13 +205,18 @@ exports.block = {
|
|||||||
|
|
||||||
exports.tx = {
|
exports.tx = {
|
||||||
maxSize: 100000,
|
maxSize: 100000,
|
||||||
fee: 10000,
|
minFee: 10000,
|
||||||
dust: 5460,
|
|
||||||
bareMultisig: true,
|
bareMultisig: true,
|
||||||
freeThreshold: exports.coin.muln(144).divn(250),
|
freeThreshold: exports.coin.muln(144).divn(250),
|
||||||
maxFreeSize: 1000
|
maxFreeSize: 1000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.tx.dustThreshold = new bn(182)
|
||||||
|
.muln(exports.tx.minFee)
|
||||||
|
.divn(1000)
|
||||||
|
.muln(3)
|
||||||
|
.toNumber();
|
||||||
|
|
||||||
exports.script = {
|
exports.script = {
|
||||||
maxSize: 10000,
|
maxSize: 10000,
|
||||||
maxStack: 1000,
|
maxStack: 1000,
|
||||||
|
|||||||
@ -27,9 +27,7 @@ network.set = function set(type) {
|
|||||||
main = network.main = {};
|
main = network.main = {};
|
||||||
|
|
||||||
main.prefixes = {
|
main.prefixes = {
|
||||||
pubkey: 0,
|
|
||||||
pubkeyhash: 0,
|
pubkeyhash: 0,
|
||||||
multisig: 0,
|
|
||||||
scripthash: 5,
|
scripthash: 5,
|
||||||
privkey: 128,
|
privkey: 128,
|
||||||
xpubkey: 0x0488b21e,
|
xpubkey: 0x0488b21e,
|
||||||
@ -132,9 +130,7 @@ testnet = network.testnet = {};
|
|||||||
testnet.type = 'testnet';
|
testnet.type = 'testnet';
|
||||||
|
|
||||||
testnet.prefixes = {
|
testnet.prefixes = {
|
||||||
pubkey: 111,
|
|
||||||
pubkeyhash: 111,
|
pubkeyhash: 111,
|
||||||
multisig: 111,
|
|
||||||
scripthash: 196,
|
scripthash: 196,
|
||||||
privkey: 239,
|
privkey: 239,
|
||||||
xpubkey: 0x043587cf,
|
xpubkey: 0x043587cf,
|
||||||
@ -220,9 +216,7 @@ regtest = network.regtest = {};
|
|||||||
regtest.type = 'testnet';
|
regtest.type = 'testnet';
|
||||||
|
|
||||||
regtest.prefixes = {
|
regtest.prefixes = {
|
||||||
pubkey: 111,
|
|
||||||
pubkeyhash: 111,
|
pubkeyhash: 111,
|
||||||
multisig: 111,
|
|
||||||
scripthash: 196,
|
scripthash: 196,
|
||||||
privkey: 239,
|
privkey: 239,
|
||||||
xpubkey: 0x043587cf,
|
xpubkey: 0x043587cf,
|
||||||
|
|||||||
@ -762,7 +762,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
n2 = script.num(stack.pop());
|
n2 = script.num(stack.pop());
|
||||||
n1 = script.num(stack.pop());
|
n1 = script.num(stack.pop());
|
||||||
val = n2.cmp(n1) <= 0 && n1.cmp(n3) < 0;
|
val = n2.cmp(n1) <= 0 && n1.cmp(n3) < 0;
|
||||||
stack.push(val.cmpn(0) !== 0 ? [ 1 ] : []);
|
stack.push(val.cmpn(0) !== 0 ? [1] : []);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -811,7 +811,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
stack.push(res ? [ 1 ] : []);
|
stack.push(res ? [1] : []);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -841,7 +841,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
stack.push(res ? [ 1 ] : []);
|
stack.push(res ? [1] : []);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -918,7 +918,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
stack.push(res ? [ 1 ] : []);
|
stack.push(res ? [1] : []);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -1204,10 +1204,11 @@ script.getRedeem = function getRedeem(s) {
|
|||||||
if (!Array.isArray(s[s.length - 1]))
|
if (!Array.isArray(s[s.length - 1]))
|
||||||
return;
|
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')
|
return (script.isPubkey(s) && 'pubkey')
|
||||||
|| (script.isPubkeyhash(s) && 'pubkeyhash')
|
|| (script.isPubkeyhash(s) && 'pubkeyhash')
|
||||||
|| (script.isMultisig(s) && 'multisig')
|
|| (script.isMultisig(s) && 'multisig')
|
||||||
@ -1268,19 +1269,20 @@ script.isEncoded = function isEncoded(s) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
script._locktime = function _locktime(s) {
|
script._locktime = function _locktime(s) {
|
||||||
var i;
|
|
||||||
|
|
||||||
if (s.length < 2)
|
if (s.length < 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < s.length; i++) {
|
if (!utils.isBuffer(s[0]))
|
||||||
if (utils.isBuffer(s[i]) && s[i + 1] === 'checklocktimeverify')
|
return;
|
||||||
return s[i];
|
|
||||||
}
|
if (s[1] !== 'checklocktimeverify')
|
||||||
|
return;
|
||||||
|
|
||||||
|
return s[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
script.isLocktime = function isLocktime(s) {
|
script.isLocktime = function isLocktime(s) {
|
||||||
return !!script._locktime(s);
|
return script._locktime(s) != null;
|
||||||
};
|
};
|
||||||
|
|
||||||
script.getLocktime = function getLocktime(s) {
|
script.getLocktime = function getLocktime(s) {
|
||||||
@ -1349,13 +1351,6 @@ script._getInputData = function _getInputData(s, type) {
|
|||||||
assert(typeof type === 'string');
|
assert(typeof type === 'string');
|
||||||
|
|
||||||
if (type === 'pubkey') {
|
if (type === 'pubkey') {
|
||||||
if (s.length < 1) {
|
|
||||||
return {
|
|
||||||
type: 'pubkey',
|
|
||||||
side: 'input',
|
|
||||||
none: true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
sig = s[0];
|
sig = s[0];
|
||||||
return {
|
return {
|
||||||
type: 'pubkey',
|
type: 'pubkey',
|
||||||
@ -1366,35 +1361,22 @@ script._getInputData = function _getInputData(s, type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'pubkeyhash') {
|
if (type === 'pubkeyhash') {
|
||||||
if (s.length < 2) {
|
|
||||||
return {
|
|
||||||
type: 'pubkeyhash',
|
|
||||||
side: 'input',
|
|
||||||
none: true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
sig = s[0];
|
sig = s[0];
|
||||||
key = s[1];
|
key = s[1];
|
||||||
hash = bcoin.wallet.key2hash(key);
|
hash = bcoin.address.hash160(key);
|
||||||
address = bcoin.wallet.hash2addr(hash, 'pubkeyhash');
|
address = bcoin.address.toAddress(hash, 'pubkeyhash');
|
||||||
return {
|
return {
|
||||||
type: 'pubkeyhash',
|
type: 'pubkeyhash',
|
||||||
side: 'input',
|
side: 'input',
|
||||||
signatures: [sig],
|
signatures: [sig],
|
||||||
keys: [key],
|
keys: [key],
|
||||||
hashes: [hash],
|
hashes: [hash],
|
||||||
|
address: address,
|
||||||
addresses: [address]
|
addresses: [address]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'multisig') {
|
if (type === 'multisig') {
|
||||||
if (s.length < 2) {
|
|
||||||
return {
|
|
||||||
type: 'multisig',
|
|
||||||
side: 'input',
|
|
||||||
none: true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
sig = s.slice(1);
|
sig = s.slice(1);
|
||||||
return {
|
return {
|
||||||
type: 'multisig',
|
type: 'multisig',
|
||||||
@ -1406,19 +1388,12 @@ script._getInputData = function _getInputData(s, type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'scripthash') {
|
if (type === 'scripthash') {
|
||||||
if (s.length < 1) {
|
|
||||||
return {
|
|
||||||
type: 'scripthash',
|
|
||||||
side: 'input',
|
|
||||||
none: true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
raw = s[s.length - 1];
|
raw = s[s.length - 1];
|
||||||
redeem = script.decode(raw);
|
redeem = script.decode(raw);
|
||||||
locktime = script.getLocktime(redeem);
|
locktime = script.getLocktime(redeem);
|
||||||
hash = bcoin.wallet.key2hash(raw);
|
hash = bcoin.address.hash160(raw);
|
||||||
address = bcoin.wallet.hash2addr(hash, 'scripthash');
|
address = bcoin.address.toAddress(hash, 'scripthash');
|
||||||
output = script.getOutputData(script.getSubscript(redeem));
|
output = script.getOutputData(redeem, true);
|
||||||
input = script._getInputData(s.slice(0, -1), output.type);
|
input = script._getInputData(s.slice(0, -1), output.type);
|
||||||
delete input.none;
|
delete input.none;
|
||||||
return utils.merge(input, output, {
|
return utils.merge(input, output, {
|
||||||
@ -1426,6 +1401,7 @@ script._getInputData = function _getInputData(s, type) {
|
|||||||
side: 'input',
|
side: 'input',
|
||||||
subtype: output.type,
|
subtype: output.type,
|
||||||
redeem: redeem,
|
redeem: redeem,
|
||||||
|
address: address,
|
||||||
scriptHash: hash,
|
scriptHash: hash,
|
||||||
scriptAddress: address,
|
scriptAddress: address,
|
||||||
locktime: locktime
|
locktime: locktime
|
||||||
@ -1435,45 +1411,56 @@ script._getInputData = function _getInputData(s, type) {
|
|||||||
return script.getUnknownData(s);
|
return script.getUnknownData(s);
|
||||||
};
|
};
|
||||||
|
|
||||||
script.getOutputData = function getOutputData(s) {
|
script.getOutputData = function getOutputData(s, inScriptHash) {
|
||||||
var key, hash, address;
|
var key, hash, address, mhash, maddress;
|
||||||
|
|
||||||
if (script.isPubkey(s)) {
|
if (script.isPubkey(s)) {
|
||||||
key = s[0];
|
key = s[0];
|
||||||
hash = bcoin.wallet.key2hash(key);
|
hash = bcoin.address.hash160(key);
|
||||||
address = bcoin.wallet.hash2addr(hash, 'pubkey');
|
// Convert p2pk to p2pkh addresses
|
||||||
|
address = bcoin.address.toAddress(hash, 'pubkeyhash');
|
||||||
return {
|
return {
|
||||||
type: 'pubkey',
|
type: 'pubkey',
|
||||||
side: 'output',
|
side: 'output',
|
||||||
keys: [key],
|
keys: [key],
|
||||||
hashes: [hash],
|
hashes: [hash],
|
||||||
|
address: address,
|
||||||
addresses: [address]
|
addresses: [address]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (script.isPubkeyhash(s)) {
|
if (script.isPubkeyhash(s)) {
|
||||||
hash = s[2];
|
hash = s[2];
|
||||||
|
address = bcoin.address.toAddress(hash, 'pubkeyhash');
|
||||||
return {
|
return {
|
||||||
type: 'pubkeyhash',
|
type: 'pubkeyhash',
|
||||||
side: 'output',
|
side: 'output',
|
||||||
hashes: [hash],
|
hashes: [hash],
|
||||||
addresses: [bcoin.wallet.hash2addr(hash, 'pubkeyhash')]
|
address: address,
|
||||||
|
addresses: [address]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (script.isMultisig(s)) {
|
if (script.isMultisig(s)) {
|
||||||
key = s.slice(1, -2);
|
key = s.slice(1, -2);
|
||||||
hash = key.map(function(key) {
|
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) {
|
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 {
|
return {
|
||||||
type: 'multisig',
|
type: 'multisig',
|
||||||
side: 'output',
|
side: 'output',
|
||||||
keys: key,
|
keys: key,
|
||||||
hashes: hash,
|
hashes: hash,
|
||||||
|
address: maddress,
|
||||||
addresses: address,
|
addresses: address,
|
||||||
m: s[0],
|
m: s[0],
|
||||||
n: s[s.length - 2]
|
n: s[s.length - 2]
|
||||||
@ -1482,11 +1469,13 @@ script.getOutputData = function getOutputData(s) {
|
|||||||
|
|
||||||
if (script.isScripthash(s)) {
|
if (script.isScripthash(s)) {
|
||||||
hash = s[1];
|
hash = s[1];
|
||||||
|
address = bcoin.address.toAddress(hash, 'scripthash');
|
||||||
return {
|
return {
|
||||||
type: 'scripthash',
|
type: 'scripthash',
|
||||||
side: 'output',
|
side: 'output',
|
||||||
|
address: address,
|
||||||
scriptHash: hash,
|
scriptHash: hash,
|
||||||
scriptAddress: bcoin.wallet.hash2addr(hash, 'scripthash')
|
scriptAddress: address
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1515,11 +1504,11 @@ script.getUnknownData = function getUnknownData(s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hash = key.map(function(key) {
|
hash = key.map(function(key) {
|
||||||
return bcoin.wallet.key2hash(key);
|
return bcoin.address.hash160(key);
|
||||||
});
|
});
|
||||||
|
|
||||||
address = hash.map(function(hash) {
|
address = hash.map(function(hash) {
|
||||||
return bcoin.wallet.hash2addr(hash, 'pubkey');
|
return bcoin.address.toAddress(hash, 'pubkeyhash');
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
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) {
|
script.isPubkey = function isPubkey(s, key) {
|
||||||
var res;
|
var res;
|
||||||
|
|
||||||
@ -1679,7 +1703,10 @@ script.isNulldata = function isNulldata(s) {
|
|||||||
return s[1];
|
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')
|
return (script.isPubkeyInput(s) && 'pubkey')
|
||||||
|| (script.isPubkeyhashInput(s) && 'pubkeyhash')
|
|| (script.isPubkeyhashInput(s) && 'pubkeyhash')
|
||||||
|| (script.isMultisigInput(s) && 'multisig')
|
|| (script.isMultisigInput(s) && 'multisig')
|
||||||
@ -1793,6 +1820,9 @@ script.isScripthashInput = function isScripthashInput(s, data, strict) {
|
|||||||
// If the last data element is a valid
|
// If the last data element is a valid
|
||||||
// signature or key, it's _extremely_
|
// signature or key, it's _extremely_
|
||||||
// unlikely this is a scripthash.
|
// unlikely this is a scripthash.
|
||||||
|
if (script.isDummy(raw))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (script.isSignatureEncoding(raw))
|
if (script.isSignatureEncoding(raw))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -1815,7 +1845,7 @@ script.isScripthashInput = function isScripthashInput(s, data, strict) {
|
|||||||
|
|
||||||
// P2SH redeem scripts can be nonstandard: make
|
// P2SH redeem scripts can be nonstandard: make
|
||||||
// it easier for other functions to parse this.
|
// it easier for other functions to parse this.
|
||||||
redeem = script.getSubscript(script.decode(raw));
|
redeem = script.decode(raw);
|
||||||
|
|
||||||
// Get the "real" scriptSig
|
// Get the "real" scriptSig
|
||||||
s = s.slice(0, -1);
|
s = s.slice(0, -1);
|
||||||
@ -2185,7 +2215,7 @@ script.getScripthashSigops = function getScripthashSigops(s) {
|
|||||||
if (!script.isPushOnly(s))
|
if (!script.isPushOnly(s))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
s = script.getSubscript(script.decode(s[s.length - 1]));
|
s = script.getRedeem(s);
|
||||||
|
|
||||||
return script.getSigops(s, true);
|
return script.getSigops(s, true);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -257,7 +257,7 @@ TX.prototype.scriptInput = function scriptInput(index, pub, redeem) {
|
|||||||
input.script = [[]];
|
input.script = [[]];
|
||||||
} else if (bcoin.script.isPubkeyhash(s)) {
|
} else if (bcoin.script.isPubkeyhash(s)) {
|
||||||
// P2PKH
|
// P2PKH
|
||||||
if (!utils.isEqual(s[2], bcoin.wallet.key2hash(pub)))
|
if (!utils.isEqual(s[2], bcoin.address.hash160(pub)))
|
||||||
return false;
|
return false;
|
||||||
// Already has a script template (at least)
|
// Already has a script template (at least)
|
||||||
if (input.script.length)
|
if (input.script.length)
|
||||||
@ -403,7 +403,7 @@ TX.prototype.signInput = function signInput(index, key, type) {
|
|||||||
|
|
||||||
// Get pubkey and pubkey hash.
|
// Get pubkey and pubkey hash.
|
||||||
pub = key.getPublic(true, 'array');
|
pub = key.getPublic(true, 'array');
|
||||||
pkh = bcoin.wallet.key2hash(pub);
|
pkh = bcoin.address.hash160(pub);
|
||||||
|
|
||||||
// Add signatures.
|
// Add signatures.
|
||||||
if (bcoin.script.isPubkey(s)) {
|
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
|
// https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki
|
||||||
// hash160 [20-byte-redeemscript-hash] equal
|
// hash160 [20-byte-redeemscript-hash] equal
|
||||||
script = bcoin.script.createScripthash(
|
script = bcoin.script.createScripthash(
|
||||||
bcoin.wallet.addr2hash(options.address, 'scripthash')
|
bcoin.address.toHash(options.address, 'scripthash')
|
||||||
);
|
);
|
||||||
} else if (options.address) {
|
} else if (options.address) {
|
||||||
// P2PKH Transaction
|
// P2PKH Transaction
|
||||||
// dup hash160 [pubkey-hash] equalverify checksig
|
// dup hash160 [pubkey-hash] equalverify checksig
|
||||||
script = bcoin.script.createPubkeyhash(
|
script = bcoin.script.createPubkeyhash(
|
||||||
bcoin.wallet.addr2hash(options.address, 'pubkeyhash')
|
bcoin.address.toHash(options.address, 'pubkeyhash')
|
||||||
);
|
);
|
||||||
} else if (options.key) {
|
} else if (options.key) {
|
||||||
// P2PK Transaction
|
// P2PK Transaction
|
||||||
@ -814,9 +814,6 @@ TX.prototype.signatureHash = function signatureHash(index, s, type) {
|
|||||||
// if strictenc is not enabled.
|
// if strictenc is not enabled.
|
||||||
// assert(utils.isFinite(type));
|
// assert(utils.isFinite(type));
|
||||||
|
|
||||||
// Remove code separators.
|
|
||||||
// s = script.getSubscript(s);
|
|
||||||
|
|
||||||
// Remove all signatures.
|
// Remove all signatures.
|
||||||
for (i = 0; i < copy.inputs.length; i++)
|
for (i = 0; i < copy.inputs.length; i++)
|
||||||
copy.inputs[i].script = [];
|
copy.inputs[i].script = [];
|
||||||
@ -881,7 +878,7 @@ TX.prototype.tbsHash = function tbsHash(enc, force) {
|
|||||||
|
|
||||||
if (!this._tbsHash || force) {
|
if (!this._tbsHash || force) {
|
||||||
for (i = 0; i < copy.inputs.length; i++) {
|
for (i = 0; i < copy.inputs.length; i++) {
|
||||||
if (!copy.isCoinbase())
|
if (!copy.inputs[i].isCoinbase())
|
||||||
copy.inputs[i].script = [];
|
copy.inputs[i].script = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1008,14 +1005,7 @@ TX.prototype.maxSize = function maxSize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Byte for varint size of input script
|
// Byte for varint size of input script
|
||||||
if (size < 0xfd)
|
size += utils.sizeIntv(size);
|
||||||
size += 0;
|
|
||||||
else if (size <= 0xffff)
|
|
||||||
size += 2;
|
|
||||||
else if (size <= 0xffffffff)
|
|
||||||
size += 4;
|
|
||||||
else
|
|
||||||
size += 8;
|
|
||||||
|
|
||||||
total += size;
|
total += size;
|
||||||
}
|
}
|
||||||
@ -1027,7 +1017,7 @@ TX.prototype.getInputs = function getInputs(unspent, address, fee) {
|
|||||||
var tx = this.clone();
|
var tx = this.clone();
|
||||||
var cost = tx.getOutputValue();
|
var cost = tx.getOutputValue();
|
||||||
var totalkb = 1;
|
var totalkb = 1;
|
||||||
var total = cost.addn(constants.tx.fee);
|
var total = cost.addn(constants.tx.minFee);
|
||||||
var inputs = [];
|
var inputs = [];
|
||||||
var lastAdded = 0;
|
var lastAdded = 0;
|
||||||
var size, newkb, change;
|
var size, newkb, change;
|
||||||
@ -1042,18 +1032,25 @@ TX.prototype.getInputs = function getInputs(unspent, address, fee) {
|
|||||||
return a.height - b.height;
|
return a.height - b.height;
|
||||||
});
|
});
|
||||||
|
|
||||||
function addInput(unspent) {
|
function addCoins() {
|
||||||
// Add new inputs until TX will have enough
|
var i, index;
|
||||||
// funds to cover both minimum post cost
|
|
||||||
// and fee.
|
for (i = lastAdded; i < unspent.length; i++) {
|
||||||
var index = tx._addInput(unspent);
|
// Add new inputs until TX will have enough
|
||||||
inputs.push(tx.inputs[index]);
|
// funds to cover both minimum post cost
|
||||||
lastAdded++;
|
// and fee.
|
||||||
return tx.getInputValue().cmp(total) < 0;
|
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.
|
// Transfer `total` funds maximum.
|
||||||
unspent.every(addInput);
|
addCoins();
|
||||||
|
|
||||||
if (!fee) {
|
if (!fee) {
|
||||||
// Add dummy output (for `change`) to
|
// Add dummy output (for `change`) to
|
||||||
@ -1064,9 +1061,9 @@ TX.prototype.getInputs = function getInputs(unspent, address, fee) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// if (this.subtractFee) {
|
// 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++) {
|
// 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);
|
// this.outputs[j].value = this.outputs[j].value.sub(f);
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
@ -1081,12 +1078,12 @@ TX.prototype.getInputs = function getInputs(unspent, address, fee) {
|
|||||||
size = tx.maxSize();
|
size = tx.maxSize();
|
||||||
|
|
||||||
newkb = Math.ceil(size / 1024) - totalkb;
|
newkb = Math.ceil(size / 1024) - totalkb;
|
||||||
total.iaddn(newkb * constants.tx.fee);
|
total.iaddn(newkb * constants.tx.minFee);
|
||||||
totalkb += newkb;
|
totalkb += newkb;
|
||||||
|
|
||||||
// Failed to get enough funds, add more inputs.
|
// Failed to get enough funds, add more inputs.
|
||||||
if (tx.getInputValue().cmp(total) < 0)
|
if (tx.getInputValue().cmp(total) < 0)
|
||||||
unspent.slice(lastAdded).every(addInput);
|
addCoins();
|
||||||
} while (tx.getInputValue().cmp(total) < 0 && lastAdded < unspent.length);
|
} 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.addInput(input);
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
if (result.change.cmpn(constants.tx.dust) < 0) {
|
if (result.change.cmpn(constants.tx.dustThreshold) < 0) {
|
||||||
// Do nothing. Change is added to fee.
|
// Do nothing. Change is added to fee.
|
||||||
assert.equal(
|
assert.equal(
|
||||||
this.getFee().toNumber(),
|
this.getFee().toNumber(),
|
||||||
@ -1210,7 +1207,7 @@ TX.prototype._recalculateFee = function recalculateFee() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size = this.maxSize();
|
size = this.maxSize();
|
||||||
real = Math.ceil(size / 1024) * constants.tx.fee;
|
real = Math.ceil(size / 1024) * constants.tx.minFee;
|
||||||
fee = this.getFee().toNumber();
|
fee = this.getFee().toNumber();
|
||||||
|
|
||||||
// if (this.hardFee)
|
// if (this.hardFee)
|
||||||
@ -1233,7 +1230,7 @@ TX.prototype._recalculateFee = function recalculateFee() {
|
|||||||
output.value.iaddn(fee - real);
|
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.outputs.pop();
|
||||||
this.changeIndex = -1;
|
this.changeIndex = -1;
|
||||||
return;
|
return;
|
||||||
@ -1428,15 +1425,22 @@ TX.prototype.setLocktime = function setLocktime(locktime) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
TX.prototype.increaseFee = function increaseFee(fee) {
|
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.hardFee = fee || this.getFee().add(new bn(10000));
|
||||||
this.fill();
|
result = this.fill();
|
||||||
|
|
||||||
for (i = 0; i < this.inputs.length; i++) {
|
for (i = 0; i < this.inputs.length; i++) {
|
||||||
input = this.inputs[i];
|
input = this.inputs[i];
|
||||||
input.sequence = 0xffffffff - 1;
|
input.sequence = 0xffffffff - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return !!result.inputs;
|
||||||
};
|
};
|
||||||
|
|
||||||
TX.prototype.hasPrevout = function hasPrevout() {
|
TX.prototype.hasPrevout = function hasPrevout() {
|
||||||
@ -1559,7 +1563,7 @@ TX.prototype.isStandard = function isStandard() {
|
|||||||
if (type === 'multisig' && !constants.tx.bareMultisig)
|
if (type === 'multisig' && !constants.tx.bareMultisig)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (output.value.cmpn(constants.tx.dust) < 0)
|
if (output.value.cmpn(constants.tx.dustThreshold) < 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -797,7 +797,7 @@ utils.sortHDKeys = function sortHDKeys(keys) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
utils.uniq = function(obj) {
|
utils.uniq = function uniq(obj) {
|
||||||
var out = [];
|
var out = [];
|
||||||
var i = 0;
|
var i = 0;
|
||||||
|
|
||||||
@ -809,6 +809,22 @@ utils.uniq = function(obj) {
|
|||||||
return out;
|
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) {
|
utils.fromCompact = function fromCompact(compact) {
|
||||||
var exponent = compact >> 24;
|
var exponent = compact >> 24;
|
||||||
var negative = (compact >> 23) & 0x01;
|
var negative = (compact >> 23) & 0x01;
|
||||||
|
|||||||
@ -77,6 +77,7 @@ function Wallet(options) {
|
|||||||
this.accountIndex = options.accountIndex || 0;
|
this.accountIndex = options.accountIndex || 0;
|
||||||
this.addressDepth = options.addressDepth || 0;
|
this.addressDepth = options.addressDepth || 0;
|
||||||
this.changeDepth = options.changeDepth || 0;
|
this.changeDepth = options.changeDepth || 0;
|
||||||
|
this.copayBIP45 = options.copayBIP45 || false;
|
||||||
this.cosignerIndex = -1;
|
this.cosignerIndex = -1;
|
||||||
this.sharedCosignerIndex = constants.hd.hardened - 1;
|
this.sharedCosignerIndex = constants.hd.hardened - 1;
|
||||||
this.purposeKeys = options.purposeKeys || [];
|
this.purposeKeys = options.purposeKeys || [];
|
||||||
@ -84,26 +85,21 @@ function Wallet(options) {
|
|||||||
|
|
||||||
this.hd = !!this.master;
|
this.hd = !!this.master;
|
||||||
this.type = options.type || 'pubkeyhash';
|
this.type = options.type || 'pubkeyhash';
|
||||||
this.subtype = options.subtype || null;
|
|
||||||
this.derivation = options.derivation || null;
|
this.derivation = options.derivation || null;
|
||||||
this.compressed = options.compressed !== false;
|
this.compressed = options.compressed !== false;
|
||||||
this.keys = [];
|
this.keys = [];
|
||||||
this.m = options.m || 1;
|
this.m = options.m || 1;
|
||||||
this.n = options.n || 1;
|
this.n = options.n || 1;
|
||||||
this.nmax = this.type === 'scripthash'
|
|
||||||
? (this.compressed ? 15 : 7)
|
|
||||||
: 3;
|
|
||||||
|
|
||||||
if (this.n > 1) {
|
if (this.n > 1)
|
||||||
if (this.type !== 'multisig')
|
this.type = 'multisig';
|
||||||
this.type = 'scripthash';
|
|
||||||
if (this.type === 'scripthash')
|
assert(this.type === 'pubkeyhash' || this.type === 'multisig');
|
||||||
this.subtype = 'multisig';
|
this.prefixType = this.type === 'multisig' ? 'scripthash' : 'pubkeyhash';
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.derivation) {
|
if (!this.derivation) {
|
||||||
if (this.master) {
|
if (this.master) {
|
||||||
if (this.type === 'scripthash' && this.subtype === 'multisig')
|
if (this.type === 'multisig')
|
||||||
this.derivation = 'bip45';
|
this.derivation = 'bip45';
|
||||||
else
|
else
|
||||||
this.derivation = 'bip44';
|
this.derivation = 'bip44';
|
||||||
@ -112,15 +108,12 @@ function Wallet(options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (network.prefixes[this.type] == null)
|
if (network.prefixes[this.prefixType] == null)
|
||||||
throw new Error('Unknown prefix: ' + this.type);
|
throw new Error('Unknown prefix: ' + this.prefixType);
|
||||||
|
|
||||||
if (this.m < 1 || this.m > this.n)
|
if (this.m < 1 || this.m > this.n)
|
||||||
throw new Error('m ranges between 1 and 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') {
|
if (this.derivation === 'bip45') {
|
||||||
this.purposeKey = this.master.isPurpose45()
|
this.purposeKey = this.master.isPurpose45()
|
||||||
? this.master
|
? this.master
|
||||||
@ -140,7 +133,6 @@ function Wallet(options) {
|
|||||||
publicKey: options.publicKey,
|
publicKey: options.publicKey,
|
||||||
pair: options.pair,
|
pair: options.pair,
|
||||||
type: this.type,
|
type: this.type,
|
||||||
subtype: this.subtype,
|
|
||||||
m: this.m,
|
m: this.m,
|
||||||
n: this.n,
|
n: this.n,
|
||||||
keys: [],
|
keys: [],
|
||||||
@ -162,23 +154,7 @@ function Wallet(options) {
|
|||||||
// generate the last receiving address. However, since "normal" wallets
|
// generate the last receiving address. However, since "normal" wallets
|
||||||
// cannot deterministically generate keys, we have to buffer the generated
|
// cannot deterministically generate keys, we have to buffer the generated
|
||||||
// key for later.
|
// key for later.
|
||||||
if (this.derivation === 'bip44') {
|
if (this.derivation === 'normal') {
|
||||||
// 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') {
|
|
||||||
// Try to find the last receiving address if there is one.
|
// Try to find the last receiving address if there is one.
|
||||||
receiving = options.addresses.filter(function(address) {
|
receiving = options.addresses.filter(function(address) {
|
||||||
return !address.change && this._isKeyOptions(address);
|
return !address.change && this._isKeyOptions(address);
|
||||||
@ -197,11 +173,11 @@ function Wallet(options) {
|
|||||||
index: key.index,
|
index: key.index,
|
||||||
path: key.path,
|
path: key.path,
|
||||||
type: this.type,
|
type: this.type,
|
||||||
subtype: this.subtype,
|
|
||||||
m: this.m,
|
m: this.m,
|
||||||
n: this.n,
|
n: this.n,
|
||||||
keys: options.keys
|
keys: options.keys
|
||||||
});
|
});
|
||||||
|
this.currentAddress._wallet = this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +195,7 @@ inherits(Wallet, EventEmitter);
|
|||||||
|
|
||||||
Wallet.prototype._pruneAddresses = function _pruneAddresses(options) {
|
Wallet.prototype._pruneAddresses = function _pruneAddresses(options) {
|
||||||
var addresses = this.addresses.slice();
|
var addresses = this.addresses.slice();
|
||||||
var address;
|
var i, address;
|
||||||
|
|
||||||
for (i = 0; i < addresses.length; i++) {
|
for (i = 0; i < addresses.length; i++) {
|
||||||
address = addresses[i];
|
address = addresses[i];
|
||||||
@ -250,17 +226,17 @@ Wallet.prototype._isKeyOptions = function _isKeyOptions(options) {
|
|||||||
// normal: Address of first key in wallet
|
// normal: Address of first key in wallet
|
||||||
Wallet.prototype.getID = function getID() {
|
Wallet.prototype.getID = function getID() {
|
||||||
if (this.derivation === 'bip45')
|
if (this.derivation === 'bip45')
|
||||||
return bcoin.address.key2addr(this.purposeKey.publicKey);
|
return bcoin.address.compile(this.purposeKey.publicKey);
|
||||||
|
|
||||||
if (this.derivation === 'bip44')
|
if (this.derivation === 'bip44')
|
||||||
return bcoin.address.key2addr(this.purposeKey.publicKey);
|
return bcoin.address.compile(this.purposeKey.publicKey);
|
||||||
|
|
||||||
if (this.derivation === 'normal') {
|
if (this.derivation === 'normal') {
|
||||||
if (this.addresses.length)
|
if (this.addresses.length)
|
||||||
return this.addresses[0].getKeyAddress();
|
return this.addresses[0].getKeyAddress();
|
||||||
|
|
||||||
if (this._firstKey)
|
if (this._firstKey)
|
||||||
return bcoin.address.key2addr(this._firstKey.publicKey);
|
return bcoin.address.compile(this._firstKey.publicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(false);
|
assert(false);
|
||||||
@ -316,6 +292,14 @@ Wallet.prototype._initAddresses = function _initAddresses() {
|
|||||||
Wallet.prototype.addKey = function addKey(key) {
|
Wallet.prototype.addKey = function addKey(key) {
|
||||||
var hdKey, has, i;
|
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))
|
if (bcoin.hd.privateKey.isExtended(key))
|
||||||
key = bcoin.hd.privateKey(key);
|
key = bcoin.hd.privateKey(key);
|
||||||
else if (bcoin.hd.publicKey.isExtended(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++) {
|
for (i = 0; i < this.purposeKeys.length; i++) {
|
||||||
if (this.purposeKeys[i].xpubkey === this.purposeKey.xpubkey) {
|
if (this.purposeKeys[i].xpubkey === this.purposeKey.xpubkey) {
|
||||||
this.cosignerIndex = i;
|
this.cosignerIndex = i;
|
||||||
|
this._cosignerIndex = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -394,6 +379,7 @@ Wallet.prototype.finalizeKeys = function finalizeKeys(key) {
|
|||||||
assert(this.cosignerIndex !== -1);
|
assert(this.cosignerIndex !== -1);
|
||||||
|
|
||||||
this._initAddresses();
|
this._initAddresses();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,6 +388,7 @@ Wallet.prototype.finalizeKeys = function finalizeKeys(key) {
|
|||||||
for (i = 0; i < this.keys.length; i++) {
|
for (i = 0; i < this.keys.length; i++) {
|
||||||
if (utils.isEqual(this.keys[i], this.currentAddress.publicKey)) {
|
if (utils.isEqual(this.keys[i], this.currentAddress.publicKey)) {
|
||||||
this.cosignerIndex = i;
|
this.cosignerIndex = i;
|
||||||
|
this._cosignerIndex = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -416,6 +403,14 @@ Wallet.prototype.removeKey = function removeKey(key) {
|
|||||||
|
|
||||||
assert(!this._keysFinalized);
|
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))
|
if (bcoin.hd.privateKey.isExtended(key))
|
||||||
key = bcoin.hd.privateKey(key);
|
key = bcoin.hd.privateKey(key);
|
||||||
else if (bcoin.hd.publicKey.isExtended(key))
|
else if (bcoin.hd.publicKey.isExtended(key))
|
||||||
@ -527,9 +522,7 @@ Wallet.prototype._getAddressTable = function() {
|
|||||||
|
|
||||||
for (i = 0; i < this.addresses.length; i++) {
|
for (i = 0; i < this.addresses.length; i++) {
|
||||||
address = this.addresses[i];
|
address = this.addresses[i];
|
||||||
if (address.type === 'scripthash')
|
addresses[address.getAddress()] = i;
|
||||||
addresses[address.getScriptAddress()] = i;
|
|
||||||
addresses[address.getKeyAddress()] = i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return addresses;
|
return addresses;
|
||||||
@ -545,20 +538,13 @@ Wallet.prototype._addressIndex = function _addressIndex(address) {
|
|||||||
if (!(address instanceof bcoin.address))
|
if (!(address instanceof bcoin.address))
|
||||||
address = bcoin.address(address);
|
address = bcoin.address(address);
|
||||||
|
|
||||||
if (address.type === 'scripthash') {
|
addr = address.getAddress();
|
||||||
addr = address.getScriptAddress();
|
|
||||||
if (this._addressTable[addr] != null)
|
|
||||||
return this._addressTable[addr];
|
|
||||||
}
|
|
||||||
|
|
||||||
addr = address.getKeyAddress();
|
|
||||||
if (this._addressTable[addr] != null)
|
if (this._addressTable[addr] != null)
|
||||||
return this._addressTable[addr];
|
return this._addressTable[addr];
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: fromPath here
|
|
||||||
Wallet.prototype.createAddress = function createAddress(change, index) {
|
Wallet.prototype.createAddress = function createAddress(change, index) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var key = this.createKey(change, index);
|
var key = this.createKey(change, index);
|
||||||
@ -573,7 +559,6 @@ Wallet.prototype.createAddress = function createAddress(change, index) {
|
|||||||
index: key.index,
|
index: key.index,
|
||||||
path: key.path,
|
path: key.path,
|
||||||
type: this.type,
|
type: this.type,
|
||||||
subtype: this.subtype,
|
|
||||||
m: this.m,
|
m: this.m,
|
||||||
n: this.n,
|
n: this.n,
|
||||||
keys: [],
|
keys: [],
|
||||||
@ -610,7 +595,7 @@ Wallet.prototype.createAddress = function createAddress(change, index) {
|
|||||||
this.keys = utils.sortKeys(options.keys);
|
this.keys = utils.sortKeys(options.keys);
|
||||||
} else if (this.derivation === 'normal') {
|
} else if (this.derivation === 'normal') {
|
||||||
this.keys.forEach(function(key, i) {
|
this.keys.forEach(function(key, i) {
|
||||||
if (i !== this.cosignerIndex)
|
if (i !== this._cosignerIndex)
|
||||||
options.keys.push(key);
|
options.keys.push(key);
|
||||||
}, this);
|
}, this);
|
||||||
options.keys.push(key.publicKey);
|
options.keys.push(key.publicKey);
|
||||||
@ -658,10 +643,7 @@ Wallet.prototype.addAddress = function addAddress(address) {
|
|||||||
self.emit('add address', address);
|
self.emit('add address', address);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (address.type === 'scripthash')
|
this._addressTable[address.getAddress()] = index;
|
||||||
this._addressTable[address.getScriptAddress()] = index;
|
|
||||||
|
|
||||||
this._addressTable[address.getKeyAddress()] = index;
|
|
||||||
|
|
||||||
if (address.label && this._labelTable[address.label] == null)
|
if (address.label && this._labelTable[address.label] == null)
|
||||||
this._labelTable[address.label] = index;
|
this._labelTable[address.label] = index;
|
||||||
@ -832,30 +814,19 @@ Wallet.prototype.ownOutput = function ownOutput(tx, index) {
|
|||||||
return tx.testOutputs(this._addressTable, index, true);
|
return tx.testOutputs(this._addressTable, index, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.fill = function fill(tx, address, fee) {
|
Wallet.prototype.fill = function fill(tx, options) {
|
||||||
var unspent, items, result;
|
var address, unspent;
|
||||||
|
|
||||||
|
if (!options)
|
||||||
|
options = {};
|
||||||
|
|
||||||
assert(this._initialized);
|
assert(this._initialized);
|
||||||
|
|
||||||
if (!address)
|
address = this.changeAddress.getAddress();
|
||||||
address = this.changeAddress.getKeyAddress();
|
|
||||||
|
|
||||||
unspent = this.getUnspent();
|
unspent = this.getUnspent();
|
||||||
|
|
||||||
items = unspent.filter(function(coin) {
|
result = tx.fill(unspent, address, options.fee);
|
||||||
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);
|
|
||||||
|
|
||||||
if (!result.inputs)
|
if (!result.inputs)
|
||||||
return false;
|
return false;
|
||||||
@ -1040,14 +1011,13 @@ Wallet.prototype.toJSON = function toJSON(encrypt) {
|
|||||||
name: 'wallet',
|
name: 'wallet',
|
||||||
network: network.type,
|
network: network.type,
|
||||||
type: this.type,
|
type: this.type,
|
||||||
subtype: this.subtype,
|
|
||||||
m: this.m,
|
m: this.m,
|
||||||
n: this.n,
|
n: this.n,
|
||||||
derivation: this.derivation,
|
derivation: this.derivation,
|
||||||
|
copayBIP45: this.copayBIP45,
|
||||||
accountIndex: this.accountIndex,
|
accountIndex: this.accountIndex,
|
||||||
addressDepth: this.addressDepth,
|
addressDepth: this.addressDepth,
|
||||||
changeDepth: this.changeDepth,
|
changeDepth: this.changeDepth,
|
||||||
cosignerIndex: this.cosignerIndex,
|
|
||||||
master: this.master ? this.master.toJSON(encrypt) : null,
|
master: this.master ? this.master.toJSON(encrypt) : null,
|
||||||
addresses: this.addresses.filter(function(address) {
|
addresses: this.addresses.filter(function(address) {
|
||||||
return !address.derived;
|
return !address.derived;
|
||||||
@ -1077,14 +1047,13 @@ Wallet.fromJSON = function fromJSON(json, decrypt) {
|
|||||||
|
|
||||||
wallet = new Wallet({
|
wallet = new Wallet({
|
||||||
type: json.type,
|
type: json.type,
|
||||||
subtype: json.subtype,
|
|
||||||
m: json.m,
|
m: json.m,
|
||||||
n: json.n,
|
n: json.n,
|
||||||
derivation: json.derivation,
|
derivation: json.derivation,
|
||||||
|
copayBIP45: json.copayBIP45,
|
||||||
accountIndex: json.accountIndex,
|
accountIndex: json.accountIndex,
|
||||||
addressDepth: json.addressDepth,
|
addressDepth: json.addressDepth,
|
||||||
changeDepth: json.changeDepth,
|
changeDepth: json.changeDepth,
|
||||||
cosignerIndex: json.cosignerIndex,
|
|
||||||
master: json.master
|
master: json.master
|
||||||
? bcoin.hd.fromJSON(json.master, decrypt)
|
? bcoin.hd.fromJSON(json.master, decrypt)
|
||||||
: null,
|
: null,
|
||||||
@ -1109,19 +1078,19 @@ Wallet.fromSecret = function fromSecret(privateKey) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Wallet.key2hash = function key2hash(key) {
|
Wallet.key2hash = function key2hash(key) {
|
||||||
return bcoin.address.key2hash(key);
|
return bcoin.address.hash160(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.hash2addr = function hash2addr(hash, prefix) {
|
Wallet.hash2addr = function hash2addr(hash, prefix) {
|
||||||
return bcoin.address.hash2addr(hash, prefix);
|
return bcoin.address.toAddress(hash, prefix);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.addr2hash = function addr2hash(addr, 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) {
|
Wallet.validateAddress = function validateAddress(addr, prefix) {
|
||||||
return bcoin.address.validateAddress(addr, prefix);
|
return bcoin.address.validate(addr, prefix);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -81,7 +81,7 @@ describe('Wallet', function() {
|
|||||||
// var k2 = w.getPublicKey().concat(1);
|
// var k2 = w.getPublicKey().concat(1);
|
||||||
var k2 = bcoin.ecdsa.genKeyPair().getPublic(true, 'array');
|
var k2 = bcoin.ecdsa.genKeyPair().getPublic(true, 'array');
|
||||||
w.addKey(k2);
|
w.addKey(k2);
|
||||||
assert.equal(w.getKeyAddress(), w.getAddress());
|
// assert.equal(w.getKeyAddress(), w.getAddress());
|
||||||
|
|
||||||
// Input transcation
|
// Input transcation
|
||||||
var src = bcoin.tx({
|
var src = bcoin.tx({
|
||||||
@ -222,7 +222,7 @@ describe('Wallet', function() {
|
|||||||
tx.out(to, 5460);
|
tx.out(to, 5460);
|
||||||
|
|
||||||
var cost = tx.funds('out');
|
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 unspent1 = w1.unspent();
|
||||||
var unspent2 = w2.unspent();
|
var unspent2 = w2.unspent();
|
||||||
@ -236,7 +236,7 @@ describe('Wallet', function() {
|
|||||||
tx.input(unspent2[0]);
|
tx.input(unspent2[0]);
|
||||||
|
|
||||||
var left = tx.funds('in').sub(total);
|
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);
|
tx.outputs[tx.outputs.length - 2].value.iadd(left);
|
||||||
left = new bn(0);
|
left = new bn(0);
|
||||||
}
|
}
|
||||||
@ -270,37 +270,35 @@ describe('Wallet', function() {
|
|||||||
// Create 3 2-of-3 wallets with our pubkeys as "shared keys"
|
// Create 3 2-of-3 wallets with our pubkeys as "shared keys"
|
||||||
var w1 = bcoin.wallet({
|
var w1 = bcoin.wallet({
|
||||||
derivation: 'bip44',
|
derivation: 'bip44',
|
||||||
type: 'scripthash',
|
type: 'multisig',
|
||||||
subtype: 'multisig',
|
|
||||||
m: 2,
|
m: 2,
|
||||||
n: 3
|
n: 3
|
||||||
});
|
});
|
||||||
|
|
||||||
var w2 = bcoin.wallet({
|
var w2 = bcoin.wallet({
|
||||||
derivation: 'bip44',
|
derivation: 'bip44',
|
||||||
type: 'scripthash',
|
type: 'multisig',
|
||||||
subtype: 'multisig',
|
|
||||||
m: 2,
|
m: 2,
|
||||||
n: 3
|
n: 3
|
||||||
});
|
});
|
||||||
|
|
||||||
var w3 = bcoin.wallet({
|
var w3 = bcoin.wallet({
|
||||||
derivation: 'bip44',
|
derivation: 'bip44',
|
||||||
type: 'scripthash',
|
type: 'multisig',
|
||||||
subtype: 'multisig',
|
|
||||||
m: 2,
|
m: 2,
|
||||||
n: 3
|
n: 3
|
||||||
});
|
});
|
||||||
// w3 = bcoin.wallet.fromJSON(w3.toJSON());
|
|
||||||
|
|
||||||
var receive = bcoin.wallet();
|
var receive = bcoin.wallet();
|
||||||
|
|
||||||
w1.addKey(w2.purposeKey);
|
w1.addKey(w2);
|
||||||
w1.addKey(w3.purposeKey);
|
w1.addKey(w3);
|
||||||
w2.addKey(w1.purposeKey);
|
w2.addKey(w1);
|
||||||
w2.addKey(w3.purposeKey);
|
w2.addKey(w3);
|
||||||
w3.addKey(w1.purposeKey);
|
w3.addKey(w1);
|
||||||
w3.addKey(w2.purposeKey);
|
w3.addKey(w2);
|
||||||
|
|
||||||
|
w3 = bcoin.wallet.fromJSON(w3.toJSON());
|
||||||
|
|
||||||
// Our p2sh address
|
// Our p2sh address
|
||||||
var addr = w1.getAddress();
|
var addr = w1.getAddress();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user