diff --git a/lib/hd/hd.js b/lib/hd/hd.js index 68c95392..9b7ebc4a 100644 --- a/lib/hd/hd.js +++ b/lib/hd/hd.js @@ -37,35 +37,32 @@ HD.fromBase58 = function fromBase58(xkey, network) { * @param {Object} options * @param {Buffer?} options.privateKey * @param {Buffer?} options.entropy - * @param {String?} network * @returns {HDPrivateKey} */ -HD.generate = function generate(network) { - return HDPrivateKey.generate(network); +HD.generate = function generate() { + return HDPrivateKey.generate(); }; /** * Generate an {@link HDPrivateKey} from a seed. * @param {Object|Mnemonic|Buffer} options - seed, * mnemonic, mnemonic options. - * @param {String?} network * @returns {HDPrivateKey} */ -HD.fromSeed = function fromSeed(options, network) { - return HDPrivateKey.fromSeed(options, network); +HD.fromSeed = function fromSeed(options) { + return HDPrivateKey.fromSeed(options); }; /** * Instantiate an hd private key from a mnemonic. * @param {Mnemonic|Object} mnemonic - * @param {String?} network * @returns {HDPrivateKey} */ -HD.fromMnemonic = function fromMnemonic(options, network) { - return HDPrivateKey.fromMnemonic(options, network); +HD.fromMnemonic = function fromMnemonic(options) { + return HDPrivateKey.fromMnemonic(options); }; /** @@ -115,7 +112,7 @@ HD.from = function from(options, network) { return HD.fromRaw(options, network); if (options && typeof options === 'object') - return HD.fromMnemonic(options, network); + return HD.fromMnemonic(options); throw new Error('Cannot create HD key from bad options.'); }; diff --git a/lib/hd/private.js b/lib/hd/private.js index 1711b31f..a0e02df0 100644 --- a/lib/hd/private.js +++ b/lib/hd/private.js @@ -38,7 +38,6 @@ const SEED_SALT = Buffer.from('Bitcoin seed', 'ascii'); * @param {Number?} options.childIndex * @param {Buffer?} options.chainCode * @param {Buffer?} options.privateKey - * @property {Network} network * @property {Number} depth * @property {Number} parentFingerPrint * @property {Number} childIndex @@ -50,7 +49,6 @@ function HDPrivateKey(options) { if (!(this instanceof HDPrivateKey)) return new HDPrivateKey(options); - this.network = Network.primary; this.depth = 0; this.parentFingerPrint = 0; this.childIndex = 0; @@ -60,8 +58,6 @@ function HDPrivateKey(options) { this.publicKey = encoding.ZERO_KEY; this.fingerPrint = -1; - this._xprivkey = null; - this._hdPublicKey = null; if (options) @@ -82,9 +78,6 @@ HDPrivateKey.prototype.fromOptions = function fromOptions(options) { assert(Buffer.isBuffer(options.chainCode)); assert(Buffer.isBuffer(options.privateKey)); - if (options.network) - this.network = Network.get(options.network); - this.depth = options.depth; this.parentFingerPrint = options.parentFingerPrint; this.childIndex = options.childIndex; @@ -115,7 +108,6 @@ HDPrivateKey.prototype.toPublic = function toPublic() { if (!key) { key = new HDPublicKey(); - key.network = this.network; key.depth = this.depth; key.parentFingerPrint = this.parentFingerPrint; key.childIndex = this.childIndex; @@ -132,10 +124,8 @@ HDPrivateKey.prototype.toPublic = function toPublic() { * @returns {Base58String} */ -HDPrivateKey.prototype.xprivkey = function xprivkey() { - if (!this._xprivkey) - this._xprivkey = this.toBase58(); - return this._xprivkey; +HDPrivateKey.prototype.xprivkey = function xprivkey(network) { + return this.toBase58(network); }; /** @@ -143,8 +133,8 @@ HDPrivateKey.prototype.xprivkey = function xprivkey() { * @returns {Base58String} */ -HDPrivateKey.prototype.xpubkey = function xpubkey() { - return this.toPublic().xpubkey(); +HDPrivateKey.prototype.xpubkey = function xpubkey(network) { + return this.toPublic().xpubkey(network); }; /** @@ -168,8 +158,6 @@ HDPrivateKey.prototype.destroy = function destroy(pub) { this._hdPublicKey.destroy(); this._hdPublicKey = null; } - - this._xprivkey = null; }; /** @@ -229,7 +217,6 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) { } const child = new HDPrivateKey(); - child.network = this.network; child.depth = this.depth + 1; child.parentFingerPrint = this.fingerPrint; child.childIndex = index; @@ -250,26 +237,26 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) { */ HDPrivateKey.prototype.getID = function getID(index) { - return this.network.keyPrefix.xprivkey58 - + this.publicKey.toString('hex') - + index; + return 'v' + this.publicKey.toString('hex') + index; }; /** * Derive a BIP44 account key. * @param {Number} purpose + * @param {Number} type * @param {Number} account * @returns {HDPrivateKey} * @throws Error if key is not a master key. */ -HDPrivateKey.prototype.deriveAccount = function deriveAccount(purpose, account) { +HDPrivateKey.prototype.deriveAccount = function deriveAccount(purpose, type, account) { assert(util.isU32(purpose), 'Purpose must be a number.'); + assert(util.isU32(type), 'Account index must be a number.'); assert(util.isU32(account), 'Account index must be a number.'); assert(this.isMaster(), 'Cannot derive account index.'); return this .derive(purpose, true) - .derive(this.network.keyPrefix.coinType, true) + .derive(type, true) .derive(account, true); }; @@ -382,8 +369,7 @@ HDPrivateKey.prototype.derivePath = function derivePath(path) { HDPrivateKey.prototype.equals = function equals(obj) { assert(HDPrivateKey.isHDPrivateKey(obj)); - return this.network === obj.network - && this.depth === obj.depth + return this.depth === obj.depth && this.parentFingerPrint === obj.parentFingerPrint && this.childIndex === obj.childIndex && this.chainCode.equals(obj.chainCode) @@ -431,10 +417,9 @@ HDPrivateKey.prototype.compare = function compare(key) { * Inject properties from seed. * @private * @param {Buffer} seed - * @param {(Network|NetworkType)?} network */ -HDPrivateKey.prototype.fromSeed = function fromSeed(seed, network) { +HDPrivateKey.prototype.fromSeed = function fromSeed(seed) { assert(Buffer.isBuffer(seed)); if (seed.length * 8 < common.MIN_ENTROPY @@ -450,7 +435,6 @@ HDPrivateKey.prototype.fromSeed = function fromSeed(seed, network) { if (!secp256k1.privateKeyVerify(left)) throw new Error('Master private key is invalid.'); - this.network = Network.get(network); this.depth = 0; this.parentFingerPrint = 0; this.childIndex = 0; @@ -464,59 +448,54 @@ HDPrivateKey.prototype.fromSeed = function fromSeed(seed, network) { /** * Instantiate an hd private key from a 512 bit seed. * @param {Buffer} seed - * @param {(Network|NetworkType)?} network * @returns {HDPrivateKey} */ -HDPrivateKey.fromSeed = function fromSeed(seed, network) { - return new HDPrivateKey().fromSeed(seed, network); +HDPrivateKey.fromSeed = function fromSeed(seed) { + return new HDPrivateKey().fromSeed(seed); }; /** * Inject properties from a mnemonic. * @private * @param {Mnemonic} mnemonic - * @param {(Network|NetworkType)?} network */ -HDPrivateKey.prototype.fromMnemonic = function fromMnemonic(mnemonic, network) { +HDPrivateKey.prototype.fromMnemonic = function fromMnemonic(mnemonic) { assert(mnemonic instanceof Mnemonic); - return this.fromSeed(mnemonic.toSeed(), network); + return this.fromSeed(mnemonic.toSeed()); }; /** * Instantiate an hd private key from a mnemonic. * @param {Mnemonic} mnemonic - * @param {(Network|NetworkType)?} network * @returns {HDPrivateKey} */ -HDPrivateKey.fromMnemonic = function fromMnemonic(mnemonic, network) { - return new HDPrivateKey().fromMnemonic(mnemonic, network); +HDPrivateKey.fromMnemonic = function fromMnemonic(mnemonic) { + return new HDPrivateKey().fromMnemonic(mnemonic); }; /** * Inject properties from a mnemonic. * @private * @param {String} mnemonic - * @param {(Network|NetworkType)?} network */ -HDPrivateKey.prototype.fromPhrase = function fromPhrase(phrase, network) { +HDPrivateKey.prototype.fromPhrase = function fromPhrase(phrase) { const mnemonic = Mnemonic.fromPhrase(phrase); - this.fromMnemonic(mnemonic, network); + this.fromMnemonic(mnemonic); return this; }; /** * Instantiate an hd private key from a phrase. * @param {String} phrase - * @param {(Network|NetworkType)?} network * @returns {HDPrivateKey} */ -HDPrivateKey.fromPhrase = function fromPhrase(phrase, network) { - return new HDPrivateKey().fromPhrase(phrase, network); +HDPrivateKey.fromPhrase = function fromPhrase(phrase) { + return new HDPrivateKey().fromPhrase(phrase); }; /** @@ -524,13 +503,11 @@ HDPrivateKey.fromPhrase = function fromPhrase(phrase, network) { * @private * @param {Buffer} key * @param {Buffer} entropy - * @param {(Network|NetworkType)?} network */ -HDPrivateKey.prototype.fromKey = function fromKey(key, entropy, network) { +HDPrivateKey.prototype.fromKey = function fromKey(key, entropy) { assert(Buffer.isBuffer(key) && key.length === 32); assert(Buffer.isBuffer(entropy) && entropy.length === 32); - this.network = Network.get(network); this.depth = 0; this.parentFingerPrint = 0; this.childIndex = 0; @@ -544,24 +521,22 @@ HDPrivateKey.prototype.fromKey = function fromKey(key, entropy, network) { * Create an hd private key from a key and entropy bytes. * @param {Buffer} key * @param {Buffer} entropy - * @param {(Network|NetworkType)?} network * @returns {HDPrivateKey} */ -HDPrivateKey.fromKey = function fromKey(key, entropy, network) { - return new HDPrivateKey().fromKey(key, entropy, network); +HDPrivateKey.fromKey = function fromKey(key, entropy) { + return new HDPrivateKey().fromKey(key, entropy); }; /** * Generate an hd private key. - * @param {(Network|NetworkType)?} network * @returns {HDPrivateKey} */ -HDPrivateKey.generate = function generate(network) { +HDPrivateKey.generate = function generate() { const key = secp256k1.generatePrivateKey(); const entropy = random.randomBytes(32); - return HDPrivateKey.fromKey(key, entropy, network); + return HDPrivateKey.fromKey(key, entropy); }; /** @@ -573,7 +548,6 @@ HDPrivateKey.generate = function generate(network) { HDPrivateKey.prototype.fromBase58 = function fromBase58(xkey, network) { assert(typeof xkey === 'string'); - this._xprivkey = xkey; return this.fromRaw(base58.decode(xkey), network); }; @@ -587,7 +561,8 @@ HDPrivateKey.prototype.fromBase58 = function fromBase58(xkey, network) { HDPrivateKey.prototype.fromReader = function fromReader(br, network) { const version = br.readU32BE(); - this.network = Network.fromPrivate(version, network); + Network.fromPrivate(version, network); + this.depth = br.readU8(); this.parentFingerPrint = br.readU32BE(); this.childIndex = br.readU32BE(); @@ -638,9 +613,6 @@ HDPrivateKey.prototype.getSize = function getSize() { */ HDPrivateKey.prototype.toWriter = function toWriter(bw, network) { - if (!network) - network = this.network; - network = Network.get(network); bw.writeU32BE(network.keyPrefix.xprivkey); @@ -703,9 +675,9 @@ HDPrivateKey.fromRaw = function fromRaw(data, network) { * @returns {Object} */ -HDPrivateKey.prototype.toJSON = function toJSON() { +HDPrivateKey.prototype.toJSON = function toJSON(network) { return { - xprivkey: this.xprivkey() + xprivkey: this.xprivkey(network) }; }; diff --git a/lib/hd/public.js b/lib/hd/public.js index e4928671..a1ecc859 100644 --- a/lib/hd/public.js +++ b/lib/hd/public.js @@ -29,7 +29,6 @@ const common = require('./common'); * @param {Number?} options.childIndex * @param {Buffer?} options.chainCode * @param {Buffer?} options.publicKey - * @property {Network} network * @property {Number} depth * @property {Number} parentFingerPrint * @property {Number} childIndex @@ -41,7 +40,6 @@ function HDPublicKey(options) { if (!(this instanceof HDPublicKey)) return new HDPublicKey(options); - this.network = Network.primary; this.depth = 0; this.parentFingerPrint = 0; this.childIndex = 0; @@ -50,8 +48,6 @@ function HDPublicKey(options) { this.fingerPrint = -1; - this._xpubkey = null; - if (options) this.fromOptions(options); } @@ -70,9 +66,6 @@ HDPublicKey.prototype.fromOptions = function fromOptions(options) { assert(Buffer.isBuffer(options.chainCode)); assert(Buffer.isBuffer(options.publicKey)); - if (options.network) - this.network = Network.get(options.network); - this.depth = options.depth; this.parentFingerPrint = options.parentFingerPrint; this.childIndex = options.childIndex; @@ -106,7 +99,7 @@ HDPublicKey.prototype.toPublic = function toPublic() { * @returns {null} */ -HDPublicKey.prototype.xprivkey = function xprivkey() { +HDPublicKey.prototype.xprivkey = function xprivkey(network) { return null; }; @@ -115,10 +108,8 @@ HDPublicKey.prototype.xprivkey = function xprivkey() { * @returns {Base58String} */ -HDPublicKey.prototype.xpubkey = function xpubkey() { - if (!this._xpubkey) - this._xpubkey = this.toBase58(); - return this._xpubkey; +HDPublicKey.prototype.xpubkey = function xpubkey(network) { + return this.toBase58(network); }; /** @@ -134,8 +125,6 @@ HDPublicKey.prototype.destroy = function destroy() { cleanse(this.publicKey); this.fingerPrint = -1; - - this._xpubkey = null; }; /** @@ -189,7 +178,6 @@ HDPublicKey.prototype.derive = function derive(index, hardened) { } const child = new HDPublicKey(); - child.network = this.network; child.depth = this.depth + 1; child.parentFingerPrint = this.fingerPrint; child.childIndex = index; @@ -209,22 +197,22 @@ HDPublicKey.prototype.derive = function derive(index, hardened) { */ HDPublicKey.prototype.getID = function getID(index) { - return this.network.keyPrefix.xpubkey58 - + this.publicKey.toString('hex') - + index; + return 'b' + this.publicKey.toString('hex') + index; }; /** * Derive a BIP44 account key (does not derive, only ensures account key). * @method * @param {Number} purpose + * @param {Number} type * @param {Number} account * @returns {HDPublicKey} * @throws Error if key is not already an account key. */ -HDPublicKey.prototype.deriveAccount = function deriveAccount(purpose, account) { +HDPublicKey.prototype.deriveAccount = function deriveAccount(purpose, type, account) { assert(util.isU32(purpose)); + assert(util.isU32(type)); assert(util.isU32(account)); assert(this.isAccount(account), 'Cannot derive account index.'); return this; @@ -295,8 +283,7 @@ HDPublicKey.prototype.derivePath = function derivePath(path) { HDPublicKey.prototype.equals = function equals(obj) { assert(HDPublicKey.isHDPublicKey(obj)); - return this.network === obj.network - && this.depth === obj.depth + return this.depth === obj.depth && this.parentFingerPrint === obj.parentFingerPrint && this.childIndex === obj.childIndex && this.chainCode.equals(obj.chainCode) @@ -345,9 +332,9 @@ HDPublicKey.prototype.compare = function compare(key) { * @returns {Object} */ -HDPublicKey.prototype.toJSON = function toJSON() { +HDPublicKey.prototype.toJSON = function toJSON(network) { return { - xpubkey: this.xpubkey() + xpubkey: this.xpubkey(network) }; }; @@ -432,7 +419,6 @@ HDPublicKey.isRaw = function isRaw(data, network) { HDPublicKey.prototype.fromBase58 = function fromBase58(xkey, network) { assert(typeof xkey === 'string'); - this._xpubkey = xkey; return this.fromRaw(base58.decode(xkey), network); }; @@ -446,7 +432,8 @@ HDPublicKey.prototype.fromBase58 = function fromBase58(xkey, network) { HDPublicKey.prototype.fromReader = function fromReader(br, network) { const version = br.readU32BE(); - this.network = Network.fromPublic(version, network); + Network.fromPublic(version, network); + this.depth = br.readU8(); this.parentFingerPrint = br.readU32BE(); this.childIndex = br.readU32BE(); @@ -486,9 +473,6 @@ HDPublicKey.prototype.toBase58 = function toBase58(network) { */ HDPublicKey.prototype.toWriter = function toWriter(bw, network) { - if (!network) - network = this.network; - network = Network.get(network); bw.writeU32BE(network.keyPrefix.xpubkey); diff --git a/lib/primitives/address.js b/lib/primitives/address.js index 8d0ea10c..2f105823 100644 --- a/lib/primitives/address.js +++ b/lib/primitives/address.js @@ -25,17 +25,15 @@ const bech32 = require('../utils/bech32'); * @property {Buffer} hash * @property {AddressPrefix} type * @property {Number} version - * @property {Network} network */ function Address(options) { if (!(this instanceof Address)) return new Address(options); - this.hash = encoding.ZERO_HASH160; this.type = Address.types.PUBKEYHASH; this.version = -1; - this.network = Network.primary; + this.hash = encoding.ZERO_HASH160; if (options) this.fromOptions(options); @@ -69,12 +67,7 @@ Address.prototype.fromOptions = function fromOptions(options) { if (typeof options === 'string') return this.fromString(options); - return this.fromHash( - options.hash, - options.type, - options.version, - options.network - ); + return this.fromHash(options.hash, options.type, options.version); }; /** @@ -128,8 +121,7 @@ Address.prototype.isNull = function isNull() { Address.prototype.equals = function equals(addr) { assert(addr instanceof Address); - return this.network === addr.network - && this.type === addr.type + return this.type === addr.type && this.version === addr.version && this.hash.equals(addr.hash); }; @@ -150,9 +142,6 @@ Address.prototype.getType = function getType() { */ Address.prototype.getPrefix = function getPrefix(network) { - if (!network) - network = this.network; - network = Network.get(network); const prefixes = network.addressPrefix; @@ -241,9 +230,6 @@ Address.prototype.toBech32 = function toBech32(network) { assert(version !== -1, 'Cannot convert non-program address to bech32.'); - if (!network) - network = this.network; - network = Network.get(network); const hrp = network.addressPrefix.bech32; @@ -322,10 +308,6 @@ Address.prototype.inspect = function inspect() { Address.prototype.fromRaw = function fromRaw(data, network) { const br = new BufferReader(data, true); - - if (data.length > 40) - throw new Error('Address is too long.'); - const prefix = br.readU8(); network = Network.fromAddress(prefix, network); @@ -333,18 +315,24 @@ Address.prototype.fromRaw = function fromRaw(data, network) { const type = Address.getType(prefix, network); let version = -1; - if (data.length > 25) { + if (type === Address.types.WITNESS) { + if (data.length > 38) + throw new Error('Address is too long.'); + version = br.readU8(); if (br.readU8() !== 0) throw new Error('Address version padding is non-zero.'); + } else { + if (data.length !== 25) + throw new Error('Address is too long.'); } const hash = br.readBytes(br.left() - 4); br.verifyChecksum(); - return this.fromHash(hash, type, version, network); + return this.fromHash(hash, type, version); }; /** @@ -402,9 +390,9 @@ Address.prototype.fromBech32 = function fromBech32(data, network) { const addr = bech32.decode(data); - network = Network.fromBech32(addr.hrp, network); + Network.fromBech32(addr.hrp, network); - return this.fromHash(addr.hash, type, addr.version, network); + return this.fromHash(addr.hash, type, addr.version); }; /** @@ -574,11 +562,10 @@ Address.fromScript = function fromScript(script) { * @param {Buffer|Hash} hash * @param {AddressPrefix} type * @param {Number} [version=-1] - * @param {(Network|NetworkType)?} network * @throws on bad hash size */ -Address.prototype.fromHash = function fromHash(hash, type, version, network) { +Address.prototype.fromHash = function fromHash(hash, type, version) { if (typeof hash === 'string') hash = Buffer.from(hash, 'hex'); @@ -593,8 +580,6 @@ Address.prototype.fromHash = function fromHash(hash, type, version, network) { if (version == null) version = -1; - network = Network.get(network); - assert(Buffer.isBuffer(hash)); assert(util.isU8(type)); assert(util.isI8(version)); @@ -618,7 +603,6 @@ Address.prototype.fromHash = function fromHash(hash, type, version, network) { this.hash = hash; this.type = type; this.version = version; - this.network = network; return this; }; @@ -628,113 +612,104 @@ Address.prototype.fromHash = function fromHash(hash, type, version, network) { * @param {Hash} hash * @param {AddressPrefix} type * @param {Number} [version=-1] - * @param {(Network|NetworkType)?} network * @returns {Address} * @throws on bad hash size */ -Address.fromHash = function fromHash(hash, type, version, network) { - return new Address().fromHash(hash, type, version, network); +Address.fromHash = function fromHash(hash, type, version) { + return new Address().fromHash(hash, type, version); }; /** * Inject properties from pubkeyhash. * @private * @param {Buffer} hash - * @param {Network?} network * @returns {Address} */ -Address.prototype.fromPubkeyhash = function fromPubkeyhash(hash, network) { +Address.prototype.fromPubkeyhash = function fromPubkeyhash(hash) { const type = Address.types.PUBKEYHASH; assert(hash.length === 20, 'P2PKH must be 20 bytes.'); - return this.fromHash(hash, type, -1, network); + return this.fromHash(hash, type, -1); }; /** * Instantiate address from pubkeyhash. * @param {Buffer} hash - * @param {Network?} network * @returns {Address} */ -Address.fromPubkeyhash = function fromPubkeyhash(hash, network) { - return new Address().fromPubkeyhash(hash, network); +Address.fromPubkeyhash = function fromPubkeyhash(hash) { + return new Address().fromPubkeyhash(hash); }; /** * Inject properties from scripthash. * @private * @param {Buffer} hash - * @param {Network?} network * @returns {Address} */ -Address.prototype.fromScripthash = function fromScripthash(hash, network) { +Address.prototype.fromScripthash = function fromScripthash(hash) { const type = Address.types.SCRIPTHASH; assert(hash && hash.length === 20, 'P2SH must be 20 bytes.'); - return this.fromHash(hash, type, -1, network); + return this.fromHash(hash, type, -1); }; /** * Instantiate address from scripthash. * @param {Buffer} hash - * @param {Network?} network * @returns {Address} */ -Address.fromScripthash = function fromScripthash(hash, network) { - return new Address().fromScripthash(hash, network); +Address.fromScripthash = function fromScripthash(hash) { + return new Address().fromScripthash(hash); }; /** * Inject properties from witness pubkeyhash. * @private * @param {Buffer} hash - * @param {Network?} network * @returns {Address} */ -Address.prototype.fromWitnessPubkeyhash = function fromWitnessPubkeyhash(hash, network) { +Address.prototype.fromWitnessPubkeyhash = function fromWitnessPubkeyhash(hash) { const type = Address.types.WITNESS; assert(hash && hash.length === 20, 'P2WPKH must be 20 bytes.'); - return this.fromHash(hash, type, 0, network); + return this.fromHash(hash, type, 0); }; /** * Instantiate address from witness pubkeyhash. * @param {Buffer} hash - * @param {Network?} network * @returns {Address} */ -Address.fromWitnessPubkeyhash = function fromWitnessPubkeyhash(hash, network) { - return new Address().fromWitnessPubkeyhash(hash, network); +Address.fromWitnessPubkeyhash = function fromWitnessPubkeyhash(hash) { + return new Address().fromWitnessPubkeyhash(hash); }; /** * Inject properties from witness scripthash. * @private * @param {Buffer} hash - * @param {Network?} network * @returns {Address} */ -Address.prototype.fromWitnessScripthash = function fromWitnessScripthash(hash, network) { +Address.prototype.fromWitnessScripthash = function fromWitnessScripthash(hash) { const type = Address.types.WITNESS; assert(hash && hash.length === 32, 'P2WPKH must be 32 bytes.'); - return this.fromHash(hash, type, 0, network); + return this.fromHash(hash, type, 0); }; /** * Instantiate address from witness scripthash. * @param {Buffer} hash - * @param {Network?} network * @returns {Address} */ -Address.fromWitnessScripthash = function fromWitnessScripthash(hash, network) { - return new Address().fromWitnessScripthash(hash, network); +Address.fromWitnessScripthash = function fromWitnessScripthash(hash) { + return new Address().fromWitnessScripthash(hash); }; /** @@ -742,11 +717,10 @@ Address.fromWitnessScripthash = function fromWitnessScripthash(hash, network) { * @private * @param {Number} version * @param {Buffer} hash - * @param {Network?} network * @returns {Address} */ -Address.prototype.fromProgram = function fromProgram(version, hash, network) { +Address.prototype.fromProgram = function fromProgram(version, hash) { const type = Address.types.WITNESS; assert(version >= 0, 'Bad version for witness program.'); @@ -754,19 +728,18 @@ Address.prototype.fromProgram = function fromProgram(version, hash, network) { if (typeof hash === 'string') hash = Buffer.from(hash, 'hex'); - return this.fromHash(hash, type, version, network); + return this.fromHash(hash, type, version); }; /** * Instantiate address from witness program. * @param {Number} version * @param {Buffer} hash - * @param {Network?} network * @returns {Address} */ -Address.fromProgram = function fromProgram(version, hash, network) { - return new Address().fromProgram(version, hash, network); +Address.fromProgram = function fromProgram(version, hash) { + return new Address().fromProgram(version, hash); }; /** @@ -863,11 +836,6 @@ Address.getHash = function getHash(data, enc, network) { hash = data; } else if (data instanceof Address) { hash = data.hash; - if (network) { - network = Network.get(network); - if (data.network !== network) - throw new Error('Network mismatch for address.'); - } } else { throw new Error('Object is not an address.'); } diff --git a/lib/primitives/keyring.js b/lib/primitives/keyring.js index aeea5fc5..529ce8ca 100644 --- a/lib/primitives/keyring.js +++ b/lib/primitives/keyring.js @@ -24,14 +24,12 @@ const secp256k1 = require('../crypto/secp256k1'); * @alias module:primitives.KeyRing * @constructor * @param {Object} options - * @param {Network} network */ -function KeyRing(options, network) { +function KeyRing(options) { if (!(this instanceof KeyRing)) - return new KeyRing(options, network); + return new KeyRing(options); - this.network = Network.primary; this.witness = false; this.nested = false; this.publicKey = encoding.ZERO_KEY; @@ -48,7 +46,7 @@ function KeyRing(options, network) { this._scriptAddress = null; if (options) - this.fromOptions(options, network); + this.fromOptions(options); } /** @@ -57,10 +55,7 @@ function KeyRing(options, network) { * @param {Object} options */ -KeyRing.prototype.fromOptions = function fromOptions(options, network) { - if (!network) - network = options.network; - +KeyRing.prototype.fromOptions = function fromOptions(options) { let key = toKey(options); if (options.witness != null) { @@ -74,7 +69,7 @@ KeyRing.prototype.fromOptions = function fromOptions(options, network) { } if (Buffer.isBuffer(key)) - return this.fromKey(key, network); + return this.fromKey(key); key = toKey(options.key); @@ -88,9 +83,9 @@ KeyRing.prototype.fromOptions = function fromOptions(options, network) { const compress = options.compressed; if (script) - return this.fromScript(key, script, compress, network); + return this.fromScript(key, script, compress); - return this.fromKey(key, compress, network); + return this.fromKey(key, compress); }; /** @@ -123,19 +118,12 @@ KeyRing.prototype.refresh = function refresh() { * @private * @param {Buffer} key * @param {Boolean?} compress - * @param {(NetworkType|Network)?} network */ -KeyRing.prototype.fromPrivate = function fromPrivate(key, compress, network) { +KeyRing.prototype.fromPrivate = function fromPrivate(key, compress) { assert(Buffer.isBuffer(key), 'Private key must be a buffer.'); assert(secp256k1.privateKeyVerify(key), 'Not a valid private key.'); - if (typeof compress !== 'boolean') { - network = compress; - compress = null; - } - - this.network = Network.get(network); this.privateKey = key; this.publicKey = secp256k1.publicKeyCreate(key, compress !== false); @@ -146,25 +134,22 @@ KeyRing.prototype.fromPrivate = function fromPrivate(key, compress, network) { * Instantiate keyring from a private key. * @param {Buffer} key * @param {Boolean?} compress - * @param {(NetworkType|Network)?} network * @returns {KeyRing} */ -KeyRing.fromPrivate = function fromPrivate(key, compress, network) { - return new KeyRing().fromPrivate(key, compress, network); +KeyRing.fromPrivate = function fromPrivate(key, compress) { + return new KeyRing().fromPrivate(key, compress); }; /** * Inject data from public key. * @private * @param {Buffer} key - * @param {(NetworkType|Network)?} network */ -KeyRing.prototype.fromPublic = function fromPublic(key, network) { +KeyRing.prototype.fromPublic = function fromPublic(key) { assert(Buffer.isBuffer(key), 'Public key must be a buffer.'); assert(secp256k1.publicKeyVerify(key), 'Not a valid public key.'); - this.network = Network.get(network); this.publicKey = key; return this; }; @@ -173,41 +158,32 @@ KeyRing.prototype.fromPublic = function fromPublic(key, network) { * Generate a keyring. * @private * @param {Boolean?} compress - * @param {(Network|NetworkType)?} network * @returns {KeyRing} */ -KeyRing.prototype.generate = function generate(compress, network) { - if (typeof compress !== 'boolean') { - network = compress; - compress = null; - } - +KeyRing.prototype.generate = function generate(compress) { const key = secp256k1.generatePrivateKey(); - - return this.fromKey(key, compress, network); + return this.fromKey(key, compress); }; /** * Generate a keyring. * @param {Boolean?} compress - * @param {(Network|NetworkType)?} network * @returns {KeyRing} */ -KeyRing.generate = function generate(compress, network) { - return new KeyRing().generate(compress, network); +KeyRing.generate = function generate(compress) { + return new KeyRing().generate(compress); }; /** * Instantiate keyring from a public key. * @param {Buffer} publicKey - * @param {(NetworkType|Network)?} network * @returns {KeyRing} */ -KeyRing.fromPublic = function fromPublic(key, network) { - return new KeyRing().fromPublic(key, network); +KeyRing.fromPublic = function fromPublic(key) { + return new KeyRing().fromPublic(key); }; /** @@ -215,33 +191,26 @@ KeyRing.fromPublic = function fromPublic(key, network) { * @private * @param {Buffer} privateKey * @param {Boolean?} compress - * @param {(NetworkType|Network)?} network */ -KeyRing.prototype.fromKey = function fromKey(key, compress, network) { +KeyRing.prototype.fromKey = function fromKey(key, compress) { assert(Buffer.isBuffer(key), 'Key must be a buffer.'); - if (typeof compress !== 'boolean') { - network = compress; - compress = null; - } - if (key.length === 32) - return this.fromPrivate(key, compress !== false, network); + return this.fromPrivate(key, compress !== false); - return this.fromPublic(key, network); + return this.fromPublic(key); }; /** * Instantiate keyring from a public key. * @param {Buffer} publicKey * @param {Boolean?} compress - * @param {(NetworkType|Network)?} network * @returns {KeyRing} */ -KeyRing.fromKey = function fromKey(key, compress, network) { - return new KeyRing().fromKey(key, compress, network); +KeyRing.fromKey = function fromKey(key, compress) { + return new KeyRing().fromKey(key, compress); }; /** @@ -250,18 +219,12 @@ KeyRing.fromKey = function fromKey(key, compress, network) { * @param {Buffer} key * @param {Script} script * @param {Boolean?} compress - * @param {(NetworkType|Network)?} network */ -KeyRing.prototype.fromScript = function fromScript(key, script, compress, network) { +KeyRing.prototype.fromScript = function fromScript(key, script, compress) { assert(script instanceof Script, 'Non-script passed into KeyRing.'); - if (typeof compress !== 'boolean') { - network = compress; - compress = null; - } - - this.fromKey(key, compress, network); + this.fromKey(key, compress); this.script = script; return this; @@ -272,12 +235,11 @@ KeyRing.prototype.fromScript = function fromScript(key, script, compress, networ * @param {Buffer} key * @param {Script} script * @param {Boolean?} compress - * @param {(NetworkType|Network)?} network * @returns {KeyRing} */ -KeyRing.fromScript = function fromScript(key, script, compress, network) { - return new KeyRing().fromScript(key, script, compress, network); +KeyRing.fromScript = function fromScript(key, script, compress) { + return new KeyRing().fromScript(key, script, compress); }; /** @@ -311,9 +273,6 @@ KeyRing.prototype.toSecret = function toSecret(network) { assert(this.privateKey, 'Cannot serialize without private key.'); - if (!network) - network = this.network; - network = Network.get(network); bw.writeU8(network.keyPrefix.privkey); @@ -339,7 +298,7 @@ KeyRing.prototype.fromSecret = function fromSecret(data, network) { const version = br.readU8(); - network = Network.fromWIF(version, network); + Network.fromWIF(version, network); const key = br.readBytes(32); @@ -352,7 +311,7 @@ KeyRing.prototype.fromSecret = function fromSecret(data, network) { br.verifyChecksum(); - return this.fromPrivate(key, compress, network); + return this.fromPrivate(key, compress); }; /** @@ -372,12 +331,12 @@ KeyRing.fromSecret = function fromSecret(data, network) { * @returns {Buffer} Private key. */ -KeyRing.prototype.getPrivateKey = function getPrivateKey(enc) { +KeyRing.prototype.getPrivateKey = function getPrivateKey(enc, network) { if (!this.privateKey) return null; if (enc === 'base58') - return this.toSecret(); + return this.toSecret(network); if (enc === 'hex') return this.privateKey.toString('hex'); @@ -459,21 +418,21 @@ KeyRing.prototype.getNestedHash = function getNestedHash(enc) { * @returns {Address|Base58Address} */ -KeyRing.prototype.getNestedAddress = function getNestedAddress(enc) { +KeyRing.prototype.getNestedAddress = function getNestedAddress(enc, network) { if (!this.witness) return null; if (!this._nestedAddress) { const hash = this.getNestedHash(); - const addr = Address.fromScripthash(hash, this.network); + const addr = Address.fromScripthash(hash); this._nestedAddress = addr; } if (enc === 'base58') - return this._nestedAddress.toBase58(); + return this._nestedAddress.toBase58(network); if (enc === 'string') - return this._nestedAddress.toString(); + return this._nestedAddress.toString(network); return this._nestedAddress; }; @@ -532,7 +491,7 @@ KeyRing.prototype.getScriptHash256 = function getScriptHash256(enc) { * @returns {Address|Base58Address} */ -KeyRing.prototype.getScriptAddress = function getScriptAddress(enc) { +KeyRing.prototype.getScriptAddress = function getScriptAddress(enc, network) { if (!this.script) return null; @@ -540,19 +499,19 @@ KeyRing.prototype.getScriptAddress = function getScriptAddress(enc) { let addr; if (this.witness) { const hash = this.getScriptHash256(); - addr = Address.fromWitnessScripthash(hash, this.network); + addr = Address.fromWitnessScripthash(hash); } else { const hash = this.getScriptHash160(); - addr = Address.fromScripthash(hash, this.network); + addr = Address.fromScripthash(hash); } this._scriptAddress = addr; } if (enc === 'base58') - return this._scriptAddress.toBase58(); + return this._scriptAddress.toBase58(network); if (enc === 'string') - return this._scriptAddress.toString(); + return this._scriptAddress.toString(network); return this._scriptAddress; }; @@ -578,24 +537,24 @@ KeyRing.prototype.getKeyHash = function getKeyHash(enc) { * @returns {Address|Base58Address} */ -KeyRing.prototype.getKeyAddress = function getKeyAddress(enc) { +KeyRing.prototype.getKeyAddress = function getKeyAddress(enc, network) { if (!this._keyAddress) { const hash = this.getKeyHash(); let addr; if (this.witness) - addr = Address.fromWitnessPubkeyhash(hash, this.network); + addr = Address.fromWitnessPubkeyhash(hash); else - addr = Address.fromPubkeyhash(hash, this.network); + addr = Address.fromPubkeyhash(hash); this._keyAddress = addr; } if (enc === 'base58') - return this._keyAddress.toBase58(); + return this._keyAddress.toBase58(network); if (enc === 'string') - return this._keyAddress.toString(); + return this._keyAddress.toString(network); return this._keyAddress; }; @@ -622,14 +581,14 @@ KeyRing.prototype.getHash = function getHash(enc) { * @returns {Address|Base58Address} */ -KeyRing.prototype.getAddress = function getAddress(enc) { +KeyRing.prototype.getAddress = function getAddress(enc, network) { if (this.nested) - return this.getNestedAddress(enc); + return this.getNestedAddress(enc, network); if (this.script) - return this.getScriptAddress(enc); + return this.getScriptAddress(enc, network); - return this.getKeyAddress(enc); + return this.getKeyAddress(enc, network); }; /** @@ -771,16 +730,15 @@ KeyRing.prototype.inspect = function inspect() { * @returns {Object} */ -KeyRing.prototype.toJSON = function toJSON() { +KeyRing.prototype.toJSON = function toJSON(network) { return { - network: this.network.type, witness: this.witness, nested: this.nested, publicKey: this.publicKey.toString('hex'), script: this.script ? this.script.toRaw().toString('hex') : null, program: this.witness ? this.getProgram().toRaw().toString('hex') : null, type: Address.typesByVal[this.getType()].toLowerCase(), - address: this.getAddress('string') + address: this.getAddress('string', network) }; }; @@ -792,13 +750,11 @@ KeyRing.prototype.toJSON = function toJSON() { KeyRing.prototype.fromJSON = function fromJSON(json) { assert(json); - assert(typeof json.network === 'string'); assert(typeof json.witness === 'boolean'); assert(typeof json.nested === 'boolean'); assert(typeof json.publicKey === 'string'); assert(!json.script || typeof json.script === 'string'); - this.nework = Network.get(json.network); this.witness = json.witness; this.nested = json.nested; this.publicKey = Buffer.from(json.publicKey, 'hex'); @@ -882,12 +838,9 @@ KeyRing.prototype.toRaw = function toRaw() { * Inject properties from buffer reader. * @private * @param {BufferReader} br - * @param {Network?} network */ -KeyRing.prototype.fromReader = function fromReader(br, network) { - this.network = Network.get(network); - +KeyRing.prototype.fromReader = function fromReader(br) { const field = br.readU8(); this.witness = (field & 1) !== 0; @@ -916,11 +869,10 @@ KeyRing.prototype.fromReader = function fromReader(br, network) { * Inject properties from serialized data. * @private * @param {Buffer} data - * @param {Network?} network */ -KeyRing.prototype.fromRaw = function fromRaw(data, network) { - return this.fromReader(new BufferReader(data), network); +KeyRing.prototype.fromRaw = function fromRaw(data) { + return this.fromReader(new BufferReader(data)); }; /** diff --git a/lib/wallet/account.js b/lib/wallet/account.js index fff6f238..cfea412d 100644 --- a/lib/wallet/account.js +++ b/lib/wallet/account.js @@ -250,9 +250,6 @@ Account.prototype.pushKey = function pushKey(key) { if (typeof key === 'string') key = HD.PublicKey.fromBase58(key, this.network); - assert(key.network === this.network, - 'Network mismatch for account key.'); - if (!HD.isPublic(key)) throw new Error('Must add HD keys to wallet.'); @@ -290,9 +287,6 @@ Account.prototype.spliceKey = function spliceKey(key) { if (typeof key === 'string') key = HD.PublicKey.fromBase58(key, this.network); - assert(key.network === this.network, - 'Network mismatch for account key.'); - if (!HD.isPublic(key)) throw new Error('Must add HD keys to wallet.'); @@ -404,21 +398,21 @@ Account.prototype.createKey = async function createKey(b, branch) { key = this.deriveReceive(this.receiveDepth); lookahead = this.deriveReceive(this.receiveDepth + this.lookahead); await this.saveKey(b, lookahead); - this.receiveDepth++; + this.receiveDepth += 1; this.receive = key; break; case 1: key = this.deriveChange(this.changeDepth); lookahead = this.deriveReceive(this.changeDepth + this.lookahead); await this.saveKey(b, lookahead); - this.changeDepth++; + this.changeDepth += 1; this.change = key; break; case 2: key = this.deriveNested(this.nestedDepth); lookahead = this.deriveNested(this.nestedDepth + this.lookahead); await this.saveKey(b, lookahead); - this.nestedDepth++; + this.nestedDepth += 1; this.nested = key; break; default: @@ -511,7 +505,8 @@ Account.prototype.deriveKey = function deriveKey(branch, index, master) { let key; if (master && master.key && !this.watchOnly) { - key = master.key.deriveAccount(44, this.accountIndex); + const type = this.network.keyPrefix.coinType; + key = master.key.deriveAccount(44, type, this.accountIndex); key = key.derive(branch).derive(index); } else { key = this.accountKey.derive(branch).derive(index); @@ -577,22 +572,16 @@ Account.prototype.initDepth = async function initDepth(b) { // Receive Address this.receiveDepth = 1; - await this.saveKey(b, this.deriveReceive(0)); - - // Lookahead - for (let i = 0; i < this.lookahead; i++) { - const key = this.deriveReceive(i + 1); + for (let i = 0; i <= this.lookahead; i++) { + const key = this.deriveReceive(i); await this.saveKey(b, key); } // Change Address this.changeDepth = 1; - await this.saveKey(b, this.deriveChange(0)); - - // Lookahead - for (let i = 0; i < this.lookahead; i++) { - const key = this.deriveChange(i + 1); + for (let i = 0; i <= this.lookahead; i++) { + const key = this.deriveChange(i); await this.saveKey(b, key); } @@ -600,11 +589,8 @@ Account.prototype.initDepth = async function initDepth(b) { if (this.witness) { this.nestedDepth = 1; - await this.saveKey(b, this.deriveNested(0)); - - // Lookahead - for (let i = 0; i < this.lookahead; i++) { - const key = this.deriveNested(i + 1); + for (let i = 0; i <= this.lookahead; i++) { + const key = this.deriveNested(i); await this.saveKey(b, key); } } @@ -634,7 +620,6 @@ Account.prototype.syncDepth = async function syncDepth(b, receive, change, neste await this.saveKey(b, key); } - this.receive = this.deriveReceive(receive - 1); this.receiveDepth = receive; derived = true; @@ -651,7 +636,6 @@ Account.prototype.syncDepth = async function syncDepth(b, receive, change, neste await this.saveKey(b, key); } - this.change = this.deriveChange(change - 1); this.changeDepth = change; derived = true; @@ -667,7 +651,6 @@ Account.prototype.syncDepth = async function syncDepth(b, receive, change, neste await this.saveKey(b, key); } - this.nested = this.deriveNested(nested - 1); this.nestedDepth = nested; derived = true; @@ -694,7 +677,6 @@ Account.prototype.setLookahead = async function setLookahead(b, lookahead) { const diff = this.lookahead - lookahead; this.receiveDepth += diff; - this.changeDepth += diff; if (this.witness) @@ -828,10 +810,14 @@ Account.prototype.nestedAddress = function nestedAddress() { */ Account.prototype.inspect = function inspect() { + const receive = this.receiveAddress(); + const change = this.changeAddress(); + const nested = this.nestedAddress(); + return { wid: this.wid, name: this.name, - network: this.network, + network: this.network.type, initialized: this.initialized, witness: this.witness, watchOnly: this.watchOnly, @@ -843,11 +829,11 @@ Account.prototype.inspect = function inspect() { changeDepth: this.changeDepth, nestedDepth: this.nestedDepth, lookahead: this.lookahead, - receiveAddress: this.receiveAddress(), - changeAddress: this.changeAddress(), - nestedAddress: this.nestedAddress(), - accountKey: this.accountKey.toBase58(), - keys: this.keys.map(key => key.toBase58()) + receiveAddress: receive ? receive.toString(this.network) : null, + changeAddress: change ? change.toString(this.network) : null, + nestedAddress: nested ? nested.toString(this.network) : null, + accountKey: this.accountKey.toBase58(this.network), + keys: this.keys.map(key => key.toBase58(this.network)) }; }; @@ -877,11 +863,11 @@ Account.prototype.toJSON = function toJSON(minimal, balance) { changeDepth: this.changeDepth, nestedDepth: this.nestedDepth, lookahead: this.lookahead, - receiveAddress: receive ? receive.toString() : null, - changeAddress: change ? change.toString() : null, - nestedAddress: nested ? nested.toString() : null, - accountKey: this.accountKey.toBase58(), - keys: this.keys.map(key => key.toBase58()), + receiveAddress: receive ? receive.toString(this.network) : null, + changeAddress: change ? change.toString(this.network) : null, + nestedAddress: nested ? nested.toString(this.network) : null, + accountKey: this.accountKey.toBase58(this.network), + keys: this.keys.map(key => key.toBase58(this.network)), balance: balance ? balance.toJSON(true) : null }; }; @@ -919,11 +905,11 @@ Account.prototype.toRaw = function toRaw() { bw.writeU32(this.changeDepth); bw.writeU32(this.nestedDepth); bw.writeU8(this.lookahead); - bw.writeBytes(this.accountKey.toRaw()); + bw.writeBytes(this.accountKey.toRaw(this.network)); bw.writeU8(this.keys.length); for (const key of this.keys) - bw.writeBytes(key.toRaw()); + bw.writeBytes(key.toRaw(this.network)); return bw.render(); }; @@ -949,14 +935,14 @@ Account.prototype.fromRaw = function fromRaw(data) { this.changeDepth = br.readU32(); this.nestedDepth = br.readU32(); this.lookahead = br.readU8(); - this.accountKey = HD.PublicKey.fromRaw(br.readBytes(82)); + this.accountKey = HD.PublicKey.fromRaw(br.readBytes(82), this.network); assert(Account.typesByVal[this.type]); const count = br.readU8(); for (let i = 0; i < count; i++) { - const key = HD.PublicKey.fromRaw(br.readBytes(82)); + const key = HD.PublicKey.fromRaw(br.readBytes(82), this.network); this.pushKey(key); } diff --git a/lib/wallet/http.js b/lib/wallet/http.js index c26a68b9..cbf6a01d 100644 --- a/lib/wallet/http.js +++ b/lib/wallet/http.js @@ -572,7 +572,7 @@ HTTPServer.prototype.initRouter = function initRouter() { return; } - res.send(200, key.toJSON()); + res.send(200, key.toJSON(this.network)); }); // Get private key @@ -590,7 +590,7 @@ HTTPServer.prototype.initRouter = function initRouter() { return; } - res.send(200, { privateKey: key.toSecret() }); + res.send(200, { privateKey: key.toSecret(this.network) }); }); // Create address @@ -599,7 +599,7 @@ HTTPServer.prototype.initRouter = function initRouter() { const acct = valid.str('account'); const address = await req.wallet.createReceive(acct); - res.send(200, address.toJSON()); + res.send(200, address.toJSON(this.network)); }); // Create change address @@ -608,7 +608,7 @@ HTTPServer.prototype.initRouter = function initRouter() { const acct = valid.str('account'); const address = await req.wallet.createChange(acct); - res.send(200, address.toJSON()); + res.send(200, address.toJSON(this.network)); }); // Create nested address @@ -617,7 +617,7 @@ HTTPServer.prototype.initRouter = function initRouter() { const acct = valid.str('account'); const address = await req.wallet.createNested(acct); - res.send(200, address.toJSON()); + res.send(200, address.toJSON(this.network)); }); // Wallet Balance @@ -851,7 +851,7 @@ HTTPServer.prototype.initSockets = function initSockets() { const json = []; for (const addr of receive) - json.push(addr.toJSON()); + json.push(addr.toJSON(this.network)); this.to(`w:${w.id}`, 'wallet address', json); }); diff --git a/lib/wallet/masterkey.js b/lib/wallet/masterkey.js index 96083e11..368a3762 100644 --- a/lib/wallet/masterkey.js +++ b/lib/wallet/masterkey.js @@ -7,6 +7,7 @@ 'use strict'; const assert = require('assert'); +const Network = require('../protocol/network'); const util = require('../utils/util'); const Lock = require('../utils/lock'); const random = require('../crypto/random'); @@ -92,6 +93,9 @@ MasterKey.algByVal = { MasterKey.prototype.fromOptions = function fromOptions(options) { assert(options); + if (options.network != null) + this.network = Network.get(options.network); + if (options.encrypted != null) { assert(typeof options.encrypted === 'boolean'); this.encrypted = options.encrypted; @@ -203,7 +207,7 @@ MasterKey.prototype._unlock = async function _unlock(passphrase, timeout) { const key = await this.derive(passphrase); const data = aes.decipher(this.ciphertext, key, this.iv); - this.fromKeyRaw(data); + this.readKey(data); this.start(timeout); @@ -388,7 +392,7 @@ MasterKey.prototype._decrypt = async function _decrypt(passphrase, clean) { const key = await this.derive(passphrase); const data = aes.decipher(this.ciphertext, key, this.iv); - this.fromKeyRaw(data); + this.readKey(data); this.encrypted = false; this.iv = null; this.ciphertext = null; @@ -430,7 +434,7 @@ MasterKey.prototype._encrypt = async function _encrypt(passphrase, clean) { if (!passphrase) throw new Error('No passphrase provided.'); - const raw = this.toKeyRaw(); + const raw = this.writeKey(); const iv = random.randomBytes(16); this.stop(); @@ -457,7 +461,7 @@ MasterKey.prototype._encrypt = async function _encrypt(passphrase, clean) { * @returns {Number} */ -MasterKey.prototype.getKeySize = function getKeySize() { +MasterKey.prototype.keySize = function keySize() { let size = 0; size += this.key.getSize(); @@ -474,10 +478,10 @@ MasterKey.prototype.getKeySize = function getKeySize() { * @returns {Buffer} */ -MasterKey.prototype.toKeyRaw = function toKeyRaw() { - const bw = new StaticWriter(this.getKeySize()); +MasterKey.prototype.writeKey = function writeKey() { + const bw = new StaticWriter(this.keySize()); - this.key.toWriter(bw); + this.key.toWriter(bw, this.network); if (this.mnemonic) { bw.writeU8(1); @@ -494,10 +498,10 @@ MasterKey.prototype.toKeyRaw = function toKeyRaw() { * @param {Buffer} data */ -MasterKey.prototype.fromKeyRaw = function fromKeyRaw(data) { +MasterKey.prototype.readKey = function readKey(data) { const br = new BufferReader(data); - this.key = HD.PrivateKey.fromReader(br); + this.key = HD.PrivateKey.fromReader(br, this.network); if (br.readU8() === 1) this.mnemonic = Mnemonic.fromReader(br); @@ -522,7 +526,7 @@ MasterKey.prototype.getSize = function getSize() { } size += 1; - size += encoding.sizeVarlen(this.getKeySize()); + size += encoding.sizeVarlen(this.keySize()); return size; }; @@ -552,10 +556,10 @@ MasterKey.prototype.toRaw = function toRaw() { bw.writeU8(0); // NOTE: useless varint - const size = this.getKeySize(); + const size = this.keySize(); bw.writeVarint(size); - bw.writeBytes(this.key.toRaw()); + bw.writeBytes(this.key.toRaw(this.network)); if (this.mnemonic) { bw.writeU8(1); @@ -573,9 +577,10 @@ MasterKey.prototype.toRaw = function toRaw() { * @param {Buffer} raw */ -MasterKey.prototype.fromRaw = function fromRaw(raw) { +MasterKey.prototype.fromRaw = function fromRaw(raw, network) { const br = new BufferReader(raw); + this.network = Network.get(network); this.encrypted = br.readU8() === 1; if (this.encrypted) { @@ -596,7 +601,7 @@ MasterKey.prototype.fromRaw = function fromRaw(raw) { // NOTE: useless varint br.readVarint(); - this.key = HD.PrivateKey.fromRaw(br.readBytes(82)); + this.key = HD.PrivateKey.fromRaw(br.readBytes(82), this.network); if (br.readU8() === 1) this.mnemonic = Mnemonic.fromReader(br); @@ -609,8 +614,8 @@ MasterKey.prototype.fromRaw = function fromRaw(raw) { * @returns {MasterKey} */ -MasterKey.fromRaw = function fromRaw(raw) { - return new MasterKey().fromRaw(raw); +MasterKey.fromRaw = function fromRaw(raw, network) { + return new MasterKey().fromRaw(raw, network); }; /** @@ -620,12 +625,13 @@ MasterKey.fromRaw = function fromRaw(raw) { * @param {Mnemonic?} mnemonic */ -MasterKey.prototype.fromKey = function fromKey(key, mnemonic) { +MasterKey.prototype.fromKey = function fromKey(key, mnemonic, network) { this.encrypted = false; this.iv = null; this.ciphertext = null; this.key = key; this.mnemonic = mnemonic || null; + this.network = Network.get(network); return this; }; @@ -636,8 +642,8 @@ MasterKey.prototype.fromKey = function fromKey(key, mnemonic) { * @returns {MasterKey} */ -MasterKey.fromKey = function fromKey(key, mnemonic) { - return new MasterKey().fromKey(key, mnemonic); +MasterKey.fromKey = function fromKey(key, mnemonic, network) { + return new MasterKey().fromKey(key, mnemonic, network); }; /** @@ -663,7 +669,7 @@ MasterKey.prototype.toJSON = function toJSON(unsafe) { return { encrypted: false, - key: unsafe ? this.key.toJSON() : undefined, + key: unsafe ? this.key.toJSON(this.network) : undefined, mnemonic: unsafe && this.mnemonic ? this.mnemonic.toJSON() : undefined }; }; @@ -677,7 +683,7 @@ MasterKey.prototype.inspect = function inspect() { const json = this.toJSON(true); if (this.key) - json.key = this.key.toJSON(); + json.key = this.key.toJSON(this.network); if (this.mnemonic) json.mnemonic = this.mnemonic.toJSON(); diff --git a/lib/wallet/path.js b/lib/wallet/path.js index 1acaea28..47d317a4 100644 --- a/lib/wallet/path.js +++ b/lib/wallet/path.js @@ -277,8 +277,8 @@ Path.prototype.toPath = function toPath() { * @returns {Address} */ -Path.prototype.toAddress = function toAddress(network) { - return Address.fromHash(this.hash, this.type, this.version, network); +Path.prototype.toAddress = function toAddress() { + return Address.fromHash(this.hash, this.type, this.version); }; /** diff --git a/lib/wallet/rpc.js b/lib/wallet/rpc.js index 95dd65cb..37335a4f 100644 --- a/lib/wallet/rpc.js +++ b/lib/wallet/rpc.js @@ -238,7 +238,7 @@ RPC.prototype.dumpPrivKey = async function dumpPrivKey(args, help) { if (!ring) throw new RPCError(errs.MISC_ERROR, 'Key not found.'); - return ring.toSecret(); + return ring.toSecret(this.network); }; RPC.prototype.dumpWallet = async function dumpWallet(args, help) { @@ -279,7 +279,7 @@ RPC.prototype.dumpWallet = async function dumpWallet(args, help) { if (ring.branch === 1) fmt = '%s %s change=1 addr=%s'; - const str = util.fmt(fmt, ring.toSecret(), time, addr); + const str = util.fmt(fmt, ring.toSecret(this.network), time, addr); out.push(str); } diff --git a/lib/wallet/txdb.js b/lib/wallet/txdb.js index 34d9e2f3..5dd5a4e2 100644 --- a/lib/wallet/txdb.js +++ b/lib/wallet/txdb.js @@ -2137,6 +2137,11 @@ Balance.prototype.applyTo = function applyTo(balance) { balance.coin += this.coin; balance.unconfirmed += this.unconfirmed; balance.confirmed += this.confirmed; + + assert(balance.tx >= 0); + assert(balance.coin >= 0); + assert(balance.unconfirmed >= 0); + assert(balance.confirmed >= 0); }; /** @@ -2204,7 +2209,6 @@ Balance.prototype.toJSON = function toJSON(minimal) { */ Balance.prototype.inspect = function inspect() { - return this; return ' 0) { - this.wdb.emit('address', this.id, derived); + this.wdb.emit('address', this, derived); this.emit('address', derived); } } @@ -2350,6 +2339,8 @@ Wallet.prototype.fromRaw = function fromRaw(data) { const br = new BufferReader(data); const network = Network.fromMagic(br.readU32()); + assert(network === this.network, 'Wallet network mismatch.'); + this.wid = br.readU32(); this.id = br.readVarString('ascii'); this.initialized = br.readU8() === 1; @@ -2357,9 +2348,7 @@ Wallet.prototype.fromRaw = function fromRaw(data) { this.accountDepth = br.readU32(); this.token = br.readBytes(32); this.tokenDepth = br.readU32(); - this.master.fromRaw(br.readVarBytes()); - - assert(network === this.wdb.network, 'Wallet network mismatch.'); + this.master.fromRaw(br.readVarBytes(), this.network); return this; }; diff --git a/lib/wallet/walletkey.js b/lib/wallet/walletkey.js index d8b0a14c..3c562b5e 100644 --- a/lib/wallet/walletkey.js +++ b/lib/wallet/walletkey.js @@ -18,11 +18,11 @@ const Path = require('./path'); * @param {Object} options */ -function WalletKey(options, network) { +function WalletKey(options) { if (!(this instanceof WalletKey)) - return new WalletKey(options, network); + return new WalletKey(options); - KeyRing.call(this, options, network); + KeyRing.call(this, options); this.keyType = Path.types.HD; @@ -48,56 +48,52 @@ WalletKey.fromOptions = function fromOptions(options) { * Instantiate wallet key from a private key. * @param {Buffer} key * @param {Boolean?} compressed - * @param {(NetworkType|Network)} network * @returns {WalletKey} */ -WalletKey.fromPrivate = function fromPrivate(key, compressed, network) { - return new WalletKey().fromPrivate(key, compressed, network); +WalletKey.fromPrivate = function fromPrivate(key, compressed) { + return new WalletKey().fromPrivate(key, compressed); }; /** * Generate a wallet key. - * @param {(Network|NetworkType)?} network + * @param {Boolean?} compressed * @returns {WalletKey} */ -WalletKey.generate = function generate(compressed, network) { - return new WalletKey().generate(compressed, network); +WalletKey.generate = function generate(compressed) { + return new WalletKey().generate(compressed); }; /** * Instantiate wallet key from a public key. * @param {Buffer} publicKey - * @param {(NetworkType|Network)} network * @returns {WalletKey} */ -WalletKey.fromPublic = function fromPublic(key, network) { - return new WalletKey().fromPublic(key, network); +WalletKey.fromPublic = function fromPublic(key) { + return new WalletKey().fromPublic(key); }; /** * Instantiate wallet key from a public key. * @param {Buffer} publicKey - * @param {(NetworkType|Network)} network * @returns {WalletKey} */ -WalletKey.fromKey = function fromKey(key, compressed, network) { - return new WalletKey().fromKey(key, compressed, network); +WalletKey.fromKey = function fromKey(key, compressed) { + return new WalletKey().fromKey(key, compressed); }; /** * Instantiate wallet key from script. * @param {Buffer} key * @param {Script} script - * @param {(NetworkType|Network)} network * @returns {WalletKey} */ -WalletKey.fromScript = function fromScript(key, script, compressed, network) { - return new WalletKey().fromScript(key, script, compressed, network); +WalletKey.fromScript = function fromScript(key, script, compressed) { + return new WalletKey().fromScript(key, script, compressed); }; /** @@ -116,9 +112,8 @@ WalletKey.fromSecret = function fromSecret(data, network) { * @returns {Object} */ -WalletKey.prototype.toJSON = function toJSON() { +WalletKey.prototype.toJSON = function toJSON(network) { return { - network: this.network.type, name: this.name, account: this.account, branch: this.branch, @@ -129,7 +124,7 @@ WalletKey.prototype.toJSON = function toJSON() { script: this.script ? this.script.toRaw().toString('hex') : null, program: this.witness ? this.getProgram().toRaw().toString('hex') : null, type: Address.typesByVal[this.getType()].toLowerCase(), - address: this.getAddress('string') + address: this.getAddress('string', network) }; }; @@ -173,9 +168,9 @@ WalletKey.prototype.fromHD = function fromHD(account, key, branch, index) { this.nested = branch === 2; if (key.privateKey) - return this.fromPrivate(key.privateKey, account.network); + return this.fromPrivate(key.privateKey); - return this.fromPublic(key.publicKey, account.network); + return this.fromPublic(key.publicKey); }; /** @@ -204,7 +199,7 @@ WalletKey.prototype.fromImport = function fromImport(account, data) { this.name = account.name; this.account = account.accountIndex; this.witness = account.witness; - return this.fromRaw(data, account.network); + return this.fromRaw(data); }; /** @@ -231,7 +226,7 @@ WalletKey.prototype.fromRing = function fromRing(account, ring) { this.name = account.name; this.account = account.accountIndex; this.witness = account.witness; - return this.fromOptions(ring, ring.network); + return this.fromOptions(ring); }; /** diff --git a/migrate/walletdb2to3.js b/migrate/walletdb2to3.js index e2832cdf..de81b0d4 100644 --- a/migrate/walletdb2to3.js +++ b/migrate/walletdb2to3.js @@ -329,7 +329,6 @@ function keyFromRaw(data, network) { const ring = {}; const p = new BufferReader(data); - ring.network = bcoin.network.get(network); ring.witness = p.readU8() === 1; const key = p.readVarBytes(); diff --git a/test/address-test.js b/test/address-test.js index 8f6ee7b1..58062a77 100644 --- a/test/address-test.js +++ b/test/address-test.js @@ -13,7 +13,7 @@ describe('Address', function() { const p2pkh = Buffer.from(raw, 'hex'); const addr = Address.fromPubkeyhash(p2pkh); const expectedAddr = '1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX'; - assert.strictEqual(addr.toString(), expectedAddr); + assert.strictEqual(addr.toString('main'), expectedAddr); }); it('should match mainnet p2pkh address 2', () => { @@ -21,15 +21,15 @@ describe('Address', function() { const p2pkh = Buffer.from(raw, 'hex'); const addr = Address.fromPubkeyhash(p2pkh); const expectedAddr = '12MzCDwodF9G1e7jfwLXfR164RNtx4BRVG'; - assert.strictEqual(addr.toString(), expectedAddr); + assert.strictEqual(addr.toString('main'), expectedAddr); }); it('should match testnet p2pkh address', () => { const raw = '78b316a08647d5b77283e512d3603f1f1c8de68f'; const p2pkh = Buffer.from(raw, 'hex'); - const addr = Address.fromPubkeyhash(p2pkh, 'testnet'); + const addr = Address.fromPubkeyhash(p2pkh); const expectedAddr = 'mrX9vMRYLfVy1BnZbc5gZjuyaqH3ZW2ZHz'; - assert.strictEqual(addr.toString(), expectedAddr); + assert.strictEqual(addr.toString('testnet'), expectedAddr); }); it('should handle wrong p2pkh hash length', () => { @@ -59,7 +59,7 @@ describe('Address', function() { const script = Script.fromRaw(p2sh); const addr = Address.fromScript(script); const expectedAddr = '3QJmV3qfvL9SuYo34YihAf3sRCW3qSinyC'; - assert.strictEqual(addr.toString(), expectedAddr); + assert.strictEqual(addr.toString('main'), expectedAddr); }); it('should match mainnet p2sh address obtained from script hash', () => { @@ -67,7 +67,7 @@ describe('Address', function() { const p2sh = Buffer.from(raw, 'hex'); const addr = Address.fromScripthash(p2sh); const expectedAddr = '3QJmV3qfvL9SuYo34YihAf3sRCW3qSinyC'; - assert.strictEqual(addr.toString(), expectedAddr); + assert.strictEqual(addr.toString('main'), expectedAddr); }); it('should match mainnet p2sh address obtained from script 2', () => { @@ -75,15 +75,15 @@ describe('Address', function() { const p2sh = Buffer.from(raw, 'hex'); const addr = Address.fromScripthash(p2sh); const expectedAddr = '3NukJ6fYZJ5Kk8bPjycAnruZkE5Q7UW7i8'; - assert.strictEqual(addr.toString(), expectedAddr); + assert.strictEqual(addr.toString('main'), expectedAddr); }); it('should match testnet p2sh address', () => { const raw = 'c579342c2c4c9220205e2cdc285617040c924a0a'; const p2sh = Buffer.from(raw, 'hex'); - const addr = Address.fromScripthash(p2sh, 'testnet'); + const addr = Address.fromScripthash(p2sh); const expectedAddr = '2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n'; - assert.strictEqual(addr.toString(), expectedAddr); + assert.strictEqual(addr.toString('testnet'), expectedAddr); }); it('should match mainnet segwit p2wpkh v0 address', () => { @@ -91,7 +91,7 @@ describe('Address', function() { const p2wpkh = Buffer.from(raw, 'hex'); const addr = Address.fromWitnessPubkeyhash(p2wpkh); const expectedAddr = 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'; - assert.strictEqual(addr.toString(), expectedAddr); + assert.strictEqual(addr.toString('main'), expectedAddr); }); it('should match mainnet segwit p2pwsh v0 address', () => { @@ -101,16 +101,16 @@ describe('Address', function() { + '6c985678cd4d27a1' + 'b8c6329604903262', 'hex'); const addr = Address.fromWitnessScripthash(p2wpkh); - assert.strictEqual(addr.toString(), + assert.strictEqual(addr.toString('main'), 'bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3'); }); it('should match testnet segwit p2wpkh v0 address', () => { const raw = '751e76e8199196d454941c45d1b3a323f1433bd6'; const p2wpkh = Buffer.from(raw, 'hex'); - const addr = Address.fromWitnessPubkeyhash(p2wpkh, 'testnet'); + const addr = Address.fromWitnessPubkeyhash(p2wpkh); const expectedAddr = 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx'; - assert.strictEqual(addr.toString(), expectedAddr); + assert.strictEqual(addr.toString('testnet'), expectedAddr); }); it('should match testnet segwit p2pwsh v0 address', () => { @@ -119,8 +119,8 @@ describe('Address', function() { + '04bd19203356da13' + '6c985678cd4d27a1' + 'b8c6329604903262', 'hex'); - const addr = Address.fromWitnessScripthash(p2wpkh, 'testnet'); - assert.strictEqual(addr.toString(), + const addr = Address.fromWitnessScripthash(p2wpkh); + assert.strictEqual(addr.toString('testnet'), 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7'); }); @@ -130,56 +130,56 @@ describe('Address', function() { + '21b2a187905e5266' + '362b99d5e91c6ce2' + '4d165dab93e86433', 'hex'); - const addr = Address.fromWitnessScripthash(p2wpkh, 'testnet'); - assert.strictEqual(addr.toString(), + const addr = Address.fromWitnessScripthash(p2wpkh); + assert.strictEqual(addr.toString('testnet'), 'tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy'); }); it('should handle invalid segwit hrp', () => { const addr = 'tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty'; - assert.throws(() => Address.fromString(addr)); + assert.throws(() => Address.fromString(addr, 'main')); }); it('should handle invalid segwit checksum', () => { const addr = 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5'; - assert.throws(() => Address.fromString(addr)); + assert.throws(() => Address.fromString(addr, 'main')); }); it('should handle invalid segwit version', () => { const addr = 'BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2'; - assert.throws(() => Address.fromString(addr)); + assert.throws(() => Address.fromString(addr, 'main')); }); it('should handle invalid segwit program length', () => { const addr = 'bc1rw5uspcuh'; - assert.throws(() => Address.fromString(addr)); + assert.throws(() => Address.fromString(addr, 'main')); }); it('should handle invalid segwit program length 2', () => { const addr = 'bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw5' + '08d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90'; - assert.throws(() => Address.fromString(addr)); + assert.throws(() => Address.fromString(addr, 'main')); }); it('should handle invalid segwit program length for witness v0', () => { const addr = 'tb1pw508d6qejxtdg4y5r3zarqfsj6c3'; - assert.throws(() => Address.fromString(addr)); + assert.throws(() => Address.fromString(addr, 'main')); }); it('should handle segwit mixed case', () => { const addr = 'tb1qrp33g0q5c5txsp9arysrx4k6z' + 'dkfs4nce4xj0gdcccefvpysxf3q0sL5k7'; - assert.throws(() => Address.fromString(addr)); + assert.throws(() => Address.fromString(addr, 'main')); }); it('should handle segwit zero padding of more than 4 bits', () => { const addr = 'tb1pw508d6qejxtdg4y5r3zarqfsj6c3'; - assert.throws(() => Address.fromString(addr)); + assert.throws(() => Address.fromString(addr, 'main')); }); it('should handle segwit non-zero padding in 8-to-5 conversion', () => { const addr = 'tb1qrp33g0q5c5txsp9arysrx4k6' + 'zdkfs4nce4xj0gdcccefvpysxf3pjxtptv'; - assert.throws(() => Address.fromString(addr)); + assert.throws(() => Address.fromString(addr, 'main')); }); }); diff --git a/test/bech32-test.js b/test/bech32-test.js index e78f78fc..fd65d6e2 100644 --- a/test/bech32-test.js +++ b/test/bech32-test.js @@ -182,16 +182,19 @@ describe('Bech32', function() { for (const [addr, script] of validAddresses) { it(`should have valid address for ${addr}`, () => { let ret = null; + let network = null; try { - ret = Address.fromBech32(addr, 'main'); + network = 'main'; + ret = Address.fromBech32(addr, network); } catch (e) { ret = null; } if (ret === null) { try { - ret = Address.fromBech32(addr, 'testnet'); + network = 'testnet'; + ret = Address.fromBech32(addr, network); } catch (e) { ret = null; } @@ -202,7 +205,7 @@ describe('Bech32', function() { const output = createProgram(ret.version, ret.hash); assert.bufferEqual(output, script); - const recreate = ret.toBech32(); + const recreate = ret.toBech32(network); assert.strictEqual(recreate, addr.toLowerCase()); }); } diff --git a/test/hd-test.js b/test/hd-test.js index 7b1293c5..4a8698ed 100644 --- a/test/hd-test.js +++ b/test/hd-test.js @@ -29,49 +29,49 @@ describe('HD', function() { it('should create master private key', () => { const seed = Buffer.from(vectors.seed, 'hex'); const key = HD.PrivateKey.fromSeed(seed); - assert.strictEqual(key.toBase58(), vectors.master_priv); - assert.strictEqual(key.toPublic().toBase58(), vectors.master_pub); + assert.strictEqual(key.toBase58('main'), vectors.master_priv); + assert.strictEqual(key.toPublic().toBase58('main'), vectors.master_pub); master = key; }); it('should derive(0) child from master', () => { const child1 = master.derive(0); - assert.strictEqual(child1.toBase58(), vectors.child1_priv); - assert.strictEqual(child1.toPublic().toBase58(), vectors.child1_pub); + assert.strictEqual(child1.toBase58('main'), vectors.child1_priv); + assert.strictEqual(child1.toPublic().toBase58('main'), vectors.child1_pub); }); it('should derive(1) child from master public key', () => { const child2 = master.toPublic().derive(1); - assert.strictEqual(child2.toBase58(), vectors.child2_pub); + assert.strictEqual(child2.toBase58('main'), vectors.child2_pub); }); it('should derive(1) child from master', () => { const child3 = master.derive(1); - assert.strictEqual(child3.toBase58(), vectors.child3_priv); - assert.strictEqual(child3.toPublic().toBase58(), vectors.child3_pub); + assert.strictEqual(child3.toBase58('main'), vectors.child3_priv); + assert.strictEqual(child3.toPublic().toBase58('main'), vectors.child3_pub); }); it('should derive(2) child from master', () => { const child4 = master.derive(2); - assert.strictEqual(child4.toBase58(), vectors.child4_priv); - assert.strictEqual(child4.toPublic().toBase58(), vectors.child4_pub); + assert.strictEqual(child4.toBase58('main'), vectors.child4_priv); + assert.strictEqual(child4.toPublic().toBase58('main'), vectors.child4_pub); child = child4; }); it('should derive(0) child from child(2)', () => { const child5 = child.derive(0); - assert.strictEqual(child5.toBase58(), vectors.child5_priv); - assert.strictEqual(child5.toPublic().toBase58(), vectors.child5_pub); + assert.strictEqual(child5.toBase58('main'), vectors.child5_priv); + assert.strictEqual(child5.toPublic().toBase58('main'), vectors.child5_pub); }); it('should derive(1) child from child(2)', () => { const child6 = child.derive(1); - assert.strictEqual(child6.toBase58(), vectors.child6_priv); - assert.strictEqual(child6.toPublic().toBase58(), vectors.child6_pub); + assert.strictEqual(child6.toBase58('main'), vectors.child6_priv); + assert.strictEqual(child6.toPublic().toBase58('main'), vectors.child6_pub); }); it('should derive correctly when private key has leading zeros', () => { - const key = HD.PrivateKey.fromBase58(vectors.zero_priv); + const key = HD.PrivateKey.fromBase58(vectors.zero_priv, 'main'); assert.strictEqual(key.privateKey.toString('hex'), '00000055378cf5fafb56c711c674143f9b0ee82ab0ba2924f19b64f5ae7cdbfd'); @@ -82,17 +82,19 @@ describe('HD', function() { }); it('should deserialize master private key', () => { - HD.PrivateKey.fromBase58(master.toBase58()); + HD.PrivateKey.fromBase58(master.toBase58('main'), 'main'); }); it('should deserialize master public key', () => { - HD.PublicKey.fromBase58(master.toPublic().toBase58()); + HD.PublicKey.fromBase58(master.toPublic().toBase58('main'), 'main'); }); it('should deserialize and reserialize json', () => { const key = HD.generate(); const json = key.toJSON(); - base58Equal(HD.fromJSON(json).toBase58(), key.toBase58()); + base58Equal( + HD.fromJSON(json, 'main').toBase58('main'), + key.toBase58('main')); }); for (const vector of [vector1, vector2]) { @@ -103,8 +105,8 @@ describe('HD', function() { const key = HD.PrivateKey.fromSeed(seed); const pub = key.toPublic(); - base58Equal(key.toBase58(), vector.m.prv); - base58Equal(pub.toBase58(), vector.m.pub); + base58Equal(key.toBase58('main'), vector.m.prv); + base58Equal(pub.toBase58('main'), vector.m.pub); master = key; }); @@ -118,8 +120,8 @@ describe('HD', function() { it(`should derive ${path} from master`, () => { const key = master.derivePath(path); const pub = key.toPublic(); - base58Equal(key.toBase58(), kp.prv); - base58Equal(pub.toBase58(), kp.pub); + base58Equal(key.toBase58('main'), kp.prv); + base58Equal(pub.toBase58('main'), kp.pub); }); } } diff --git a/test/http-test.js b/test/http-test.js index 748f2042..0f7cc4a6 100644 --- a/test/http-test.js +++ b/test/http-test.js @@ -60,10 +60,10 @@ describe('HTTP', function() { it('should get wallet info', async () => { const info = await wallet.getInfo(); assert.strictEqual(info.id, 'test'); - assert.typeOf(info.account, 'object'); - const str = info.account.receiveAddress; + const acct = await wallet.getAccount('default'); + const str = acct.receiveAddress; assert.typeOf(str, 'string'); - addr = Address.fromString(str); + addr = Address.fromString(str, node.network); }); it('should fill with funds', async () => { @@ -95,7 +95,7 @@ describe('HTTP', function() { await co.timeout(300); assert(receive); - assert.strictEqual(receive.id, 'test'); + assert.strictEqual(receive.name, 'default'); assert.strictEqual(receive.type, 'pubkeyhash'); assert.strictEqual(receive.branch, 0); assert(balance); @@ -116,7 +116,7 @@ describe('HTTP', function() { rate: 10000, outputs: [{ value: 10000, - address: addr.toString() + address: addr.toString(node.network) }] }; @@ -232,11 +232,11 @@ describe('HTTP', function() { it('should validate an address', async () => { const json = await wallet.client.rpc.execute('validateaddress', [ - addr.toString() + addr.toString(node.network) ]); assert.deepStrictEqual(json, { isvalid: true, - address: addr.toString(), + address: addr.toString(node.network), scriptPubKey: Script.fromAddress(addr).toRaw().toString('hex'), ismine: false, iswatchonly: false diff --git a/test/input-test.js b/test/input-test.js index 98101e37..3ec7a2ff 100644 --- a/test/input-test.js +++ b/test/input-test.js @@ -51,7 +51,7 @@ describe('Input', function() { const input = Input.fromRaw(raw); const type = input.getType(); - const addr = input.getAddress().toBase58(); + const addr = input.getAddress().toBase58('main'); const prevout = input.prevout.toRaw(); assert.strictEqual(type, 'pubkeyhash'); @@ -100,7 +100,7 @@ describe('Input', function() { const type = input.getType(); const subtype = input.getSubtype(); - const addr = input.getAddress().toBase58(); + const addr = input.getAddress().toBase58('main'); const prevout = input.prevout.toRaw(); const redeem = input.getRedeem().toRaw(); diff --git a/test/keyring-test.js b/test/keyring-test.js index 87cc0c2f..9f37701d 100644 --- a/test/keyring-test.js +++ b/test/keyring-test.js @@ -7,10 +7,10 @@ const assert = require('./util/assert'); const KeyRing = require('../lib/primitives/keyring'); const uncompressed = KeyRing.fromSecret( - '5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss'); + '5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss', 'main'); const compressed = KeyRing.fromSecret( - 'L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1'); + 'L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1', 'main'); describe('KeyRing', function() { it('should get uncompressed public key', () => { @@ -23,13 +23,13 @@ describe('KeyRing', function() { it('should get uncompressed public key address', () => { assert.strictEqual( '1HZwkjkeaoZfTSaJxDw6aKkxp45agDiEzN', - uncompressed.getKeyAddress('base58')); + uncompressed.getKeyAddress('base58', 'main')); }); it('should get uncompressed WIF', () => { assert.strictEqual( '5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss', - uncompressed.toSecret()); + uncompressed.toSecret('main')); }); it('should get compressed public key', () => { @@ -41,12 +41,12 @@ describe('KeyRing', function() { it('should get compressed public key address', () => { assert.strictEqual( '1F3sAm6ZtwLAUnj7d38pGFxtP3RVEvtsbV', - compressed.getKeyAddress('base58')); + compressed.getKeyAddress('base58', 'main')); }); it('should get compressed WIF', () => { assert.strictEqual( 'L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1', - compressed.toSecret()); + compressed.toSecret('main')); }); }); diff --git a/test/mnemonic-test.js b/test/mnemonic-test.js index 10429cee..2ecc77a4 100644 --- a/test/mnemonic-test.js +++ b/test/mnemonic-test.js @@ -36,7 +36,7 @@ describe('Mnemonic', function() { assert.bufferEqual(mnemonic.toSeed(), seed); const key = HDPrivateKey.fromMnemonic(mnemonic); - assert.strictEqual(key.toBase58(), xpriv); + assert.strictEqual(key.toBase58('main'), xpriv); }); it(`should create a ${language} mnemonic from phrase (${i})`, () => { @@ -51,7 +51,7 @@ describe('Mnemonic', function() { assert.bufferEqual(mnemonic.toSeed(), seed); const key = HDPrivateKey.fromMnemonic(mnemonic); - assert.strictEqual(key.toBase58(), xpriv); + assert.strictEqual(key.toBase58('main'), xpriv); }); i += 1; diff --git a/test/node-test.js b/test/node-test.js index 3bac5733..b1d37d7b 100644 --- a/test/node-test.js +++ b/test/node-test.js @@ -551,17 +551,15 @@ describe('Node', function() { it('should validate an address', async () => { const addr = new Address(); - addr.network = node.network; - const json = await node.rpc.call({ method: 'validateaddress', - params: [addr.toString()] + params: [addr.toString(node.network)] }, {}); assert.deepStrictEqual(json.result, { isvalid: true, - address: addr.toString(), - scriptPubKey: Script.fromAddress(addr).toJSON(), + address: addr.toString(node.network), + scriptPubKey: Script.fromAddress(addr, node.network).toJSON(), ismine: false, iswatchonly: false }); diff --git a/test/util/memwallet.js b/test/util/memwallet.js index a2364df5..917abf73 100644 --- a/test/util/memwallet.js +++ b/test/util/memwallet.js @@ -87,8 +87,10 @@ MemWallet.prototype.init = function init() { if (!this.master) this.master = HD.PrivateKey.generate(); - if (!this.key) - this.key = this.master.deriveAccount(44, this.account); + if (!this.key) { + const type = this.network.keyPrefix.coinType; + this.key = this.master.deriveAccount(44, type, this.account); + } i = this.receiveDepth; while (i--) @@ -132,7 +134,8 @@ MemWallet.prototype.derivePath = function derivePath(path) { }; MemWallet.prototype.deriveKey = function deriveKey(branch, index) { - let key = this.master.deriveAccount(44, this.account); + const type = this.network.keyPrefix.coinType; + let key = this.master.deriveAccount(44, type, this.account); key = key.derive(branch).derive(index); const ring = new KeyRing({ network: this.network, diff --git a/test/wallet-test.js b/test/wallet-test.js index d7245528..327027f3 100644 --- a/test/wallet-test.js +++ b/test/wallet-test.js @@ -73,7 +73,7 @@ async function testP2PKH(witness, nesting) { const wallet = await wdb.create({ witness }); const waddr = await wallet.receiveAddress(); - const addr = Address.fromString(waddr.toString()); + const addr = Address.fromString(waddr.toString(wdb.network), wdb.network); assert.strictEqual(addr.type, type); assert.strictEqual(addr.type, waddr.type); @@ -235,19 +235,19 @@ describe('Wallet', function() { const addr1 = await wallet.receiveAddress(); assert(addr1); - const str = addr1.toString(); - const addr2 = Address.fromString(str); + const str = addr1.toString(wdb.network); + const addr2 = Address.fromString(str, wdb.network); assert(addr2.equals(addr1)); }); it('should validate existing address', () => { - assert(Address.fromString('1KQ1wMNwXHUYj1nV2xzsRcKUH8gVFpTFUc')); + assert(Address.fromString('1KQ1wMNwXHUYj1nV2xzsRcKUH8gVFpTFUc', 'main')); }); it('should fail to validate invalid address', () => { assert.throws(() => { - Address.fromString('1KQ1wMNwXHUYj1nv2xzsRcKUH8gVFpTFUc'); + Address.fromString('1KQ1wMNwXHUYj1nv2xzsRcKUH8gVFpTFUc', 'main'); }); }); @@ -277,7 +277,7 @@ describe('Wallet', function() { }); const xpriv = HD.PrivateKey.generate(); - const key = xpriv.deriveAccount(44, 0).toPublic(); + const key = xpriv.deriveAccount(44, 0, 0).toPublic(); await wallet.addSharedKey(0, key); @@ -1303,7 +1303,7 @@ describe('Wallet', function() { const details = await wallet.toDetails(txs); assert(details.some((tx) => { - return tx.toJSON().outputs[0].path.name === 'foo'; + return tx.toJSON(wdb.network).outputs[0].path.name === 'foo'; })); });