hd and wallet work.
This commit is contained in:
parent
517a5d488b
commit
fa22c79dbe
@ -39,6 +39,9 @@ bcoin.protocol.network.set(process.env.BCOIN_NETWORK || 'main');
|
||||
|
||||
bcoin.bn = bn;
|
||||
bcoin.elliptic = elliptic;
|
||||
bcoin.signature = require('elliptic/lib/elliptic/ec/signature');
|
||||
bcoin.utils.assert(!bcoin.ecdsa.signature);
|
||||
bcoin.ecdsa.signature = require('elliptic/lib/elliptic/ec/signature');
|
||||
bcoin.utils.assert(!bcoin.ecdsa.keypair);
|
||||
bcoin.ecdsa.keypair = require('elliptic/lib/elliptic/ec/key');
|
||||
bcoin.hash = hash;
|
||||
bcoin.async = async;
|
||||
|
||||
@ -34,15 +34,9 @@ function Address(options) {
|
||||
this.storage = options.storage;
|
||||
this.label = options.label || '';
|
||||
this.change = !!options.change;
|
||||
this.derived = !!options.derived;
|
||||
|
||||
this.key = bcoin.keypair({
|
||||
priv: options.priv,
|
||||
pub: options.pub,
|
||||
key: options.key,
|
||||
personalization: options.personalization,
|
||||
entropy: options.entropy,
|
||||
compressed: options.compressed
|
||||
});
|
||||
this.key = bcoin.keypair(options);
|
||||
|
||||
this.type = options.type || 'pubkeyhash';
|
||||
this.subtype = options.subtype;
|
||||
|
||||
211
lib/bcoin/hd.js
211
lib/bcoin/hd.js
@ -538,7 +538,7 @@ HDPrivateKey.prototype._normalize = function _normalize(data, version) {
|
||||
};
|
||||
|
||||
HDPrivateKey.prototype._seed = function _seed(seed) {
|
||||
if (seed instanceof bcoin.hd.seed)
|
||||
if (seed instanceof HDSeed)
|
||||
seed = seed.seed;
|
||||
|
||||
if (utils.isHex(seed))
|
||||
@ -592,27 +592,20 @@ HDPrivateKey.prototype._unbuild = function _unbuild(xkey) {
|
||||
};
|
||||
|
||||
HDPrivateKey.prototype._build = function _build(data) {
|
||||
var sequence = [];
|
||||
var sequence = new Array(82);
|
||||
var off = 0;
|
||||
var checksum, xprivkey, pair, privateKey, publicKey, size, fingerPrint;
|
||||
|
||||
utils.copy(data.version, sequence, off, true);
|
||||
off += data.version.length;
|
||||
utils.copy(data.depth, sequence, off, true);
|
||||
off += data.depth.length;
|
||||
utils.copy(data.parentFingerPrint, sequence, off, true);
|
||||
off += data.parentFingerPrint.length;
|
||||
utils.copy(data.childIndex, sequence, off, true);
|
||||
off += data.childIndex.length;
|
||||
utils.copy(data.chainCode, sequence, off, true);
|
||||
off += data.chainCode.length;
|
||||
utils.copy([0], sequence, off, true);
|
||||
off += [0].length;
|
||||
utils.copy(data.privateKey, sequence, off, true);
|
||||
off += data.privateKey.length;
|
||||
checksum = utils.dsha256(sequence).slice(0, 4);
|
||||
utils.copy(checksum, sequence, off, true);
|
||||
off += checksum.length;
|
||||
off += utils.copy(data.version, sequence, off);
|
||||
off += utils.copy(data.depth, sequence, off);
|
||||
off += utils.copy(data.parentFingerPrint, sequence, off);
|
||||
off += utils.copy(data.childIndex, sequence, off);
|
||||
off += utils.copy(data.chainCode, sequence, off);
|
||||
off += utils.copy([0], sequence, off);
|
||||
off += utils.copy(data.privateKey, sequence, off);
|
||||
checksum = utils.dsha256(sequence.slice(0, off)).slice(0, 4);
|
||||
off += utils.copy(checksum, sequence, off);
|
||||
assert(off === 82);
|
||||
|
||||
xprivkey = utils.toBase58(sequence);
|
||||
|
||||
@ -635,7 +628,18 @@ HDPrivateKey.prototype._build = function _build(data) {
|
||||
this.fingerPrint = fingerPrint;
|
||||
this.publicKey = publicKey;
|
||||
|
||||
this.hdpub = bcoin.hd.pub(this);
|
||||
this.hdpub = new HDPublicKey({
|
||||
version: this.version,
|
||||
depth: this.depth,
|
||||
parentFingerPrint: this.parentFingerPrint,
|
||||
childIndex: this.childIndex,
|
||||
chainCode: this.chainCode,
|
||||
privateKey: this.privateKey,
|
||||
checksum: this.checksum,
|
||||
publicKey: this.publicKey,
|
||||
master: this.master
|
||||
});
|
||||
|
||||
this.xpubkey = this.hdpub.xpubkey;
|
||||
this.pair = bcoin.ecdsa.keyPair({ priv: this.privateKey });
|
||||
};
|
||||
@ -697,18 +701,6 @@ HDPrivateKey._getIndexes = function _getIndexes(path) {
|
||||
|
||||
index = +step;
|
||||
|
||||
if (i === 0) {
|
||||
indexes.purpose = index;
|
||||
} else if (i === 1) {
|
||||
indexes.coinType = index;
|
||||
} else if (i === 2) {
|
||||
indexes.accountIndex = index;
|
||||
} else if (i === 3) {
|
||||
indexes.isChange = index === 1;
|
||||
} else if (i === 4) {
|
||||
indexes.addressIndex = index;
|
||||
}
|
||||
|
||||
if (hardened)
|
||||
index += constants.hd.hardened;
|
||||
|
||||
@ -743,130 +735,76 @@ HDPrivateKey.prototype.deriveString = function deriveString(path) {
|
||||
|
||||
indexes = HDPrivateKey._getIndexes(path);
|
||||
|
||||
child = indexes.reduce(function(prev, index, i) {
|
||||
return indexes.reduce(function(prev, index, i) {
|
||||
return prev.derive(index);
|
||||
}, this);
|
||||
|
||||
child.purpose = indexes.purpose;
|
||||
child.coinType = indexes.coinType;
|
||||
child.accountIndex = indexes.accountIndex;
|
||||
child.isChange = indexes.isChange;
|
||||
child.addressIndex = indexes.addressIndex;
|
||||
|
||||
return child;
|
||||
};
|
||||
|
||||
HDPrivateKey.prototype.toJSON = function toJSON(encrypt) {
|
||||
var json = {
|
||||
v: 1,
|
||||
name: 'keypair',
|
||||
name: 'hdkey',
|
||||
encrypted: encrypt ? true : false
|
||||
};
|
||||
|
||||
if (this.hd) {
|
||||
if (this.hd.xprivkey) {
|
||||
if (this.hd.seed) {
|
||||
json.mnemonic = encrypt
|
||||
? encrypt(this.hd.seed.mnemonic)
|
||||
: this.hd.seed.mnemonic;
|
||||
json.passphrase = encrypt
|
||||
? encrypt(this.hd.seed.passphrase)
|
||||
: this.hd.seed.passphrase;
|
||||
return json;
|
||||
}
|
||||
json.xpriv = encrypt
|
||||
? encrypt(this.hd.xprivkey)
|
||||
: this.hd.xprivkey;
|
||||
if (this instanceof HDPrivateKey) {
|
||||
if (this.seed) {
|
||||
json.mnemonic = encrypt
|
||||
? encrypt(this.seed.mnemonic)
|
||||
: this.seed.mnemonic;
|
||||
json.passphrase = encrypt
|
||||
? encrypt(this.seed.passphrase)
|
||||
: this.seed.passphrase;
|
||||
return json;
|
||||
}
|
||||
|
||||
json.xpub = this.hd.xpubkey;
|
||||
|
||||
json.xprivkey = encrypt
|
||||
? encrypt(this.xprivkey)
|
||||
: this.xprivkey;
|
||||
return json;
|
||||
}
|
||||
|
||||
if (this._key.priv) {
|
||||
json.priv = encrypt
|
||||
? encrypt(this.getPrivate('base58'))
|
||||
: this.getPrivate('base58');
|
||||
return json;
|
||||
}
|
||||
json.xpubkey = this.hd.xpubkey;
|
||||
|
||||
json.pub = this.getPublic('hex');
|
||||
return json;
|
||||
};
|
||||
|
||||
HDPrivateKey.fromJSON = function fromJSON(json, decrypt) {
|
||||
var key, priv, pub, compressed, xprivkey;
|
||||
var path = {};
|
||||
|
||||
assert.equal(json.v, 1);
|
||||
assert.equal(json.name, 'keypair');
|
||||
assert.equal(json.name, 'hdkey');
|
||||
|
||||
if (json.encrypted && !decrypt)
|
||||
throw new Error('Cannot decrypt address');
|
||||
|
||||
if (json.mnemonic) {
|
||||
return new KeyPair({
|
||||
key: bcoin.hd.priv({
|
||||
seed: bcoin.hd.seed({
|
||||
mnemonic: json.encrypted
|
||||
? decrypt(json.mnemonic)
|
||||
: json.mnemonic,
|
||||
passphrase: json.encrypted
|
||||
? decrypt(json.passphrase)
|
||||
: json.passphrase
|
||||
})
|
||||
return new HDPrivateKey({
|
||||
seed: new HDSeed({
|
||||
mnemonic: json.encrypted
|
||||
? decrypt(json.mnemonic)
|
||||
: json.mnemonic,
|
||||
passphrase: json.encrypted
|
||||
? decrypt(json.passphrase)
|
||||
: json.passphrase
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
if (json.xpriv) {
|
||||
xprivkey = json.xpriv;
|
||||
if (json.encrypted)
|
||||
xprivkey = decrypt(xprivkey);
|
||||
return new KeyPair({
|
||||
key: bcoin.hd.priv({
|
||||
xkey: xprivkey
|
||||
})
|
||||
if (json.xprivkey) {
|
||||
return new HDPrivateKey({
|
||||
xkey: json.encrypted
|
||||
? decrypt(json.xprivkey)
|
||||
: json.xprivkey
|
||||
});
|
||||
}
|
||||
|
||||
if (json.xpub) {
|
||||
return new KeyPair({
|
||||
key: bcoin.hd.pub({
|
||||
xkey: json.xpub
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
if (json.priv) {
|
||||
priv = json.priv;
|
||||
if (json.encrypted)
|
||||
priv = decrypt(priv);
|
||||
|
||||
key = KeyPair.fromSecret(json.priv);
|
||||
priv = key.priv;
|
||||
compressed = key.compressed;
|
||||
return new KeyPair({
|
||||
priv: priv,
|
||||
compressed: compressed
|
||||
});
|
||||
}
|
||||
|
||||
if (json.pub) {
|
||||
pub = bcoin.utils.toArray(json.pub, 'hex');
|
||||
compressed = pub[0] !== 0x04;
|
||||
return new KeyPair({
|
||||
pub: pub,
|
||||
compressed: compressed
|
||||
if (json.xpubkey) {
|
||||
return new HDPublicKey({
|
||||
xkey: json.xpubkey
|
||||
});
|
||||
}
|
||||
|
||||
assert(false);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* HD Public Key
|
||||
*/
|
||||
@ -917,6 +855,8 @@ HDPublicKey.prototype.deriveCosignerAddress = HDPrivateKey.prototype.deriveCosig
|
||||
|
||||
HDPublicKey.prototype.isPurpose45 = HDPrivateKey.prototype.isPurpose45;
|
||||
HDPublicKey.prototype.isAccount44 = HDPrivateKey.prototype.isAccount44;
|
||||
HDPublicKey.prototype.toJSON = HDPrivateKey.prototype.toJSON;
|
||||
HDPublicKey.fromJSON = HDPrivateKey.fromJSON;
|
||||
|
||||
HDPublicKey.isExtended = function isExtended(data) {
|
||||
if (typeof data !== 'string')
|
||||
@ -956,25 +896,19 @@ HDPublicKey.prototype._unbuild = function _unbuild(xkey) {
|
||||
};
|
||||
|
||||
HDPublicKey.prototype._build = function _build(data) {
|
||||
var sequence = [];
|
||||
var sequence = new Array(82);
|
||||
var off = 0;
|
||||
var checksum, xpubkey, publicKey, size, fingerPrint;
|
||||
|
||||
utils.copy(data.version, sequence, off, true);
|
||||
off += data.version.length;
|
||||
utils.copy(data.depth, sequence, off, true);
|
||||
off += data.depth.length;
|
||||
utils.copy(data.parentFingerPrint, sequence, off, true);
|
||||
off += data.parentFingerPrint.length;
|
||||
utils.copy(data.childIndex, sequence, off, true);
|
||||
off += data.childIndex.length;
|
||||
utils.copy(data.chainCode, sequence, off, true);
|
||||
off += data.chainCode.length;
|
||||
utils.copy(data.publicKey, sequence, off, true);
|
||||
off += data.publicKey.length;
|
||||
checksum = utils.dsha256(sequence).slice(0, 4);
|
||||
utils.copy(checksum, sequence, off, true);
|
||||
off += checksum.length;
|
||||
off += utils.copy(data.version, sequence, off);
|
||||
off += utils.copy(data.depth, sequence, off);
|
||||
off += utils.copy(data.parentFingerPrint, sequence, off);
|
||||
off += utils.copy(data.childIndex, sequence, off);
|
||||
off += utils.copy(data.chainCode, sequence, off);
|
||||
off += utils.copy(data.publicKey, sequence, off);
|
||||
checksum = utils.dsha256(sequence.slice(0, off)).slice(0, 4);
|
||||
off += utils.copy(checksum, sequence, off);
|
||||
assert(off === 82);
|
||||
|
||||
if (!data.checksum || !data.checksum.length)
|
||||
data.checksum = checksum;
|
||||
@ -1156,10 +1090,10 @@ function pbkdf2(key, salt, iterations, dkLen) {
|
||||
if (typeof salt === 'string')
|
||||
salt = utils.toArray(salt, null);
|
||||
|
||||
var DK = new Array(dkLen);
|
||||
var U = new Array(hLen);
|
||||
var T = new Array(hLen);
|
||||
var block1 = new Array(salt.length + 4);
|
||||
var DK = new Buffer(dkLen);
|
||||
var U = new Buffer(hLen);
|
||||
var T = new Buffer(hLen);
|
||||
var block1 = new Buffer(salt.length + 4);
|
||||
|
||||
var l = Math.ceil(dkLen / hLen);
|
||||
var r = dkLen - (l - 1) * hLen;
|
||||
@ -1200,4 +1134,7 @@ function pbkdf2(key, salt, iterations, dkLen) {
|
||||
hd.seed = HDSeed;
|
||||
hd.priv = HDPrivateKey;
|
||||
hd.pub = HDPublicKey;
|
||||
hd.privateKey = HDPrivateKey;
|
||||
hd.publicKey = HDPublicKey;
|
||||
hd.pbkdf2 = pbkdf2;
|
||||
hd.fromJSON = HDPrivateKey.fromJSON;
|
||||
|
||||
@ -29,59 +29,59 @@ function KeyPair(options) {
|
||||
return options.key;
|
||||
|
||||
this.options = options;
|
||||
this._key = options.key || null;
|
||||
this.hd = options.hd || null;
|
||||
this.pair = null;
|
||||
this.compressed = options.compressed !== false;
|
||||
|
||||
if (options.privateKey)
|
||||
options.priv = options.privateKey;
|
||||
if (options.key)
|
||||
options.pair = options.key;
|
||||
|
||||
if (options.publicKey)
|
||||
options.pub = options.publicKey;
|
||||
if (options.priv)
|
||||
options.privateKey = options.priv;
|
||||
|
||||
if (options.priv instanceof bcoin.hd.priv) {
|
||||
this.hd = options.priv;
|
||||
this._key = options.priv.pair;
|
||||
} else if (options.pub instanceof bcoin.hd.pub) {
|
||||
this.hd = options.pub;
|
||||
this._key = options.pub.pair;
|
||||
} else if (options.hd) {
|
||||
this.hd = typeof options.hd === 'object'
|
||||
? bcoin.hd.priv(options.hd)
|
||||
: bcoin.hd.priv();
|
||||
this._key = this.hd.pair;
|
||||
} else if (options.key) {
|
||||
if ((options.key instanceof bcoin.hd.priv)
|
||||
|| (options.key instanceof bcoin.hd.pub)) {
|
||||
this.hd = options.key;
|
||||
this._key = options.key.pair;
|
||||
} else {
|
||||
this._key = options.key;
|
||||
}
|
||||
} else if (options.priv || options.pub) {
|
||||
this._key = bcoin.ecdsa.keyPair({
|
||||
priv: options.priv,
|
||||
pub: options.pub
|
||||
if (options.pub)
|
||||
options.publicKey = options.pub;
|
||||
|
||||
if (options.passphrase)
|
||||
options.entropy = utils.sha256(options.passphrase);
|
||||
|
||||
if (options.privateKey instanceof bcoin.hd.privateKey) {
|
||||
this.pair = options.privateKey.pair;
|
||||
} else if (options.publicKey instanceof bcoin.hd.publicKey) {
|
||||
this.pair = options.publicKey.pair;
|
||||
} else if (options.pair) {
|
||||
assert(options.pair instanceof bcoin.ecdsa.keypair);
|
||||
this.pair = options.pair;
|
||||
} else if (options.privateKey || options.publicKey) {
|
||||
this.pair = bcoin.ecdsa.keyPair({
|
||||
priv: options.privateKey,
|
||||
pub: options.publicKey
|
||||
});
|
||||
} else {
|
||||
this._key = bcoin.ecdsa.genKeyPair({
|
||||
this.pair = bcoin.ecdsa.genKeyPair({
|
||||
pers: options.personalization,
|
||||
entropy: options.entropy
|
||||
|| (options.passphrase ? utils.sha256(options.passphrase) : null)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
KeyPair.prototype.__defineGetter__('priv', function() {
|
||||
return this._key.getPrivate();
|
||||
return this.pair.getPrivate();
|
||||
});
|
||||
|
||||
KeyPair.prototype.__defineGetter__('pub', function() {
|
||||
return this._key.getPublic();
|
||||
return this.pair.getPublic();
|
||||
});
|
||||
|
||||
KeyPair.prototype.__defineGetter__('privateKey', function() {
|
||||
return this.pair.getPrivate();
|
||||
});
|
||||
|
||||
KeyPair.prototype.__defineGetter__('publicKey', function() {
|
||||
return this.pair.getPublic();
|
||||
});
|
||||
|
||||
KeyPair.prototype.getPrivate = function getPrivate(enc) {
|
||||
var priv = this._key.getPrivate();
|
||||
var priv = this.pair.getPrivate();
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
@ -98,7 +98,7 @@ KeyPair.prototype.getPrivate = function getPrivate(enc) {
|
||||
};
|
||||
|
||||
KeyPair.prototype.getPublic = function getPublic(enc) {
|
||||
var pub = this._key.getPublic(this.compressed, 'array');
|
||||
var pub = this.pair.getPublic(this.compressed, 'array');
|
||||
|
||||
if (enc === 'base58')
|
||||
return utils.toBase58(pub);
|
||||
@ -125,7 +125,7 @@ KeyPair.toSecret = function toSecret(priv, compressed) {
|
||||
|
||||
arr = arr.concat(priv);
|
||||
|
||||
if (compressed)
|
||||
if (compressed !== false)
|
||||
arr.push(1);
|
||||
|
||||
chk = utils.checksum(arr);
|
||||
@ -151,7 +151,7 @@ KeyPair.fromSecret = function fromSecret(priv) {
|
||||
}
|
||||
|
||||
return new KeyPair({
|
||||
priv: priv,
|
||||
privateKey: priv,
|
||||
compressed: compressed
|
||||
});
|
||||
};
|
||||
@ -163,29 +163,7 @@ KeyPair.prototype.toJSON = function toJSON(encrypt) {
|
||||
encrypted: encrypt ? true : false
|
||||
};
|
||||
|
||||
if (this.hd) {
|
||||
if (this.hd.xprivkey) {
|
||||
if (this.hd.seed) {
|
||||
json.mnemonic = encrypt
|
||||
? encrypt(this.hd.seed.mnemonic)
|
||||
: this.hd.seed.mnemonic;
|
||||
json.passphrase = encrypt
|
||||
? encrypt(this.hd.seed.passphrase)
|
||||
: this.hd.seed.passphrase;
|
||||
return json;
|
||||
}
|
||||
json.xpriv = encrypt
|
||||
? encrypt(this.hd.xprivkey)
|
||||
: this.hd.xprivkey;
|
||||
return json;
|
||||
}
|
||||
|
||||
json.xpub = this.hd.xpubkey;
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
if (this._key.priv) {
|
||||
if (this.pair.priv) {
|
||||
json.priv = encrypt
|
||||
? encrypt(this.getPrivate('base58'))
|
||||
: this.getPrivate('base58');
|
||||
@ -206,40 +184,6 @@ KeyPair.fromJSON = function fromJSON(json, decrypt) {
|
||||
if (json.encrypted && !decrypt)
|
||||
throw new Error('Cannot decrypt address');
|
||||
|
||||
if (json.mnemonic) {
|
||||
return new KeyPair({
|
||||
key: bcoin.hd.priv({
|
||||
seed: bcoin.hd.seed({
|
||||
mnemonic: json.encrypted
|
||||
? decrypt(json.mnemonic)
|
||||
: json.mnemonic,
|
||||
passphrase: json.encrypted
|
||||
? decrypt(json.passphrase)
|
||||
: json.passphrase
|
||||
})
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
if (json.xpriv) {
|
||||
xprivkey = json.xpriv;
|
||||
if (json.encrypted)
|
||||
xprivkey = decrypt(xprivkey);
|
||||
return new KeyPair({
|
||||
key: bcoin.hd.priv({
|
||||
xkey: xprivkey
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
if (json.xpub) {
|
||||
return new KeyPair({
|
||||
key: bcoin.hd.pub({
|
||||
xkey: json.xpub
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
if (json.priv) {
|
||||
priv = json.priv;
|
||||
if (json.encrypted)
|
||||
@ -249,7 +193,7 @@ KeyPair.fromJSON = function fromJSON(json, decrypt) {
|
||||
priv = key.priv;
|
||||
compressed = key.compressed;
|
||||
return new KeyPair({
|
||||
priv: priv,
|
||||
privateKey: priv,
|
||||
compressed: compressed
|
||||
});
|
||||
}
|
||||
@ -258,7 +202,7 @@ KeyPair.fromJSON = function fromJSON(json, decrypt) {
|
||||
pub = bcoin.utils.toArray(json.pub, 'hex');
|
||||
compressed = pub[0] !== 0x04;
|
||||
return new KeyPair({
|
||||
pub: pub,
|
||||
publicKey: pub,
|
||||
compressed: compressed
|
||||
});
|
||||
}
|
||||
|
||||
@ -2061,7 +2061,7 @@ script.isLowDER = function isLowDER(sig) {
|
||||
return false;
|
||||
|
||||
try {
|
||||
sig = new bcoin.signature(sig.slice(0, -1));
|
||||
sig = new bcoin.ecdsa.signature(sig.slice(0, -1));
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -307,6 +307,23 @@ TXPool.prototype.fromJSON = function fromJSON(json) {
|
||||
}, this);
|
||||
};
|
||||
|
||||
TXPool.fromJSON = function fromJSON(wallet, json) {
|
||||
var txPool;
|
||||
|
||||
assert.equal(json.v, 1);
|
||||
assert.equal(json.type, 'tx-pool');
|
||||
|
||||
txPool = new TXPool(wallet);
|
||||
|
||||
utils.nextTick(function() {
|
||||
json.txs.forEach(function(tx) {
|
||||
txPool.add(bcoin.tx.fromJSON(tx));
|
||||
});
|
||||
});
|
||||
|
||||
return tx;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
@ -240,7 +240,7 @@ utils.array2utf8 = function array2utf8(arr) {
|
||||
|
||||
utils.copy = function copy(src, dst, off, force) {
|
||||
if (Buffer.isBuffer(src) && Buffer.isBuffer(dst)) {
|
||||
assert(!force);
|
||||
utils.assert(!force);
|
||||
return src.copy(dst, off, 0, src.length);
|
||||
}
|
||||
|
||||
|
||||
@ -38,32 +38,38 @@ function Wallet(options) {
|
||||
delete options.hd;
|
||||
}
|
||||
|
||||
if (options.priv
|
||||
|| options.pub
|
||||
|| options.key
|
||||
if (options.key)
|
||||
options.pair = options.key;
|
||||
|
||||
if (options.priv)
|
||||
options.privateKey = options.priv;
|
||||
|
||||
if (options.pub)
|
||||
options.publicKey = options.pub;
|
||||
|
||||
if (options.privateKey
|
||||
|| options.publicKey
|
||||
|| options.pair
|
||||
|| options.personalization
|
||||
|| options.entropy
|
||||
|| options.passphrase
|
||||
|| options.compressed) {
|
||||
if ((options.key instanceof bcoin.hd.priv)
|
||||
|| options.key instanceof bcoin.hd.pub) {
|
||||
options.master = options.key;
|
||||
delete options.key;
|
||||
} else if (options.priv instanceof bcoin.hd.priv) {
|
||||
options.master = options.priv;
|
||||
delete options.priv;
|
||||
} else if (options.pub instanceof bcoin.hd.pub) {
|
||||
options.master = options.pub;
|
||||
delete options.pub;
|
||||
if ((options.pair instanceof bcoin.hd.privateKey)
|
||||
|| options.pair instanceof bcoin.hd.publicKey) {
|
||||
options.master = options.pair;
|
||||
delete options.pair;
|
||||
} else if (options.privateKey instanceof bcoin.hd.privateKey) {
|
||||
options.master = options.privateKey;
|
||||
delete options.privateKey;
|
||||
} else if (options.publicKey instanceof bcoin.hd.publicKey) {
|
||||
options.master = options.publicKey;
|
||||
delete options.publicKey;
|
||||
}
|
||||
}
|
||||
|
||||
this.options = options;
|
||||
this.addresses = [];
|
||||
this.master = options.master || null;
|
||||
|
||||
if (this.master && !(this.master instanceof bcoin.keypair))
|
||||
this.master = bcoin.keypair({ hd: this.master });
|
||||
|
||||
this._addressTable = {};
|
||||
this._labelMap = {};
|
||||
|
||||
@ -119,28 +125,29 @@ function Wallet(options) {
|
||||
throw new Error('n ranges between 1 and ' + this.nmax);
|
||||
|
||||
if (this.bip45) {
|
||||
this.purposeKey = this.master.hd.isPurpose45()
|
||||
? this.master.hd
|
||||
: this.master.hd.derivePurpose45();
|
||||
} else if (this.hd) {
|
||||
this.accountKey = this.master.hd.isAccount44()
|
||||
? this.master.hd
|
||||
: this.master.hd.deriveAccount44(this.accountIndex);
|
||||
this.purposeKey = this.master.isPurpose45()
|
||||
? this.master
|
||||
: this.master.derivePurpose45();
|
||||
} else if (this.bip44) {
|
||||
this.accountKey = this.master.isAccount44()
|
||||
? this.master
|
||||
: this.master.deriveAccount44(this.accountIndex);
|
||||
}
|
||||
|
||||
if (!options.addresses)
|
||||
options.addresses = [];
|
||||
|
||||
if (options.priv
|
||||
|| options.pub
|
||||
|| options.key
|
||||
if (options.privateKey
|
||||
|| options.publicKey
|
||||
|| options.pair
|
||||
|| options.personalization
|
||||
|| options.entropy
|
||||
|| options.passphrase
|
||||
|| options.compressed) {
|
||||
options.addresses.push({
|
||||
priv: options.priv,
|
||||
pub: options.pub,
|
||||
key: options.key,
|
||||
privateKey: options.privateKey,
|
||||
publicKey: options.publicKey,
|
||||
pair: options.pair,
|
||||
personalization: options.personalization,
|
||||
entropy: options.entropy,
|
||||
compressed: options.compressed,
|
||||
@ -168,10 +175,33 @@ function Wallet(options) {
|
||||
// generate the last receiving address. However, since "normal" wallets
|
||||
// cannot deterministically generate keys, we have to buffer the generated
|
||||
// key for later.
|
||||
if (!this.bip45) {
|
||||
if (this.hd) {
|
||||
// Generate the last known receiving address
|
||||
key = this.createKey(false, Math.max(0, this.addressDepth - 1));
|
||||
if (this.bip44) {
|
||||
// Generate the last known receiving address
|
||||
key = this.createKey(false, Math.max(0, this.addressDepth - 1));
|
||||
this.current = bcoin.address({
|
||||
priv: key.priv,
|
||||
type: this.type,
|
||||
subtype: this.subtype,
|
||||
m: this.m,
|
||||
n: this.n,
|
||||
keys: options.keys,
|
||||
derived: true
|
||||
});
|
||||
} else if (this.normal) {
|
||||
// Try to find the last receiving address if there is one.
|
||||
receiving = options.addresses.filter(function(address) {
|
||||
return !address.change
|
||||
&& ((address.priv || address.privateKey)
|
||||
|| (address.pub || address.publicKey)
|
||||
|| (address.key || address.pair));
|
||||
}).pop();
|
||||
if (receiving) {
|
||||
this.current = bcoin.address(receiving);
|
||||
} else {
|
||||
// No receiving address is in this wallet yet, generate
|
||||
// it and save it so createKey can recreate it later.
|
||||
key = this.createKey();
|
||||
this._firstKey = key;
|
||||
this.current = bcoin.address({
|
||||
priv: key.priv,
|
||||
type: this.type,
|
||||
@ -180,27 +210,6 @@ function Wallet(options) {
|
||||
n: this.n,
|
||||
keys: options.keys
|
||||
});
|
||||
} else {
|
||||
// Try to find the last receiving address if there is one.
|
||||
receiving = options.addresses.filter(function(address) {
|
||||
return !address.change && (address.priv || address.pub || address.key);
|
||||
}).pop();
|
||||
if (receiving) {
|
||||
this.current = bcoin.address(receiving);
|
||||
} else {
|
||||
// No receiving address is in this wallet yet, generate
|
||||
// it and save it so createKey can recreate it later.
|
||||
key = this.createKey();
|
||||
this._firstKey = key;
|
||||
this.current = bcoin.address({
|
||||
priv: key.priv,
|
||||
type: this.type,
|
||||
subtype: this.subtype,
|
||||
m: this.m,
|
||||
n: this.n,
|
||||
keys: options.keys
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,13 +227,13 @@ inherits(Wallet, EventEmitter);
|
||||
|
||||
// Wallet ID:
|
||||
// bip45: Purpose key address
|
||||
// HD: Account key address
|
||||
// Normal: Address of first key in wallet
|
||||
// bip44: Account key address
|
||||
// normal: Address of first key in wallet
|
||||
Wallet.prototype.getID = function() {
|
||||
if (this.bip45)
|
||||
return bcoin.address.key2addr(this.purposeKey.publicKey);
|
||||
|
||||
if (this.hd)
|
||||
if (this.bip44)
|
||||
return bcoin.address.key2addr(this.accountKey.publicKey);
|
||||
|
||||
if (this.addresses.length)
|
||||
@ -274,7 +283,7 @@ Wallet.prototype._initAddresses = function() {
|
||||
|
||||
this.prefix = 'bt/wallet/' + this.getID() + '/';
|
||||
|
||||
this.tx = new bcoin.txPool(this);
|
||||
this.tx = options.tx || bcoin.txPool(this);
|
||||
|
||||
this._init();
|
||||
};
|
||||
@ -513,7 +522,8 @@ Wallet.prototype.createAddress = function createAddress(change, index) {
|
||||
m: this.m,
|
||||
n: this.n,
|
||||
keys: [],
|
||||
change: change
|
||||
change: change,
|
||||
derived: !!this.hd
|
||||
};
|
||||
|
||||
if (index == null) {
|
||||
@ -652,7 +662,7 @@ Wallet.prototype.getPublicKey = function getPublicKey(enc) {
|
||||
};
|
||||
|
||||
Wallet.prototype.createKey = function createKey(change, index) {
|
||||
var key, pub, priv;
|
||||
var key;
|
||||
|
||||
if (!this.hd) {
|
||||
if (this._firstKey) {
|
||||
@ -931,6 +941,12 @@ Wallet.prototype.toJSON = function toJSON(encrypt) {
|
||||
addressDepth: this.addressDepth,
|
||||
changeDepth: this.changeDepth,
|
||||
cosignerIndex: this.cosignerIndex,
|
||||
master: this.master ? this.master.toJSON(encrypt) : null,
|
||||
addresses: this.addresses.filter(function(address) {
|
||||
return !address.derived;
|
||||
}, this).map(function(address) {
|
||||
return address.toJSON(encrypt);
|
||||
}),
|
||||
keys: this.bip45
|
||||
? this.purposeKeys.map(function(key) {
|
||||
return key.xpubkey;
|
||||
@ -938,14 +954,6 @@ Wallet.prototype.toJSON = function toJSON(encrypt) {
|
||||
: this.keys.map(function(key) {
|
||||
return utils.toBase58(key);
|
||||
}),
|
||||
master: this.master ? this.master.toJSON(encrypt) : null,
|
||||
addresses: this.addresses.filter(function(address) {
|
||||
if (this.hd)
|
||||
return false;
|
||||
return true;
|
||||
}, this).map(function(address) {
|
||||
return address.toJSON(encrypt);
|
||||
}),
|
||||
balance: utils.toBTC(this.getBalance()),
|
||||
tx: this.tx.toJSON()
|
||||
};
|
||||
@ -970,12 +978,12 @@ Wallet.fromJSON = function fromJSON(json, decrypt) {
|
||||
changeDepth: json.changeDepth,
|
||||
cosignerIndex: json.cosignerIndex,
|
||||
master: json.master
|
||||
? bcoin.address.fromJSON(json.master, decrypt)
|
||||
? bcoin.hd.fromJSON(json.master, decrypt)
|
||||
: null,
|
||||
keys: json.keys,
|
||||
addresses: json.addresses.map(function(address) {
|
||||
return bcoin.address.fromJSON(address, decrypt);
|
||||
})
|
||||
}),
|
||||
keys: json.keys
|
||||
});
|
||||
|
||||
w.tx.fromJSON(json.tx);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user