sapling sign/broadcash, update package
This commit is contained in:
parent
e97ae1dd2e
commit
a12f3ce5ed
5
index.js
5
index.js
|
@ -13,8 +13,8 @@ bitcore.versionGuard = function(version) {
|
|||
//throw new Error(message);
|
||||
}
|
||||
};
|
||||
bitcore.versionGuard(global._bitcore);
|
||||
global._bitcore = bitcore.version;
|
||||
bitcore.versionGuard(global._bitcoreZec);
|
||||
global._bitcoreZec = bitcore.version;
|
||||
|
||||
// crypto
|
||||
bitcore.crypto = {};
|
||||
|
@ -67,5 +67,4 @@ bitcore.deps.elliptic = require('elliptic');
|
|||
bitcore.deps._ = require('lodash');
|
||||
|
||||
// Internal usage, exposed for testing/advanced tweaking
|
||||
bitcore._HDKeyCache = require('./lib/hdkeycache');
|
||||
bitcore.Transaction.sighash = require('./lib/transaction/sighash');
|
||||
|
|
|
@ -196,10 +196,14 @@ Address._transformBuffer = function(buffer, network, type) {
|
|||
throw new TypeError('Address buffers must be exactly 22 bytes.');
|
||||
}
|
||||
|
||||
network = Networks.get(network);
|
||||
var networkObj = Networks.get(network);
|
||||
var bufferVersion = Address._classifyFromVersion(buffer);
|
||||
|
||||
if (!bufferVersion.network || (network && network !== bufferVersion.network)) {
|
||||
if (network && !networkObj) {
|
||||
throw new TypeError('Unknown network');
|
||||
}
|
||||
|
||||
if (!bufferVersion.network || (networkObj && networkObj !== bufferVersion.network)) {
|
||||
throw new TypeError('Address has mismatched network type.');
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ function Block(arg) {
|
|||
}
|
||||
|
||||
// https://github.com/bitcoin/bitcoin/blob/b5fa132329f0377d787a4a21c1686609c2bfaece/src/primitives/block.h#L14
|
||||
Block.MAX_BLOCK_SIZE = 1000000;
|
||||
Block.MAX_BLOCK_SIZE = 2000000;
|
||||
|
||||
/**
|
||||
* @param {*} - A Buffer, JSON string or Object
|
||||
|
|
|
@ -9,8 +9,7 @@ var Hash = require('../crypto/hash');
|
|||
var JSUtil = require('../util/js');
|
||||
var $ = require('../util/preconditions');
|
||||
|
||||
// Mainnet 0x1f07ffff, Testnet 0x2007ffff
|
||||
var GENESIS_BITS = 0x2007ffff;
|
||||
var GENESIS_BITS = 0x1f07ffff;
|
||||
|
||||
/**
|
||||
* Instantiate a BlockHeader from a Buffer, JSON object, or Object with
|
||||
|
|
|
@ -8,6 +8,7 @@ var BufferWriter = require('../encoding/bufferwriter');
|
|||
var Hash = require('../crypto/hash');
|
||||
var JSUtil = require('../util/js');
|
||||
var Transaction = require('../transaction');
|
||||
var errors = require('../errors');
|
||||
var $ = require('../util/preconditions');
|
||||
|
||||
/**
|
||||
|
@ -149,19 +150,53 @@ MerkleBlock.prototype.validMerkleTree = function validMerkleTree() {
|
|||
return BufferUtil.equals(root, this.header.merkleRoot);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a list of all the txs hash that match the filter
|
||||
* @returns {Array} - txs hash that match the filter
|
||||
*/
|
||||
MerkleBlock.prototype.filterdTxsHash = function filterdTxsHash() {
|
||||
$.checkState(_.isArray(this.flags), 'MerkleBlock flags is not an array');
|
||||
$.checkState(_.isArray(this.hashes), 'MerkleBlock hashes is not an array');
|
||||
|
||||
// Can't have more hashes than numTransactions
|
||||
if(this.hashes.length > this.numTransactions) {
|
||||
throw new errors.MerkleBlock.InvalidMerkleTree();
|
||||
}
|
||||
|
||||
// Can't have more flag bits than num hashes
|
||||
if(this.flags.length * 8 < this.hashes.length) {
|
||||
throw new errors.MerkleBlock.InvalidMerkleTree();
|
||||
}
|
||||
|
||||
// If there is only one hash the filter do not match any txs in the block
|
||||
if(this.hashes.length === 1) {
|
||||
return [];
|
||||
};
|
||||
|
||||
var height = this._calcTreeHeight();
|
||||
var opts = { hashesUsed: 0, flagBitsUsed: 0 };
|
||||
var txs = this._traverseMerkleTree(height, 0, opts, true);
|
||||
if(opts.hashesUsed !== this.hashes.length) {
|
||||
throw new errors.MerkleBlock.InvalidMerkleTree();
|
||||
}
|
||||
return txs;
|
||||
};
|
||||
|
||||
/**
|
||||
* Traverse a the tree in this MerkleBlock, validating it along the way
|
||||
* Modeled after Bitcoin Core merkleblock.cpp TraverseAndExtract()
|
||||
* @param {Number} - depth - Current height
|
||||
* @param {Number} - pos - Current position in the tree
|
||||
* @param {Object} - opts - Object with values that need to be mutated throughout the traversal
|
||||
* @param {Boolean} - checkForTxs - if true return opts.txs else return the Merkle Hash
|
||||
* @param {Number} - opts.flagBitsUsed - Number of flag bits used, should start at 0
|
||||
* @param {Number} - opts.hashesUsed - Number of hashes used, should start at 0
|
||||
* @param {Array} - opts.txs - Will finish populated by transactions found during traversal
|
||||
* @param {Array} - opts.txs - Will finish populated by transactions found during traversal that match the filter
|
||||
* @returns {Buffer|null} - Buffer containing the Merkle Hash for that height
|
||||
* @returns {Array} - transactions found during traversal that match the filter
|
||||
* @private
|
||||
*/
|
||||
MerkleBlock.prototype._traverseMerkleTree = function traverseMerkleTree(depth, pos, opts) {
|
||||
MerkleBlock.prototype._traverseMerkleTree = function traverseMerkleTree(depth, pos, opts, checkForTxs) {
|
||||
/* jshint maxcomplexity: 12*/
|
||||
/* jshint maxstatements: 20 */
|
||||
|
||||
|
@ -169,6 +204,7 @@ MerkleBlock.prototype._traverseMerkleTree = function traverseMerkleTree(depth, p
|
|||
opts.txs = opts.txs || [];
|
||||
opts.flagBitsUsed = opts.flagBitsUsed || 0;
|
||||
opts.hashesUsed = opts.hashesUsed || 0;
|
||||
var checkForTxs = checkForTxs || false;
|
||||
|
||||
if(opts.flagBitsUsed > this.flags.length * 8) {
|
||||
return null;
|
||||
|
@ -189,7 +225,11 @@ MerkleBlock.prototype._traverseMerkleTree = function traverseMerkleTree(depth, p
|
|||
if(pos*2+1 < this._calcTreeWidth(depth-1)) {
|
||||
right = this._traverseMerkleTree(depth-1, pos*2+1, opts);
|
||||
}
|
||||
return Hash.sha256sha256(new Buffer.concat([left, right]));
|
||||
if (checkForTxs){
|
||||
return opts.txs;
|
||||
} else {
|
||||
return Hash.sha256sha256(new Buffer.concat([left, right]));
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ ECDSA.prototype.toPublicKey = function() {
|
|||
}
|
||||
|
||||
// Compute -e from e
|
||||
var eNeg = e.neg().mod(n);
|
||||
var eNeg = e.neg().umod(n);
|
||||
|
||||
// 1.6.1 Compute Q = r^-1 (sR - eG)
|
||||
// Q = r^-1 (sR + -eG)
|
||||
|
@ -174,15 +174,15 @@ ECDSA.prototype.sigError = function() {
|
|||
} : undefined);
|
||||
var n = Point.getN();
|
||||
var sinv = s.invm(n);
|
||||
var u1 = sinv.mul(e).mod(n);
|
||||
var u2 = sinv.mul(r).mod(n);
|
||||
var u1 = sinv.mul(e).umod(n);
|
||||
var u2 = sinv.mul(r).umod(n);
|
||||
|
||||
var p = Point.getG().mulAdd(u1, this.pubkey.point, u2);
|
||||
if (p.isInfinity()) {
|
||||
return 'p is infinity';
|
||||
}
|
||||
|
||||
if (p.getX().mod(n).cmp(r) !== 0) {
|
||||
if (p.getX().umod(n).cmp(r) !== 0) {
|
||||
return 'Invalid signature';
|
||||
} else {
|
||||
return false;
|
||||
|
@ -211,8 +211,8 @@ ECDSA.prototype._findSignature = function(d, e) {
|
|||
badrs++;
|
||||
k = this.k;
|
||||
Q = G.mul(k);
|
||||
r = Q.x.mod(N);
|
||||
s = k.invm(N).mul(e.add(d.mul(r))).mod(N);
|
||||
r = Q.x.umod(N);
|
||||
s = k.invm(N).mul(e.add(d.mul(r))).umod(N);
|
||||
} while (r.cmp(BN.Zero) <= 0 || s.cmp(BN.Zero) <= 0);
|
||||
|
||||
s = ECDSA.toLowS(s);
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
var BN = require('./bn');
|
||||
var BufferUtil = require('../util/buffer');
|
||||
var ec = require('elliptic').curves.secp256k1;
|
||||
|
||||
var EC = require('elliptic').ec;
|
||||
var ec = new EC('secp256k1');
|
||||
var ecPoint = ec.curve.point.bind(ec.curve);
|
||||
var ecPointFromX = ec.curve.pointFromX.bind(ec.curve);
|
||||
|
||||
|
@ -19,7 +21,11 @@ var ecPointFromX = ec.curve.pointFromX.bind(ec.curve);
|
|||
* @constructor
|
||||
*/
|
||||
var Point = function Point(x, y, isRed) {
|
||||
var point = ecPoint(x, y, isRed);
|
||||
try {
|
||||
var point = ecPoint(x, y, isRed);
|
||||
} catch (e) {
|
||||
throw new Error('Invalid Point');
|
||||
}
|
||||
point.validate();
|
||||
return point;
|
||||
};
|
||||
|
@ -36,7 +42,11 @@ Point.prototype = Object.getPrototypeOf(ec.curve.point());
|
|||
* @returns {Point} An instance of Point
|
||||
*/
|
||||
Point.fromX = function fromX(odd, x){
|
||||
var point = ecPointFromX(odd, x);
|
||||
try {
|
||||
var point = ecPointFromX(x, odd);
|
||||
} catch (e) {
|
||||
throw new Error('Invalid X');
|
||||
}
|
||||
point.validate();
|
||||
return point;
|
||||
};
|
||||
|
@ -63,7 +73,8 @@ Point.getN = function getN() {
|
|||
return new BN(ec.curve.n.toArray());
|
||||
};
|
||||
|
||||
Point.prototype._getX = Point.prototype.getX;
|
||||
if (!Point.prototype._getX)
|
||||
Point.prototype._getX = Point.prototype.getX;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -75,7 +86,8 @@ Point.prototype.getX = function getX() {
|
|||
return new BN(this._getX().toArray());
|
||||
};
|
||||
|
||||
Point.prototype._getY = Point.prototype.getY;
|
||||
if (!Point.prototype._getY)
|
||||
Point.prototype._getY = Point.prototype.getY;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -102,22 +114,17 @@ Point.prototype.validate = function validate() {
|
|||
throw new Error('Point cannot be equal to Infinity');
|
||||
}
|
||||
|
||||
if (this.getX().cmp(BN.Zero) === 0 || this.getY().cmp(BN.Zero) === 0){
|
||||
throw new Error('Invalid x,y value for curve, cannot equal 0.');
|
||||
var p2;
|
||||
try {
|
||||
p2 = ecPointFromX(this.getX(), this.getY().isOdd());
|
||||
} catch (e) {
|
||||
throw new Error('Point does not lie on the curve');
|
||||
}
|
||||
|
||||
var p2 = ecPointFromX(this.getY().isOdd(), this.getX());
|
||||
|
||||
if (p2.y.cmp(this.y) !== 0) {
|
||||
throw new Error('Invalid y value for curve.');
|
||||
}
|
||||
|
||||
var xValidRange = (this.getX().gt(BN.Minus1) && this.getX().lt(Point.getN()));
|
||||
var yValidRange = (this.getY().gt(BN.Minus1) && this.getY().lt(Point.getN()));
|
||||
|
||||
if ( !xValidRange || !yValidRange ) {
|
||||
throw new Error('Point does not lie on the curve');
|
||||
}
|
||||
|
||||
//todo: needs test case
|
||||
if (!(this.mul(Point.getN()).isInfinity())) {
|
||||
|
|
|
@ -26,7 +26,7 @@ Base58.validCharacters = function validCharacters(chars) {
|
|||
if (buffer.Buffer.isBuffer(chars)) {
|
||||
chars = chars.toString();
|
||||
}
|
||||
return _.all(_.map(chars, function(char) { return _.contains(ALPHABET, char); }));
|
||||
return _.every(_.map(chars, function(char) { return _.includes(ALPHABET, char); }));
|
||||
};
|
||||
|
||||
Base58.prototype.set = function(obj) {
|
||||
|
|
|
@ -83,6 +83,12 @@ BufferReader.prototype.readUInt32LE = function() {
|
|||
return val;
|
||||
};
|
||||
|
||||
BufferReader.prototype.readInt32LE = function() {
|
||||
var val = this.buf.readInt32LE(this.pos);
|
||||
this.pos = this.pos + 4;
|
||||
return val;
|
||||
};
|
||||
|
||||
BufferReader.prototype.readUInt64BEBN = function() {
|
||||
var buf = this.buf.slice(this.pos, this.pos + 8);
|
||||
var bn = BN.fromBuffer(buf);
|
||||
|
@ -111,6 +117,12 @@ BufferReader.prototype.readUInt64LEBN = function() {
|
|||
return bn;
|
||||
};
|
||||
|
||||
BufferReader.prototype.readUInt64LE = function() {
|
||||
var val = this.buf.readUInt32LE(this.pos) + this.buf.readUInt32LE(this.pos + 4) * 0x100000000
|
||||
this.pos = this.pos + 8;
|
||||
return val;
|
||||
};
|
||||
|
||||
BufferReader.prototype.readVarintNum = function() {
|
||||
var first = this.readUInt8();
|
||||
switch (first) {
|
||||
|
|
|
@ -6,6 +6,7 @@ var assert = require('assert');
|
|||
var BufferWriter = function BufferWriter(obj) {
|
||||
if (!(this instanceof BufferWriter))
|
||||
return new BufferWriter(obj);
|
||||
this.bufLen = 0;
|
||||
if (obj)
|
||||
this.set(obj);
|
||||
else
|
||||
|
@ -14,6 +15,7 @@ var BufferWriter = function BufferWriter(obj) {
|
|||
|
||||
BufferWriter.prototype.set = function(obj) {
|
||||
this.bufs = obj.bufs || this.bufs || [];
|
||||
this.bufLen = this.bufs.reduce(function(prev, buf){ return prev + buf.length; }, 0);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
@ -22,18 +24,20 @@ BufferWriter.prototype.toBuffer = function() {
|
|||
};
|
||||
|
||||
BufferWriter.prototype.concat = function() {
|
||||
return Buffer.concat(this.bufs);
|
||||
return Buffer.concat(this.bufs, this.bufLen);
|
||||
};
|
||||
|
||||
BufferWriter.prototype.write = function(buf) {
|
||||
assert(bufferUtil.isBuffer(buf));
|
||||
this.bufs.push(buf);
|
||||
this.bufLen += buf.length;
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferWriter.prototype.writeReverse = function(buf) {
|
||||
assert(bufferUtil.isBuffer(buf));
|
||||
this.bufs.push(bufferUtil.reverse(buf));
|
||||
this.bufLen += buf.length;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
@ -91,6 +95,14 @@ BufferWriter.prototype.writeUInt64LEBN = function(bn) {
|
|||
return this;
|
||||
};
|
||||
|
||||
BufferWriter.prototype.writeUInt64LE = function(n) {
|
||||
var buf = new Buffer(8);
|
||||
buf.writeUInt32LE(n & -1, 0);
|
||||
buf.writeUInt32LE(Math.floor(n / 0x100000000), 4);
|
||||
this.write(buf);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferWriter.prototype.writeVarintNum = function(n) {
|
||||
var buf = BufferWriter.varintBufNum(n);
|
||||
this.write(buf);
|
||||
|
|
|
@ -44,6 +44,13 @@ module.exports = [{
|
|||
'name': 'InvalidRate',
|
||||
'message': 'Invalid exchange rate: {0}'
|
||||
}]
|
||||
}, {
|
||||
name: 'MerkleBlock',
|
||||
message: 'Internal Error on MerkleBlock {0}',
|
||||
errors: [{
|
||||
'name': 'InvalidMerkleTree',
|
||||
'message': 'This MerkleBlock contain an invalid Merkle Tree'
|
||||
}]
|
||||
}, {
|
||||
name: 'Transaction',
|
||||
message: 'Internal Error on Transaction {0}',
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
_cache: {},
|
||||
_count: 0,
|
||||
_eraseIndex: 0,
|
||||
_usedList: {},
|
||||
_usedIndex: {},
|
||||
_CACHE_SIZE: 5000,
|
||||
|
||||
get: function(xkey, number, hardened) {
|
||||
hardened = !!hardened;
|
||||
var key = xkey + '/' + number + '/' + hardened;
|
||||
if (this._cache[key]) {
|
||||
this._cacheHit(key);
|
||||
return this._cache[key];
|
||||
}
|
||||
},
|
||||
set: function(xkey, number, hardened, derived) {
|
||||
hardened = !!hardened;
|
||||
var key = xkey + '/' + number + '/' + hardened;
|
||||
this._cache[key] = derived;
|
||||
this._cacheHit(key);
|
||||
},
|
||||
_cacheHit: function(key) {
|
||||
if (this._usedIndex[key]) {
|
||||
delete this._usedList[this._usedIndex[key]];
|
||||
}
|
||||
this._usedList[this._count] = key;
|
||||
this._usedIndex[key] = this._count;
|
||||
this._count++;
|
||||
this._cacheRemove();
|
||||
},
|
||||
_cacheRemove: function() {
|
||||
while (this._eraseIndex < this._count - this._CACHE_SIZE) {
|
||||
if (this._usedList[this._eraseIndex]) {
|
||||
var removeKey = this._usedList[this._eraseIndex];
|
||||
delete this._usedIndex[removeKey];
|
||||
delete this._cache[removeKey];
|
||||
}
|
||||
delete this._usedList[this._eraseIndex];
|
||||
this._eraseIndex++;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -11,7 +11,6 @@ var Base58 = require('./encoding/base58');
|
|||
var Base58Check = require('./encoding/base58check');
|
||||
var Hash = require('./crypto/hash');
|
||||
var Network = require('./networks');
|
||||
var HDKeyCache = require('./hdkeycache');
|
||||
var Point = require('./crypto/point');
|
||||
var PrivateKey = require('./privatekey');
|
||||
var Random = require('./crypto/random');
|
||||
|
@ -75,7 +74,7 @@ function HDPrivateKey(arg) {
|
|||
HDPrivateKey.isValidPath = function(arg, hardened) {
|
||||
if (_.isString(arg)) {
|
||||
var indexes = HDPrivateKey._getDerivationIndexes(arg);
|
||||
return indexes !== null && _.all(indexes, HDPrivateKey.isValidPath);
|
||||
return indexes !== null && _.every(indexes, HDPrivateKey.isValidPath);
|
||||
}
|
||||
|
||||
if (_.isNumber(arg)) {
|
||||
|
@ -100,11 +99,11 @@ HDPrivateKey._getDerivationIndexes = function(path) {
|
|||
var steps = path.split('/');
|
||||
|
||||
// Special cases:
|
||||
if (_.contains(HDPrivateKey.RootElementAlias, path)) {
|
||||
if (_.includes(HDPrivateKey.RootElementAlias, path)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!_.contains(HDPrivateKey.RootElementAlias, steps[0])) {
|
||||
if (!_.includes(HDPrivateKey.RootElementAlias, steps[0])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -124,10 +123,13 @@ HDPrivateKey._getDerivationIndexes = function(path) {
|
|||
return index;
|
||||
});
|
||||
|
||||
return _.any(indexes, isNaN) ? null : indexes;
|
||||
return _.some(indexes, isNaN) ? null : indexes;
|
||||
};
|
||||
|
||||
/**
|
||||
* WARNING: This method is deprecated. Use deriveChild or deriveNonCompliantChild instead. This is not BIP32 compliant
|
||||
*
|
||||
*
|
||||
* Get a derived child based on a string or number.
|
||||
*
|
||||
* If the first argument is a string, it's parsed as the full path of
|
||||
|
@ -151,6 +153,39 @@ HDPrivateKey._getDerivationIndexes = function(path) {
|
|||
* @param {boolean?} hardened
|
||||
*/
|
||||
HDPrivateKey.prototype.derive = function(arg, hardened) {
|
||||
return this.deriveNonCompliantChild(arg, hardened);
|
||||
};
|
||||
|
||||
/**
|
||||
* WARNING: This method will not be officially supported until v1.0.0.
|
||||
*
|
||||
*
|
||||
* Get a derived child based on a string or number.
|
||||
*
|
||||
* If the first argument is a string, it's parsed as the full path of
|
||||
* derivation. Valid values for this argument include "m" (which returns the
|
||||
* same private key), "m/0/1/40/2'/1000", where the ' quote means a hardened
|
||||
* derivation.
|
||||
*
|
||||
* If the first argument is a number, the child with that index will be
|
||||
* derived. If the second argument is truthy, the hardened version will be
|
||||
* derived. See the example usage for clarification.
|
||||
*
|
||||
* WARNING: The `nonCompliant` option should NOT be used, except for older implementation
|
||||
* that used a derivation strategy that used a non-zero padded private key.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* var parent = new HDPrivateKey('xprv...');
|
||||
* var child_0_1_2h = parent.deriveChild(0).deriveChild(1).deriveChild(2, true);
|
||||
* var copy_of_child_0_1_2h = parent.deriveChild("m/0/1/2'");
|
||||
* assert(child_0_1_2h.xprivkey === copy_of_child_0_1_2h);
|
||||
* ```
|
||||
*
|
||||
* @param {string|number} arg
|
||||
* @param {boolean?} hardened
|
||||
*/
|
||||
HDPrivateKey.prototype.deriveChild = function(arg, hardened) {
|
||||
if (_.isNumber(arg)) {
|
||||
return this._deriveWithNumber(arg, hardened);
|
||||
} else if (_.isString(arg)) {
|
||||
|
@ -160,7 +195,33 @@ HDPrivateKey.prototype.derive = function(arg, hardened) {
|
|||
}
|
||||
};
|
||||
|
||||
HDPrivateKey.prototype._deriveWithNumber = function(index, hardened) {
|
||||
/**
|
||||
* WARNING: This method will not be officially supported until v1.0.0
|
||||
*
|
||||
*
|
||||
* WARNING: If this is a new implementation you should NOT use this method, you should be using
|
||||
* `derive` instead.
|
||||
*
|
||||
* This method is explicitly for use and compatibility with an implementation that
|
||||
* was not compliant with BIP32 regarding the derivation algorithm. The private key
|
||||
* must be 32 bytes hashing, and this implementation will use the non-zero padded
|
||||
* serialization of a private key, such that it's still possible to derive the privateKey
|
||||
* to recover those funds.
|
||||
*
|
||||
* @param {string|number} arg
|
||||
* @param {boolean?} hardened
|
||||
*/
|
||||
HDPrivateKey.prototype.deriveNonCompliantChild = function(arg, hardened) {
|
||||
if (_.isNumber(arg)) {
|
||||
return this._deriveWithNumber(arg, hardened, true);
|
||||
} else if (_.isString(arg)) {
|
||||
return this._deriveFromString(arg, true);
|
||||
} else {
|
||||
throw new hdErrors.InvalidDerivationArgument(arg);
|
||||
}
|
||||
};
|
||||
|
||||
HDPrivateKey.prototype._deriveWithNumber = function(index, hardened, nonCompliant) {
|
||||
/* jshint maxstatements: 20 */
|
||||
/* jshint maxcomplexity: 10 */
|
||||
if (!HDPrivateKey.isValidPath(index, hardened)) {
|
||||
|
@ -172,15 +233,18 @@ HDPrivateKey.prototype._deriveWithNumber = function(index, hardened) {
|
|||
index += HDPrivateKey.Hardened;
|
||||
}
|
||||
|
||||
var cached = HDKeyCache.get(this.xprivkey, index, hardened);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
var indexBuffer = BufferUtil.integerAsBuffer(index);
|
||||
var data;
|
||||
if (hardened) {
|
||||
data = BufferUtil.concat([new buffer.Buffer([0]), this.privateKey.toBuffer(), indexBuffer]);
|
||||
if (hardened && nonCompliant) {
|
||||
// The private key serialization in this case will not be exactly 32 bytes and can be
|
||||
// any value less, and the value is not zero-padded.
|
||||
var nonZeroPadded = this.privateKey.bn.toBuffer();
|
||||
data = BufferUtil.concat([new buffer.Buffer([0]), nonZeroPadded, indexBuffer]);
|
||||
} else if (hardened) {
|
||||
// This will use a 32 byte zero padded serialization of the private key
|
||||
var privateKeyBuffer = this.privateKey.bn.toBuffer({size: 32});
|
||||
assert(privateKeyBuffer.length === 32, 'length of private key buffer is expected to be 32 bytes');
|
||||
data = BufferUtil.concat([new buffer.Buffer([0]), privateKeyBuffer, indexBuffer]);
|
||||
} else {
|
||||
data = BufferUtil.concat([this.publicKey.toBuffer(), indexBuffer]);
|
||||
}
|
||||
|
@ -190,10 +254,15 @@ HDPrivateKey.prototype._deriveWithNumber = function(index, hardened) {
|
|||
});
|
||||
var chainCode = hash.slice(32, 64);
|
||||
|
||||
var privateKey = leftPart.add(this.privateKey.toBigNumber()).mod(Point.getN()).toBuffer({
|
||||
var privateKey = leftPart.add(this.privateKey.toBigNumber()).umod(Point.getN()).toBuffer({
|
||||
size: 32
|
||||
});
|
||||
|
||||
if (!PrivateKey.isValid(privateKey)) {
|
||||
// Index at this point is already hardened, we can pass null as the hardened arg
|
||||
return this._deriveWithNumber(index + 1, null, nonCompliant);
|
||||
}
|
||||
|
||||
var derived = new HDPrivateKey({
|
||||
network: this.network,
|
||||
depth: this.depth + 1,
|
||||
|
@ -202,18 +271,18 @@ HDPrivateKey.prototype._deriveWithNumber = function(index, hardened) {
|
|||
chainCode: chainCode,
|
||||
privateKey: privateKey
|
||||
});
|
||||
HDKeyCache.set(this.xprivkey, index, hardened, derived);
|
||||
|
||||
return derived;
|
||||
};
|
||||
|
||||
HDPrivateKey.prototype._deriveFromString = function(path) {
|
||||
HDPrivateKey.prototype._deriveFromString = function(path, nonCompliant) {
|
||||
if (!HDPrivateKey.isValidPath(path)) {
|
||||
throw new hdErrors.InvalidPath(path);
|
||||
}
|
||||
|
||||
var indexes = HDPrivateKey._getDerivationIndexes(path);
|
||||
var derived = indexes.reduce(function(prev, index) {
|
||||
return prev._deriveWithNumber(index);
|
||||
return prev._deriveWithNumber(index, null, nonCompliant);
|
||||
}, this);
|
||||
|
||||
return derived;
|
||||
|
|
|
@ -8,7 +8,6 @@ var Base58 = require('./encoding/base58');
|
|||
var Base58Check = require('./encoding/base58check');
|
||||
var Hash = require('./crypto/hash');
|
||||
var HDPrivateKey = require('./hdprivatekey');
|
||||
var HDKeyCache = require('./hdkeycache');
|
||||
var Network = require('./networks');
|
||||
var Point = require('./crypto/point');
|
||||
var PublicKey = require('./publickey');
|
||||
|
@ -76,7 +75,7 @@ function HDPublicKey(arg) {
|
|||
HDPublicKey.isValidPath = function(arg) {
|
||||
if (_.isString(arg)) {
|
||||
var indexes = HDPrivateKey._getDerivationIndexes(arg);
|
||||
return indexes !== null && _.all(indexes, HDPublicKey.isValidPath);
|
||||
return indexes !== null && _.every(indexes, HDPublicKey.isValidPath);
|
||||
}
|
||||
|
||||
if (_.isNumber(arg)) {
|
||||
|
@ -87,6 +86,9 @@ HDPublicKey.isValidPath = function(arg) {
|
|||
};
|
||||
|
||||
/**
|
||||
* WARNING: This method is deprecated. Use deriveChild instead.
|
||||
*
|
||||
*
|
||||
* Get a derivated child based on a string or number.
|
||||
*
|
||||
* If the first argument is a string, it's parsed as the full path of
|
||||
|
@ -109,6 +111,35 @@ HDPublicKey.isValidPath = function(arg) {
|
|||
* @param {string|number} arg
|
||||
*/
|
||||
HDPublicKey.prototype.derive = function(arg, hardened) {
|
||||
return this.deriveChild(arg, hardened);
|
||||
};
|
||||
|
||||
/**
|
||||
* WARNING: This method will not be officially supported until v1.0.0.
|
||||
*
|
||||
*
|
||||
* Get a derivated child based on a string or number.
|
||||
*
|
||||
* If the first argument is a string, it's parsed as the full path of
|
||||
* derivation. Valid values for this argument include "m" (which returns the
|
||||
* same public key), "m/0/1/40/2/1000".
|
||||
*
|
||||
* Note that hardened keys can't be derived from a public extended key.
|
||||
*
|
||||
* If the first argument is a number, the child with that index will be
|
||||
* derived. See the example usage for clarification.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* var parent = new HDPublicKey('xpub...');
|
||||
* var child_0_1_2 = parent.deriveChild(0).deriveChild(1).deriveChild(2);
|
||||
* var copy_of_child_0_1_2 = parent.deriveChild("m/0/1/2");
|
||||
* assert(child_0_1_2.xprivkey === copy_of_child_0_1_2);
|
||||
* ```
|
||||
*
|
||||
* @param {string|number} arg
|
||||
*/
|
||||
HDPublicKey.prototype.deriveChild = function(arg, hardened) {
|
||||
if (_.isNumber(arg)) {
|
||||
return this._deriveWithNumber(arg, hardened);
|
||||
} else if (_.isString(arg)) {
|
||||
|
@ -125,10 +156,6 @@ HDPublicKey.prototype._deriveWithNumber = function(index, hardened) {
|
|||
if (index < 0) {
|
||||
throw new hdErrors.InvalidPath(index);
|
||||
}
|
||||
var cached = HDKeyCache.get(this.xpubkey, index, false);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
var indexBuffer = BufferUtil.integerAsBuffer(index);
|
||||
var data = BufferUtil.concat([this.publicKey.toBuffer(), indexBuffer]);
|
||||
|
@ -136,7 +163,12 @@ HDPublicKey.prototype._deriveWithNumber = function(index, hardened) {
|
|||
var leftPart = BN.fromBuffer(hash.slice(0, 32), {size: 32});
|
||||
var chainCode = hash.slice(32, 64);
|
||||
|
||||
var publicKey = PublicKey.fromPoint(Point.getG().mul(leftPart).add(this.publicKey.point));
|
||||
var publicKey;
|
||||
try {
|
||||
publicKey = PublicKey.fromPoint(Point.getG().mul(leftPart).add(this.publicKey.point));
|
||||
} catch (e) {
|
||||
return this._deriveWithNumber(index + 1);
|
||||
}
|
||||
|
||||
var derived = new HDPublicKey({
|
||||
network: this.network,
|
||||
|
@ -146,13 +178,13 @@ HDPublicKey.prototype._deriveWithNumber = function(index, hardened) {
|
|||
chainCode: chainCode,
|
||||
publicKey: publicKey
|
||||
});
|
||||
HDKeyCache.set(this.xpubkey, index, false, derived);
|
||||
|
||||
return derived;
|
||||
};
|
||||
|
||||
HDPublicKey.prototype._deriveFromString = function(path) {
|
||||
/* jshint maxcomplexity: 8 */
|
||||
if (_.contains(path, "'")) {
|
||||
if (_.includes(path, "'")) {
|
||||
throw new hdErrors.InvalidIndexCantDeriveHardened();
|
||||
} else if (!HDPublicKey.isValidPath(path)) {
|
||||
throw new hdErrors.InvalidPath(path);
|
||||
|
|
|
@ -38,7 +38,7 @@ function get(arg, keys) {
|
|||
return networks[index][key] === arg;
|
||||
};
|
||||
for (var index in networks) {
|
||||
if (_.any(keys, containsArg)) {
|
||||
if (_.some(keys, containsArg)) {
|
||||
return networks[index];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -336,6 +336,19 @@ PrivateKey.prototype.toBigNumber = function(){
|
|||
* @returns {Buffer} A buffer of the private key
|
||||
*/
|
||||
PrivateKey.prototype.toBuffer = function(){
|
||||
// TODO: use `return this.bn.toBuffer({ size: 32 })` in v1.0.0
|
||||
return this.bn.toBuffer();
|
||||
};
|
||||
|
||||
/**
|
||||
* WARNING: This method will not be officially supported until v1.0.0.
|
||||
*
|
||||
*
|
||||
* Will return the private key as a BN buffer without leading zero padding
|
||||
*
|
||||
* @returns {Buffer} A buffer of the private key
|
||||
*/
|
||||
PrivateKey.prototype.toBufferNoPadding = function() {
|
||||
return this.bn.toBuffer();
|
||||
};
|
||||
|
||||
|
|
|
@ -36,15 +36,17 @@ var Script = function Script(from) {
|
|||
return Script.fromAddress(from);
|
||||
} else if (from instanceof Script) {
|
||||
return Script.fromBuffer(from.toBuffer());
|
||||
} else if (typeof from === 'string') {
|
||||
} else if (_.isString(from)) {
|
||||
return Script.fromString(from);
|
||||
} else if (typeof from !== 'undefined') {
|
||||
} else if (_.isObject(from) && _.isArray(from.chunks)) {
|
||||
this.set(from);
|
||||
}
|
||||
};
|
||||
|
||||
Script.prototype.set = function(obj) {
|
||||
this.chunks = obj.chunks || this.chunks;
|
||||
$.checkArgument(_.isObject(obj));
|
||||
$.checkArgument(_.isArray(obj.chunks));
|
||||
this.chunks = obj.chunks;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
@ -228,7 +230,21 @@ Script.prototype._chunkToString = function(chunk, type) {
|
|||
if (!chunk.buf) {
|
||||
// no data chunk
|
||||
if (typeof Opcode.reverseMap[opcodenum] !== 'undefined') {
|
||||
str = str + ' ' + Opcode(opcodenum).toString();
|
||||
if (asm) {
|
||||
// A few cases where the opcode name differs from reverseMap
|
||||
// aside from 1 to 16 data pushes.
|
||||
if (opcodenum === 0) {
|
||||
// OP_0 -> 0
|
||||
str = str + ' 0';
|
||||
} else if(opcodenum === 79) {
|
||||
// OP_1NEGATE -> 1
|
||||
str = str + ' -1';
|
||||
} else {
|
||||
str = str + ' ' + Opcode(opcodenum).toString();
|
||||
}
|
||||
} else {
|
||||
str = str + ' ' + Opcode(opcodenum).toString();
|
||||
}
|
||||
} else {
|
||||
var numstr = opcodenum.toString(16);
|
||||
if (numstr.length % 2 !== 0) {
|
||||
|
@ -242,7 +258,7 @@ Script.prototype._chunkToString = function(chunk, type) {
|
|||
}
|
||||
} else {
|
||||
// data chunk
|
||||
if (opcodenum === Opcode.OP_PUSHDATA1 ||
|
||||
if (!asm && opcodenum === Opcode.OP_PUSHDATA1 ||
|
||||
opcodenum === Opcode.OP_PUSHDATA2 ||
|
||||
opcodenum === Opcode.OP_PUSHDATA4) {
|
||||
str = str + ' ' + Opcode(opcodenum).toString();
|
||||
|
@ -328,7 +344,7 @@ Script.prototype.isPublicKeyHashIn = function() {
|
|||
};
|
||||
|
||||
Script.prototype.getPublicKey = function() {
|
||||
$.checkState(this.isPublicKeyOut(), 'Can\'t retreive PublicKey from a non-PK output');
|
||||
$.checkState(this.isPublicKeyOut(), 'Can\'t retrieve PublicKey from a non-PK output');
|
||||
return this.chunks[0].buf;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,218 +1,218 @@
|
|||
'use strict';
|
||||
|
||||
var _ = require('lodash');
|
||||
var $ = require('../util/preconditions');
|
||||
var BN = require('../crypto/bn');
|
||||
var buffer = require('buffer');
|
||||
var BufferWriter = require('../encoding/bufferwriter');
|
||||
var BufferUtil = require('../util/buffer');
|
||||
var JSUtil = require('../util/js');
|
||||
|
||||
// TODO: Update ZCProof for Groth
|
||||
//var ZCProof = require('../zcash/proof');
|
||||
|
||||
var ZC_NUM_JS_INPUTS = 2;
|
||||
var ZC_NUM_JS_OUTPUTS = 2;
|
||||
|
||||
// leading + v + rho + r + memo + auth
|
||||
var ZC_NOTECIPHERTEXT_SIZE = 1 + 8 + 32 + 32 + 512 + 16;
|
||||
|
||||
function JSDescription(params) {
|
||||
if (!(this instanceof JSDescription)) {
|
||||
return new JSDescription(params);
|
||||
}
|
||||
this.nullifiers = [];
|
||||
this.commitments = [];
|
||||
this.ciphertexts = [];
|
||||
this.macs = [];
|
||||
if (params) {
|
||||
return this._fromObject(params);
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(JSDescription.prototype, 'vpub_old', {
|
||||
configurable: false,
|
||||
enumerable: true,
|
||||
get: function() {
|
||||
return this._vpub_old;
|
||||
},
|
||||
set: function(num) {
|
||||
if (num instanceof BN) {
|
||||
this._vpub_oldBN = num;
|
||||
this._vpub_old = num.toNumber();
|
||||
} else if (_.isString(num)) {
|
||||
this._vpub_old = parseInt(num);
|
||||
this._vpub_oldBN = BN.fromNumber(this._vpub_old);
|
||||
} else {
|
||||
$.checkArgument(
|
||||
JSUtil.isNaturalNumber(num),
|
||||
'vpub_old is not a natural number'
|
||||
);
|
||||
this._vpub_oldBN = BN.fromNumber(num);
|
||||
this._vpub_old = num;
|
||||
}
|
||||
$.checkState(
|
||||
JSUtil.isNaturalNumber(this._vpub_old),
|
||||
'vpub_old is not a natural number'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(JSDescription.prototype, 'vpub_new', {
|
||||
configurable: false,
|
||||
enumerable: true,
|
||||
get: function() {
|
||||
return this._vpub_new;
|
||||
},
|
||||
set: function(num) {
|
||||
if (num instanceof BN) {
|
||||
this._vpub_newBN = num;
|
||||
this._vpub_new = num.toNumber();
|
||||
} else if (_.isString(num)) {
|
||||
this._vpub_new = parseInt(num);
|
||||
this._vpub_newBN = BN.fromNumber(this._vpub_new);
|
||||
} else {
|
||||
$.checkArgument(
|
||||
JSUtil.isNaturalNumber(num),
|
||||
'vpub_new is not a natural number'
|
||||
);
|
||||
this._vpub_newBN = BN.fromNumber(num);
|
||||
this._vpub_new = num;
|
||||
}
|
||||
$.checkState(
|
||||
JSUtil.isNaturalNumber(this._vpub_new),
|
||||
'vpub_new is not a natural number'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
JSDescription.fromObject = function(obj) {
|
||||
$.checkArgument(_.isObject(obj));
|
||||
var jsdesc = new JSDescription();
|
||||
return jsdesc._fromObject(obj);
|
||||
};
|
||||
|
||||
JSDescription.prototype._fromObject = function(params) {
|
||||
var nullifiers = [];
|
||||
_.each(params.nullifiers, function(nullifier) {
|
||||
nullifiers.push(BufferUtil.reverse(new buffer.Buffer(nullifier, 'hex')));
|
||||
});
|
||||
var commitments = [];
|
||||
_.each(params.commitments, function(commitment) {
|
||||
commitments.push(BufferUtil.reverse(new buffer.Buffer(commitment, 'hex')));
|
||||
});
|
||||
var ciphertexts = [];
|
||||
_.each(params.ciphertexts, function(ciphertext) {
|
||||
ciphertexts.push(new buffer.Buffer(ciphertext, 'hex'));
|
||||
});
|
||||
var macs = [];
|
||||
_.each(params.macs, function(mac) {
|
||||
macs.push(BufferUtil.reverse(new buffer.Buffer(mac, 'hex')));
|
||||
});
|
||||
this.vpub_old = params.vpub_old;
|
||||
this.vpub_new = params.vpub_new;
|
||||
this.anchor = BufferUtil.reverse(new buffer.Buffer(params.anchor, 'hex'));
|
||||
this.nullifiers = nullifiers;
|
||||
this.commitments = commitments;
|
||||
this.ephemeralKey = BufferUtil.reverse(new buffer.Buffer(params.ephemeralKey, 'hex'));
|
||||
this.ciphertexts = ciphertexts;
|
||||
this.randomSeed = BufferUtil.reverse(new buffer.Buffer(params.randomSeed, 'hex'));
|
||||
this.macs = macs;
|
||||
this.proof = params.proof; // TODO: Update ZCProof for Groth: ZCProof.fromObject(params.proof);
|
||||
return this;
|
||||
};
|
||||
|
||||
JSDescription.prototype.toObject = JSDescription.prototype.toJSON = function toObject() {
|
||||
var nullifiers = [];
|
||||
_.each(this.nullifiers, function(nullifier) {
|
||||
nullifiers.push(BufferUtil.reverse(nullifier).toString('hex'));
|
||||
});
|
||||
var commitments = [];
|
||||
_.each(this.commitments, function(commitment) {
|
||||
commitments.push(BufferUtil.reverse(commitment).toString('hex'));
|
||||
});
|
||||
var ciphertexts = [];
|
||||
_.each(this.ciphertexts, function(ciphertext) {
|
||||
ciphertexts.push(ciphertext.toString('hex'));
|
||||
});
|
||||
var macs = [];
|
||||
_.each(this.macs, function(mac) {
|
||||
macs.push(BufferUtil.reverse(mac).toString('hex'));
|
||||
});
|
||||
var obj = {
|
||||
vpub_old: this.vpub_old,
|
||||
vpub_new: this.vpub_new,
|
||||
anchor: BufferUtil.reverse(this.anchor).toString('hex'),
|
||||
nullifiers: nullifiers,
|
||||
commitments: commitments,
|
||||
ephemeralKey: BufferUtil.reverse(this.ephemeralKey).toString('hex'),
|
||||
ciphertexts: ciphertexts,
|
||||
randomSeed: BufferUtil.reverse(this.randomSeed).toString('hex'),
|
||||
macs: macs,
|
||||
proof: this.proof, // TODO: Update ZCProof for Groth: this.proof.toObject(),
|
||||
};
|
||||
return obj;
|
||||
};
|
||||
|
||||
JSDescription.fromBufferReader = function(br, useGrothFlagParam) {
|
||||
var i;
|
||||
var jsdesc = new JSDescription();
|
||||
jsdesc.vpub_old = br.readUInt64LEBN();
|
||||
jsdesc.vpub_new = br.readUInt64LEBN();
|
||||
jsdesc.anchor = br.read(32);
|
||||
for (i = 0; i < ZC_NUM_JS_INPUTS; i++) {
|
||||
jsdesc.nullifiers.push(br.read(32));
|
||||
}
|
||||
for (i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
||||
jsdesc.commitments.push(br.read(32));
|
||||
}
|
||||
jsdesc.ephemeralKey = br.read(32);
|
||||
jsdesc.randomSeed = br.read(32);
|
||||
for (i = 0; i < ZC_NUM_JS_INPUTS; i++) {
|
||||
jsdesc.macs.push(br.read(32));
|
||||
}
|
||||
|
||||
// Default parameter requires ECMASCript 6 which might not be available, so use workaround.
|
||||
var useGrothFlag = useGrothFlagParam || false;
|
||||
if (!useGrothFlag) {
|
||||
jsdesc.proof = br.read(296); // TODO: Update ZCProof for Groth: ZCProof.fromBufferReader(br);
|
||||
} else {
|
||||
jsdesc.proof = br.read(48 + 96 + 48);
|
||||
}
|
||||
|
||||
for (i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
||||
jsdesc.ciphertexts.push(br.read(ZC_NOTECIPHERTEXT_SIZE));
|
||||
}
|
||||
return jsdesc;
|
||||
};
|
||||
|
||||
JSDescription.prototype.toBufferWriter = function(writer) {
|
||||
var i;
|
||||
if (!writer) {
|
||||
writer = new BufferWriter();
|
||||
}
|
||||
writer.writeUInt64LEBN(this._vpub_oldBN);
|
||||
writer.writeUInt64LEBN(this._vpub_newBN);
|
||||
writer.write(this.anchor);
|
||||
for (i = 0; i < ZC_NUM_JS_INPUTS; i++) {
|
||||
writer.write(this.nullifiers[i]);
|
||||
}
|
||||
for (i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
||||
writer.write(this.commitments[i]);
|
||||
}
|
||||
writer.write(this.ephemeralKey);
|
||||
writer.write(this.randomSeed);
|
||||
for (i = 0; i < ZC_NUM_JS_INPUTS; i++) {
|
||||
writer.write(this.macs[i]);
|
||||
}
|
||||
|
||||
// TODO: Update ZCProof for Groth: this.proof.toBufferWriter(writer);
|
||||
writer.write(this.proof);
|
||||
|
||||
for (i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
||||
writer.write(this.ciphertexts[i]);
|
||||
}
|
||||
return writer;
|
||||
};
|
||||
|
||||
module.exports = JSDescription;
|
||||
'use strict';
|
||||
|
||||
var _ = require('lodash');
|
||||
var $ = require('../util/preconditions');
|
||||
var BN = require('../crypto/bn');
|
||||
var buffer = require('buffer');
|
||||
var BufferWriter = require('../encoding/bufferwriter');
|
||||
var BufferUtil = require('../util/buffer');
|
||||
var JSUtil = require('../util/js');
|
||||
|
||||
// TODO: Update ZCProof for Groth
|
||||
//var ZCProof = require('../zcash/proof');
|
||||
|
||||
var ZC_NUM_JS_INPUTS = 2;
|
||||
var ZC_NUM_JS_OUTPUTS = 2;
|
||||
|
||||
// leading + v + rho + r + memo + auth
|
||||
var ZC_NOTECIPHERTEXT_SIZE = 1 + 8 + 32 + 32 + 512 + 16;
|
||||
|
||||
function JSDescription(params) {
|
||||
if (!(this instanceof JSDescription)) {
|
||||
return new JSDescription(params);
|
||||
}
|
||||
this.nullifiers = [];
|
||||
this.commitments = [];
|
||||
this.ciphertexts = [];
|
||||
this.macs = [];
|
||||
if (params) {
|
||||
return this._fromObject(params);
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(JSDescription.prototype, 'vpub_old', {
|
||||
configurable: false,
|
||||
enumerable: true,
|
||||
get: function() {
|
||||
return this._vpub_old;
|
||||
},
|
||||
set: function(num) {
|
||||
if (num instanceof BN) {
|
||||
this._vpub_oldBN = num;
|
||||
this._vpub_old = num.toNumber();
|
||||
} else if (_.isString(num)) {
|
||||
this._vpub_old = parseInt(num);
|
||||
this._vpub_oldBN = BN.fromNumber(this._vpub_old);
|
||||
} else {
|
||||
$.checkArgument(
|
||||
JSUtil.isNaturalNumber(num),
|
||||
'vpub_old is not a natural number'
|
||||
);
|
||||
this._vpub_oldBN = BN.fromNumber(num);
|
||||
this._vpub_old = num;
|
||||
}
|
||||
$.checkState(
|
||||
JSUtil.isNaturalNumber(this._vpub_old),
|
||||
'vpub_old is not a natural number'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(JSDescription.prototype, 'vpub_new', {
|
||||
configurable: false,
|
||||
enumerable: true,
|
||||
get: function() {
|
||||
return this._vpub_new;
|
||||
},
|
||||
set: function(num) {
|
||||
if (num instanceof BN) {
|
||||
this._vpub_newBN = num;
|
||||
this._vpub_new = num.toNumber();
|
||||
} else if (_.isString(num)) {
|
||||
this._vpub_new = parseInt(num);
|
||||
this._vpub_newBN = BN.fromNumber(this._vpub_new);
|
||||
} else {
|
||||
$.checkArgument(
|
||||
JSUtil.isNaturalNumber(num),
|
||||
'vpub_new is not a natural number'
|
||||
);
|
||||
this._vpub_newBN = BN.fromNumber(num);
|
||||
this._vpub_new = num;
|
||||
}
|
||||
$.checkState(
|
||||
JSUtil.isNaturalNumber(this._vpub_new),
|
||||
'vpub_new is not a natural number'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
JSDescription.fromObject = function(obj) {
|
||||
$.checkArgument(_.isObject(obj));
|
||||
var jsdesc = new JSDescription();
|
||||
return jsdesc._fromObject(obj);
|
||||
};
|
||||
|
||||
JSDescription.prototype._fromObject = function(params) {
|
||||
var nullifiers = [];
|
||||
_.each(params.nullifiers, function(nullifier) {
|
||||
nullifiers.push(BufferUtil.reverse(new buffer.Buffer(nullifier, 'hex')));
|
||||
});
|
||||
var commitments = [];
|
||||
_.each(params.commitments, function(commitment) {
|
||||
commitments.push(BufferUtil.reverse(new buffer.Buffer(commitment, 'hex')));
|
||||
});
|
||||
var ciphertexts = [];
|
||||
_.each(params.ciphertexts, function(ciphertext) {
|
||||
ciphertexts.push(new buffer.Buffer(ciphertext, 'hex'));
|
||||
});
|
||||
var macs = [];
|
||||
_.each(params.macs, function(mac) {
|
||||
macs.push(BufferUtil.reverse(new buffer.Buffer(mac, 'hex')));
|
||||
});
|
||||
this.vpub_old = params.vpub_old;
|
||||
this.vpub_new = params.vpub_new;
|
||||
this.anchor = BufferUtil.reverse(new buffer.Buffer(params.anchor, 'hex'));
|
||||
this.nullifiers = nullifiers;
|
||||
this.commitments = commitments;
|
||||
this.ephemeralKey = BufferUtil.reverse(new buffer.Buffer(params.ephemeralKey, 'hex'));
|
||||
this.ciphertexts = ciphertexts;
|
||||
this.randomSeed = BufferUtil.reverse(new buffer.Buffer(params.randomSeed, 'hex'));
|
||||
this.macs = macs;
|
||||
this.proof = params.proof; // TODO: Update ZCProof for Groth: ZCProof.fromObject(params.proof);
|
||||
return this;
|
||||
};
|
||||
|
||||
JSDescription.prototype.toObject = JSDescription.prototype.toJSON = function toObject() {
|
||||
var nullifiers = [];
|
||||
_.each(this.nullifiers, function(nullifier) {
|
||||
nullifiers.push(BufferUtil.reverse(nullifier).toString('hex'));
|
||||
});
|
||||
var commitments = [];
|
||||
_.each(this.commitments, function(commitment) {
|
||||
commitments.push(BufferUtil.reverse(commitment).toString('hex'));
|
||||
});
|
||||
var ciphertexts = [];
|
||||
_.each(this.ciphertexts, function(ciphertext) {
|
||||
ciphertexts.push(ciphertext.toString('hex'));
|
||||
});
|
||||
var macs = [];
|
||||
_.each(this.macs, function(mac) {
|
||||
macs.push(BufferUtil.reverse(mac).toString('hex'));
|
||||
});
|
||||
var obj = {
|
||||
vpub_old: this.vpub_old,
|
||||
vpub_new: this.vpub_new,
|
||||
anchor: BufferUtil.reverse(this.anchor).toString('hex'),
|
||||
nullifiers: nullifiers,
|
||||
commitments: commitments,
|
||||
ephemeralKey: BufferUtil.reverse(this.ephemeralKey).toString('hex'),
|
||||
ciphertexts: ciphertexts,
|
||||
randomSeed: BufferUtil.reverse(this.randomSeed).toString('hex'),
|
||||
macs: macs,
|
||||
proof: this.proof, // TODO: Update ZCProof for Groth: this.proof.toObject(),
|
||||
};
|
||||
return obj;
|
||||
};
|
||||
|
||||
JSDescription.fromBufferReader = function(br, useGrothFlagParam) {
|
||||
var i;
|
||||
var jsdesc = new JSDescription();
|
||||
jsdesc.vpub_old = br.readUInt64LEBN();
|
||||
jsdesc.vpub_new = br.readUInt64LEBN();
|
||||
jsdesc.anchor = br.read(32);
|
||||
for (i = 0; i < ZC_NUM_JS_INPUTS; i++) {
|
||||
jsdesc.nullifiers.push(br.read(32));
|
||||
}
|
||||
for (i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
||||
jsdesc.commitments.push(br.read(32));
|
||||
}
|
||||
jsdesc.ephemeralKey = br.read(32);
|
||||
jsdesc.randomSeed = br.read(32);
|
||||
for (i = 0; i < ZC_NUM_JS_INPUTS; i++) {
|
||||
jsdesc.macs.push(br.read(32));
|
||||
}
|
||||
|
||||
// Default parameter requires ECMASCript 6 which might not be available, so use workaround.
|
||||
var useGrothFlag = useGrothFlagParam || false;
|
||||
if (!useGrothFlag) {
|
||||
jsdesc.proof = br.read(296); // TODO: Update ZCProof for Groth: ZCProof.fromBufferReader(br);
|
||||
} else {
|
||||
jsdesc.proof = br.read(48 + 96 + 48);
|
||||
}
|
||||
|
||||
for (i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
||||
jsdesc.ciphertexts.push(br.read(ZC_NOTECIPHERTEXT_SIZE));
|
||||
}
|
||||
return jsdesc;
|
||||
};
|
||||
|
||||
JSDescription.prototype.toBufferWriter = function(writer) {
|
||||
var i;
|
||||
if (!writer) {
|
||||
writer = new BufferWriter();
|
||||
}
|
||||
writer.writeUInt64LEBN(this._vpub_oldBN);
|
||||
writer.writeUInt64LEBN(this._vpub_newBN);
|
||||
writer.write(this.anchor);
|
||||
for (i = 0; i < ZC_NUM_JS_INPUTS; i++) {
|
||||
writer.write(this.nullifiers[i]);
|
||||
}
|
||||
for (i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
||||
writer.write(this.commitments[i]);
|
||||
}
|
||||
writer.write(this.ephemeralKey);
|
||||
writer.write(this.randomSeed);
|
||||
for (i = 0; i < ZC_NUM_JS_INPUTS; i++) {
|
||||
writer.write(this.macs[i]);
|
||||
}
|
||||
|
||||
// TODO: Update ZCProof for Groth: this.proof.toBufferWriter(writer);
|
||||
writer.write(this.proof);
|
||||
|
||||
for (i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
||||
writer.write(this.ciphertexts[i]);
|
||||
}
|
||||
return writer;
|
||||
};
|
||||
|
||||
module.exports = JSDescription;
|
||||
|
|
|
@ -11,10 +11,162 @@ var BN = require('../crypto/bn');
|
|||
var Hash = require('../crypto/hash');
|
||||
var ECDSA = require('../crypto/ecdsa');
|
||||
var $ = require('../util/preconditions');
|
||||
var BufferUtil = require('../util/buffer');
|
||||
var blake2b = require('blake2b')
|
||||
var _ = require('lodash');
|
||||
|
||||
var SIGHASH_SINGLE_BUG = '0000000000000000000000000000000000000000000000000000000000000001';
|
||||
var BITS_64_ON = 'ffffffffffffffff';
|
||||
var ZERO = Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex')
|
||||
|
||||
var sighashSapling = function sighash(transaction, sighashType, inputNumber, subscript) {
|
||||
// Copyright (C) 2019 by LitecoinZ Developers.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
var input = transaction.inputs[inputNumber];
|
||||
|
||||
function getBlake2bHash(bufferToHash, personalization) {
|
||||
var out = Buffer.allocUnsafe(32);
|
||||
return blake2b(out.length, null, null, Buffer.from(personalization)).update(bufferToHash).digest(out);
|
||||
}
|
||||
|
||||
function GetPrevoutHash(tx) {
|
||||
var writer = new BufferWriter()
|
||||
|
||||
_.each(tx.inputs, function(input) {
|
||||
writer.writeReverse(input.prevTxId);
|
||||
writer.writeUInt32LE(input.outputIndex);
|
||||
});
|
||||
|
||||
return getBlake2bHash(writer.toBuffer(), 'ZcashPrevoutHash');
|
||||
}
|
||||
|
||||
function GetSequenceHash(tx) {
|
||||
var writer = new BufferWriter()
|
||||
|
||||
_.each(tx.inputs, function(input) {
|
||||
writer.writeUInt32LE(input.sequenceNumber);
|
||||
});
|
||||
|
||||
return getBlake2bHash(writer.toBuffer(), 'ZcashSequencHash');
|
||||
}
|
||||
|
||||
function GetOutputsHash(tx, n) {
|
||||
var writer = new BufferWriter()
|
||||
|
||||
if ( _.isUndefined(n)) {
|
||||
_.each(tx.outputs, function(output) {
|
||||
output.toBufferWriter(writer);
|
||||
});
|
||||
} else {
|
||||
tx.outputs[n].toBufferWriter(writer);
|
||||
}
|
||||
|
||||
return getBlake2bHash(writer.toBuffer(), 'ZcashOutputsHash');
|
||||
}
|
||||
|
||||
var hashPrevouts = ZERO;
|
||||
var hashSequence = ZERO;
|
||||
var hashOutputs = ZERO;
|
||||
var hashJoinSplits = ZERO;
|
||||
var hashShieldedSpends = ZERO;
|
||||
var hashShieldedOutputs = ZERO;
|
||||
|
||||
var writer = new BufferWriter();
|
||||
|
||||
// header of the transaction (4-byte little endian)
|
||||
var header = transaction.version | (1 << 31);
|
||||
writer.writeInt32LE(header);
|
||||
|
||||
// nVersionGroupId of the transaction (4-byte little endian)
|
||||
writer.writeUInt32LE(transaction.nVersionGroupId);
|
||||
|
||||
// hashPrevouts (32-byte hash)
|
||||
if (!(sighashType & Signature.SIGHASH_ANYONECANPAY)) {
|
||||
hashPrevouts = GetPrevoutHash(transaction);
|
||||
}
|
||||
writer.write(hashPrevouts);
|
||||
|
||||
// hashSequence (32-byte hash)
|
||||
if (!(sighashType & Signature.SIGHASH_ANYONECANPAY) &&
|
||||
(sighashType & 31) != Signature.SIGHASH_SINGLE &&
|
||||
(sighashType & 31) != Signature.SIGHASH_NONE) {
|
||||
hashSequence = GetSequenceHash(transaction);
|
||||
}
|
||||
writer.write(hashSequence);
|
||||
|
||||
// hashOutputs (32-byte hash)
|
||||
if ((sighashType & 31) != Signature.SIGHASH_SINGLE && (sighashType & 31) != Signature.SIGHASH_NONE) {
|
||||
hashOutputs = GetOutputsHash(transaction);
|
||||
} else if ((sighashType & 31) == Signature.SIGHASH_SINGLE && inputNumber < transaction.outputs.length) {
|
||||
hashOutputs = GetOutputsHash(transaction, inputNumber);
|
||||
}
|
||||
writer.write(hashOutputs);
|
||||
|
||||
// hashJoinSplits (32-byte hash)
|
||||
writer.write(hashJoinSplits);
|
||||
|
||||
// hashShieldedSpends (32-byte hash)
|
||||
writer.write(hashShieldedSpends);
|
||||
|
||||
// hashShieldedOutputs (32-byte hash)
|
||||
writer.write(hashShieldedOutputs);
|
||||
|
||||
// nLockTime of the transaction (4-byte little endian)
|
||||
writer.writeUInt32LE(transaction.nLockTime);
|
||||
|
||||
// nExpiryHeight of the transaction (4-byte little endian)
|
||||
writer.writeUInt32LE(transaction.nExpiryHeight);
|
||||
|
||||
// valueBalance of the transaction (8-byte little endian)
|
||||
writer.writeUInt64LE(transaction.valueBalance);
|
||||
|
||||
// sighash type of the signature (4-byte little endian)
|
||||
writer.writeUInt32LE(sighashType >>>0);
|
||||
|
||||
// outpoint (32-byte hash + 4-byte little endian)
|
||||
writer.writeReverse(input.prevTxId);
|
||||
writer.writeUInt32LE(input.outputIndex);
|
||||
|
||||
// scriptCode of the input (serialized as scripts inside CTxOuts)
|
||||
writer.writeVarintNum(subscript.toBuffer().length)
|
||||
writer.write(subscript.toBuffer());
|
||||
|
||||
// value of the output spent by this input (8-byte little endian)
|
||||
writer.writeUInt64LE(input.output.satoshis);
|
||||
|
||||
// nSequence of the input (4-byte little endian)
|
||||
var sequenceNumber = input.sequenceNumber;
|
||||
writer.writeUInt32LE(sequenceNumber);
|
||||
|
||||
var personalization = Buffer.alloc(16);
|
||||
var prefix = 'ZcashSigHash'
|
||||
var consensusBranchId = 1991772603;
|
||||
|
||||
personalization.write(prefix);
|
||||
personalization.writeUInt32LE(consensusBranchId, prefix.length);
|
||||
|
||||
var ret = getBlake2bHash(writer.toBuffer(), personalization)
|
||||
ret = new BufferReader(ret).readReverse();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a buffer of length 32 bytes with the hash that needs to be signed
|
||||
|
@ -30,6 +182,10 @@ var sighash = function sighash(transaction, sighashType, inputNumber, subscript)
|
|||
var Transaction = require('./transaction');
|
||||
var Input = require('./input');
|
||||
|
||||
if (transaction.version >= 4) {
|
||||
return sighashSapling(transaction, sighashType, inputNumber, subscript);
|
||||
}
|
||||
|
||||
var i;
|
||||
// Copy transaction
|
||||
var txcopy = Transaction.shallowCopy(transaction);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,8 +18,8 @@ module.exports = {
|
|||
argumentName = argumentName || '(unknown name)';
|
||||
if (_.isString(type)) {
|
||||
if (type === 'Buffer') {
|
||||
var BufferUtil = require('./buffer');
|
||||
if (!BufferUtil.isBuffer(argument)) {
|
||||
var buffer = require('buffer'); // './buffer' fails on cordova & RN
|
||||
if (!buffer.Buffer.isBuffer(argument)) {
|
||||
throw new errors.InvalidArgumentType(argument, type, argumentName);
|
||||
}
|
||||
} else if (typeof argument !== type) {
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
{
|
||||
"name": "bitcore",
|
||||
"version": "0.13.19",
|
||||
"dependencies": {
|
||||
"bn.js": {
|
||||
"version": "2.0.4",
|
||||
"from": "bn.js@=2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-2.0.4.tgz"
|
||||
},
|
||||
"bs58": {
|
||||
"version": "2.0.0",
|
||||
"from": "bs58@=2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bs58/-/bs58-2.0.0.tgz"
|
||||
},
|
||||
"buffer-compare": {
|
||||
"version": "1.0.0",
|
||||
"from": "buffer-compare@=1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer-compare/-/buffer-compare-1.0.0.tgz"
|
||||
},
|
||||
"elliptic": {
|
||||
"version": "3.0.3",
|
||||
"from": "elliptic@=3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-3.0.3.tgz",
|
||||
"dependencies": {
|
||||
"brorand": {
|
||||
"version": "1.0.5",
|
||||
"from": "brorand@^1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz"
|
||||
},
|
||||
"hash.js": {
|
||||
"version": "1.0.3",
|
||||
"from": "hash.js@=1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.3.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"from": "inherits@=2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
||||
},
|
||||
"lodash": {
|
||||
"version": "3.10.1",
|
||||
"from": "lodash@=3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz"
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
221
package.json
221
package.json
|
@ -1,110 +1,111 @@
|
|||
{
|
||||
"name": "bitcore-lib-zcash",
|
||||
"version": "0.13.19",
|
||||
"description": "A pure and powerful JavaScript Zcash library.",
|
||||
"author": "BitPay <dev@bitpay.com>",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"lint": "gulp lint",
|
||||
"test": "gulp test",
|
||||
"coverage": "gulp coverage",
|
||||
"build": "gulp"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Daniel Cousens",
|
||||
"email": "bitcoin@dcousens.com"
|
||||
},
|
||||
{
|
||||
"name": "Esteban Ordano",
|
||||
"email": "eordano@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Gordon Hall",
|
||||
"email": "gordon@bitpay.com"
|
||||
},
|
||||
{
|
||||
"name": "Jeff Garzik",
|
||||
"email": "jgarzik@bitpay.com"
|
||||
},
|
||||
{
|
||||
"name": "Kyle Drake",
|
||||
"email": "kyle@kyledrake.net"
|
||||
},
|
||||
{
|
||||
"name": "Manuel Araoz",
|
||||
"email": "manuelaraoz@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Matias Alejo Garcia",
|
||||
"email": "ematiu@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Ryan X. Charles",
|
||||
"email": "ryanxcharles@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Stefan Thomas",
|
||||
"email": "moon@justmoon.net"
|
||||
},
|
||||
{
|
||||
"name": "Stephen Pair",
|
||||
"email": "stephen@bitpay.com"
|
||||
},
|
||||
{
|
||||
"name": "Wei Lu",
|
||||
"email": "luwei.here@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Jack Grigg",
|
||||
"email": "jack@z.cash"
|
||||
},
|
||||
{
|
||||
"name": "Simon Liu",
|
||||
"email": "simon@z.cash"
|
||||
},
|
||||
{
|
||||
"name": "Ian Munoz",
|
||||
"email": "ian.org@gmail.com"
|
||||
}
|
||||
],
|
||||
"keywords": [
|
||||
"zcash",
|
||||
"transaction",
|
||||
"address",
|
||||
"p2p",
|
||||
"ecies",
|
||||
"cryptocurrency",
|
||||
"blockchain",
|
||||
"payment",
|
||||
"bip21",
|
||||
"bip32",
|
||||
"bip37",
|
||||
"bip69",
|
||||
"bip70",
|
||||
"multisig"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/zcash-hackworks/bitcore-lib-zcash.git"
|
||||
},
|
||||
"browser": {
|
||||
"request": "browser-request"
|
||||
},
|
||||
"dependencies": {
|
||||
"bn.js": "=2.0.4",
|
||||
"bs58": "=2.0.0",
|
||||
"buffer-compare": "=1.0.0",
|
||||
"elliptic": "=3.0.3",
|
||||
"inherits": "=2.0.1",
|
||||
"lodash": "=3.10.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bitcore-build-zcash": "zcash-hackworks/bitcore-build-zcash",
|
||||
"brfs": "^1.2.0",
|
||||
"chai": "^1.10.0",
|
||||
"gulp": "^3.8.10",
|
||||
"sinon": "^1.13.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
{
|
||||
"name": "bitcore-lib-zcash",
|
||||
"version": "1.0.2",
|
||||
"description": "A pure and powerful JavaScript Zcash library.",
|
||||
"author": "BitPay <dev@bitpay.com>",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"lint": "gulp lint",
|
||||
"test": "gulp test",
|
||||
"coverage": "gulp coverage",
|
||||
"build": "gulp"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Daniel Cousens",
|
||||
"email": "bitcoin@dcousens.com"
|
||||
},
|
||||
{
|
||||
"name": "Esteban Ordano",
|
||||
"email": "eordano@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Gordon Hall",
|
||||
"email": "gordon@bitpay.com"
|
||||
},
|
||||
{
|
||||
"name": "Jeff Garzik",
|
||||
"email": "jgarzik@bitpay.com"
|
||||
},
|
||||
{
|
||||
"name": "Kyle Drake",
|
||||
"email": "kyle@kyledrake.net"
|
||||
},
|
||||
{
|
||||
"name": "Manuel Araoz",
|
||||
"email": "manuelaraoz@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Matias Alejo Garcia",
|
||||
"email": "ematiu@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Ryan X. Charles",
|
||||
"email": "ryanxcharles@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Stefan Thomas",
|
||||
"email": "moon@justmoon.net"
|
||||
},
|
||||
{
|
||||
"name": "Stephen Pair",
|
||||
"email": "stephen@bitpay.com"
|
||||
},
|
||||
{
|
||||
"name": "Wei Lu",
|
||||
"email": "luwei.here@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Jack Grigg",
|
||||
"email": "jack@z.cash"
|
||||
},
|
||||
{
|
||||
"name": "Simon Liu",
|
||||
"email": "simon@z.cash"
|
||||
},
|
||||
{
|
||||
"name": "Ian Munoz",
|
||||
"email": "ian.org@gmail.com"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"bn.js": "=4.11.8",
|
||||
"bs58": "=4.0.1",
|
||||
"buffer-compare": "=1.1.1",
|
||||
"elliptic": "=6.4.0",
|
||||
"inherits": "=2.0.1",
|
||||
"lodash": "=4.17.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bitcore-build-zcash": "zcash-hackworks/bitcore-build-zcash",
|
||||
"brfs": "^1.2.0",
|
||||
"chai": "^1.10.0",
|
||||
"gulp": "^3.8.10",
|
||||
"sinon": "^1.13.0"
|
||||
},
|
||||
"keywords": [
|
||||
"zcash",
|
||||
"transaction",
|
||||
"address",
|
||||
"p2p",
|
||||
"ecies",
|
||||
"cryptocurrency",
|
||||
"blockchain",
|
||||
"payment",
|
||||
"bip21",
|
||||
"bip32",
|
||||
"bip37",
|
||||
"bip69",
|
||||
"bip70",
|
||||
"multisig"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/zcash-hackworks/bitcore-lib-zcash.git"
|
||||
},
|
||||
"browser": {
|
||||
"request": "browser-request"
|
||||
},
|
||||
|
||||
"license": "MIT"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue