Skip to content
This repository was archived by the owner on Apr 3, 2019. It is now read-only.

Commit 75ef027

Browse files
authored
Merge pull request #168 from matiu/ref/re-add-version-guard
Ref/re add version guard
2 parents eee3874 + b1bbd00 commit 75ef027

File tree

5 files changed

+122
-21
lines changed

5 files changed

+122
-21
lines changed

bitcore-lib.js

Lines changed: 98 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,14 @@ Address._transformBuffer = function(buffer, network, type) {
197197
throw new TypeError('Address buffers must be exactly 21 bytes.');
198198
}
199199

200-
network = Networks.get(network);
200+
var networkObj = Networks.get(network);
201201
var bufferVersion = Address._classifyFromVersion(buffer);
202202

203-
if (!bufferVersion.network || (network && network !== bufferVersion.network)) {
203+
if (network && !networkObj) {
204+
throw new TypeError('Unknown network');
205+
}
206+
207+
if (!bufferVersion.network || (networkObj && networkObj !== bufferVersion.network)) {
204208
throw new TypeError('Address has mismatched network type.');
205209
}
206210

@@ -1103,6 +1107,7 @@ var BufferWriter = require('../encoding/bufferwriter');
11031107
var Hash = require('../crypto/hash');
11041108
var JSUtil = require('../util/js');
11051109
var Transaction = require('../transaction');
1110+
var errors = require('../errors');
11061111
var $ = require('../util/preconditions');
11071112

11081113
/**
@@ -1158,6 +1163,7 @@ function MerkleBlock(arg) {
11581163
_.extend(this,info);
11591164
this._flagBitsUsed = 0;
11601165
this._hashesUsed = 0;
1166+
11611167
return this;
11621168
}
11631169

@@ -1244,26 +1250,61 @@ MerkleBlock.prototype.validMerkleTree = function validMerkleTree() {
12441250
return BufferUtil.equals(root, this.header.merkleRoot);
12451251
};
12461252

1253+
/**
1254+
* Return a list of all the txs hash that match the filter
1255+
* @returns {Array} - txs hash that match the filter
1256+
*/
1257+
MerkleBlock.prototype.filterdTxsHash = function filterdTxsHash() {
1258+
$.checkState(_.isArray(this.flags), 'MerkleBlock flags is not an array');
1259+
$.checkState(_.isArray(this.hashes), 'MerkleBlock hashes is not an array');
1260+
1261+
// Can't have more hashes than numTransactions
1262+
if(this.hashes.length > this.numTransactions) {
1263+
throw new errors.MerkleBlock.InvalidMerkleTree();
1264+
}
1265+
1266+
// Can't have more flag bits than num hashes
1267+
if(this.flags.length * 8 < this.hashes.length) {
1268+
throw new errors.MerkleBlock.InvalidMerkleTree();
1269+
}
1270+
1271+
// If there is only one hash the filter do not match any txs in the block
1272+
if(this.hashes.length === 1) {
1273+
return [];
1274+
};
1275+
1276+
var height = this._calcTreeHeight();
1277+
var opts = { hashesUsed: 0, flagBitsUsed: 0 };
1278+
var txs = this._traverseMerkleTree(height, 0, opts, true);
1279+
if(opts.hashesUsed !== this.hashes.length) {
1280+
throw new errors.MerkleBlock.InvalidMerkleTree();
1281+
}
1282+
return txs;
1283+
};
1284+
12471285
/**
12481286
* Traverse a the tree in this MerkleBlock, validating it along the way
12491287
* Modeled after Bitcoin Core merkleblock.cpp TraverseAndExtract()
12501288
* @param {Number} - depth - Current height
12511289
* @param {Number} - pos - Current position in the tree
12521290
* @param {Object} - opts - Object with values that need to be mutated throughout the traversal
1291+
* @param {Boolean} - checkForTxs - if true return opts.txs else return the Merkle Hash
12531292
* @param {Number} - opts.flagBitsUsed - Number of flag bits used, should start at 0
12541293
* @param {Number} - opts.hashesUsed - Number of hashes used, should start at 0
1255-
* @param {Array} - opts.txs - Will finish populated by transactions found during traversal
1294+
* @param {Array} - opts.txs - Will finish populated by transactions found during traversal that match the filter
12561295
* @returns {Buffer|null} - Buffer containing the Merkle Hash for that height
1296+
* @returns {Array} - transactions found during traversal that match the filter
12571297
* @private
12581298
*/
1259-
MerkleBlock.prototype._traverseMerkleTree = function traverseMerkleTree(depth, pos, opts) {
1299+
MerkleBlock.prototype._traverseMerkleTree = function traverseMerkleTree(depth, pos, opts, checkForTxs) {
12601300
/* jshint maxcomplexity: 12*/
12611301
/* jshint maxstatements: 20 */
12621302

12631303
opts = opts || {};
12641304
opts.txs = opts.txs || [];
12651305
opts.flagBitsUsed = opts.flagBitsUsed || 0;
12661306
opts.hashesUsed = opts.hashesUsed || 0;
1307+
var checkForTxs = checkForTxs || false;
12671308

12681309
if(opts.flagBitsUsed > this.flags.length * 8) {
12691310
return null;
@@ -1284,7 +1325,11 @@ MerkleBlock.prototype._traverseMerkleTree = function traverseMerkleTree(depth, p
12841325
if(pos*2+1 < this._calcTreeWidth(depth-1)) {
12851326
right = this._traverseMerkleTree(depth-1, pos*2+1, opts);
12861327
}
1287-
return Hash.sha256sha256(new Buffer.concat([left, right]));
1328+
if (checkForTxs){
1329+
return opts.txs;
1330+
} else {
1331+
return Hash.sha256sha256(new Buffer.concat([left, right]));
1332+
};
12881333
}
12891334
};
12901335

@@ -1367,7 +1412,7 @@ MerkleBlock.fromObject = function fromObject(obj) {
13671412
module.exports = MerkleBlock;
13681413

13691414
}).call(this,require("buffer").Buffer)
1370-
},{"../crypto/hash":8,"../encoding/bufferreader":14,"../encoding/bufferwriter":15,"../transaction":28,"../util/buffer":42,"../util/js":43,"../util/preconditions":44,"./blockheader":3,"buffer":47,"lodash":319}],6:[function(require,module,exports){
1415+
},{"../crypto/hash":8,"../encoding/bufferreader":14,"../encoding/bufferwriter":15,"../errors":17,"../transaction":28,"../util/buffer":42,"../util/js":43,"../util/preconditions":44,"./blockheader":3,"buffer":47,"lodash":319}],6:[function(require,module,exports){
13711416
(function (Buffer){
13721417
'use strict';
13731418

@@ -3210,6 +3255,13 @@ module.exports = [{
32103255
'name': 'InvalidRate',
32113256
'message': 'Invalid exchange rate: {0}'
32123257
}]
3258+
}, {
3259+
name: 'MerkleBlock',
3260+
message: 'Internal Error on MerkleBlock {0}',
3261+
errors: [{
3262+
'name': 'InvalidMerkleTree',
3263+
'message': 'This MerkleBlock contain an invalid Merkle Tree'
3264+
}]
32133265
}, {
32143266
name: 'Transaction',
32153267
message: 'Internal Error on Transaction {0}',
@@ -7130,15 +7182,17 @@ var Script = function Script(from) {
71307182
return Script.fromAddress(from);
71317183
} else if (from instanceof Script) {
71327184
return Script.fromBuffer(from.toBuffer());
7133-
} else if (typeof from === 'string') {
7185+
} else if (_.isString(from)) {
71347186
return Script.fromString(from);
7135-
} else if (typeof from !== 'undefined') {
7187+
} else if (_.isObject(from) && _.isArray(from.chunks)) {
71367188
this.set(from);
71377189
}
71387190
};
71397191

71407192
Script.prototype.set = function(obj) {
7141-
this.chunks = obj.chunks || this.chunks;
7193+
$.checkArgument(_.isObject(obj));
7194+
$.checkArgument(_.isArray(obj.chunks));
7195+
this.chunks = obj.chunks;
71427196
return this;
71437197
};
71447198

@@ -7322,7 +7376,21 @@ Script.prototype._chunkToString = function(chunk, type) {
73227376
if (!chunk.buf) {
73237377
// no data chunk
73247378
if (typeof Opcode.reverseMap[opcodenum] !== 'undefined') {
7325-
str = str + ' ' + Opcode(opcodenum).toString();
7379+
if (asm) {
7380+
// A few cases where the opcode name differs from reverseMap
7381+
// aside from 1 to 16 data pushes.
7382+
if (opcodenum === 0) {
7383+
// OP_0 -> 0
7384+
str = str + ' 0';
7385+
} else if(opcodenum === 79) {
7386+
// OP_1NEGATE -> 1
7387+
str = str + ' -1';
7388+
} else {
7389+
str = str + ' ' + Opcode(opcodenum).toString();
7390+
}
7391+
} else {
7392+
str = str + ' ' + Opcode(opcodenum).toString();
7393+
}
73267394
} else {
73277395
var numstr = opcodenum.toString(16);
73287396
if (numstr.length % 2 !== 0) {
@@ -7336,7 +7404,7 @@ Script.prototype._chunkToString = function(chunk, type) {
73367404
}
73377405
} else {
73387406
// data chunk
7339-
if (opcodenum === Opcode.OP_PUSHDATA1 ||
7407+
if (!asm && opcodenum === Opcode.OP_PUSHDATA1 ||
73407408
opcodenum === Opcode.OP_PUSHDATA2 ||
73417409
opcodenum === Opcode.OP_PUSHDATA4) {
73427410
str = str + ' ' + Opcode(opcodenum).toString();
@@ -9762,13 +9830,13 @@ Transaction.prototype.fromObject = function fromObject(arg) {
97629830

97639831
Transaction.prototype._checkConsistency = function(arg) {
97649832
if (!_.isUndefined(this._changeIndex)) {
9765-
$.checkState(this._changeScript);
9766-
$.checkState(this.outputs[this._changeIndex]);
9833+
$.checkState(this._changeScript, 'Change script is expected.');
9834+
$.checkState(this.outputs[this._changeIndex], 'Change index points to undefined output.');
97679835
$.checkState(this.outputs[this._changeIndex].script.toString() ===
9768-
this._changeScript.toString());
9836+
this._changeScript.toString(), 'Change output has an unexpected script.');
97699837
}
97709838
if (arg && arg.hash) {
9771-
$.checkState(arg.hash === this.hash, 'Hash in object does not match transaction hash');
9839+
$.checkState(arg.hash === this.hash, 'Hash in object does not match transaction hash.');
97729840
}
97739841
};
97749842

@@ -10419,7 +10487,7 @@ Transaction.prototype.removeInput = function(txId, outputIndex) {
1041910487
* @return {Transaction} this, for chaining
1042010488
*/
1042110489
Transaction.prototype.sign = function(privateKey, sigtype) {
10422-
$.checkState(this.hasAllUtxoInfo());
10490+
$.checkState(this.hasAllUtxoInfo(), 'Not all utxo information is available to sign the transaction.');
1042310491
var self = this;
1042410492
if (_.isArray(privateKey)) {
1042510493
_.each(privateKey, function(privateKey) {
@@ -53953,7 +54021,7 @@ arguments[4][262][0].apply(exports,arguments)
5395354021
},{}],320:[function(require,module,exports){
5395454022
module.exports={
5395554023
"name": "bitcore-lib",
53956-
"version": "5.0.0-beta.1",
54024+
"version": "0.15.0",
5395754025
"description": "A pure and powerful JavaScript Bitcoin library.",
5395854026
"author": "BitPay <[email protected]>",
5395954027
"main": "index.js",
@@ -53988,6 +54056,7 @@ module.exports={
5398854056
},
5398954057
"dependencies": {
5399054058
"bn.js": "=4.11.8",
54059+
"bs58": "=4.0.1",
5399154060
"buffer-compare": "=1.1.1",
5399254061
"elliptic": "=6.4.0",
5399354062
"inherits": "=2.0.1",
@@ -54004,13 +54073,23 @@ module.exports={
5400454073
}
5400554074

5400654075
},{}],"bitcore-lib":[function(require,module,exports){
54007-
(function (Buffer){
54076+
(function (global,Buffer){
5400854077
'use strict';
5400954078

5401054079
var bitcore = module.exports;
5401154080

5401254081
// module information
5401354082
bitcore.version = 'v' + require('./package.json').version;
54083+
bitcore.versionGuard = function(version) {
54084+
if (version !== undefined) {
54085+
var message = 'More than one instance of bitcore-lib found. ' +
54086+
'Please make sure to require bitcore-lib and check that submodules do' +
54087+
' not also include their own bitcore-lib dependency.';
54088+
throw new Error(message);
54089+
}
54090+
};
54091+
bitcore.versionGuard(global._bitcore);
54092+
global._bitcore = bitcore.version;
5401454093

5401554094
// crypto
5401654095
bitcore.crypto = {};
@@ -54065,5 +54144,5 @@ bitcore.deps._ = require('lodash');
5406554144
// Internal usage, exposed for testing/advanced tweaking
5406654145
bitcore.Transaction.sighash = require('./lib/transaction/sighash');
5406754146

54068-
}).call(this,require("buffer").Buffer)
54147+
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
5406954148
},{"./lib/address":1,"./lib/block":4,"./lib/block/blockheader":3,"./lib/block/merkleblock":5,"./lib/crypto/bn":6,"./lib/crypto/ecdsa":7,"./lib/crypto/hash":8,"./lib/crypto/point":9,"./lib/crypto/random":10,"./lib/crypto/signature":11,"./lib/encoding/base58":12,"./lib/encoding/base58check":13,"./lib/encoding/bufferreader":14,"./lib/encoding/bufferwriter":15,"./lib/encoding/varint":16,"./lib/errors":17,"./lib/hdprivatekey.js":19,"./lib/hdpublickey.js":20,"./lib/networks":21,"./lib/opcode":22,"./lib/privatekey":23,"./lib/publickey":24,"./lib/script":25,"./lib/transaction":28,"./lib/transaction/sighash":36,"./lib/unit":40,"./lib/uri":41,"./lib/util/buffer":42,"./lib/util/js":43,"./lib/util/preconditions":44,"./package.json":320,"bn.js":280,"bs58":281,"buffer":47,"elliptic":285,"lodash":319}]},{},[]);

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Bitcore v5.0.0-beta.1
1+
# Bitcore v0.15.0
22

33
## Principles
44

index.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ var bitcore = module.exports;
44

55
// module information
66
bitcore.version = 'v' + require('./package.json').version;
7+
bitcore.versionGuard = function(version) {
8+
if (version !== undefined) {
9+
var message = 'More than one instance of bitcore-lib found. ' +
10+
'Please make sure to require bitcore-lib and check that submodules do' +
11+
' not also include their own bitcore-lib dependency.';
12+
throw new Error(message);
13+
}
14+
};
15+
bitcore.versionGuard(global._bitcore);
16+
global._bitcore = bitcore.version;
717

818
// crypto
919
bitcore.crypto = {};

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "bitcore-lib",
3-
"version": "5.0.0-beta.1",
3+
"version": "0.15.0",
44
"description": "A pure and powerful JavaScript Bitcoin library.",
55
"author": "BitPay <[email protected]>",
66
"main": "index.js",

test/index.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,15 @@
22

33
var should = require("chai").should();
44
var bitcore = require("../");
5+
6+
describe('#versionGuard', function() {
7+
it('global._bitcore should be defined', function() {
8+
should.equal(global._bitcore, bitcore.version);
9+
});
10+
11+
it('throw an error if version is already defined', function() {
12+
(function() {
13+
bitcore.versionGuard('version');
14+
}).should.throw('More than one instance of bitcore');
15+
});
16+
});

0 commit comments

Comments
 (0)