refactor.
This commit is contained in:
parent
14088e5b0c
commit
1002c222a6
@ -116,7 +116,6 @@ function Environment(options) {
|
||||
|
||||
this.options = options;
|
||||
|
||||
this._ensured = false;
|
||||
this._debug = null;
|
||||
|
||||
this.isBrowser = utils.isBrowser;
|
||||
@ -211,11 +210,8 @@ Environment.prototype.set = function set(options) {
|
||||
options.prefix = options.prefix
|
||||
|| process.env.BCOIN_PREFIX;
|
||||
|
||||
if (!options.prefix) {
|
||||
if (!options.prefix)
|
||||
options.prefix = utils.HOME + '/.bcoin';
|
||||
if (options.network !== 'main')
|
||||
options.prefix += '/' + options.network;
|
||||
}
|
||||
|
||||
if (!options.db)
|
||||
options.db = process.env.BCOIN_DB;
|
||||
@ -244,8 +240,12 @@ Environment.prototype.set = function set(options) {
|
||||
if (options.workerTime == null && process.env.BCOIN_WORKER_TIMEOUT != null)
|
||||
options.workerTimeout = +process.env.BCOIN_WORKER_TIMEOUT;
|
||||
|
||||
if (options.debugFile && typeof options.debugFile !== 'string')
|
||||
options.debugFile = options.prefix + '/debug.log';
|
||||
if (options.debugFile && typeof options.debugFile !== 'string') {
|
||||
options.debugFile = options.prefix;
|
||||
if (options.network !== 'main')
|
||||
options.debugFile += '/' + options.network;
|
||||
options.debugFile += '/debug.log';
|
||||
}
|
||||
|
||||
this.prefix = options.prefix;
|
||||
this.networkType = options.network;
|
||||
@ -272,23 +272,26 @@ Environment.prototype.set = function set(options) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Ensure the `prefix`.
|
||||
* @private
|
||||
* Ensure a directory.
|
||||
* @param {String} path
|
||||
* @param {Boolean?} dirname
|
||||
*/
|
||||
|
||||
Environment.prototype.ensurePrefix = function ensurePrefix() {
|
||||
Environment.prototype.mkdir = function mkdir(path, dirname) {
|
||||
if (this.isBrowser)
|
||||
return;
|
||||
|
||||
if (this._ensured)
|
||||
path = normalize(path, dirname);
|
||||
|
||||
if (!mkdir.paths)
|
||||
mkdir.paths = {};
|
||||
|
||||
if (mkdir.paths[path])
|
||||
return;
|
||||
|
||||
this._ensured = true;
|
||||
mkdir.paths[path] = true;
|
||||
|
||||
mkdirp(this.prefix);
|
||||
|
||||
if (this.profile)
|
||||
mkdirp(this.prefix + '/profiler');
|
||||
return mkdirp(path);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -369,7 +372,7 @@ Environment.prototype.write = function write(msg) {
|
||||
return;
|
||||
|
||||
if (!this._debug) {
|
||||
this.ensurePrefix();
|
||||
this.mkdir(this.debugFile, true);
|
||||
this._debug = fs.createWriteStream(this.debugFile, { flags: 'a' });
|
||||
}
|
||||
|
||||
@ -385,6 +388,25 @@ Environment.prototype.now = function now() {
|
||||
return this.time.now();
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalize a path.
|
||||
* @param {String} path
|
||||
* @param {Boolean?} dirname
|
||||
*/
|
||||
|
||||
function normalize(path, dirname) {
|
||||
var parts;
|
||||
|
||||
path = path.replace(/\\/g, '/');
|
||||
path = path.replace(/\/+$/, '');
|
||||
parts = path.split(/\/+/);
|
||||
|
||||
if (dirname)
|
||||
parts.pop();
|
||||
|
||||
return parts.join('/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a full directory structure.
|
||||
* @param {String} path
|
||||
|
||||
@ -456,9 +456,9 @@ function HDPrivateKey(options) {
|
||||
this.publicKey = ec.publicKeyCreate(options.privateKey, true);
|
||||
this.fingerPrint = null;
|
||||
|
||||
this.mnemonic = options.mnemonic;
|
||||
this.mnemonic = options.mnemonic || null;
|
||||
|
||||
this._xprivkey = options.xprivkey;
|
||||
this._xprivkey = options.xprivkey || null;
|
||||
|
||||
this.hdPrivateKey = this;
|
||||
this._hdPublicKey = null;
|
||||
@ -692,6 +692,24 @@ HDPrivateKey.prototype.derivePath = function derivePath(path) {
|
||||
return key;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compare a key against an object.
|
||||
* @param {Object} obj
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.equal = function equal(obj) {
|
||||
if (!HDPrivateKey.isHDPrivateKey(obj))
|
||||
return false;
|
||||
|
||||
return this.network === obj.network
|
||||
&& this.depth === obj.depth
|
||||
&& utils.equal(this.parentFingerPrint, obj.parentFingerPrint)
|
||||
&& this.childIndex === obj.childIndex
|
||||
&& utils.equal(this.chainCode, obj.chainCode)
|
||||
&& utils.equal(this.privateKey, obj.privateKey);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an hd private key from a seed.
|
||||
* @param {Buffer|Mnemonic|Object} options - A seed,
|
||||
@ -1021,8 +1039,8 @@ HDPrivateKey.fromJSON = function fromJSON(json, passphrase) {
|
||||
|
||||
HDPrivateKey.isHDPrivateKey = function isHDPrivateKey(obj) {
|
||||
return obj
|
||||
&& obj.hdPublicKey
|
||||
&& obj.hdPublicKey !== obj
|
||||
&& obj.privateKey
|
||||
&& Buffer.isBuffer(obj.chainCode)
|
||||
&& typeof obj.derive === 'function';
|
||||
};
|
||||
|
||||
@ -1219,6 +1237,24 @@ HDPublicKey.prototype.derivePath = function derivePath(path) {
|
||||
return key;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compare a key against an object.
|
||||
* @param {Object} obj
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
HDPublicKey.prototype.equal = function equal(obj) {
|
||||
if (!HDPublicKey.isHDPublicKey(obj))
|
||||
return false;
|
||||
|
||||
return this.network === obj.network
|
||||
&& this.depth === obj.depth
|
||||
&& utils.equal(this.parentFingerPrint, obj.parentFingerPrint)
|
||||
&& this.childIndex === obj.childIndex
|
||||
&& utils.equal(this.chainCode, obj.chainCode)
|
||||
&& utils.equal(this.publicKey, obj.publicKey);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert key to a more json-friendly object.
|
||||
* @method
|
||||
@ -1344,8 +1380,8 @@ HDPublicKey.fromBase58 = function fromBase58(xkey) {
|
||||
|
||||
HDPublicKey.isHDPublicKey = function isHDPublicKey(obj) {
|
||||
return obj
|
||||
&& obj.hdPublicKey
|
||||
&& obj.hdPublicKey === obj
|
||||
&& !obj.privateKey
|
||||
&& Buffer.isBuffer(obj.chainCode)
|
||||
&& typeof obj.derive === 'function';
|
||||
};
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
var bcoin = require('./env');
|
||||
var LowlevelUp = require('./lowlevelup');
|
||||
var utils = bcoin.utils;
|
||||
var assert = utils.assert;
|
||||
var db = {};
|
||||
|
||||
/**
|
||||
@ -28,16 +29,13 @@ var db = {};
|
||||
*/
|
||||
|
||||
function ldb(options) {
|
||||
var file = ldb.getLocation(options);
|
||||
options = ldb.parseOptions(options);
|
||||
|
||||
if (!db[file]) {
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
db[file] = new LowlevelUp(file, {
|
||||
keyEncoding: 'ascii',
|
||||
valueEncoding: 'binary',
|
||||
if (!db[options.location]) {
|
||||
if (options.backend !== 'bst' && !bcoin.isBrowser)
|
||||
bcoin.mkdir(options.location, true);
|
||||
|
||||
db[options.location] = new LowlevelUp(options.location, {
|
||||
// LevelDB and others
|
||||
createIfMissing: true,
|
||||
errorIfExists: false,
|
||||
@ -54,11 +52,11 @@ function ldb(options) {
|
||||
mapSize: options.mapSize || 300 * (1024 << 20),
|
||||
writeMap: options.writeMap || false,
|
||||
|
||||
db: ldb.getBackend(options.db)
|
||||
db: options.db
|
||||
});
|
||||
}
|
||||
|
||||
return db[file];
|
||||
return db[options.location];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,7 +65,7 @@ function ldb(options) {
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
ldb.getName = function getName(db) {
|
||||
ldb.getBackend = function getBackend(db) {
|
||||
var name, ext;
|
||||
|
||||
if (!db)
|
||||
@ -106,38 +104,38 @@ ldb.getName = function getName(db) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get database location based on options.
|
||||
* Parse options.
|
||||
* @param {Object} options
|
||||
* @returns {String} Path.
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
ldb.getLocation = function getLocation(options) {
|
||||
var backend = ldb.getName(options.db);
|
||||
ldb.parseOptions = function parseOptions(options) {
|
||||
var network = bcoin.network.get(options.network);
|
||||
var backend = ldb.getBackend(options.db);
|
||||
var location = options.location;
|
||||
var db;
|
||||
|
||||
if (options.location)
|
||||
return options.location;
|
||||
|
||||
return bcoin.prefix + '/' + options.name + '.' + backend.ext;
|
||||
};
|
||||
|
||||
/**
|
||||
* Require database backend module.
|
||||
* @param {String} db
|
||||
* @returns {Object} Module.
|
||||
*/
|
||||
|
||||
ldb.getBackend = function getBackend(db) {
|
||||
var backend = ldb.getName(db);
|
||||
if (!location) {
|
||||
assert(typeof options.name === 'string', 'Name or location required.');
|
||||
location = bcoin.prefix;
|
||||
if (network.type !== 'main')
|
||||
location += '/' + network.type;
|
||||
location += '/' + options.name + '.' + backend.ext;
|
||||
}
|
||||
|
||||
if (backend.name === 'bst')
|
||||
return require('./bst');
|
||||
db = require('./bst');
|
||||
else if (bcoin.isBrowser)
|
||||
db = require('level-js');
|
||||
else
|
||||
db = require(options.db);
|
||||
|
||||
if (bcoin.isBrowser)
|
||||
return require('level-js');
|
||||
|
||||
bcoin.ensurePrefix();
|
||||
|
||||
return require(backend.name);
|
||||
return utils.merge({}, options, {
|
||||
backend: backend.name,
|
||||
ext: backend.ext,
|
||||
location: location,
|
||||
db: db
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -147,13 +145,12 @@ ldb.getBackend = function getBackend(db) {
|
||||
*/
|
||||
|
||||
ldb.destroy = function destroy(options, callback) {
|
||||
var file = ldb.getLocation(options);
|
||||
var backend = ldb.getBackend(options.db);
|
||||
options = ldb.parseOptions(options);
|
||||
|
||||
if (!backend.destroy)
|
||||
if (!options.db.destroy)
|
||||
return utils.nextTick(callback);
|
||||
|
||||
backend.destroy(file, callback);
|
||||
options.db.backend.destroy(options.location, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -163,13 +160,12 @@ ldb.destroy = function destroy(options, callback) {
|
||||
*/
|
||||
|
||||
ldb.repair = function repair(options, callback) {
|
||||
var file = ldb.getLocation(options);
|
||||
var backend = ldb.getBackend(options.db);
|
||||
options = ldb.parseOptions(options);
|
||||
|
||||
if (!backend.repair)
|
||||
if (!options.db.backend.repair)
|
||||
return utils.asyncify(callback)(new Error('Cannot repair.'));
|
||||
|
||||
backend.repair(file, callback);
|
||||
options.db.backend.repair(options.location, callback);
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -767,6 +767,24 @@ MTX.prototype.maxSize = function maxSize(options, force) {
|
||||
if (options.wallet)
|
||||
wallet = options.wallet;
|
||||
|
||||
function getRedeem(vector, hash) {
|
||||
var redeem = vector.getRedeem();
|
||||
var address;
|
||||
|
||||
if (redeem)
|
||||
return redeem;
|
||||
|
||||
if (!wallet)
|
||||
return;
|
||||
|
||||
address = wallet.receiveAddress;
|
||||
|
||||
if (address.program && hash.length === 20)
|
||||
return address.program;
|
||||
|
||||
return address.script;
|
||||
}
|
||||
|
||||
// Calculate the size, minus the input scripts.
|
||||
total = this.getBaseSize();
|
||||
|
||||
@ -800,10 +818,7 @@ MTX.prototype.maxSize = function maxSize(options, force) {
|
||||
// here since it will be ignored by
|
||||
// the isMultisig clause.
|
||||
// OP_PUSHDATA2 [redeem]
|
||||
redeem = wallet
|
||||
? wallet.getRedeem(prev.code[1])
|
||||
: input.script.getRedeem();
|
||||
|
||||
redeem = getRedeem(input.script, prev.code[1]);
|
||||
if (redeem) {
|
||||
prev = redeem;
|
||||
sz = prev.getSize();
|
||||
@ -834,10 +849,7 @@ MTX.prototype.maxSize = function maxSize(options, force) {
|
||||
hadWitness = true;
|
||||
|
||||
if (prev.isWitnessScripthash()) {
|
||||
redeem = wallet
|
||||
? wallet.getRedeem(prev.code[1])
|
||||
: input.witness.getRedeem();
|
||||
|
||||
redeem = getRedeem(input.witness, prev.code[1]);
|
||||
if (redeem) {
|
||||
prev = redeem;
|
||||
sz = prev.getSize();
|
||||
|
||||
@ -23,7 +23,6 @@ function ensure() {
|
||||
if (bcoin.profile && !bcoin.isBrowser) {
|
||||
v8profiler = require('v8-' + 'profiler');
|
||||
fs = require('f' + 's');
|
||||
bcoin.ensurePrefix();
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,6 +108,8 @@ Profile.prototype.save = function save(callback) {
|
||||
+ self.name
|
||||
+ '.cpuprofile';
|
||||
|
||||
bcoin.mkdir(file, true);
|
||||
|
||||
fs.writeFile(file, result, callback);
|
||||
});
|
||||
};
|
||||
@ -202,6 +203,8 @@ Snapshot.prototype.save = function save(callback) {
|
||||
+ self.name
|
||||
+ '.heapsnapshot';
|
||||
|
||||
bcoin.mkdir(file, true);
|
||||
|
||||
fs.writeFile(file, result, callback);
|
||||
});
|
||||
};
|
||||
|
||||
@ -58,15 +58,18 @@ function Wallet(options) {
|
||||
|
||||
this.options = options;
|
||||
this.network = bcoin.network.get(options.network);
|
||||
this.db = options.db || bcoin.walletdb({ name: 'wtmp', db: 'memory' });
|
||||
this.db = options.db;
|
||||
|
||||
if (!this.db)
|
||||
this.db = new bcoin.walletdb({ name: 'wtmp', db: 'memory' });
|
||||
|
||||
if (!options.master)
|
||||
options.master = bcoin.hd.fromMnemonic(null, this.network);
|
||||
|
||||
if (!(options.master instanceof bcoin.hd) && !(options.master instanceof MasterKey))
|
||||
if (!bcoin.hd.isHD(options.master) && !MasterKey.isMasterKey(options.master))
|
||||
options.master = bcoin.hd.fromAny(options.master, this.network);
|
||||
|
||||
if (!(options.master instanceof MasterKey))
|
||||
if (!MasterKey.isMasterKey(options.master))
|
||||
options.master = MasterKey.fromKey(options.master);
|
||||
|
||||
this.id = options.id || null;
|
||||
@ -81,8 +84,7 @@ function Wallet(options) {
|
||||
this.copayBIP45 = options.copayBIP45 || false;
|
||||
this.lookahead = options.lookahead != null ? options.lookahead : 5;
|
||||
this.cosignerIndex = -1;
|
||||
this.saved = options.saved || false;
|
||||
this.initialized = options.initialized || false;
|
||||
this.initialized = false;
|
||||
|
||||
this.type = options.type || 'pubkeyhash';
|
||||
this.derivation = options.derivation || 'bip44';
|
||||
@ -111,6 +113,8 @@ function Wallet(options) {
|
||||
key = key.derivePurpose45().hdPublicKey;
|
||||
else if (this.derivation === 'bip44')
|
||||
key = key.deriveAccount44(this.accountIndex).hdPublicKey;
|
||||
else
|
||||
assert(false);
|
||||
|
||||
this.accountKey = key;
|
||||
}
|
||||
@ -136,20 +140,20 @@ Wallet.prototype.init = function init(callback) {
|
||||
var addresses = [];
|
||||
var i;
|
||||
|
||||
this.saved = true;
|
||||
|
||||
// Waiting for more keys.
|
||||
if (this.keys.length !== this.n) {
|
||||
assert(!this.initialized);
|
||||
return this.save(callback);
|
||||
return this.db.open(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.save(callback);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.initialized) {
|
||||
assert(this.saved);
|
||||
this.receiveAddress = this.deriveReceive(this.receiveDepth - 1);
|
||||
this.changeAddress = this.deriveChange(this.changeDepth - 1);
|
||||
//return callback();
|
||||
return this.save(callback);
|
||||
return this.db.open(callback);
|
||||
}
|
||||
|
||||
this.initialized = true;
|
||||
@ -172,74 +176,17 @@ Wallet.prototype.init = function init(callback) {
|
||||
addresses.push(this.receiveAddress);
|
||||
addresses.push(this.changeAddress);
|
||||
|
||||
return this.saveAddress(addresses, function(err) {
|
||||
return this.db.open(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return self.save(callback);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Open the wallet, wait for the database to load.
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
Wallet.prototype.open = function open(callback) {
|
||||
var self = this;
|
||||
|
||||
if (this.loaded)
|
||||
return utils.nextTick(callback);
|
||||
|
||||
if (this._loading)
|
||||
return this.once('open', callback);
|
||||
|
||||
this._loading = true;
|
||||
|
||||
this.db.register(this.id, this);
|
||||
|
||||
this.db.open(function(err) {
|
||||
if (err)
|
||||
return self.emit('error', err);
|
||||
|
||||
if (0)
|
||||
if (self.saved) {
|
||||
utils.nextTick(function() {
|
||||
self.loaded = true;
|
||||
self.emit('open');
|
||||
callback();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
self.init(function(err) {
|
||||
if (err) {
|
||||
self.emit('error', err);
|
||||
return self.saveAddress(addresses, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
}
|
||||
self.loaded = true;
|
||||
self.emit('open');
|
||||
callback();
|
||||
return self.save(callback);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Close the wallet, wait for the database to close.
|
||||
* @method
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
Wallet.prototype.close =
|
||||
Wallet.prototype.destroy = function destroy(callback) {
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
if (!this.db)
|
||||
return utils.nextTick(callback);
|
||||
|
||||
this.db.unregister(this.id, this);
|
||||
this.db = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a public account/purpose key to the wallet for multisig.
|
||||
* @param {HDPublicKey|Base58String} key - Account (bip44) or
|
||||
@ -248,14 +195,17 @@ Wallet.prototype.destroy = function destroy(callback) {
|
||||
*/
|
||||
|
||||
Wallet.prototype._addKey = function addKey(key) {
|
||||
var result = false;
|
||||
var index, i;
|
||||
|
||||
assert(key, 'Key required.');
|
||||
|
||||
if (Array.isArray(key)) {
|
||||
for (i = 0; i < key.length; i++)
|
||||
this._addKey(key[i]);
|
||||
return;
|
||||
for (i = 0; i < key.length; i++) {
|
||||
if (this._addKey(key[i]))
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (key instanceof bcoin.wallet) {
|
||||
@ -269,25 +219,26 @@ Wallet.prototype._addKey = function addKey(key) {
|
||||
if (key.hdPublicKey)
|
||||
key = key.hdPublicKey;
|
||||
|
||||
assert(key instanceof bcoin.hd, 'Must add HD keys to wallet.');
|
||||
if (!bcoin.hd.isHD(key))
|
||||
throw new Error('Must add HD keys to wallet.');
|
||||
|
||||
if (this.derivation === 'bip44') {
|
||||
if (!key || !key.isAccount44())
|
||||
if (!key.isAccount44())
|
||||
throw new Error('Must add HD account keys to BIP44 wallet.');
|
||||
} else if (this.derivation === 'bip45') {
|
||||
if (!key || !key.isPurpose45())
|
||||
if (!key.isPurpose45())
|
||||
throw new Error('Must add HD purpose keys to BIP45 wallet.');
|
||||
}
|
||||
|
||||
for (i = 0; i < this.keys.length; i++) {
|
||||
if (this.keys[i].xpubkey === key.xpubkey) {
|
||||
if (this.keys[i].equal(key)) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index != null)
|
||||
return;
|
||||
return false;
|
||||
|
||||
assert(!this._keysFinalized);
|
||||
|
||||
@ -295,11 +246,13 @@ Wallet.prototype._addKey = function addKey(key) {
|
||||
|
||||
if (this.keys.length === this.n)
|
||||
this._finalizeKeys();
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
Wallet.prototype.addKey = function addKey(key, callback) {
|
||||
this._addKey(key);
|
||||
this.init(callback);
|
||||
if (this._addKey(key))
|
||||
this.init(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -310,14 +263,17 @@ Wallet.prototype.addKey = function addKey(key, callback) {
|
||||
*/
|
||||
|
||||
Wallet.prototype._removeKey = function removeKey(key) {
|
||||
var result = false;
|
||||
var index, i;
|
||||
|
||||
assert(!this._keysFinalized);
|
||||
|
||||
if (Array.isArray(key)) {
|
||||
for (i = 0; i < key.length; i++)
|
||||
this._removeKey(key[i]);
|
||||
return;
|
||||
for (i = 0; i < key.length; i++) {
|
||||
if (this._removeKey(key[i]))
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
assert(key, 'Key required.');
|
||||
@ -333,27 +289,30 @@ Wallet.prototype._removeKey = function removeKey(key) {
|
||||
if (key.hdPublicKey)
|
||||
key = key.hdPublicKey;
|
||||
|
||||
assert(key instanceof bcoin.hd, 'Must add HD keys to wallet.');
|
||||
if (!bcoin.hd.isHD(key))
|
||||
throw new Error('Must add HD keys to wallet.');
|
||||
|
||||
if (this.derivation === 'bip44') {
|
||||
if (!key || !key.isAccount44())
|
||||
if (!key.isAccount44())
|
||||
throw new Error('Must add HD account keys to BIP44 wallet.');
|
||||
} else if (this.derivation === 'bip45') {
|
||||
if (!key || !key.isPurpose45())
|
||||
if (!key.isPurpose45())
|
||||
throw new Error('Must add HD purpose keys to BIP45 wallet.');
|
||||
}
|
||||
|
||||
for (i = 0; i < this.keys.length; i++) {
|
||||
if (this.keys[i].xpubkey === key.xpubkey) {
|
||||
if (this.keys[i].equal(key)) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == null)
|
||||
return;
|
||||
return false;
|
||||
|
||||
this.keys.splice(index, 1);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
Wallet.prototype.removeKey = function removeKey(key, callback) {
|
||||
@ -362,8 +321,8 @@ Wallet.prototype.removeKey = function removeKey(key, callback) {
|
||||
if (this.keys.length === this.n)
|
||||
return callback(new Error('Cannot remove the fucking key now.'));
|
||||
|
||||
this._removeKey(key);
|
||||
this.save(callback);
|
||||
if (this._removeKey(key))
|
||||
this.save(callback);
|
||||
};
|
||||
|
||||
Wallet.prototype._finalizeKeys = function _finalizeKeys() {
|
||||
@ -375,7 +334,7 @@ Wallet.prototype._finalizeKeys = function _finalizeKeys() {
|
||||
this.keys = utils.sortHDKeys(this.keys);
|
||||
|
||||
for (i = 0; i < this.keys.length; i++) {
|
||||
if (this.keys[i].xpubkey === this.accountKey.xpubkey) {
|
||||
if (this.keys[i].equal(this.accountKey)) {
|
||||
this.cosignerIndex = i;
|
||||
break;
|
||||
}
|
||||
@ -754,7 +713,7 @@ Wallet.prototype.fill = function fill(tx, options, callback) {
|
||||
rate: options.rate != null
|
||||
? options.rate
|
||||
: self.network.getRate(),
|
||||
//wallet: self,
|
||||
wallet: self,
|
||||
m: self.m,
|
||||
n: self.n
|
||||
});
|
||||
@ -835,7 +794,8 @@ Wallet.prototype.createTX = function createTX(options, outputs, callback) {
|
||||
try {
|
||||
tx.addOutput(outputs[i]);
|
||||
} catch (e) {
|
||||
return utils.asyncify(callback)(e);
|
||||
callback = utils.asyncify(callback);
|
||||
return callback(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -860,10 +820,15 @@ Wallet.prototype.createTX = function createTX(options, outputs, callback) {
|
||||
if (!tx.checkInputs(height))
|
||||
return callback(new Error('CheckInputs failed.'));
|
||||
|
||||
if (!self.scriptInputs(tx))
|
||||
return callback(new Error('scriptInputs failed.'));
|
||||
self.scriptInputs(tx, function(err, total) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return callback(null, tx);
|
||||
if (total === 0)
|
||||
return callback(new Error('scriptInputs failed.'));
|
||||
|
||||
return callback(null, tx);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@ -1233,7 +1198,7 @@ Wallet.prototype.scriptInputs = function scriptInputs(tx, callback) {
|
||||
Wallet.prototype.sign = function sign(tx, options, callback) {
|
||||
var self = this;
|
||||
var total = 0;
|
||||
var i, address, key;
|
||||
var i, address, key, master;
|
||||
|
||||
if (Array.isArray(tx)) {
|
||||
utils.forEachSerial(tx, function(tx, next) {
|
||||
@ -1255,24 +1220,27 @@ Wallet.prototype.sign = function sign(tx, options, callback) {
|
||||
return callback(err);
|
||||
|
||||
try {
|
||||
var master = self.master.decrypt(options.passphrase);
|
||||
master = self.master.decrypt(options.passphrase);
|
||||
} catch (e) {
|
||||
return callback(null, 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < addresses.length; i++) {
|
||||
address = addresses[i];
|
||||
|
||||
key = master;
|
||||
|
||||
if (self.derivation === 'bip44') {
|
||||
key = key.deriveAccount44(self.accountIndex);
|
||||
assert.equal(key.xpubkey, self.accountKey.xpubkey);
|
||||
} else if (self.derivation === 'bip45')
|
||||
} else if (self.derivation === 'bip45') {
|
||||
key = key.derivePurpose45();
|
||||
else
|
||||
assert.equal(key.xpubkey, self.accountKey.xpubkey);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
key = key.derive(address.path);
|
||||
|
||||
assert(utils.equal(key.getPublicKey(), address.key));
|
||||
|
||||
total += address.sign(tx, key, options.index, options.type);
|
||||
@ -1590,8 +1558,6 @@ Wallet.prototype.toJSON = function toJSON() {
|
||||
type: this.type,
|
||||
m: this.m,
|
||||
n: this.n,
|
||||
initialized: this.initialized,
|
||||
saved: this.saved,
|
||||
witness: this.witness,
|
||||
derivation: this.derivation,
|
||||
copayBIP45: this.copayBIP45,
|
||||
@ -1627,8 +1593,6 @@ Wallet.parseJSON = function parseJSON(json) {
|
||||
type: json.type,
|
||||
m: json.m,
|
||||
n: json.n,
|
||||
initialized: json.initialized,
|
||||
saved: json.saved,
|
||||
witness: json.witness,
|
||||
derivation: json.derivation,
|
||||
copayBIP45: json.copayBIP45,
|
||||
@ -1704,26 +1668,18 @@ MasterKey.fromJSON = function fromJSON(json) {
|
||||
});
|
||||
};
|
||||
|
||||
MasterKey.isMasterKey = function isMasterKey(obj) {
|
||||
return obj
|
||||
&& obj.json
|
||||
&& typeof obj.decrypt === 'function';
|
||||
};
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Wallet;
|
||||
|
||||
/*!
|
||||
* wallet.js - wallet object for bcoin
|
||||
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/indutny/bcoin
|
||||
*/
|
||||
|
||||
var bcoin = require('./env');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var utils = require('./utils');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.protocol.constants;
|
||||
var BufferWriter = require('./writer');
|
||||
|
||||
/**
|
||||
* HD BIP-44/45 wallet
|
||||
* @exports Wallet
|
||||
@ -1764,7 +1720,7 @@ function CWallet(id, db) {
|
||||
EventEmitter.call(this);
|
||||
|
||||
this.network = db.network;
|
||||
this.db = db || bcoin.walletdb({ name: 'wtmp', db: 'memory' });
|
||||
this.db = db;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@ -1963,28 +1919,7 @@ CWallet.prototype.getPath = function getPath(address, callback) {
|
||||
*/
|
||||
|
||||
CWallet.prototype.getRedeem = function getRedeem(hash, callback) {
|
||||
var self = this;
|
||||
var address;
|
||||
|
||||
if (typeof hash === 'string')
|
||||
hash = new Buffer(hash, 'hex');
|
||||
|
||||
this.getPath(hash.toString('hex'), function(err, path) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!path)
|
||||
return callback();
|
||||
|
||||
address = self.deriveAddress(path);
|
||||
|
||||
if (address.program && hash.length === 20) {
|
||||
if (utils.equal(hash, address.programHash))
|
||||
return callback(null, address.program);
|
||||
}
|
||||
|
||||
return callback(null, address.script);
|
||||
});
|
||||
;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2109,119 +2044,21 @@ CWallet.prototype.getReceiveAddress = function getReceiveAddress(callback) {
|
||||
return this.db.getReceiveAddress(this.id, callback);
|
||||
};
|
||||
|
||||
CWallet.prototype.getInfo = function getInfo(callback) {
|
||||
return this.db.get(this.id, function(err, cwallet, wallet) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback(null, wallet);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert the wallet to a more inspection-friendly object.
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
CWallet.prototype.inspect = function inspect() {
|
||||
return {
|
||||
id: this.id,
|
||||
type: this.type,
|
||||
network: this.network.type,
|
||||
m: this.m,
|
||||
n: this.n,
|
||||
keyAddress: this.initialized
|
||||
? this.keyAddress
|
||||
: null,
|
||||
scriptAddress: this.initialized
|
||||
? this.scriptAddress
|
||||
: null,
|
||||
programAddress: this.initialized
|
||||
? this.programAddress
|
||||
: null,
|
||||
witness: this.witness,
|
||||
derivation: this.derivation,
|
||||
copayBIP45: this.copayBIP45,
|
||||
accountIndex: this.accountIndex,
|
||||
receiveDepth: this.receiveDepth,
|
||||
changeDepth: this.changeDepth,
|
||||
master: this.master.toJSON(),
|
||||
accountKey: this.accountKey.xpubkey,
|
||||
keys: this.keys.map(function(key) {
|
||||
return key.xpubkey;
|
||||
})
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert the wallet to an object suitable for
|
||||
* serialization. Will automatically encrypt the
|
||||
* master key based on the `passphrase` option.
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
CWallet.prototype.toJSON = function toJSON() {
|
||||
return {
|
||||
v: 3,
|
||||
name: 'wallet',
|
||||
network: this.network.type,
|
||||
id: this.id,
|
||||
type: this.type,
|
||||
m: this.m,
|
||||
n: this.n,
|
||||
initialized: this.initialized,
|
||||
saved: this.saved,
|
||||
witness: this.witness,
|
||||
derivation: this.derivation,
|
||||
copayBIP45: this.copayBIP45,
|
||||
accountIndex: this.accountIndex,
|
||||
receiveDepth: this.receiveDepth,
|
||||
changeDepth: this.changeDepth,
|
||||
master: this.master.toJSON(),
|
||||
accountKey: this.accountKey.xpubkey,
|
||||
keys: this.keys.map(function(key) {
|
||||
return key.xpubkey;
|
||||
})
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a deserialized JSON wallet object.
|
||||
* @returns {Object} A "naked" wallet (a
|
||||
* plain javascript object which is suitable
|
||||
* for passing to the Wallet constructor).
|
||||
* @param {Object} json
|
||||
* @param {String?} passphrase
|
||||
* @returns {Object}
|
||||
* @throws Error on bad decrypt
|
||||
*/
|
||||
|
||||
CWallet.parseJSON = function parseJSON(json) {
|
||||
assert.equal(json.v, 3);
|
||||
assert.equal(json.name, 'wallet');
|
||||
|
||||
return {
|
||||
network: json.network,
|
||||
id: json.id,
|
||||
type: json.type,
|
||||
m: json.m,
|
||||
n: json.n,
|
||||
initialized: json.initialized,
|
||||
saved: json.saved,
|
||||
witness: json.witness,
|
||||
derivation: json.derivation,
|
||||
copayBIP45: json.copayBIP45,
|
||||
accountIndex: json.accountIndex,
|
||||
receiveDepth: json.receiveDepth,
|
||||
changeDepth: json.changeDepth,
|
||||
master: MasterKey.fromJSON(json.master),
|
||||
accountKey: bcoin.hd.fromBase58(json.accountKey),
|
||||
keys: json.keys.map(function(key) {
|
||||
return bcoin.hd.fromBase58(key);
|
||||
})
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate a Wallet from a
|
||||
* jsonified wallet object.
|
||||
* @param {Object} json - The jsonified wallet object.
|
||||
* @returns {Wallet}
|
||||
*/
|
||||
|
||||
CWallet.fromJSON = function fromJSON(json) {
|
||||
return new CWallet(CWallet.parseJSON(json));
|
||||
return '<CWallet id=' + this.id + '>';
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2232,8 +2069,9 @@ CWallet.fromJSON = function fromJSON(json) {
|
||||
|
||||
CWallet.isCWallet = function isCWallet(obj) {
|
||||
return obj
|
||||
&& typeof obj.receiveDepth === 'number'
|
||||
&& obj.deriveAddress === 'function';
|
||||
&& obj.db
|
||||
&& obj.id
|
||||
&& obj.getInfo === 'function';
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -403,7 +403,7 @@ WalletDB.prototype.get = function get(id, callback) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
wallet.open(function(err) {
|
||||
wallet.init(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -474,7 +474,7 @@ WalletDB.prototype.create = function create(options, callback) {
|
||||
options.db = self;
|
||||
wallet = new bcoin.wallet(options);
|
||||
|
||||
wallet.open(function(err) {
|
||||
wallet.init(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -514,7 +514,7 @@ WalletDB.prototype.ensure = function ensure(options, callback) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
wallet.open(function(err) {
|
||||
wallet.init(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
|
||||
@ -8,13 +8,14 @@ var opcodes = constants.opcodes;
|
||||
constants.tx.COINBASE_MATURITY = 0;
|
||||
|
||||
describe('Chain', function() {
|
||||
var chain, wallet, miner;
|
||||
var chain, wallet, miner, walletdb;
|
||||
var competingTip, oldTip, ch1, ch2, cb1, cb2;
|
||||
|
||||
this.timeout(5000);
|
||||
|
||||
chain = new bcoin.chain({ name: 'chain-test', db: 'memory' });
|
||||
wallet = new bcoin.wallet();
|
||||
walletdb = new bcoin.walletdb({ name: 'chain-test-wdb', db: 'memory' });
|
||||
wallet = new bcoin.wallet({ db: walletdb });
|
||||
miner = new bcoin.miner({
|
||||
chain: chain,
|
||||
address: wallet.getAddress()
|
||||
@ -40,13 +41,16 @@ describe('Chain', function() {
|
||||
value: utils.satoshi('25.0')
|
||||
});
|
||||
redeemer.addOutput({
|
||||
address: wallet.createAddress().getAddress(),
|
||||
address: wallet.deriveAddress(false, 100).getAddress(),
|
||||
value: utils.satoshi('5.0')
|
||||
});
|
||||
redeemer.addInput(tx, 0);
|
||||
redeemer.setLocktime(chain.height);
|
||||
wallet.sign(redeemer);
|
||||
attempt.addTX(redeemer);
|
||||
return wallet.sign(redeemer, function(err) {
|
||||
assert.ifError(err);
|
||||
attempt.addTX(redeemer);
|
||||
callback(null, attempt.mineSync());
|
||||
});
|
||||
}
|
||||
callback(null, attempt.mineSync());
|
||||
});
|
||||
@ -68,7 +72,10 @@ describe('Chain', function() {
|
||||
}
|
||||
|
||||
it('should open chain and miner', function(cb) {
|
||||
miner.open(cb);
|
||||
miner.open(function(err) {
|
||||
assert.ifError(cb);
|
||||
wallet.init(cb);
|
||||
});
|
||||
});
|
||||
|
||||
it('should mine a block', function(cb) {
|
||||
|
||||
@ -60,7 +60,7 @@ describe('Wallet', function() {
|
||||
|
||||
it('should generate new key and address', function() {
|
||||
var w = bcoin.wallet();
|
||||
w.open(function(err) {
|
||||
w.init(function(err) {
|
||||
assert.ifError(err);
|
||||
var addr = w.getAddress();
|
||||
assert(addr);
|
||||
@ -139,7 +139,7 @@ describe('Wallet', function() {
|
||||
m: 1,
|
||||
n: 2
|
||||
});
|
||||
w.open(function(err) {
|
||||
w.init(function(err) {
|
||||
assert.ifError(err);
|
||||
var k2 = bcoin.hd.fromMnemonic().deriveAccount44(0).hdPublicKey;
|
||||
w.addKey(k2, function(err) {
|
||||
@ -556,6 +556,43 @@ describe('Wallet', function() {
|
||||
|
||||
var w1, w2, w3, receive;
|
||||
|
||||
function getInfo(callback) {
|
||||
var info = { change: {} };
|
||||
utils.serial([
|
||||
function(next) {
|
||||
w1.getInfo(function(err, info_) {
|
||||
assert.ifError(err);
|
||||
info.w1 = info_;
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
w2.getInfo(function(err, info_) {
|
||||
assert.ifError(err);
|
||||
info.w2 = info_;
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
w3.getInfo(function(err, info_) {
|
||||
assert.ifError(err);
|
||||
info.w3 = info_;
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
receive.getInfo(function(err, info_) {
|
||||
assert.ifError(err);
|
||||
info.receive = info_;
|
||||
next();
|
||||
});
|
||||
}
|
||||
], function(err) {
|
||||
assert.ifError(err);
|
||||
return callback(null, info);
|
||||
});
|
||||
}
|
||||
|
||||
utils.serial([
|
||||
function(next) {
|
||||
wdb.create(utils.merge({}, options), function(err, w1_) {
|
||||
@ -584,38 +621,42 @@ describe('Wallet', function() {
|
||||
receive = receive_;
|
||||
next();
|
||||
});
|
||||
},
|
||||
}
|
||||
], function(err) {
|
||||
assert.ifError(err);
|
||||
|
||||
getInfo(function(err, a) {
|
||||
assert.ifError(err);
|
||||
utils.serial([
|
||||
w1.addKey.bind(w1, w2),
|
||||
w1.addKey.bind(w1, w3),
|
||||
w2.addKey.bind(w2, w1),
|
||||
w2.addKey.bind(w2, w3),
|
||||
w3.addKey.bind(w3, w1),
|
||||
w3.addKey.bind(w3, w2)
|
||||
w1.addKey.bind(w1, a.w2.accountKey),
|
||||
w1.addKey.bind(w1, a.w3.accountKey),
|
||||
w2.addKey.bind(w2, a.w1.accountKey),
|
||||
w2.addKey.bind(w2, a.w3.accountKey),
|
||||
w3.addKey.bind(w3, a.w1.accountKey),
|
||||
w3.addKey.bind(w3, a.w2.accountKey)
|
||||
], function(err) {
|
||||
assert.ifError(err);
|
||||
getInfo(function(err, a) {
|
||||
assert.ifError(err);
|
||||
|
||||
// w3 = bcoin.wallet.fromJSON(w3.toJSON());
|
||||
|
||||
// Our p2sh address
|
||||
var addr = w1.getAddress();
|
||||
var addr = a.w1.getAddress();
|
||||
|
||||
if (witness)
|
||||
assert(bcoin.address.parseBase58(addr).type === 'witnessscripthash');
|
||||
else
|
||||
assert(bcoin.address.parseBase58(addr).type === 'scripthash');
|
||||
|
||||
assert.equal(w1.getAddress(), addr);
|
||||
assert.equal(w2.getAddress(), addr);
|
||||
assert.equal(w3.getAddress(), addr);
|
||||
assert.equal(a.w1.getAddress(), addr);
|
||||
assert.equal(a.w2.getAddress(), addr);
|
||||
assert.equal(a.w3.getAddress(), addr);
|
||||
|
||||
var paddr = w1.getProgramAddress();
|
||||
assert.equal(w1.getProgramAddress(), paddr);
|
||||
assert.equal(w2.getProgramAddress(), paddr);
|
||||
assert.equal(w3.getProgramAddress(), paddr);
|
||||
var paddr = a.w1.getProgramAddress();
|
||||
assert.equal(a.w1.getProgramAddress(), paddr);
|
||||
assert.equal(a.w2.getProgramAddress(), paddr);
|
||||
assert.equal(a.w3.getProgramAddress(), paddr);
|
||||
|
||||
// Add a shared unspent transaction to our wallets
|
||||
var utx = bcoin.mtx();
|
||||
@ -631,7 +672,7 @@ describe('Wallet', function() {
|
||||
utx.ts = 1;
|
||||
utx.height = 1;
|
||||
|
||||
assert.equal(w1.receiveDepth, 1);
|
||||
assert.equal(a.w1.receiveDepth, 1);
|
||||
|
||||
wdb.addTX(utx, function(err) {
|
||||
assert.ifError(err);
|
||||
@ -640,18 +681,20 @@ describe('Wallet', function() {
|
||||
wdb.addTX(utx, function(err) {
|
||||
assert.ifError(err);
|
||||
|
||||
assert.equal(w1.receiveDepth, 2);
|
||||
assert.equal(w1.changeDepth, 1);
|
||||
getInfo(function(err, a) {
|
||||
assert.ifError(err);
|
||||
assert.equal(a.w1.receiveDepth, 2);
|
||||
assert.equal(a.w1.changeDepth, 1);
|
||||
|
||||
assert(w1.getAddress() !== addr);
|
||||
addr = w1.getAddress();
|
||||
assert.equal(w1.getAddress(), addr);
|
||||
assert.equal(w2.getAddress(), addr);
|
||||
assert.equal(w3.getAddress(), addr);
|
||||
assert(a.w1.getAddress() !== addr);
|
||||
addr = a.w1.getAddress();
|
||||
assert.equal(a.w1.getAddress(), addr);
|
||||
assert.equal(a.w2.getAddress(), addr);
|
||||
assert.equal(a.w3.getAddress(), addr);
|
||||
|
||||
// Create a tx requiring 2 signatures
|
||||
var send = bcoin.mtx();
|
||||
send.addOutput({ address: receive.getAddress(), value: 5460 });
|
||||
send.addOutput({ address: a.receive.getAddress(), value: 5460 });
|
||||
assert(!send.verify(null, true, flags));
|
||||
w1.fill(send, { rate: 10000, round: true }, function(err) {
|
||||
assert.ifError(err);
|
||||
@ -665,11 +708,11 @@ describe('Wallet', function() {
|
||||
|
||||
assert(send.verify(null, true, flags));
|
||||
|
||||
assert.equal(w1.changeDepth, 1);
|
||||
var change = w1.changeAddress.getAddress();
|
||||
assert.equal(w1.changeAddress.getAddress(), change);
|
||||
assert.equal(w2.changeAddress.getAddress(), change);
|
||||
assert.equal(w3.changeAddress.getAddress(), change);
|
||||
assert.equal(a.w1.changeDepth, 1);
|
||||
var change = a.w1.changeAddress.getAddress();
|
||||
assert.equal(a.w1.changeAddress.getAddress(), change);
|
||||
assert.equal(a.w2.changeAddress.getAddress(), change);
|
||||
assert.equal(a.w3.changeAddress.getAddress(), change);
|
||||
|
||||
// Simulate a confirmation
|
||||
send.ps = 0;
|
||||
@ -682,32 +725,35 @@ describe('Wallet', function() {
|
||||
assert.ifError(err);
|
||||
wdb.addTX(send, function(err) {
|
||||
assert.ifError(err);
|
||||
getInfo(function(err, a) {
|
||||
assert.ifError(err);
|
||||
|
||||
assert.equal(w1.receiveDepth, 2);
|
||||
assert.equal(w1.changeDepth, 2);
|
||||
assert.equal(a.w1.receiveDepth, 2);
|
||||
assert.equal(a.w1.changeDepth, 2);
|
||||
|
||||
assert(w1.getAddress() === addr);
|
||||
assert(w1.changeAddress.getAddress() !== change);
|
||||
change = w1.changeAddress.getAddress();
|
||||
assert.equal(w1.changeAddress.getAddress(), change);
|
||||
assert.equal(w2.changeAddress.getAddress(), change);
|
||||
assert.equal(w3.changeAddress.getAddress(), change);
|
||||
assert(a.w1.getAddress() === addr);
|
||||
assert(a.w1.changeAddress.getAddress() !== change);
|
||||
change = a.w1.changeAddress.getAddress();
|
||||
assert.equal(a.w1.changeAddress.getAddress(), change);
|
||||
assert.equal(a.w2.changeAddress.getAddress(), change);
|
||||
assert.equal(a.w3.changeAddress.getAddress(), change);
|
||||
|
||||
if (witness)
|
||||
send.inputs[0].witness.items[2] = new Buffer([]);
|
||||
else
|
||||
send.inputs[0].script.code[2] = 0;
|
||||
if (witness)
|
||||
send.inputs[0].witness.items[2] = new Buffer([]);
|
||||
else
|
||||
send.inputs[0].script.code[2] = 0;
|
||||
|
||||
assert(!send.verify(null, true, flags));
|
||||
assert.equal(send.getFee(), 10000);
|
||||
assert(!send.verify(null, true, flags));
|
||||
assert.equal(send.getFee(), 10000);
|
||||
|
||||
w3 = bcoin.wallet.fromJSON(w3.toJSON());
|
||||
assert.equal(w3.receiveDepth, 2);
|
||||
assert.equal(w3.changeDepth, 2);
|
||||
//assert.equal(w3.getAddress(), addr);
|
||||
//assert.equal(w3.changeAddress.getAddress(), change);
|
||||
// w3 = bcoin.wallet.fromJSON(w3.toJSON());
|
||||
// assert.equal(a.w3.receiveDepth, 2);
|
||||
// assert.equal(a.w3.changeDepth, 2);
|
||||
//assert.equal(a.w3.getAddress(), addr);
|
||||
//assert.equal(a.w3.changeAddress.getAddress(), change);
|
||||
|
||||
cb();
|
||||
cb();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -715,8 +761,11 @@ describe('Wallet', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user