refactor: move constants around.

This commit is contained in:
Christopher Jeffrey 2017-01-06 09:57:55 -08:00
parent d1a4e53896
commit 5caf6210b9
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
78 changed files with 2320 additions and 2028 deletions

View File

@ -5,7 +5,7 @@ var constants = require('../lib/protocol/constants');
var crypto = require('../lib/crypto/crypto');
var Script = require('../lib/script/script');
var bench = require('./bench');
var opcodes = constants.opcodes;
var opcodes = Script.opcodes;
var i, hashes, end;
Script.prototype.fromPubkeyhashOld = function fromScripthash(hash) {

View File

@ -4,10 +4,12 @@ var fs = require('fs');
var Block = require('../lib/primitives/block');
var Address = require('../lib/primitives/address');
var TX = require('../lib/primitives/tx');
var Script = require('../lib/script/script');
var MTX = require('../lib/primitives/mtx');
var Coin = require('../lib/primitives/coin');
var CoinView = require('../lib/coins/coinview');
var constants = require('../lib/protocol/constants');
var encoding = require('../lib/utils/encoding');
var crypto = require('../lib/crypto/crypto');
var bench = require('./bench');
@ -92,7 +94,7 @@ end(i);
end = bench('verify');
for (i = 0; i < 3000; i++)
tx3.tx.verify(tx3.view, constants.flags.VERIFY_P2SH);
tx3.tx.verify(tx3.view, Script.flags.VERIFY_P2SH);
end(i * tx3.tx.inputs.length);
end = bench('fee');
@ -100,7 +102,7 @@ for (i = 0; i < 1000; i++)
tx3.tx.getFee(tx3.view);
end(i);
flags = constants.flags.VERIFY_P2SH | constants.flags.VERIFY_DERSIG;
flags = Script.flags.VERIFY_P2SH | Script.flags.VERIFY_DERSIG;
end = bench('verify multisig');
for (i = 0; i < 3000; i++)
btx.tx.verify(btx.view, flags);
@ -111,7 +113,7 @@ tx = new MTX();
for (i = 0; i < 100; i++) {
tx.addInput({
prevout: {
hash: constants.NULL_HASH,
hash: encoding.NULL_HASH,
index: 0
},
script: [

View File

@ -12,12 +12,13 @@ var Network = require('../protocol/network');
var Logger = require('../node/logger');
var ChainDB = require('./chaindb');
var constants = require('../protocol/constants');
var consensus = require('../protocol/consensus');
var util = require('../utils/util');
var btcutils = require('../btc/utils');
var Locker = require('../utils/locker');
var LRU = require('../utils/lru');
var ChainEntry = require('./chainentry');
var CoinView = require('../coins/coinview');
var Script = require('../script/script');
var assert = require('assert');
var errors = require('../btc/errors');
var VerifyError = errors.VerifyError;
@ -414,7 +415,7 @@ Chain.prototype.verify = co(function* verify(block, prev) {
// Check block weight (different from block size
// check in non-contextual verification).
if (block.getWeight() > constants.block.MAX_WEIGHT) {
if (block.getWeight() > consensus.MAX_BLOCK_WEIGHT) {
throw new VerifyError(block,
'invalid',
'bad-blk-weight',
@ -468,8 +469,8 @@ Chain.prototype.getDeployments = co(function* getDeployments(block, prev) {
// not have a signature. See:
// 6a26d2ecb67f27d1fa5524763b49029d7106e91e3cc05743073461a719776192
// 9c08a4d78931342b37fd5f72900fb9983087e6f46c4a097d8a1f52c74e28eaf6
if (block.ts >= constants.block.BIP16_TIME)
state.flags |= constants.flags.VERIFY_P2SH;
if (block.ts >= consensus.BIP16_TIME)
state.flags |= Script.flags.VERIFY_P2SH;
// Coinbase heights are now enforced (bip34).
if (height >= this.network.block.bip34height)
@ -477,16 +478,16 @@ Chain.prototype.getDeployments = co(function* getDeployments(block, prev) {
// Signature validation is now enforced (bip66).
if (height >= this.network.block.bip66height)
state.flags |= constants.flags.VERIFY_DERSIG;
state.flags |= Script.flags.VERIFY_DERSIG;
// CHECKLOCKTIMEVERIFY is now usable (bip65)
if (height >= this.network.block.bip65height)
state.flags |= constants.flags.VERIFY_CHECKLOCKTIMEVERIFY;
state.flags |= Script.flags.VERIFY_CHECKLOCKTIMEVERIFY;
// Segregrated witness is now usable (bip141 - segnet3)
if (this.options.witness && this.network.oldWitness) {
if (height >= this.network.block.bip141height)
state.flags |= constants.flags.VERIFY_WITNESS;
state.flags |= Script.flags.VERIFY_WITNESS;
}
if (this.network.oldWitness)
@ -496,18 +497,18 @@ Chain.prototype.getDeployments = co(function* getDeployments(block, prev) {
// past locktimes are now usable (bip9 & bip113).
active = yield this.isActive(prev, deployments.csv);
if (active) {
state.flags |= constants.flags.VERIFY_CHECKSEQUENCEVERIFY;
state.lockFlags |= constants.flags.VERIFY_SEQUENCE;
state.lockFlags |= constants.flags.MEDIAN_TIME_PAST;
state.flags |= Script.flags.VERIFY_CHECKSEQUENCEVERIFY;
state.lockFlags |= constants.lockFlags.VERIFY_SEQUENCE;
state.lockFlags |= constants.lockFlags.MEDIAN_TIME_PAST;
}
// Segregrated witness is now usable (bip141 - segnet4)
active = yield this.isActive(prev, deployments.segwit);
if (active) {
if (this.options.witness)
state.flags |= constants.flags.VERIFY_WITNESS;
state.flags |= Script.flags.VERIFY_WITNESS;
// BIP147
state.flags |= constants.flags.VERIFY_NULLDUMMY;
state.flags |= Script.flags.VERIFY_NULLDUMMY;
}
return state;
@ -575,8 +576,8 @@ Chain.prototype.verifyDuplicates = co(function* verifyDuplicates(block, prev, st
// Blocks 91842 and 91880 created duplicate
// txids by using the same exact output script
// and extraNonce.
if (constants.bip30[height]) {
if (block.hash('hex') === constants.bip30[height])
if (this.network.bip30[height]) {
if (block.hash('hex') === this.network.bip30[height])
continue;
}
throw new VerifyError(block, 'invalid', 'bad-txns-BIP30', 100);
@ -648,7 +649,7 @@ Chain.prototype.verifyInputs = co(function* verifyInputs(block, prev, state) {
// Count sigops (legacy + scripthash? + witness?)
sigops += tx.getSigopsCost(view, state.flags);
if (sigops > constants.block.MAX_SIGOPS_COST) {
if (sigops > consensus.MAX_BLOCK_SIGOPS_COST) {
throw new VerifyError(block,
'invalid',
'bad-blk-sigops',
@ -1988,7 +1989,7 @@ Chain.prototype.retarget = function retarget(prev, first) {
return prev.bits;
actualTimespan = prev.ts - first.ts;
target = btcutils.fromCompact(prev.bits);
target = consensus.fromCompact(prev.bits);
if (actualTimespan < targetTimespan / 4 | 0)
actualTimespan = targetTimespan / 4 | 0;
@ -2002,7 +2003,7 @@ Chain.prototype.retarget = function retarget(prev, first) {
if (target.cmp(pow.limit) > 0)
return pow.bits;
return btcutils.toCompact(target);
return consensus.toCompact(target);
};
/**
@ -2222,10 +2223,10 @@ Chain.prototype.verifyFinal = co(function* verifyFinal(prev, tx, flags) {
var ts;
// We can skip MTP if the locktime is height.
if (tx.locktime < constants.LOCKTIME_THRESHOLD)
if (tx.locktime < consensus.LOCKTIME_THRESHOLD)
return tx.isFinal(height, -1);
if (flags & constants.flags.MEDIAN_TIME_PAST) {
if (flags & constants.lockFlags.MEDIAN_TIME_PAST) {
ts = yield prev.getMedianTimeAsync();
return tx.isFinal(height, ts);
}
@ -2244,11 +2245,11 @@ Chain.prototype.verifyFinal = co(function* verifyFinal(prev, tx, flags) {
*/
Chain.prototype.getLocks = co(function* getLocks(prev, tx, view, flags) {
var mask = constants.sequence.MASK;
var granularity = constants.sequence.GRANULARITY;
var disableFlag = constants.sequence.DISABLE_FLAG;
var typeFlag = constants.sequence.TYPE_FLAG;
var hasFlag = flags & constants.flags.VERIFY_SEQUENCE;
var mask = consensus.SEQUENCE_MASK;
var granularity = consensus.SEQUENCE_GRANULARITY;
var disableFlag = consensus.SEQUENCE_DISABLE_FLAG;
var typeFlag = consensus.SEQUENCE_TYPE_FLAG;
var hasFlag = flags & constants.lockFlags.VERIFY_SEQUENCE;
var nextHeight = this.height + 1;
var minHeight = -1;
var minTime = -1;
@ -2325,9 +2326,9 @@ function DeploymentState() {
if (!(this instanceof DeploymentState))
return new DeploymentState();
this.flags = constants.flags.MANDATORY_VERIFY_FLAGS;
this.flags &= ~constants.flags.VERIFY_P2SH;
this.lockFlags = constants.flags.MANDATORY_LOCKTIME_FLAGS;
this.flags = Script.flags.MANDATORY_VERIFY_FLAGS;
this.flags &= ~Script.flags.VERIFY_P2SH;
this.lockFlags = constants.lockFlags.MANDATORY_LOCKTIME_FLAGS;
this.bip34 = false;
}
@ -2337,7 +2338,7 @@ function DeploymentState() {
*/
DeploymentState.prototype.hasP2SH = function hasP2SH() {
return (this.flags & constants.flags.VERIFY_P2SH) !== 0;
return (this.flags & Script.flags.VERIFY_P2SH) !== 0;
};
/**
@ -2355,7 +2356,7 @@ DeploymentState.prototype.hasBIP34 = function hasBIP34() {
*/
DeploymentState.prototype.hasBIP66 = function hasBIP66() {
return (this.flags & constants.flags.VERIFY_DERSIG) !== 0;
return (this.flags & Script.flags.VERIFY_DERSIG) !== 0;
};
/**
@ -2364,7 +2365,7 @@ DeploymentState.prototype.hasBIP66 = function hasBIP66() {
*/
DeploymentState.prototype.hasCLTV = function hasCLTV() {
return (this.flags & constants.flags.VERIFY_CHECKLOCKTIMEVERIFY) !== 0;
return (this.flags & Script.flags.VERIFY_CHECKLOCKTIMEVERIFY) !== 0;
};
/**
@ -2373,7 +2374,7 @@ DeploymentState.prototype.hasCLTV = function hasCLTV() {
*/
DeploymentState.prototype.hasMTP = function hasMTP() {
return (this.lockFlags & constants.flags.MEDIAN_TIME_PAST) !== 0;
return (this.lockFlags & constants.lockFlags.MEDIAN_TIME_PAST) !== 0;
};
/**
@ -2382,7 +2383,7 @@ DeploymentState.prototype.hasMTP = function hasMTP() {
*/
DeploymentState.prototype.hasCSV = function hasCSV() {
return (this.flags & constants.flags.VERIFY_CHECKSEQUENCEVERIFY) !== 0;
return (this.flags & Script.flags.VERIFY_CHECKSEQUENCEVERIFY) !== 0;
};
/**
@ -2391,7 +2392,7 @@ DeploymentState.prototype.hasCSV = function hasCSV() {
*/
DeploymentState.prototype.hasWitness = function hasWitness() {
return (this.flags & constants.flags.VERIFY_WITNESS) !== 0;
return (this.flags & Script.flags.VERIFY_WITNESS) !== 0;
};
/**

View File

@ -7,10 +7,9 @@
'use strict';
var AsyncObject = require('../utils/async');
var constants = require('../protocol/constants');
var util = require('../utils/util');
var assert = require('assert');
var AsyncObject = require('../utils/async');
var util = require('../utils/util');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var Amount = require('../btc/amount');
@ -312,7 +311,7 @@ ChainDB.prototype.getHeight = co(function* getHeight(hash) {
assert(typeof hash === 'string');
if (hash === constants.NULL_HASH)
if (hash === encoding.NULL_HASH)
return -1;
entry = this.cacheHash.get(hash);
@ -441,7 +440,7 @@ ChainDB.prototype.getEntryByHash = co(function* getEntryByHash(hash) {
assert(typeof hash === 'string');
if (hash === constants.NULL_HASH)
if (hash === encoding.NULL_HASH)
return;
entry = this.cacheHash.get(hash);
@ -567,8 +566,8 @@ ChainDB.prototype.getStateCache = co(function* getStateCache() {
var i, items, item, key, bit, hash, state;
items = yield this.db.range({
gte: layout.v(0, constants.ZERO_HASH),
lte: layout.v(255, constants.MAX_HASH),
gte: layout.v(0, encoding.ZERO_HASH),
lte: layout.v(255, encoding.MAX_HASH),
values: true
});
@ -690,8 +689,8 @@ ChainDB.prototype.invalidateCache = co(function* invalidateCache(bit, batch) {
var i, keys, key;
keys = yield this.db.keys({
gte: layout.v(bit, constants.ZERO_HASH),
lte: layout.v(bit, constants.MAX_HASH)
gte: layout.v(bit, encoding.ZERO_HASH),
lte: layout.v(bit, encoding.MAX_HASH)
});
for (i = 0; i < keys.length; i++) {
@ -731,7 +730,7 @@ ChainDB.prototype.isMainChain = co(function* isMainChain(hash) {
return true;
}
if (hash === constants.NULL_HASH)
if (hash === encoding.NULL_HASH)
return false;
entry = this.cacheHash.get(hash);
@ -756,8 +755,8 @@ ChainDB.prototype.isMainChain = co(function* isMainChain(hash) {
ChainDB.prototype.getEntries = function getEntries() {
var self = this;
return this.db.values({
gte: layout.e(constants.ZERO_HASH),
lte: layout.e(constants.MAX_HASH),
gte: layout.e(encoding.ZERO_HASH),
lte: layout.e(encoding.MAX_HASH),
parse: function(value) {
return ChainEntry.fromRaw(self.chain, value);
}
@ -771,8 +770,8 @@ ChainDB.prototype.getEntries = function getEntries() {
ChainDB.prototype.getTips = function getTips() {
return this.db.keys({
gte: layout.p(constants.ZERO_HASH),
lte: layout.p(constants.MAX_HASH),
gte: layout.p(encoding.ZERO_HASH),
lte: layout.p(encoding.MAX_HASH),
parse: layout.pp
});
};
@ -1058,8 +1057,8 @@ ChainDB.prototype.getCoinsByAddress = co(function* getCoinsByAddress(addresses)
continue;
keys = yield this.db.keys({
gte: layout.C(hash, constants.ZERO_HASH, 0),
lte: layout.C(hash, constants.MAX_HASH, 0xffffffff),
gte: layout.C(hash, encoding.ZERO_HASH, 0),
lte: layout.C(hash, encoding.MAX_HASH, 0xffffffff),
parse: layout.Cc
});
@ -1096,8 +1095,8 @@ ChainDB.prototype.getHashesByAddress = co(function* getHashesByAddress(addresses
continue;
yield this.db.keys({
gte: layout.T(hash, constants.ZERO_HASH),
lte: layout.T(hash, constants.MAX_HASH),
gte: layout.T(hash, encoding.ZERO_HASH),
lte: layout.T(hash, encoding.MAX_HASH),
parse: function(key) {
var hash = layout.Tt(key);
hashes[hash] = true;
@ -2062,7 +2061,7 @@ ChainOptions.fromRaw = function fromRaw(data) {
*/
function ChainState() {
this.tip = constants.ZERO_HASH;
this.tip = encoding.ZERO_HASH;
this.tx = 0;
this.coin = 0;
this.value = 0;

View File

@ -7,13 +7,14 @@
'use strict';
var assert = require('assert');
var BN = require('bn.js');
var Network = require('../protocol/network');
var constants = require('../protocol/constants');
var consensus = require('../protocol/consensus');
var util = require('../utils/util');
var btcutils = require('../btc/utils');
var crypto = require('../crypto/crypto');
var assert = require('assert');
var encoding = require('../utils/encoding');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var Headers = require('../primitives/headers');
@ -52,10 +53,10 @@ function ChainEntry(chain, options, prev) {
this.chain = chain;
this.network = chain ? chain.network : Network.primary;
this.hash = constants.NULL_HASH;
this.hash = encoding.NULL_HASH;
this.version = 1;
this.prevBlock = constants.NULL_HASH;
this.merkleRoot = constants.NULL_HASH;
this.prevBlock = encoding.NULL_HASH;
this.merkleRoot = encoding.NULL_HASH;
this.ts = 0;
this.bits = 0;
this.nonce = 0;
@ -66,6 +67,21 @@ function ChainEntry(chain, options, prev) {
this.fromOptions(options, prev);
}
/**
* The max chainwork (1 << 256).
* @const {BN}
*/
ChainEntry.MAX_CHAINWORK = new BN(1).ushln(256);
/**
* Size of set to pick median time from.
* @const {Number}
* @default
*/
ChainEntry.MEDIAN_TIMESPAN = 11;
/**
* Inject properties from options.
* @private
@ -112,20 +128,13 @@ ChainEntry.fromOptions = function fromOptions(chain, options, prev) {
return new ChainEntry(chain).fromOptions(options, prev);
};
/**
* The max chainwork (1 << 256).
* @const {BN}
*/
ChainEntry.MAX_CHAINWORK = new BN(1).ushln(256);
/**
* Calculate the proof: (1 << 256) / (target + 1)
* @returns {BN} proof
*/
ChainEntry.prototype.getProof = function getProof() {
var target = btcutils.fromCompact(this.bits);
var target = consensus.fromCompact(this.bits);
if (target.isNeg() || target.cmpn(0) === 0)
return new BN(0);
return ChainEntry.MAX_CHAINWORK.div(target.iaddn(1));
@ -164,7 +173,7 @@ ChainEntry.prototype.isGenesis = function isGenesis() {
*/
ChainEntry.prototype.getRetargetAncestors = function getRetargetAncestors() {
var timespan = constants.block.MEDIAN_TIMESPAN;
var timespan = ChainEntry.MEDIAN_TIMESPAN;
var interval = this.network.pow.retargetInterval;
var reset = this.network.pow.difficultyReset;
var max = timespan;
@ -317,7 +326,7 @@ ChainEntry.prototype.getNextEntry = co(function* getNextEntry() {
*/
ChainEntry.prototype.getMedianTime = function getMedianTime(ancestors) {
var timespan = constants.block.MEDIAN_TIMESPAN;
var timespan = ChainEntry.MEDIAN_TIMESPAN;
var entry = this;
var median = [];
var i;
@ -336,7 +345,7 @@ ChainEntry.prototype.getMedianTime = function getMedianTime(ancestors) {
*/
ChainEntry.prototype.getMedianTimeAsync = co(function* getMedianTimeAsync() {
var timespan = constants.block.MEDIAN_TIMESPAN;
var timespan = ChainEntry.MEDIAN_TIMESPAN;
var ancestors = yield this.getAncestors(timespan);
return this.getMedianTime(ancestors);
});

View File

@ -9,8 +9,6 @@
var assert = require('assert');
var util = require('../utils/util');
var constants = require('../protocol/constants');
var Amount = require('./amount');
/**
* An error thrown during verification. Can be either
@ -69,95 +67,9 @@ function VerifyResult() {
this.score = 0;
}
/**
* An error thrown from the scripting system,
* potentially pertaining to Script execution.
* @exports ScriptError
* @constructor
* @extends Error
* @param {String} code - Error code.
* @param {(Number|String)?} op - Opcode.
* @param {Number?} ip - Instruction pointer.
* @property {String} message - Error message.
* @property {String} code - Original code passed in.
* @property {String?} op - Symbolic opcode.
* @property {Number?} ip - Instruction pointer.
*/
function ScriptError(code, op, ip) {
Error.call(this);
if (Error.captureStackTrace)
Error.captureStackTrace(this, ScriptError);
this.type = 'ScriptError';
this.code = code;
if (typeof op !== 'string') {
if (op || ip != null) {
code += ' (';
if (op) {
op = constants.opcodesByVal[op] || op;
code += 'op=' + op;
if (ip != null)
code += ', ';
}
if (ip != null)
code += 'ip=' + ip;
code += ')';
}
this.message = code;
this.op = op || '';
this.ip = ip != null ? ip : -1;
} else {
this.message = op;
this.op = '';
this.ip = -1;
}
}
util.inherits(ScriptError, Error);
/**
* An error thrown from the coin selector.
* @exports FundingError
* @constructor
* @extends Error
* @param {String} msg
* @param {Amount} available
* @param {Amount} required
* @property {String} message - Error message.
* @property {Amount} availableFunds
* @property {Amount} requiredFunds
*/
function FundingError(msg, available, required) {
Error.call(this);
if (Error.captureStackTrace)
Error.captureStackTrace(this, FundingError);
this.type = 'FundingError';
this.message = msg;
this.availableFunds = -1;
this.requiredFunds = -1;
if (available != null) {
this.message += ' (available=' + Amount.btc(available) + ',';
this.message += ' required=' + Amount.btc(required) + ')';
this.availableFunds = available;
this.requiredFunds = required;
}
}
util.inherits(FundingError, Error);
/*
* Expose
*/
exports.VerifyError = VerifyError;
exports.VerifyResult = VerifyResult;
exports.ScriptError = ScriptError;
exports.FundingError = FundingError;

View File

@ -1,324 +0,0 @@
/*!
* utils.js - bitcoin-related utils for bcoin
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var assert = require('assert');
var BN = require('bn.js');
var constants = require('../protocol/constants');
var util = require('../utils/util');
var Amount = require('./amount');
var utils = exports;
/**
* Convert a compact number to a big number.
* Used for `block.bits` -> `target` conversion.
* @param {Number} compact
* @returns {BN}
*/
utils.fromCompact = function fromCompact(compact) {
var exponent = compact >>> 24;
var negative = (compact >>> 23) & 1;
var mantissa = compact & 0x7fffff;
var num;
if (compact === 0)
return new BN(0);
// Logic ported from btcd since
// the bitcoind code is a nightmare.
if (exponent <= 3) {
mantissa >>>= 8 * (3 - exponent);
num = new BN(mantissa);
} else {
num = new BN(mantissa);
num.iushln(8 * (exponent - 3));
}
if (negative)
num.ineg();
return num;
};
/**
* Convert a big number to a compact number.
* Used for `target` -> `block.bits` conversion.
* @param {BN} num
* @returns {Number}
*/
utils.toCompact = function toCompact(num) {
var mantissa, exponent, compact;
if (num.cmpn(0) === 0)
return 0;
exponent = num.byteLength();
// Logic ported from btcd since
// the bitcoind code is a nightmare.
if (exponent <= 3) {
mantissa = num.toNumber();
mantissa <<= 8 * (3 - exponent);
} else {
mantissa = num.ushrn(8 * (exponent - 3)).toNumber();
}
if (mantissa & 0x800000) {
mantissa >>= 8;
exponent++;
}
compact = (exponent << 24) | mantissa;
if (num.isNeg())
compact |= 0x800000;
compact >>>= 0;
return compact;
};
/**
* Verify proof-of-work.
* @returns {Boolean}
*/
utils.verifyPOW = function verifyPOW(hash, bits) {
var target = utils.fromCompact(bits);
if (target.isNeg() || target.cmpn(0) === 0)
return false;
hash = new BN(hash, 'le');
if (hash.cmp(target) > 0)
return false;
return true;
};
/**
* Calculate block subsidy.
* @param {Number} height - Reward era by height.
* @returns {Amount}
*/
utils.getReward = function getReward(height, interval) {
var halvings = Math.floor(height / interval);
assert(height >= 0, 'Bad height for reward.');
// BIP 42 (well, our own version of it,
// since we can only handle 32 bit shifts).
// https://github.com/bitcoin/bips/blob/master/bip-0042.mediawiki
if (halvings >= 33)
return 0;
// We need to shift right by `halvings`,
// but 50 btc is a 33 bit number, so we
// cheat. We only start halving once the
// halvings are at least 1.
if (halvings === 0)
return 5000000000;
return 2500000000 >>> (halvings - 1);
};
/**
* Calculate minimum fee based on rate and size.
* @param {Number?} size
* @param {Rate?} rate - Rate of satoshi per kB.
* @returns {Amount} fee
*/
utils.getMinFee = function getMinFee(size, rate) {
var fee;
if (rate == null)
rate = constants.tx.MIN_RELAY;
fee = Math.floor(rate * size / 1000);
if (fee === 0 && rate > 0)
fee = rate;
return fee;
};
/**
* Calculate the minimum fee in order for the transaction
* to be relayable, but _round to the nearest kilobyte
* when taking into account size.
* @param {Number?} size
* @param {Rate?} rate - Rate of satoshi per kB.
* @returns {Amount} fee
*/
utils.getRoundFee = function getRoundFee(size, rate) {
var fee;
if (rate == null)
rate = constants.tx.MIN_RELAY;
fee = rate * Math.ceil(size / 1000);
if (fee === 0 && rate > 0)
fee = rate;
return fee;
};
/**
* Calculate a fee rate based on size and fees.
* @param {Number} size
* @param {Amount} fee
* @returns {Rate}
*/
utils.getRate = function getRate(size, fee) {
return Math.floor(fee * 1000 / size);
};
/**
* Safely convert satoshis to a BTC string.
* This function explicitly avoids any
* floating point arithmetic.
* @param {Amount} value - Satoshis.
* @returns {String} BTC string.
*/
utils.btc = function btc(value) {
if (util.isFloat(value))
return value;
return Amount.fromValue(value).toBTC();
};
/**
* Safely convert a BTC string to satoshis.
* This function explicitly avoids any
* floating point arithmetic. It also does
* extra validation to ensure the resulting
* Number will be 53 bits or less.
* @param {String} value - BTC
* @returns {Amount} Satoshis.
* @throws on parse error
*/
utils.satoshi = function satoshi(value) {
if (util.isInt(value))
return value;
return Amount.fromBTC(value).toValue();
};
/**
* Test and validate a satoshi value (Number).
* @param {Number?} value
* @returns {Boolean}
*/
utils.isSatoshi = function isSatoshi(value) {
try {
Amount.fromValue(value);
return true;
} catch (e) {
return false;
}
};
/**
* Test and validate a BTC string.
* @param {String?} value
* @returns {Boolean}
*/
utils.isBTC = function isBTC(value) {
try {
Amount.fromBTC(value);
return true;
} catch (e) {
return false;
}
};
/**
* Sort an array of transactions in dependency order.
* @param {TX[]} txs
* @returns {TX[]}
*/
utils.sortTX = function sortTX(txs) {
var depMap = {};
var count = {};
var result = [];
var top = [];
var map = txs;
var i, j, tx, hash, input;
var prev, hasDeps, deps;
if (Array.isArray(txs)) {
map = {};
for (i = 0; i < txs.length; i++) {
tx = txs[i];
hash = tx.hash('hex');
map[hash] = tx;
}
}
for (i = 0; i < txs.length; i++) {
tx = txs[i];
hash = tx.hash('hex');
hasDeps = false;
count[hash] = 0;
for (j = 0; j < tx.inputs.length; j++) {
input = tx.inputs[j];
prev = input.prevout.hash;
if (!map[prev])
continue;
count[hash] += 1;
hasDeps = true;
if (!depMap[prev])
depMap[prev] = [];
depMap[prev].push(tx);
}
if (hasDeps)
continue;
top.push(tx);
}
for (i = 0; i < top.length; i++) {
tx = top[i];
hash = tx.hash('hex');
result.push(tx);
deps = depMap[hash];
if (!deps)
continue;
for (j = 0; j < deps.length; j++) {
tx = deps[j];
hash = tx.hash('hex');
if (--count[hash] === 0)
top.push(tx);
}
}
return result;
};

View File

@ -8,7 +8,6 @@
var util = require('../utils/util');
var assert = require('assert');
var constants = require('../protocol/constants');
var Coin = require('../primitives/coin');
var Output = require('../primitives/output');
var BufferReader = require('../utils/reader');
@ -35,7 +34,7 @@ function Coins(options) {
return new Coins(options);
this.version = 1;
this.hash = constants.NULL_HASH;
this.hash = encoding.NULL_HASH;
this.height = -1;
this.coinbase = true;
this.outputs = [];

View File

@ -7,9 +7,48 @@
'use strict';
var LRU = require('../utils/lru');
var constants = require('../protocol/constants');
var common = exports;
/**
* Index at which hardening begins.
* @const {Number}
* @default
*/
common.HARDENED = 0x80000000;
/**
* Max index (u32max + 1).
* @const {Number}
* @default
*/
common.MAX_INDEX = 0x100000000;
/**
* Min entropy bits.
* @const {Number}
* @default
*/
common.MIN_ENTROPY = 128;
/**
* Max entropy bits.
* @const {Number}
* @default
*/
common.MAX_ENTROPY = 512;
/**
* Seed salt for key derivation ("Bitcoin seed").
* @const {Buffer}
* @default
*/
common.SEED_SALT = new Buffer('Bitcoin seed', 'ascii');
/**
* LRU cache to avoid deriving keys twice.
* @type {LRU}
@ -32,7 +71,7 @@ common.parsePath = function parsePath(path, max) {
var i, hardened, index;
if (max == null)
max = constants.hd.MAX_INDEX;
max = common.MAX_INDEX;
if (root !== 'm'
&& root !== 'M'
@ -54,7 +93,7 @@ common.parsePath = function parsePath(path, max) {
index = parseInt(index, 10);
if (hardened)
index += constants.hd.HARDENED;
index += common.HARDENED;
if (!(index >= 0 && index < max))
throw new Error('Index out of range.');
@ -86,10 +125,10 @@ common.isMaster = function isMaster(key) {
common.isAccount44 = function isAccount44(key, accountIndex) {
if (accountIndex != null) {
if (key.childIndex !== constants.hd.HARDENED + accountIndex)
if (key.childIndex !== common.HARDENED + accountIndex)
return false;
}
return key.depth === 3 && key.childIndex >= constants.hd.HARDENED;
return key.depth === 3 && key.childIndex >= common.HARDENED;
};
/**
@ -99,5 +138,5 @@ common.isAccount44 = function isAccount44(key, accountIndex) {
*/
common.isPurpose45 = function isPurpose45(key) {
return key.depth === 1 && key.childIndex === constants.hd.HARDENED + 45;
return key.depth === 1 && key.childIndex === common.HARDENED + 45;
};

View File

@ -6,14 +6,14 @@
'use strict';
var assert = require('assert');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var assert = require('assert');
var constants = require('../protocol/constants');
var StaticWriter = require('../utils/staticwriter');
var BufferReader = require('../utils/reader');
var encoding = require('../utils/encoding');
var wordlist = require('./wordlist');
var common = require('./common');
var nfkd = require('../utils/nfkd');
/**
@ -37,7 +37,7 @@ function Mnemonic(options) {
if (!(this instanceof Mnemonic))
return new Mnemonic(options);
this.bits = constants.hd.MIN_ENTROPY;
this.bits = common.MIN_ENTROPY;
this.language = 'english';
this.entropy = null;
this.phrase = null;
@ -74,8 +74,8 @@ Mnemonic.prototype.fromOptions = function fromOptions(options) {
if (options.bits != null) {
assert(util.isNumber(options.bits));
assert(options.bits >= constants.hd.MIN_ENTROPY);
assert(options.bits <= constants.hd.MAX_ENTROPY);
assert(options.bits >= common.MIN_ENTROPY);
assert(options.bits <= common.MAX_ENTROPY);
assert(options.bits % 32 === 0);
this.bits = options.bits;
}
@ -119,7 +119,7 @@ Mnemonic.fromOptions = function fromOptions(options) {
*/
Mnemonic.prototype.destroy = function destroy() {
this.bits = constants.hd.MIN_ENTROPY;
this.bits = common.MIN_ENTROPY;
this.language = 'english';
if (this.entropy) {
crypto.cleanse(this.entropy);
@ -238,8 +238,8 @@ Mnemonic.prototype.fromPhrase = function fromPhrase(phrase) {
cbytes = Math.ceil(cbits / 8);
bits -= cbits;
assert(bits >= constants.hd.MIN_ENTROPY);
assert(bits <= constants.hd.MAX_ENTROPY);
assert(bits >= common.MIN_ENTROPY);
assert(bits <= common.MAX_ENTROPY);
assert(bits % 32 === 0);
assert(cbits !== 0, 'Invalid checksum.');
@ -308,8 +308,8 @@ Mnemonic.fromPhrase = function fromPhrase(phrase) {
Mnemonic.prototype.fromEntropy = function fromEntropy(entropy, lang) {
assert(Buffer.isBuffer(entropy));
assert(entropy.length * 8 >= constants.hd.MIN_ENTROPY);
assert(entropy.length * 8 <= constants.hd.MAX_ENTROPY);
assert(entropy.length * 8 >= common.MIN_ENTROPY);
assert(entropy.length * 8 <= common.MAX_ENTROPY);
assert((entropy.length * 8) % 32 === 0);
assert(!lang || Mnemonic.languages.indexOf(lang) !== -1);
@ -390,8 +390,8 @@ Mnemonic.prototype.fromJSON = function fromJSON(json) {
assert(typeof json.entropy === 'string');
assert(typeof json.phrase === 'string');
assert(typeof json.passphrase === 'string');
assert(json.bits >= constants.hd.MIN_ENTROPY);
assert(json.bits <= constants.hd.MAX_ENTROPY);
assert(json.bits >= common.MIN_ENTROPY);
assert(json.bits <= common.MAX_ENTROPY);
assert(json.bits % 32 === 0);
assert(json.bits / 8 === json.entropy.length / 2);
@ -471,8 +471,8 @@ Mnemonic.prototype.fromReader = function fromReader(br) {
this.passphrase = br.readVarString('utf8');
assert(this.language);
assert(this.bits >= constants.hd.MIN_ENTROPY);
assert(this.bits <= constants.hd.MAX_ENTROPY);
assert(this.bits >= common.MIN_ENTROPY);
assert(this.bits <= common.MAX_ENTROPY);
assert(this.bits % 32 === 0);
return this;

View File

@ -6,27 +6,20 @@
'use strict';
var assert = require('assert');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var ec = require('../crypto/ec');
var assert = require('assert');
var constants = require('../protocol/constants');
var networks = require('../protocol/networks');
var Network = require('../protocol/network');
var StaticWriter = require('../utils/staticwriter');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var base58 = require('../utils/base58');
var encoding = require('../utils/encoding');
var common = require('./common');
var Mnemonic = require('./mnemonic');
var HDPublicKey = require('./public');
var common = require('./common');
/*
* Constants
*/
var FINGER_PRINT = new Buffer('00000000', 'hex');
var SEED_SALT = new Buffer('Bitcoin seed', 'ascii');
/**
* HDPrivateKey
@ -55,12 +48,12 @@ function HDPrivateKey(options) {
this.network = Network.primary;
this.depth = 0;
this.parentFingerPrint = FINGER_PRINT;
this.parentFingerPrint = encoding.ZERO_U32;
this.childIndex = 0;
this.chainCode = constants.ZERO_HASH;
this.privateKey = constants.ZERO_HASH;
this.chainCode = encoding.ZERO_HASH;
this.privateKey = encoding.ZERO_HASH;
this.publicKey = constants.ZERO_KEY;
this.publicKey = encoding.ZERO_KEY;
this.fingerPrint = null;
this.mnemonic = null;
@ -229,12 +222,12 @@ HDPrivateKey.prototype.derive = function derive(index, hardened, cache) {
if (typeof index === 'string')
return this.derivePath(index, cache);
hardened = index >= constants.hd.HARDENED ? true : hardened;
hardened = index >= common.HARDENED ? true : hardened;
if (index < constants.hd.HARDENED && hardened)
index += constants.hd.HARDENED;
if (index < common.HARDENED && hardened)
index += common.HARDENED;
if (!(index >= 0 && index < constants.hd.MAX_INDEX))
if (!(index >= 0 && index < common.MAX_INDEX))
throw new Error('Index out of range.');
if (this.depth >= 0xff)
@ -416,7 +409,7 @@ HDPrivateKey.isValidPath = function isValidPath(path) {
return false;
try {
common.parsePath(path, constants.hd.MAX_INDEX);
common.parsePath(path, common.MAX_INDEX);
return true;
} catch (e) {
return false;
@ -431,7 +424,7 @@ HDPrivateKey.isValidPath = function isValidPath(path) {
*/
HDPrivateKey.prototype.derivePath = function derivePath(path, cache) {
var indexes = common.parsePath(path, constants.hd.MAX_INDEX);
var indexes = common.parsePath(path, common.MAX_INDEX);
var key = this;
var i;
@ -511,12 +504,12 @@ HDPrivateKey.prototype.fromSeed = function fromSeed(seed, network) {
assert(Buffer.isBuffer(seed));
if (!(seed.length * 8 >= constants.hd.MIN_ENTROPY
&& seed.length * 8 <= constants.hd.MAX_ENTROPY)) {
if (!(seed.length * 8 >= common.MIN_ENTROPY
&& seed.length * 8 <= common.MAX_ENTROPY)) {
throw new Error('Entropy not in range.');
}
hash = crypto.hmac('sha512', seed, SEED_SALT);
hash = crypto.hmac('sha512', seed, common.SEED_SALT);
left = hash.slice(0, 32);
right = hash.slice(32, 64);

View File

@ -6,24 +6,18 @@
'use strict';
var assert = require('assert');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var ec = require('../crypto/ec');
var assert = require('assert');
var constants = require('../protocol/constants');
var networks = require('../protocol/networks');
var Network = require('../protocol/network');
var StaticWriter = require('../utils/staticwriter');
var BufferReader = require('../utils/reader');
var base58 = require('../utils/base58');
var encoding = require('../utils/encoding');
var common = require('./common');
/*
* Constants
*/
var FINGER_PRINT = new Buffer('00000000', 'hex');
/**
* HDPublicKey
* @exports HDPublicKey
@ -49,10 +43,10 @@ function HDPublicKey(options) {
this.network = Network.primary;
this.depth = 0;
this.parentFingerPrint = FINGER_PRINT;
this.parentFingerPrint = encoding.ZERO_U32;
this.childIndex = 0;
this.chainCode = constants.ZERO_HASH;
this.publicKey = constants.ZERO_KEY;
this.chainCode = encoding.ZERO_HASH;
this.publicKey = encoding.ZERO_KEY;
this.fingerPrint = null;
@ -187,7 +181,7 @@ HDPublicKey.prototype.derive = function derive(index, hardened, cache) {
if (typeof index === 'string')
return this.derivePath(index, cache);
if (index >= constants.hd.HARDENED || hardened)
if (index >= common.HARDENED || hardened)
throw new Error('Index out of range.');
if (index < 0)
@ -316,7 +310,7 @@ HDPublicKey.isValidPath = function isValidPath(path) {
return false;
try {
common.parsePath(path, constants.hd.HARDENED);
common.parsePath(path, common.HARDENED);
return true;
} catch (e) {
return false;
@ -332,7 +326,7 @@ HDPublicKey.isValidPath = function isValidPath(path) {
*/
HDPublicKey.prototype.derivePath = function derivePath(path, cache) {
var indexes = common.parsePath(path, constants.hd.HARDENED);
var indexes = common.parsePath(path, common.HARDENED);
var key = this;
var i;

View File

@ -8,7 +8,6 @@
var fs = require('fs');
var EventEmitter = require('events').EventEmitter;
var util = require('../utils/util');
var co = require('../utils/co');
var crypto = require('../crypto/crypto');
@ -32,6 +31,9 @@ var Output = require('../primitives/output');
var TX = require('../primitives/tx');
var Logger = require('../node/logger');
var IP = require('../utils/ip');
var encoding = require('../utils/encoding');
var consensus = require('../protocol/consensus');
var USER_VERSION = require('../../package.json').version;
/**
* RPC
@ -322,8 +324,8 @@ RPC.prototype.getinfo = co(function* getinfo(args) {
balance = yield this.wallet.getBalance();
return {
version: constants.USER_VERSION,
protocolversion: constants.VERSION,
version: USER_VERSION,
protocolversion: this.pool.protoVersion,
walletversion: 0,
balance: Amount.btc(balance.unconfirmed, true),
blocks: this.chain.height,
@ -375,14 +377,14 @@ RPC.prototype.getnetworkinfo = co(function* getnetworkinfo(args) {
throw new RPCError('getnetworkinfo');
return {
version: constants.USER_VERSION,
subversion: constants.USER_AGENT,
protocolversion: constants.VERSION,
localservices: this.pool.services,
version: USER_VERSION,
subversion: this.pool.userAgent,
protocolversion: this.pool.protoVersion,
localservices: this.pool.address.services,
timeoffset: this.network.time.offset,
connections: this.pool.peers.size(),
networks: [],
relayfee: Amount.btc(this.network.getMinRelay(), true),
relayfee: Amount.btc(this.network.minRelay, true),
localaddresses: [],
warnings: ''
};
@ -889,7 +891,7 @@ RPC.prototype._headerToJSON = co(function* _headerToJSON(entry) {
bits: entry.bits,
difficulty: this._getDifficulty(entry),
chainwork: entry.chainwork.toString('hex', 64),
previousblockhash: entry.prevBlock !== constants.NULL_HASH
previousblockhash: entry.prevBlock !== encoding.NULL_HASH
? util.revHex(entry.prevBlock)
: null,
nextblockhash: nextHash ? util.revHex(nextHash) : null
@ -920,7 +922,7 @@ RPC.prototype._blockToJSON = co(function* _blockToJSON(entry, block, txDetails)
bits: entry.bits,
difficulty: this._getDifficulty(entry),
chainwork: entry.chainwork.toString('hex', 64),
previousblockhash: entry.prevBlock !== constants.NULL_HASH
previousblockhash: entry.prevBlock !== encoding.NULL_HASH
? util.revHex(entry.prevBlock)
: null,
nextblockhash: nextHash ? util.revHex(nextHash) : null
@ -1441,7 +1443,7 @@ RPC.prototype.submitblock = co(function* submitblock(args) {
this.logger.debug(tx);
// Recreate witness nonce (all zeroes).
tx.inputs[0].witness.set(0, constants.ZERO_HASH);
tx.inputs[0].witness.set(0, encoding.ZERO_HASH);
tx.inputs[0].witness.compile();
tx.refresh();
@ -1560,7 +1562,7 @@ RPC.prototype._template = co(function* _template(version, coinbase, rules) {
RPC.prototype.__template = co(function* _template(version, coinbase, rules) {
var attempt = yield this._getAttempt(false);
var scale = attempt.witness ? 1 : constants.WITNESS_SCALE_FACTOR;
var scale = attempt.witness ? 1 : consensus.WITNESS_SCALE_FACTOR;
var block = attempt.block;
var mutable = ['time', 'transactions', 'prevblock'];
var txs = [];
@ -1652,9 +1654,9 @@ RPC.prototype.__template = co(function* _template(version, coinbase, rules) {
mintime: block.ts,
maxtime: block.ts + 7200,
expires: block.ts + 7200,
sigoplimit: constants.block.MAX_SIGOPS_COST / scale | 0,
sizelimit: constants.block.MAX_RAW_SIZE,
weightlimit: constants.block.MAX_WEIGHT,
sigoplimit: consensus.MAX_BLOCK_SIGOPS_COST / scale | 0,
sizelimit: consensus.MAX_RAW_BLOCK_SIZE,
weightlimit: consensus.MAX_BLOCK_WEIGHT,
longpollid: this.chain.tip.rhash() + util.pad32(this._totalTX()),
submitold: false,
coinbaseaux: {
@ -2187,7 +2189,7 @@ RPC.prototype.signrawtransaction = co(function* signrawtransaction(args) {
});
RPC.prototype._signrawtransaction = co(function* signrawtransaction(wallet, tx, args) {
var type = constants.hashType.ALL;
var type = Script.hashType.ALL;
var keys = [];
var keyMap = {};
var i, j, k, secret, key;
@ -2262,7 +2264,7 @@ RPC.prototype._signrawtransaction = co(function* signrawtransaction(wallet, tx,
if (args.length > 3) {
parts = toString(args[3]).split('|');
type = constants.hashType[parts[0]];
type = Script.hashType[parts[0]];
if (type == null)
throw new RPCError('Invalid parameter');
@ -2273,7 +2275,7 @@ RPC.prototype._signrawtransaction = co(function* signrawtransaction(wallet, tx,
if (parts.length === 2) {
if (parts[1] !== 'ANYONECANPAY')
throw new RPCError('Invalid parameter');
type |= constants.hashType.ANYONECANPAY;
type |= Script.hashType.ANYONECANPAY;
}
}
@ -2373,7 +2375,7 @@ RPC.prototype._createRedeem = co(function* _createRedeem(args) {
throw new RPCError('Invalid parameters.');
}
if (script.getSize() > constants.script.MAX_PUSH)
if (script.getSize() > consensus.MAX_SCRIPT_PUSH)
throw new RPCError('Redeem script exceeds size limit.');
return script;
@ -2726,7 +2728,7 @@ RPC.prototype.dumpwallet = co(function* dumpwallet(args) {
file = toString(args[0]);
time = util.date();
out = [
util.fmt('# Wallet Dump created by BCoin %s', constants.USER_VERSION),
util.fmt('# Wallet Dump created by BCoin %s', USER_VERSION),
util.fmt('# * Created on %s', time),
util.fmt('# * Best block at time of backup was %d (%s),',
this.chain.height, this.chain.tip.rhash()),
@ -3535,7 +3537,7 @@ RPC.prototype.listsinceblock = co(function* listsinceblock(args) {
transactions: out,
lastblock: highest && highest.block
? util.revHex(highest.block)
: constants.NULL_HASH
: encoding.NULL_HASH
};
});

View File

@ -12,7 +12,6 @@
var EventEmitter = require('events').EventEmitter;
var assert = require('assert');
var constants = require('../protocol/constants');
var HTTPBase = require('./base');
var util = require('../utils/util');
var co = require('../utils/co');
@ -26,6 +25,7 @@ var Outpoint = require('../primitives/outpoint');
var HD = require('../hd/hd');
var Script = require('../script/script');
var crypto = require('../crypto/crypto');
var USER_VERSION = require('../../package.json').version;
var con = co.con;
var RPC;
@ -126,8 +126,8 @@ HTTPServer.prototype._init = function _init() {
return res.end();
}
res.setHeader('X-Bcoin-Version', constants.USER_VERSION);
res.setHeader('X-Bcoin-Agent', constants.USER_AGENT);
res.setHeader('X-Bcoin-Version', USER_VERSION);
res.setHeader('X-Bcoin-Agent', this.pool.userAgent);
res.setHeader('X-Bcoin-Network', this.network.type);
res.setHeader('X-Bcoin-Height', this.chain.height + '');
res.setHeader('X-Bcoin-Tip', util.revHex(this.chain.tip.hash));
@ -633,8 +633,8 @@ HTTPServer.prototype._init = function _init() {
var size = this.mempool ? this.mempool.getSize() : 0;
send(200, {
version: constants.USER_VERSION,
agent: constants.USER_AGENT,
version: USER_VERSION,
agent: this.pool.userAgent,
network: this.network.type,
chain: {
height: this.chain.height,
@ -1314,8 +1314,8 @@ HTTPServer.prototype._initIO = function _initIO() {
});
socket.emit('version', {
version: constants.USER_VERSION,
agent: constants.USER_AGENT,
version: USER_VERSION,
agent: self.pool.userAgent,
network: self.network.type
});
});

View File

@ -8,9 +8,10 @@
'use strict';
var util = require('../utils/util');
var assert = require('assert');
var constants = require('../protocol/constants');
var util = require('../utils/util');
var consensus = require('../protocol/consensus');
var policy = require('../protocol/policy');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var encoding = require('../utils/encoding');
@ -32,13 +33,13 @@ var SUFFICIENT_FEETXS = 1;
var SUFFICIENT_PRITXS = 0.2;
var MIN_FEERATE = 10;
var MAX_FEERATE = 1e7;
var INF_FEERATE = constants.MAX_MONEY;
var INF_FEERATE = consensus.MAX_MONEY;
var MIN_PRIORITY = 10;
var MAX_PRIORITY = 1e16;
var INF_PRIORITY = 1e9 * constants.MAX_MONEY;
var INF_PRIORITY = 1e9 * consensus.MAX_MONEY;
var FEE_SPACING = 1.1;
var PRI_SPACING = 2;
var FREE_THRESHOLD = constants.tx.FREE_THRESHOLD;
var FREE_THRESHOLD = policy.FREE_THRESHOLD;
/**
* Confirmation stats.

View File

@ -6,18 +6,18 @@
'use strict';
var assert = require('assert');
var AsyncObject = require('../utils/async');
var constants = require('../protocol/constants');
var policy = require('../protocol/policy');
var util = require('../utils/util');
var co = require('../utils/co');
var assert = require('assert');
var crypto = require('../crypto/crypto');
var errors = require('../btc/errors');
var VerifyError = errors.VerifyError;
var VerifyResult = errors.VerifyResult;
var Bloom = require('../utils/bloom');
var Address = require('../primitives/address');
var Coin = require('../primitives/coin');
var Script = require('../script/script');
var Locker = require('../utils/locker');
var Outpoint = require('../primitives/outpoint');
var TX = require('../primitives/tx');
@ -26,6 +26,8 @@ var TXMeta = require('../primitives/txmeta');
var MempoolEntry = require('./mempoolentry');
var CoinView = require('../coins/coinview');
var Coins = require('../coins/coins');
var VerifyError = errors.VerifyError;
var VerifyResult = errors.VerifyResult;
/**
* Represents a mempool.
@ -106,15 +108,48 @@ function Mempool(options) {
this.paranoid = !!this.options.paranoid;
this.replaceByFee = !!this.options.replaceByFee;
this.maxSize = options.maxSize || constants.mempool.MAX_MEMPOOL_SIZE;
this.maxOrphans = options.maxOrphans || constants.mempool.MAX_ORPHAN_TX;
this.maxAncestors = options.maxAncestors || constants.mempool.ANCESTOR_LIMIT;
this.expiryTime = options.expiryTime || constants.mempool.MEMPOOL_EXPIRY;
this.maxSize = options.maxSize || Mempool.MAX_SIZE;
this.maxOrphans = options.maxOrphans || Mempool.MAX_ORPHANS;
this.maxAncestors = options.maxAncestors || Mempool.ANCESTOR_LIMIT;
this.expiryTime = options.expiryTime || Mempool.EXPIRY_TIME;
this.minRelay = this.network.minRelay;
}
util.inherits(Mempool, AsyncObject);
/**
* Default ancestor limit.
* @const {Number}
* @default
*/
Mempool.ANCESTOR_LIMIT = 25;
/**
* Default maximum mempool size in bytes.
* @const {Number}
* @default
*/
Mempool.MAX_SIZE = 100 * 1000000;
/**
* Time at which transactions
* fall out of the mempool.
* @const {Number}
* @default
*/
Mempool.EXPIRY_TIME = 72 * 60 * 60;
/**
* Maximum number of orphan transactions.
* @const {Number}
* @default
*/
Mempool.MAX_ORPHANS = 100;
/**
* Open the chain, wait for the database to load.
* @alias Mempool#open
@ -657,7 +692,7 @@ Mempool.prototype.addTX = co(function* addTX(tx) {
*/
Mempool.prototype._addTX = co(function* _addTX(tx) {
var lockFlags = constants.flags.STANDARD_LOCKTIME_FLAGS;
var lockFlags = constants.lockFlags.STANDARD_LOCKTIME_FLAGS;
var hash = tx.hash('hex');
var ret = new VerifyResult();
var entry, view, missing;
@ -796,8 +831,8 @@ Mempool.prototype._addTX = co(function* _addTX(tx) {
Mempool.prototype.verify = co(function* verify(entry, view) {
var height = this.chain.height + 1;
var lockFlags = constants.flags.STANDARD_LOCKTIME_FLAGS;
var flags = constants.flags.STANDARD_VERIFY_FLAGS;
var lockFlags = constants.lockFlags.STANDARD_LOCKTIME_FLAGS;
var flags = Script.flags.STANDARD_VERIFY_FLAGS;
var ret = new VerifyResult();
var tx = entry.tx;
var now, minFee, result;
@ -831,7 +866,7 @@ Mempool.prototype.verify = co(function* verify(entry, view) {
}
// Annoying process known as sigops counting.
if (entry.sigops > constants.tx.MAX_SIGOPS_COST) {
if (entry.sigops > policy.MAX_TX_SIGOPS_COST) {
throw new VerifyError(tx,
'nonstandard',
'bad-txns-too-many-sigops',
@ -895,8 +930,8 @@ Mempool.prototype.verify = co(function* verify(entry, view) {
throw err;
// Try without segwit and cleanstack.
flags &= ~constants.flags.VERIFY_WITNESS;
flags &= ~constants.flags.VERIFY_CLEANSTACK;
flags &= ~Script.flags.VERIFY_WITNESS;
flags &= ~Script.flags.VERIFY_CLEANSTACK;
result = yield this.verifyResult(tx, view, flags);
// If it failed, the first verification
@ -906,7 +941,7 @@ Mempool.prototype.verify = co(function* verify(entry, view) {
// If it succeeded, segwit may be causing the
// failure. Try with segwit but without cleanstack.
flags |= constants.flags.VERIFY_CLEANSTACK;
flags |= Script.flags.VERIFY_CLEANSTACK;
result = yield this.verifyResult(tx, view, flags);
// Cleanstack was causing the failure.
@ -920,7 +955,7 @@ Mempool.prototype.verify = co(function* verify(entry, view) {
// Paranoid checks.
if (this.paranoid) {
flags = constants.flags.MANDATORY_VERIFY_FLAGS;
flags = Script.flags.MANDATORY_VERIFY_FLAGS;
result = yield this.verifyResult(tx, view, flags);
assert(result, 'BUG: Verify failed for mandatory but not standard.');
}
@ -959,14 +994,14 @@ Mempool.prototype.verifyInputs = co(function* verifyInputs(tx, view, flags) {
if (yield tx.verifyAsync(view, flags))
return;
if (!(flags & constants.flags.UNSTANDARD_VERIFY_FLAGS)) {
if (!(flags & Script.flags.UNSTANDARD_VERIFY_FLAGS)) {
throw new VerifyError(tx,
'nonstandard',
'non-mandatory-script-verify-flag',
0);
}
flags &= ~constants.flags.UNSTANDARD_VERIFY_FLAGS;
flags &= ~Script.flags.UNSTANDARD_VERIFY_FLAGS;
if (yield tx.verifyAsync(view, flags)) {
throw new VerifyError(tx,
@ -1318,7 +1353,7 @@ Mempool.prototype.storeOrphan = function storeOrphan(tx, missing) {
var hash = tx.hash('hex');
var i, prev;
if (tx.getWeight() > constants.tx.MAX_WEIGHT) {
if (tx.getWeight() > policy.MAX_TX_WEIGHT) {
this.logger.debug('Ignoring large orphan: %s', tx.txid());
if (!tx.hasWitness())
this.rejects.add(tx.hash());

View File

@ -7,8 +7,9 @@
'use strict';
var constants = require('../protocol/constants');
var policy = require('../protocol/policy');
var util = require('../utils/util');
var btcutils = require('../btc/utils');
var Script = require('../script/script');
/**
* Represents a mempool entry.
@ -82,7 +83,7 @@ MempoolEntry.fromOptions = function fromOptions(options) {
*/
MempoolEntry.prototype.fromTX = function fromTX(tx, view, height) {
var flags = constants.flags.STANDARD_VERIFY_FLAGS;
var flags = Script.flags.STANDARD_VERIFY_FLAGS;
var priority = tx.getPriority(view, height);
var value = tx.getChainValue(view, height);
var sigops = tx.getSigopsCost(view, flags);
@ -156,7 +157,7 @@ MempoolEntry.prototype.getFee = function getFee() {
*/
MempoolEntry.prototype.getRate = function getRate() {
return btcutils.getRate(this.size, this.fee);
return policy.getRate(this.size, this.fee);
};
/**
@ -169,7 +170,7 @@ MempoolEntry.prototype.getRate = function getRate() {
MempoolEntry.prototype.isFree = function isFree(height) {
var priority = this.getPriority(height);
return priority > constants.tx.FREE_THRESHOLD;
return priority > policy.FREE_THRESHOLD;
};
/*

View File

@ -7,14 +7,15 @@
'use strict';
var assert = require('assert');
var util = require('../utils/util');
var co = require('../utils/co');
var assert = require('assert');
var constants = require('../protocol/constants');
var AsyncObject = require('../utils/async');
var Address = require('../primitives/address');
var MinerBlock = require('./minerblock');
var BlockEntry = MinerBlock.BlockEntry;
var consensus = require('../protocol/consensus');
var policy = require('../protocol/policy');
/**
* A bitcoin miner (supports mining witness blocks).
@ -53,10 +54,10 @@ function Miner(options) {
this.coinbaseFlags = new Buffer('mined by bcoin', 'ascii');
this.minWeight = 0;
this.maxWeight = 750000 * constants.WITNESS_SCALE_FACTOR;
this.maxSigops = constants.block.MAX_SIGOPS_COST;
this.priorityWeight = 50000 * constants.WITNESS_SCALE_FACTOR;
this.minPriority = constants.tx.FREE_THRESHOLD;
this.maxWeight = 750000 * consensus.WITNESS_SCALE_FACTOR;
this.maxSigops = consensus.MAX_BLOCK_SIGOPS_COST;
this.priorityWeight = 50000 * consensus.WITNESS_SCALE_FACTOR;
this.minPriority = policy.FREE_THRESHOLD;
this._initOptions(options);
this._init();
@ -106,7 +107,7 @@ Miner.prototype._initOptions = function _initOptions(options) {
if (options.maxSigops != null) {
assert(util.isNumber(options.maxSigops));
assert(options.maxSigops <= constants.block.MAX_SIGOPS_COST);
assert(options.maxSigops <= consensus.MAX_BLOCK_SIGOPS_COST);
this.maxSigops = options.maxSigops;
}

View File

@ -8,13 +8,11 @@
'use strict';
var assert = require('assert');
var BN = require('bn.js');
var util = require('../utils/util');
var btcutils = require('../btc/utils');
var co = require('../utils/co');
var StaticWriter = require('../utils/staticwriter');
var constants = require('../protocol/constants');
var Network = require('../protocol/network');
var BN = require('bn.js');
var EventEmitter = require('events').EventEmitter;
var TX = require('../primitives/tx');
var Block = require('../primitives/block');
@ -22,6 +20,8 @@ var Input = require('../primitives/input');
var Output = require('../primitives/output');
var mine = require('./mine');
var workerPool = require('../workers/workerpool').pool;
var consensus = require('../protocol/consensus');
var encoding = require('../utils/encoding');
/**
* MinerBlock
@ -52,7 +52,7 @@ function MinerBlock(options) {
this.version = options.version;
this.height = options.tip.height + 1;
this.bits = options.bits;
this.target = btcutils.fromCompact(this.bits).toArrayLike(Buffer, 'le', 32);
this.target = consensus.fromCompact(this.bits).toArrayLike(Buffer, 'le', 32);
this.locktime = options.locktime;
this.flags = options.flags;
this.nonce1 = 0;
@ -62,7 +62,7 @@ function MinerBlock(options) {
this.witness = options.witness;
this.address = options.address;
this.network = Network.get(options.network);
this.reward = btcutils.getReward(this.height, this.network.halvingInterval);
this.reward = consensus.getReward(this.height, this.network.halvingInterval);
this.destroyed = false;
this.committed = false;
@ -115,7 +115,7 @@ MinerBlock.prototype.getRate = function() {
*/
MinerBlock.prototype._init = function _init() {
var scale = constants.WITNESS_SCALE_FACTOR;
var scale = consensus.WITNESS_SCALE_FACTOR;
var block = this.block;
var cb = this.coinbase;
var input, output, nonce;
@ -123,7 +123,7 @@ MinerBlock.prototype._init = function _init() {
// Setup our block.
block.version = this.version;
block.prevBlock = this.tip.hash;
block.merkleRoot = constants.NULL_HASH;
block.merkleRoot = encoding.NULL_HASH;
block.ts = Math.max(this.network.now(), this.tip.ts + 1);
block.bits = this.bits;
block.nonce = 0;
@ -138,6 +138,7 @@ MinerBlock.prototype._init = function _init() {
// miner succeeded.
input.script.set(1, this.coinbaseFlags);
// Smaller nonce for good measure.
input.script.set(2, util.nonce().slice(0, 4));
// extraNonce - incremented when
@ -183,9 +184,6 @@ MinerBlock.prototype._init = function _init() {
// 4 extra bytes for varint tx count.
this.weight += 4 * scale;
// 8 extra bytes for extra nonce.
this.weight += 8 * scale;
// Initialize sigops weight.
this.sigops = cb.getSigopsCost(null, this.flags);
};
@ -301,10 +299,10 @@ MinerBlock.prototype.addTX = function addTX(tx, view) {
if (!tx.isFinal(this.height, this.locktime))
return false;
if (this.weight + weight > constants.block.MAX_WEIGHT)
if (this.weight + weight > consensus.MAX_BLOCK_WEIGHT)
return false;
if (this.sigops + sigops > constants.block.MAX_SIGOPS_COST)
if (this.sigops + sigops > consensus.MAX_BLOCK_SIGOPS_COST)
return false;
if (!this.witness && tx.hasWitness())

View File

@ -9,15 +9,15 @@
'use strict';
var EventEmitter = require('events').EventEmitter;
var assert = require('assert');
var util = require('../utils/util');
var co = require('../utils/co');
var crypto = require('../crypto/crypto');
var packets = require('./packets');
var assert = require('assert');
var constants = require('../protocol/constants');
var ec = require('../crypto/ec');
var StaticWriter = require('../utils/staticwriter');
var base58 = require('../utils/base58');
var encoding = require('../utils/encoding');
/**
* Represents a BIP150 input and output stream.
@ -85,13 +85,13 @@ BIP150.prototype.challenge = function challenge(hash) {
assert(!this.challengeReceived, 'Peer challenged twice.');
this.challengeReceived = true;
if (util.equal(hash, constants.ZERO_HASH))
if (util.equal(hash, encoding.ZERO_HASH))
throw new Error('Auth failure.');
msg = this.hash(this.input.sid, type, this.publicKey);
if (!crypto.ccmp(hash, msg))
return constants.ZERO_SIG64;
return encoding.ZERO_SIG64;
if (this.isAuthed()) {
this.auth = true;
@ -112,7 +112,7 @@ BIP150.prototype.reply = function reply(data) {
assert(!this.replyReceived, 'Peer replied twice.');
this.replyReceived = true;
if (util.equal(data, constants.ZERO_SIG64))
if (util.equal(data, encoding.ZERO_SIG64))
throw new Error('Auth failure.');
if (!this.peerIdentity)
@ -149,7 +149,7 @@ BIP150.prototype.propose = function propose(hash) {
match = this.findAuthorized(hash);
if (!match)
return constants.ZERO_HASH;
return encoding.ZERO_HASH;
this.peerIdentity = match;

View File

@ -17,7 +17,6 @@ var util = require('../utils/util');
var co = require('../utils/co');
var crypto = require('../crypto/crypto');
var assert = require('assert');
var constants = require('../protocol/constants');
var chachapoly = require('../crypto/chachapoly');
var packets = require('./packets');
var ec = require('../crypto/ec');
@ -325,6 +324,14 @@ function BIP151(cipher) {
util.inherits(BIP151, EventEmitter);
/**
* Max message size.
* @const {Number}
* @default
*/
BIP151.MAX_MESSAGE = 12 * 1000 * 1000;
/**
* Emit an error.
* @param {...String} msg
@ -387,7 +394,7 @@ BIP151.prototype.toEncack = function toEncack() {
BIP151.prototype.toRekey = function toRekey() {
assert(this.handshake, 'Cannot rekey before handshake.');
return new EncackPacket(constants.ZERO_KEY);
return new EncackPacket(encoding.ZERO_KEY);
};
/**
@ -410,7 +417,7 @@ BIP151.prototype.encinit = function encinit(publicKey, cipher) {
BIP151.prototype.encack = function encack(publicKey) {
assert(this.initSent, 'Unsolicited ACK.');
if (util.equal(publicKey, constants.ZERO_KEY)) {
if (util.equal(publicKey, encoding.ZERO_KEY)) {
assert(this.handshake, 'No initialization before rekey.');
if (this.bip150 && this.bip150.auth) {
@ -678,7 +685,7 @@ BIP151.prototype.parse = function parse(data) {
// potential dos'er or a cipher state mismatch.
// Note that 6 is the minimum size:
// varint-cmdlen(1) str-cmd(1) u32-size(4) payload(0)
if (size < 6 || size > constants.MAX_MESSAGE * 3) {
if (size < 6 || size > BIP151.MAX_MESSAGE) {
this.waiting = 4;
this.error('Bad packet size: %d.', util.mb(size));
return;

View File

@ -11,9 +11,9 @@ var BufferReader = require('../utils/reader');
var BufferWriter = require('../utils/writer');
var StaticWriter = require('../utils/staticwriter');
var encoding = require('../utils/encoding');
var consensus = require('../protocol/consensus');
var crypto = require('../crypto/crypto');
var assert = require('assert');
var constants = require('../protocol/constants');
var siphash = require('../crypto/siphash');
var AbstractBlock = require('../primitives/abstractblock');
var TX = require('../primitives/tx');
@ -298,7 +298,7 @@ CompactBlock.prototype.init = function init() {
if (this.totalTX === 0)
throw new Error('Empty vectors.');
if (this.totalTX > constants.block.MAX_SIZE / 10)
if (this.totalTX > consensus.MAX_BLOCK_SIZE / 10)
throw new Error('Compact block too big.');
// No sparse arrays here, v8.

112
lib/net/common.js Normal file
View File

@ -0,0 +1,112 @@
/*!
* common.js - p2p constants for bcoin
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var USER_VERSION = require('../../package.json').version;
/**
* Default protocol version.
* @const {Number}
* @default
*/
exports.PROTOCOL_VERSION = 70014;
/**
* Minimum protocol version we're willing to talk to.
* @const {Number}
* @default
*/
exports.MIN_VERSION = 70001;
/**
* Service bits.
* @enum {Number}
* @default
*/
exports.services = {
/**
* Whether network services are enabled.
*/
NETWORK: 1 << 0,
/**
* Whether the peer supports the getutxos packet.
*/
GETUTXO: 1 << 1,
/**
* Whether the peer supports BIP37.
*/
BLOOM: 1 << 2,
/**
* Whether the peer supports segregated witness.
*/
WITNESS: 1 << 3
};
/**
* BCoin's services (we support everything).
* @const {Number}
* @default
*/
exports.LOCAL_SERVICES = 0
| exports.services.NETWORK
| exports.services.GETUTXO
| exports.services.BLOOM
| exports.services.WITNESS;
/**
* Required services (network and segwit).
* @const {Number}
* @default
*/
exports.REQUIRED_SERVICES = 0
| exports.services.NETWORK
| exports.services.WITNESS;
/**
* Default user agent: `/bcoin:[version]/`.
* @const {String}
* @default
*/
exports.USER_AGENT = '/bcoin:' + USER_VERSION + '/';
/**
* Max message size (~4mb with segwit, formerly 2mb)
* @const {Number}
* @default
*/
exports.MAX_MESSAGE = 4 * 1000 * 1000;
/**
* Amount of time to ban misbheaving peers.
* @const {Number}
* @default
*/
exports.BAN_TIME = 24 * 60 * 60;
/**
* Ban score threshold before ban is placed in effect.
* @const {Number}
* @default
*/
exports.BAN_SCORE = 100;

View File

@ -3,11 +3,12 @@
exports.BIP150 = require('./bip150');
exports.BIP151 = require('./bip151');
exports.bip152 = require('./bip152');
exports.packets = require('./packets');
exports.common = require('./common');
exports.dns = require('./dns');
exports.Framer = require('./framer');
exports.HostList = require('./hostlist');
exports.packets = require('./packets');
exports.Parser = require('./parser');
exports.Peer = require('./peer');
exports.Pool = require('./pool');
exports.tcp = require('./tcp');
exports.dns = require('./dns');

View File

@ -7,7 +7,7 @@
'use strict';
var constants = require('../protocol/constants');
var common = require('./common');
var util = require('../utils/util');
var assert = require('assert');
var crypto = require('../crypto/crypto');
@ -172,13 +172,13 @@ function VersionPacket(options) {
Packet.call(this);
this.version = constants.VERSION;
this.services = constants.LOCAL_SERVICES;
this.version = common.PROTOCOL_VERSION;
this.services = common.LOCAL_SERVICES;
this.ts = util.now();
this.recv = new NetAddress();
this.from = new NetAddress();
this.nonce = constants.ZERO_U64;
this.agent = constants.USER_AGENT;
this.nonce = encoding.ZERO_U64;
this.agent = common.USER_AGENT;
this.height = 0;
this.noRelay = false;
@ -289,7 +289,7 @@ VersionPacket.prototype.toRaw = function toRaw() {
*/
VersionPacket.prototype.hasNetwork = function hasNetwork() {
return (this.services & constants.services.NETWORK) !== 0;
return (this.services & common.services.NETWORK) !== 0;
};
/**
@ -299,7 +299,7 @@ VersionPacket.prototype.hasNetwork = function hasNetwork() {
VersionPacket.prototype.hasBloom = function hasBloom() {
return this.version >= 70011
&& (this.services & constants.services.BLOOM) !== 0;
&& (this.services & common.services.BLOOM) !== 0;
};
/**
@ -308,7 +308,7 @@ VersionPacket.prototype.hasBloom = function hasBloom() {
*/
VersionPacket.prototype.hasUTXO = function hasUTXO() {
return (this.services & constants.services.GETUTXO) !== 0;
return (this.services & common.services.GETUTXO) !== 0;
};
/**
@ -317,7 +317,7 @@ VersionPacket.prototype.hasUTXO = function hasUTXO() {
*/
VersionPacket.prototype.hasWitness = function hasWitness() {
return (this.services & constants.services.WITNESS) !== 0;
return (this.services & common.services.WITNESS) !== 0;
};
/**
@ -577,7 +577,7 @@ function PongPacket(nonce) {
Packet.call(this);
this.nonce = nonce || constants.ZERO_U64;
this.nonce = nonce || encoding.ZERO_U64;
}
util.inherits(PongPacket, Packet);
@ -695,7 +695,7 @@ function AlertPacket(options) {
this.cancel = 0;
this.cancels = [];
this.minVer = 10000;
this.maxVer = constants.VERSION;
this.maxVer = common.PROTOCOL_VERSION;
this.subVers = [];
this.priority = 100;
this.comment = '';
@ -1350,7 +1350,7 @@ function GetBlocksPacket(locator, stop) {
Packet.call(this);
this.version = constants.VERSION;
this.version = common.PROTOCOL_VERSION;
this.locator = locator || [];
this.stop = stop || null;
}
@ -1388,7 +1388,7 @@ GetBlocksPacket.prototype.toWriter = function toWriter(bw) {
for (i = 0; i < this.locator.length; i++)
bw.writeHash(this.locator[i]);
bw.writeHash(this.stop || constants.ZERO_HASH);
bw.writeHash(this.stop || encoding.ZERO_HASH);
return bw;
};
@ -1421,7 +1421,7 @@ GetBlocksPacket.prototype.fromReader = function fromReader(br) {
this.stop = br.readHash('hex');
if (this.stop === constants.NULL_HASH)
if (this.stop === encoding.NULL_HASH)
this.stop = null;
return this;
@ -1854,7 +1854,7 @@ TXPacket.fromRaw = function fromRaw(data, enc) {
* @exports RejectPacket
* @constructor
* @property {(Number|String)?} code - Code
* (see {@link constants.reject}).
* (see {@link RejectPacket.codes}).
* @property {String?} msg - Message.
* @property {String?} reason - Reason.
* @property {(Hash|Buffer)?} data - Transaction or block hash.
@ -1867,7 +1867,7 @@ function RejectPacket(options) {
Packet.call(this);
this.message = '';
this.code = constants.reject.INVALID;
this.code = RejectPacket.codes.INVALID;
this.reason = '';
this.hash = null;
@ -1877,6 +1877,36 @@ function RejectPacket(options) {
util.inherits(RejectPacket, Packet);
/**
* Reject codes. Note that `internal` and higher
* are not meant for use on the p2p network.
* @enum {Number}
* @default
*/
RejectPacket.codes = {
MALFORMED: 0x01,
INVALID: 0x10,
OBSOLETE: 0x11,
DUPLICATE: 0x12,
NONSTANDARD: 0x40,
DUST: 0x41,
INSUFFICIENTFEE: 0x42,
CHECKPOINT: 0x43,
// Internal codes (NOT FOR USE ON NETWORK)
INTERNAL: 0x100,
HIGHFEE: 0x100,
ALREADYKNOWN: 0x101,
CONFLICT: 0x102
};
/**
* Reject codes by value.
* @const {RevMap}
*/
RejectPacket.codesByVal = util.revMap(RejectPacket.codes);
RejectPacket.prototype.cmd = 'reject';
RejectPacket.prototype.type = exports.types.REJECT;
@ -1894,10 +1924,10 @@ RejectPacket.prototype.fromOptions = function fromOptions(options) {
if (code != null) {
if (typeof code === 'string')
code = constants.reject[code.toUpperCase()];
code = RejectPacket.codes[code.toUpperCase()];
if (code >= constants.reject.INTERNAL)
code = constants.reject.INVALID;
if (code >= RejectPacket.codes.INTERNAL)
code = RejectPacket.codes.INVALID;
this.code = code;
}
@ -1936,7 +1966,7 @@ RejectPacket.prototype.rhash = function rhash() {
*/
RejectPacket.prototype.getCode = function getCode() {
var code = constants.rejectByVal[this.code];
var code = RejectPacket.codesByVal[this.code];
if (!code)
return this.code + '';
@ -2058,13 +2088,13 @@ RejectPacket.fromRaw = function fromRaw(data, enc) {
RejectPacket.prototype.fromReason = function fromReason(code, reason, obj) {
if (typeof code === 'string')
code = constants.reject[code.toUpperCase()];
code = RejectPacket.codes[code.toUpperCase()];
if (!code)
code = constants.reject.INVALID;
code = RejectPacket.codes.INVALID;
if (code >= constants.reject.INTERNAL)
code = constants.reject.INVALID;
if (code >= RejectPacket.codes.INTERNAL)
code = RejectPacket.codes.INVALID;
this.message = '';
this.code = code;
@ -2109,7 +2139,7 @@ RejectPacket.fromError = function fromError(err, obj) {
RejectPacket.prototype.inspect = function inspect() {
return '<Reject:'
+ ' msg=' + this.message
+ ' code=' + (constants.rejectByVal[this.code] || this.code)
+ ' code=' + (RejectPacket.codesByVal[this.code] || this.code)
+ ' reason=' + this.reason
+ ' hash=' + (this.hash ? util.revHex(this.hash) : null)
+ '>';
@ -2595,7 +2625,7 @@ function UTXOsPacket(options) {
Packet.call(this);
this.height = -1;
this.tip = constants.NULL_HASH;
this.tip = encoding.NULL_HASH;
this.hits = [];
this.coins = [];
@ -3351,7 +3381,7 @@ function EncinitPacket(publicKey, cipher) {
Packet.call(this);
this.publicKey = publicKey || constants.ZERO_KEY;
this.publicKey = publicKey || encoding.ZERO_KEY;
this.cipher = cipher || 0;
}
@ -3448,7 +3478,7 @@ function EncackPacket(publicKey) {
Packet.call(this);
this.publicKey = publicKey || constants.ZERO_KEY;
this.publicKey = publicKey || encoding.ZERO_KEY;
}
util.inherits(EncackPacket, Packet);
@ -3542,7 +3572,7 @@ function AuthChallengePacket(hash) {
Packet.call(this);
this.hash = hash || constants.ZERO_HASH;
this.hash = hash || encoding.ZERO_HASH;
}
util.inherits(AuthChallengePacket, Packet);
@ -3636,7 +3666,7 @@ function AuthReplyPacket(signature) {
Packet.call(this);
this.signature = signature || constants.ZERO_SIG64;
this.signature = signature || encoding.ZERO_SIG64;
}
util.inherits(AuthReplyPacket, Packet);
@ -3730,7 +3760,7 @@ function AuthProposePacket(hash) {
Packet.call(this);
this.hash = hash || constants.ZERO_HASH;
this.hash = hash || encoding.ZERO_HASH;
}
util.inherits(AuthProposePacket, Packet);

View File

@ -12,7 +12,7 @@ var EventEmitter = require('events').EventEmitter;
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var assert = require('assert');
var constants = require('../protocol/constants');
var common = require('./common');
var packets = require('./packets');
/**
@ -123,7 +123,7 @@ Parser.prototype.feed = function feed(data) {
Parser.prototype.parse = function parse(data) {
var payload, checksum;
assert(data.length <= constants.MAX_MESSAGE);
assert(data.length <= common.MAX_MESSAGE);
if (!this.header) {
this.header = this.parseHeader(data);
@ -177,7 +177,7 @@ Parser.prototype.parseHeader = function parseHeader(data) {
size = data.readUInt32LE(16, true);
if (size > constants.MAX_MESSAGE) {
if (size > common.MAX_MESSAGE) {
this.waiting = 24;
return this.error('Packet length too large: %dmb.', util.mb(size));
}

View File

@ -14,7 +14,8 @@ var co = require('../utils/co');
var Parser = require('./parser');
var Framer = require('./framer');
var packets = require('./packets');
var constants = require('../protocol/constants');
var consensus = require('../protocol/consensus');
var common = require('./common');
var InvItem = require('../primitives/invitem');
var Locker = require('../utils/locker');
var Bloom = require('../utils/bloom');
@ -23,6 +24,7 @@ var BIP150 = require('./bip150');
var BIP152 = require('./bip152');
var Block = require('../primitives/block');
var TX = require('../primitives/tx');
var encoding = require('../utils/encoding');
var errors = require('../btc/errors');
var NetAddress = require('../primitives/netaddress');
var invTypes = InvItem.types;
@ -823,12 +825,12 @@ Peer.prototype.sendHeaders = function sendHeaders(items) {
Peer.prototype.sendVersion = function sendVersion() {
var packet = new packets.VersionPacket();
packet.version = constants.VERSION;
packet.version = this.pool.protoVersion;
packet.services = this.pool.address.services;
packet.ts = this.network.now();
packet.from = this.pool.address;
packet.nonce = this.pool.localNonce;
packet.agent = constants.USER_AGENT;
packet.agent = this.pool.userAgent;
packet.height = this.chain.height;
packet.noRelay = this.options.noRelay;
this.send(packet);
@ -1528,7 +1530,7 @@ Peer.prototype.handleFilterLoad = co(function* handleFilterLoad(packet) {
Peer.prototype.handleFilterAdd = co(function* handleFilterAdd(packet) {
var data = packet.data;
if (data.length > constants.script.MAX_PUSH) {
if (data.length > consensus.MAX_SCRIPT_PUSH) {
this.increaseBan(100);
return;
}
@ -1588,7 +1590,7 @@ Peer.prototype.handleMerkleBlock = co(function* handleMerkleBlock(packet) {
Peer.prototype.handleFeeFilter = co(function* handleFeeFilter(packet) {
var rate = packet.rate;
if (!(rate >= 0 && rate <= constants.MAX_MONEY)) {
if (!(rate >= 0 && rate <= consensus.MAX_MONEY)) {
this.increaseBan(100);
return;
}
@ -1790,7 +1792,7 @@ Peer.prototype.handleVersion = co(function* handleVersion(packet) {
throw new Error('We connected to ourself. Oops.');
}
if (packet.version < constants.MIN_VERSION)
if (packet.version < common.MIN_VERSION)
throw new Error('Peer does not support required protocol version.');
if (this.options.witness) {
@ -2211,7 +2213,7 @@ Peer.prototype.handlePong = co(function* handlePong(packet) {
}
if (!util.equal(nonce, this.challenge)) {
if (util.equal(nonce, constants.ZERO_U64)) {
if (util.equal(nonce, encoding.ZERO_U64)) {
this.logger.debug('Peer sent a zero nonce (%s).', this.hostname);
this.challenge = null;
return;

View File

@ -13,7 +13,7 @@ var AsyncObject = require('../utils/async');
var util = require('../utils/util');
var IP = require('../utils/ip');
var co = require('../utils/co');
var constants = require('../protocol/constants');
var common = require('./common');
var errors = require('../btc/errors');
var NetAddress = require('../primitives/netaddress');
var Address = require('../primitives/address');
@ -28,6 +28,7 @@ var List = require('../utils/list');
var tcp = require('./tcp');
var dns = require('./dns');
var HostList = require('./hostlist');
var InvItem = require('../primitives/invitem');
var invTypes = InvItem.types;
var VerifyError = errors.VerifyError;
var VerifyResult = errors.VerifyResult;
@ -104,6 +105,7 @@ function Pool(options) {
this.maxOutbound = 8;
this.maxInbound = 8;
this.connected = false;
this.syncing = false;
this.createSocket = tcp.createSocket;
this.createServer = tcp.createServer;
this.resolve = dns.resolve;
@ -111,19 +113,16 @@ function Pool(options) {
this.authdb = null;
this.identityKey = null;
this.proxyServer = null;
this.banTime = constants.BAN_TIME;
this.banScore = constants.BAN_SCORE;
this.banTime = common.BAN_TIME;
this.banScore = common.BAN_SCORE;
this.feeRate = -1;
// Required services.
this.reqServices = constants.services.NETWORK;
this.reqServices |= constants.services.WITNESS;
this.syncing = false;
this.reqServices = common.REQUIRED_SERVICES;
this.address = new NetAddress();
this.address.ts = this.network.now();
this.address.services = constants.LOCAL_SERVICES;
this.address.services = common.LOCAL_SERVICES;
this.address.setPort(this.network.port);
this.hosts = new HostList(this);
@ -131,6 +130,9 @@ function Pool(options) {
this.localNonce = util.nonce();
this.protoVersion = common.PROTOCOL_VERSION;
this.userAgent = common.USER_AGENT;
this.spvFilter = null;
this.txFilter = null;
@ -165,8 +167,8 @@ Pool.prototype._initOptions = function _initOptions() {
this.options.headers = this.options.spv;
if (!this.options.witness) {
this.address.services &= ~constants.services.WITNESS;
this.reqServices &= ~constants.services.WITNESS;
this.address.services &= ~common.services.WITNESS;
this.reqServices &= ~common.services.WITNESS;
}
if (this.options.host != null) {
@ -211,12 +213,23 @@ Pool.prototype._initOptions = function _initOptions() {
if (this.options.selfish) {
assert(typeof this.options.selfish === 'boolean');
this.address.services &= ~constants.services.NETWORK;
this.address.services &= ~common.services.NETWORK;
}
if (this.options.spv) {
assert(typeof this.options.spv === 'boolean');
this.address.services &= ~constants.services.NETWORK;
this.address.services &= ~common.services.NETWORK;
}
if (this.options.protoVersion) {
assert(typeof this.options.protoVersion === 'number');
this.protoVersion = this.options.protoVersion;
}
if (this.options.userAgent) {
assert(typeof this.options.userAgent === 'string');
assert(this.options.userAgent.length < 256);
this.userAgent = this.options.userAgent;
}
if (this.options.bip150) {
@ -260,7 +273,7 @@ Pool.prototype._initOptions = function _initOptions() {
if (this.options.spv) {
this.spvFilter = Bloom.fromRate(10000, 0.001, Bloom.flags.ALL);
this.reqServices |= constants.services.BLOOM;
this.reqServices |= common.services.BLOOM;
}
if (!this.options.mempool)

View File

@ -7,7 +7,6 @@
'use strict';
var constants = require('../protocol/constants');
var util = require('../utils/util');
var co = require('../utils/co');
var Node = require('./node');
@ -18,6 +17,7 @@ var Pool = require('../net/pool');
var Miner = require('../mining/miner');
var WalletDB = require('../wallet/walletdb');
var HTTPServer = require('../http/server');
var policy = require('../protocol/policy');
/**
* Create a fullnode complete with a chain,
@ -80,7 +80,7 @@ function FullNode(options) {
// Fee estimation.
this.fees = new Fees(
constants.tx.MIN_RELAY,
policy.MIN_RELAY,
this.network,
this.logger);

View File

@ -8,13 +8,13 @@
'use strict';
var assert = require('assert');
var constants = require('../protocol/constants');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var btcutils = require('../btc/utils');
var VerifyResult = require('../btc/errors').VerifyResult;
var StaticWriter = require('../utils/staticwriter');
var InvItem = require('./invitem');
var encoding = require('../utils/encoding');
var consensus = require('../protocol/consensus');
/**
* The class which all block-like objects inherit from.
@ -40,8 +40,8 @@ function AbstractBlock() {
return new AbstractBlock();
this.version = 1;
this.prevBlock = constants.NULL_HASH;
this.merkleRoot = constants.NULL_HASH;
this.prevBlock = encoding.NULL_HASH;
this.merkleRoot = encoding.NULL_HASH;
this.ts = 0;
this.bits = 0;
this.nonce = 0;
@ -312,7 +312,7 @@ AbstractBlock.prototype._verifyHeaders = function verifyHeaders(ret) {
*/
AbstractBlock.prototype.verifyPOW = function verifyPOW() {
return btcutils.verifyPOW(this.hash(), this.bits);
return consensus.verifyPOW(this.hash(), this.bits);
};
/**

View File

@ -7,16 +7,16 @@
'use strict';
var assert = require('assert');
var Network = require('../protocol/network');
var networks = require('../protocol/networks');
var constants = require('../protocol/constants');
var encoding = require('../script/encoding');
var enc = require('../utils/encoding');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var assert = require('assert');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var base58 = require('../utils/base58');
var scriptTypes = constants.scriptTypes;
/**
* Represents an address.
@ -38,8 +38,8 @@ function Address(options) {
if (!(this instanceof Address))
return new Address(options);
this.hash = constants.ZERO_HASH160;
this.type = scriptTypes.PUBKEYHASH;
this.hash = enc.ZERO_HASH160;
this.type = Address.types.PUBKEYHASH;
this.version = -1;
this.network = Network.primary;
@ -52,7 +52,14 @@ function Address(options) {
* @enum {Number}
*/
Address.types = scriptTypes;
Address.types = encoding.types;
/**
* Address types by value.
* @const {RevMap}
*/
Address.typesByVal = encoding.typesByVal;
/**
* Inject properties from options object.
@ -127,7 +134,7 @@ Address.prototype.verifyNetwork = function verifyNetwork(network) {
*/
Address.prototype.getType = function getType() {
return constants.scriptTypesByVal[this.type].toLowerCase();
return encoding.typesByVal[this.type].toLowerCase();
};
/**
@ -283,42 +290,42 @@ Address.fromBase58 = function fromBase58(address) {
Address.prototype.fromScript = function fromScript(script) {
if (script.isPubkey()) {
this.hash = crypto.hash160(script.get(0));
this.type = scriptTypes.PUBKEYHASH;
this.type = Address.types.PUBKEYHASH;
this.version = -1;
return this;
}
if (script.isPubkeyhash()) {
this.hash = script.get(2);
this.type = scriptTypes.PUBKEYHASH;
this.type = Address.types.PUBKEYHASH;
this.version = -1;
return this;
}
if (script.isScripthash()) {
this.hash = script.get(1);
this.type = scriptTypes.SCRIPTHASH;
this.type = Address.types.SCRIPTHASH;
this.version = -1;
return this;
}
if (script.isWitnessPubkeyhash()) {
this.hash = script.get(1);
this.type = scriptTypes.WITNESSPUBKEYHASH;
this.type = Address.types.WITNESSPUBKEYHASH;
this.version = 0;
return this;
}
if (script.isWitnessScripthash()) {
this.hash = script.get(1);
this.type = scriptTypes.WITNESSSCRIPTHASH;
this.type = Address.types.WITNESSSCRIPTHASH;
this.version = 0;
return this;
}
if (script.isWitnessMasthash()) {
this.hash = script.get(1);
this.type = scriptTypes.WITNESSSCRIPTHASH;
this.type = Address.types.WITNESSSCRIPTHASH;
this.version = 1;
return this;
}
@ -326,7 +333,7 @@ Address.prototype.fromScript = function fromScript(script) {
// Put this last: it's the slowest to check.
if (script.isMultisig()) {
this.hash = script.hash160();
this.type = scriptTypes.SCRIPTHASH;
this.type = Address.types.SCRIPTHASH;
this.version = -1;
return this;
}
@ -343,14 +350,14 @@ Address.prototype.fromWitness = function fromWitness(witness) {
// since we can't get the version.
if (witness.isPubkeyhashInput()) {
this.hash = crypto.hash160(witness.get(1));
this.type = scriptTypes.WITNESSPUBKEYHASH;
this.type = Address.types.WITNESSPUBKEYHASH;
this.version = 0;
return this;
}
if (witness.isScripthashInput()) {
this.hash = crypto.sha256(witness.get(witness.length - 1));
this.type = scriptTypes.WITNESSSCRIPTHASH;
this.type = Address.types.WITNESSSCRIPTHASH;
this.version = 0;
return this;
}
@ -365,14 +372,14 @@ Address.prototype.fromWitness = function fromWitness(witness) {
Address.prototype.fromInputScript = function fromInputScript(script) {
if (script.isPubkeyhashInput()) {
this.hash = crypto.hash160(script.get(1));
this.type = scriptTypes.PUBKEYHASH;
this.type = Address.types.PUBKEYHASH;
this.version = -1;
return this;
}
if (script.isScripthashInput()) {
this.hash = crypto.hash160(script.get(script.length - 1));
this.type = scriptTypes.SCRIPTHASH;
this.type = Address.types.SCRIPTHASH;
this.version = -1;
return this;
}
@ -430,10 +437,10 @@ Address.prototype.fromHash = function fromHash(hash, type, version, network) {
hash = new Buffer(hash, 'hex');
if (typeof type === 'string')
type = scriptTypes[type.toUpperCase()];
type = Address.types[type.toUpperCase()];
if (type == null)
type = scriptTypes.PUBKEYHASH;
type = Address.types.PUBKEYHASH;
if (version == null)
version = -1;
@ -452,11 +459,11 @@ Address.prototype.fromHash = function fromHash(hash, type, version, network) {
} else {
assert(Address.isWitness(type), 'Wrong version (non-witness).');
assert(version >= 0 && version <= 16, 'Bad program version.');
if (version === 0 && type === scriptTypes.WITNESSPUBKEYHASH)
if (version === 0 && type === Address.types.WITNESSPUBKEYHASH)
assert(hash.length === 20, 'Hash is the wrong size.');
else if (version === 0 && type === scriptTypes.WITNESSSCRIPTHASH)
else if (version === 0 && type === Address.types.WITNESSSCRIPTHASH)
assert(hash.length === 32, 'Hash is the wrong size.');
else if (version === 1 && type === scriptTypes.WITNESSSCRIPTHASH)
else if (version === 1 && type === Address.types.WITNESSSCRIPTHASH)
assert(hash.length === 32, 'Hash is the wrong size.');
}
@ -493,9 +500,9 @@ Address.fromHash = function fromHash(hash, type, version, network) {
Address.prototype.fromData = function fromData(data, type, version, network) {
if (typeof type === 'string')
type = scriptTypes[type.toUpperCase()];
type = Address.types[type.toUpperCase()];
if (type === scriptTypes.WITNESSSCRIPTHASH) {
if (type === Address.types.WITNESSSCRIPTHASH) {
if (version === 0) {
assert(Buffer.isBuffer(data));
data = crypto.sha256(data);
@ -505,7 +512,7 @@ Address.prototype.fromData = function fromData(data, type, version, network) {
} else {
throw new Error('Cannot create from version=' + version);
}
} else if (type === scriptTypes.WITNESSPUBKEYHASH) {
} else if (type === Address.types.WITNESSPUBKEYHASH) {
if (version !== 0)
throw new Error('Cannot create from version=' + version);
assert(Buffer.isBuffer(data));
@ -554,7 +561,7 @@ Address.validate = function validate(address, type) {
}
if (typeof type === 'string')
type = scriptTypes[type.toUpperCase()];
type = Address.types[type.toUpperCase()];
if (type && address.type !== type)
return false;
@ -604,13 +611,13 @@ Address.getHash = function getHash(data, enc) {
Address.getPrefix = function getPrefix(type, network) {
var prefixes = network.addressPrefix;
switch (type) {
case scriptTypes.PUBKEYHASH:
case Address.types.PUBKEYHASH:
return prefixes.pubkeyhash;
case scriptTypes.SCRIPTHASH:
case Address.types.SCRIPTHASH:
return prefixes.scripthash;
case scriptTypes.WITNESSPUBKEYHASH:
case Address.types.WITNESSPUBKEYHASH:
return prefixes.witnesspubkeyhash;
case scriptTypes.WITNESSSCRIPTHASH:
case Address.types.WITNESSSCRIPTHASH:
return prefixes.witnessscripthash;
default:
return -1;
@ -628,13 +635,13 @@ Address.getType = function getType(prefix, network) {
var prefixes = network.addressPrefix;
switch (prefix) {
case prefixes.pubkeyhash:
return scriptTypes.PUBKEYHASH;
return Address.types.PUBKEYHASH;
case prefixes.scripthash:
return scriptTypes.SCRIPTHASH;
return Address.types.SCRIPTHASH;
case prefixes.witnesspubkeyhash:
return scriptTypes.WITNESSPUBKEYHASH;
return Address.types.WITNESSPUBKEYHASH;
case prefixes.witnessscripthash:
return scriptTypes.WITNESSSCRIPTHASH;
return Address.types.WITNESSSCRIPTHASH;
default:
return -1;
}
@ -648,9 +655,9 @@ Address.getType = function getType(prefix, network) {
Address.isWitness = function isWitness(type) {
switch (type) {
case scriptTypes.WITNESSPUBKEYHASH:
case Address.types.WITNESSPUBKEYHASH:
return true;
case scriptTypes.WITNESSSCRIPTHASH:
case Address.types.WITNESSSCRIPTHASH:
return true;
default:
return false;

View File

@ -11,8 +11,7 @@ var assert = require('assert');
var util = require('../utils/util');
var encoding = require('../utils/encoding');
var crypto = require('../crypto/crypto');
var btcutils = require('../btc/utils');
var constants = require('../protocol/constants');
var consensus = require('../protocol/consensus');
var AbstractBlock = require('./abstractblock');
var VerifyResult = require('../btc/errors').VerifyResult;
var BufferReader = require('../utils/reader');
@ -188,7 +187,7 @@ Block.prototype.getSizes = function getSizes() {
*/
Block.prototype.getVirtualSize = function getVirtualSize() {
var scale = constants.WITNESS_SCALE_FACTOR;
var scale = consensus.WITNESS_SCALE_FACTOR;
return (this.getWeight() + scale - 1) / scale | 0;
};
@ -200,7 +199,7 @@ Block.prototype.getVirtualSize = function getVirtualSize() {
Block.prototype.getWeight = function getWeight() {
var sizes = this.getSizes();
var base = sizes.total - sizes.witness;
return base * (constants.WITNESS_SCALE_FACTOR - 1) + sizes.total;
return base * (consensus.WITNESS_SCALE_FACTOR - 1) + sizes.total;
};
/**
@ -316,7 +315,7 @@ Block.prototype.createMerkleRoot = function createMerkleRoot(enc) {
*/
Block.prototype.createWitnessNonce = function createWitnessNonce() {
return util.copy(constants.ZERO_HASH);
return util.copy(encoding.ZERO_HASH);
};
/**
@ -333,7 +332,7 @@ Block.prototype.createCommitmentHash = function createCommitmentHash(enc) {
assert(nonce, 'No witness nonce present.');
leaves.push(constants.ZERO_HASH);
leaves.push(encoding.ZERO_HASH);
for (i = 1; i < this.txs.length; i++) {
tx = this.txs[i];
@ -443,7 +442,7 @@ Block.prototype.getCommitmentHash = function getCommitmentHash(enc) {
Block.prototype._verify = function _verify(ret) {
var sigops = 0;
var scale = constants.WITNESS_SCALE_FACTOR;
var scale = consensus.WITNESS_SCALE_FACTOR;
var i, tx, merkle;
if (!ret)
@ -471,8 +470,8 @@ Block.prototype._verify = function _verify(ret) {
// Check base size.
if (this.txs.length === 0
|| this.txs.length > constants.block.MAX_SIZE
|| this.getBaseSize() > constants.block.MAX_SIZE) {
|| this.txs.length > consensus.MAX_BLOCK_SIZE
|| this.getBaseSize() > consensus.MAX_BLOCK_SIZE) {
ret.reason = 'bad-blk-length';
ret.score = 100;
return false;
@ -502,7 +501,7 @@ Block.prototype._verify = function _verify(ret) {
// Count legacy sigops (do not count scripthash or witness).
sigops += tx.getLegacySigops();
if (sigops * scale > constants.block.MAX_SIGOPS_COST) {
if (sigops * scale > consensus.MAX_BLOCK_SIGOPS_COST) {
ret.reason = 'bad-blk-sigops';
ret.score = 100;
return false;
@ -550,14 +549,14 @@ Block.prototype.getReward = function getReward(view, height, network) {
assert(typeof height === 'number');
network = Network.get(network);
reward = btcutils.getReward(height, network.halvingInterval);
reward = consensus.getReward(height, network.halvingInterval);
for (i = 1; i < this.txs.length; i++) {
tx = this.txs[i];
fee = tx.getFee(view);
if (fee < 0 || fee > constants.MAX_MONEY)
if (fee < 0 || fee > consensus.MAX_MONEY)
return -1;
reward += fee;
@ -569,7 +568,7 @@ Block.prototype.getReward = function getReward(view, height, network) {
// MAX_MONEY is 51 bits. The result of
// (51 bits + 51 bits) is _never_ greater
// than 52 bits.
if (reward < 0 || reward > constants.MAX_MONEY)
if (reward < 0 || reward > consensus.MAX_MONEY)
return -1;
}

View File

@ -9,7 +9,6 @@
var assert = require('assert');
var util = require('../utils/util');
var constants = require('../protocol/constants');
var Network = require('../protocol/network');
var Amount = require('../btc/amount');
var Output = require('./output');
@ -17,6 +16,7 @@ var Script = require('../script/script');
var Network = require('../protocol/network');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var encoding = require('../utils/encoding');
/**
* Represents an unspent output.
@ -43,7 +43,7 @@ function Coin(options) {
this.value = 0;
this.script = new Script();
this.coinbase = true;
this.hash = constants.NULL_HASH;
this.hash = encoding.NULL_HASH;
this.index = 0;
if (options)

View File

@ -7,9 +7,8 @@
'use strict';
var util = require('../utils/util');
var assert = require('assert');
var constants = require('../protocol/constants');
var util = require('../utils/util');
var Network = require('../protocol/network');
var Script = require('../script/script');
var Witness = require('../script/witness');
@ -99,7 +98,7 @@ Input.prototype.getType = function getType(coin) {
else
type = this.script.getInputType();
return constants.scriptTypesByVal[type].toLowerCase();
return Script.typesByVal[type].toLowerCase();
};
/**
@ -159,7 +158,7 @@ Input.prototype.getSubtype = function getSubtype(coin) {
type = redeem.getType();
return constants.scriptTypesByVal[type].toLowerCase();
return Script.typesByVal[type].toLowerCase();
};
/**

View File

@ -7,7 +7,6 @@
'use strict';
var constants = require('../protocol/constants');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var util = require('../utils/util');

View File

@ -7,11 +7,10 @@
'use strict';
var constants = require('../protocol/constants');
var assert = require('assert');
var util = require('../utils/util');
var encoding = require('../utils/encoding');
var crypto = require('../crypto/crypto');
var assert = require('assert');
var networks = require('../protocol/networks');
var Network = require('../protocol/network');
var BufferReader = require('../utils/reader');
@ -37,7 +36,7 @@ function KeyRing(options, network) {
this.network = Network.primary;
this.witness = false;
this.nested = false;
this.publicKey = constants.ZERO_KEY;
this.publicKey = encoding.ZERO_KEY;
this.privateKey = null;
this.script = null;
@ -796,7 +795,7 @@ KeyRing.prototype.toJSON = function toJSON() {
publicKey: this.publicKey.toString('hex'),
script: this.script ? this.script.toRaw().toString('hex') : null,
program: this.witness ? this.getProgram().toRaw().toString('hex') : null,
type: constants.scriptTypesByVal[this.getType()].toLowerCase(),
type: Script.typesByVal[this.getType()].toLowerCase(),
address: this.getAddress('base58')
};
};

View File

@ -7,18 +7,18 @@
'use strict';
var assert = require('assert');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var assert = require('assert');
var constants = require('../protocol/constants');
var DUMMY = new Buffer([0]);
var AbstractBlock = require('./abstractblock');
var VerifyResult = require('../btc/errors').VerifyResult;
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var encoding = require('../utils/encoding');
var consensus = require('../protocol/consensus');
var Headers = require('./headers');
var TX = require('./tx');
var DUMMY = new Buffer([0]);
/**
* Represents a merkle (filtered) block.
@ -206,7 +206,7 @@ MerkleBlock.prototype.extractTree = function extractTree() {
if (bitsUsed >= flags.length * 8) {
failed = true;
return constants.ZERO_HASH;
return encoding.ZERO_HASH;
}
parent = (flags[bitsUsed / 8 | 0] >>> (bitsUsed % 8)) & 1;
@ -215,7 +215,7 @@ MerkleBlock.prototype.extractTree = function extractTree() {
if (height === 0 || !parent) {
if (hashUsed >= hashes.length) {
failed = true;
return constants.ZERO_HASH;
return encoding.ZERO_HASH;
}
hash = hashes[hashUsed++];
if (height === 0 && parent) {
@ -248,7 +248,7 @@ MerkleBlock.prototype.extractTree = function extractTree() {
if (totalTX === 0)
return;
if (totalTX > constants.block.MAX_SIZE / 60)
if (totalTX > consensus.MAX_BLOCK_SIZE / 60)
return;
if (hashes.length > totalTX)

View File

@ -10,11 +10,7 @@
var assert = require('assert');
var util = require('../utils/util');
var co = require('../utils/co');
var btcutils = require('../btc/utils');
var constants = require('../protocol/constants');
var Script = require('../script/script');
var opcodes = Script.opcodes;
var FundingError = require('../btc/errors').FundingError;
var TX = require('./tx');
var Input = require('./input');
var Output = require('./output');
@ -25,6 +21,10 @@ var KeyRing = require('./keyring');
var Address = require('./address');
var workerPool = require('../workers/workerpool').pool;
var encoding = require('../utils/encoding');
var consensus = require('../protocol/consensus');
var policy = require('../protocol/policy');
var Amount = require('../btc/amount');
var opcodes = Script.opcodes;
/**
* A mutable transaction object.
@ -63,6 +63,24 @@ function MTX(options) {
util.inherits(MTX, TX);
/**
* Minimum fee to start with
* during coin selection.
* @const {Amount}
* @default
*/
MTX.MIN_FEE = 10000;
/**
* Maximum fee to allow
* after coin selection.
* @const {Amount}
* @default
*/
MTX.MAX_FEE = consensus.COIN / 10;
/**
* Inject properties from options object.
* @private
@ -739,10 +757,10 @@ MTX.prototype.signature = function signature(index, prev, value, key, type, vers
var hash;
if (type == null)
type = constants.hashType.ALL;
type = Script.hashType.ALL;
if (typeof type === 'string')
type = constants.hashType[type.toUpperCase()];
type = Script.hashType[type.toUpperCase()];
// Get the hash of the current tx, minus the other
// inputs, plus the sighash type.
@ -972,7 +990,7 @@ MTX.prototype.signAsync = function signAsync(ring, type) {
*/
MTX.prototype.estimateSize = co(function* estimateSize(estimate) {
var scale = constants.WITNESS_SCALE_FACTOR;
var scale = consensus.WITNESS_SCALE_FACTOR;
var total = 0;
var i, input, output, size, prev, coin;
@ -1209,7 +1227,7 @@ MTX.prototype.fund = co(function* fund(coins, options) {
change = this.outputs[this.outputs.length - 1];
if (change.isDust(constants.tx.MIN_RELAY)) {
if (change.isDust(policy.MIN_RELAY)) {
// Do nothing. Change is added to fee.
this.outputs.pop();
this.changeIndex = -1;
@ -1291,10 +1309,10 @@ MTX.prototype.setSequence = function setSequence(index, locktime, seconds) {
this.version = 2;
if (seconds) {
locktime >>>= constants.sequence.GRANULARITY;
locktime = constants.sequence.TYPE_FLAG | locktime;
locktime >>>= consensus.SEQUENCE_GRANULARITY;
locktime = consensus.SEQUENCE_TYPE_FLAG | locktime;
} else {
locktime = constants.sequence.MASK & locktime;
locktime = consensus.SEQUENCE_MASK & locktime;
}
input.sequence = locktime;
@ -1426,7 +1444,7 @@ function CoinSelector(tx, options) {
this.height = -1;
this.confirmations = -1;
this.hardFee = -1;
this.rate = constants.tx.MIN_FEE;
this.rate = MTX.MIN_FEE;
this.maxFee = -1;
this.round = false;
this.changeAddress = null;
@ -1566,7 +1584,6 @@ CoinSelector.prototype.isFull = function isFull() {
*/
CoinSelector.prototype.isSpendable = function isSpendable(coin) {
var maturity = constants.tx.COINBASE_MATURITY;
var conf;
if (this.height === -1)
@ -1576,7 +1593,7 @@ CoinSelector.prototype.isSpendable = function isSpendable(coin) {
if (coin.height === -1)
return false;
if (this.height + 1 < coin.height + maturity)
if (this.height + 1 < coin.height + consensus.COINBASE_MATURITY)
return false;
}
@ -1608,12 +1625,12 @@ CoinSelector.prototype.getFee = function getFee(size) {
var fee;
if (this.round)
fee = btcutils.getRoundFee(size, this.rate);
fee = policy.getRoundFee(size, this.rate);
else
fee = btcutils.getMinFee(size, this.rate);
fee = policy.getMinFee(size, this.rate);
if (fee > constants.tx.MAX_FEE)
fee = constants.tx.MAX_FEE;
if (fee > MTX.MAX_FEE)
fee = MTX.MAX_FEE;
return fee;
};
@ -1659,7 +1676,7 @@ CoinSelector.prototype.select = co(function* select(coins) {
if (this.hardFee !== -1)
this.selectHard(this.hardFee);
else
yield this.selectEstimate(constants.tx.MIN_FEE);
yield this.selectEstimate(MTX.MIN_FEE);
if (!this.isFull()) {
// Still failing to get enough funds.
@ -1696,7 +1713,7 @@ CoinSelector.prototype.selectEstimate = co(function* selectEstimate(fee) {
// use a fake p2pkh output to gauge size.
script: this.changeAddress
? Script.fromAddress(this.changeAddress)
: Script.fromPubkeyhash(constants.ZERO_HASH160),
: Script.fromPubkeyhash(encoding.ZERO_HASH160),
value: 0
});
@ -1725,13 +1742,47 @@ CoinSelector.prototype.selectHard = function selectHard(fee) {
// Initial fee.
this.fee = fee;
if (this.fee > constants.tx.MAX_FEE)
this.fee = constants.tx.MAX_FEE;
if (this.fee > MTX.MAX_FEE)
this.fee = MTX.MAX_FEE;
// Transfer `total` funds maximum.
this.fund();
};
/**
* An error thrown from the coin selector.
* @exports FundingError
* @constructor
* @extends Error
* @param {String} msg
* @param {Amount} available
* @param {Amount} required
* @property {String} message - Error message.
* @property {Amount} availableFunds
* @property {Amount} requiredFunds
*/
function FundingError(msg, available, required) {
Error.call(this);
if (Error.captureStackTrace)
Error.captureStackTrace(this, FundingError);
this.type = 'FundingError';
this.message = msg;
this.availableFunds = -1;
this.requiredFunds = -1;
if (available != null) {
this.message += ' (available=' + Amount.btc(available) + ',';
this.message += ' required=' + Amount.btc(required) + ')';
this.availableFunds = available;
this.requiredFunds = required;
}
}
util.inherits(FundingError, Error);
/*
* Helpers
*/

View File

@ -7,7 +7,7 @@
'use strict';
var assert = require('assert');
var constants = require('../protocol/constants');
var common = require('../net/common');
var Network = require('../protocol/network');
var util = require('../utils/util');
var IP = require('../utils/ip');
@ -43,6 +43,18 @@ function NetAddress(options) {
this.fromOptions(options);
}
/**
* Default services for
* unknown outbound peers.
* @const {Number}
* @default
*/
NetAddress.DEFAULT_SERVICES = 0
| common.services.NETWORK
| common.services.WITNESS
| common.services.BLOOM;
/**
* Inject properties from options object.
* @private
@ -89,7 +101,7 @@ NetAddress.fromOptions = function fromOptions(options) {
*/
NetAddress.prototype.hasNetwork = function hasNetwork() {
return (this.services & constants.services.NETWORK) !== 0;
return (this.services & common.services.NETWORK) !== 0;
};
/**
@ -98,7 +110,7 @@ NetAddress.prototype.hasNetwork = function hasNetwork() {
*/
NetAddress.prototype.hasBloom = function hasBloom() {
return (this.services & constants.services.BLOOM) !== 0;
return (this.services & common.services.BLOOM) !== 0;
};
/**
@ -107,7 +119,7 @@ NetAddress.prototype.hasBloom = function hasBloom() {
*/
NetAddress.prototype.hasUTXO = function hasUTXO() {
return (this.services & constants.services.GETUTXO) !== 0;
return (this.services & common.services.GETUTXO) !== 0;
};
/**
@ -116,7 +128,7 @@ NetAddress.prototype.hasUTXO = function hasUTXO() {
*/
NetAddress.prototype.hasWitness = function hasWitness() {
return (this.services & constants.services.WITNESS) !== 0;
return (this.services & common.services.WITNESS) !== 0;
};
/**
@ -218,7 +230,7 @@ NetAddress.prototype.fromHost = function fromHost(host, port, network) {
this.host = host;
this.port = port || network.port;
this.services = constants.services.NETWORK | constants.services.WITNESS | constants.services.BLOOM;
this.services = NetAddress.DEFAULT_SERVICES;
this.ts = network.now();
this.hostname = IP.hostname(this.host, this.port);

View File

@ -8,9 +8,9 @@
var util = require('../utils/util');
var assert = require('assert');
var constants = require('../protocol/constants');
var StaticWriter = require('../utils/writer');
var BufferReader = require('../utils/reader');
var encoding = require('../utils/encoding');
/**
* Represents a COutPoint.
@ -26,7 +26,7 @@ function Outpoint(hash, index) {
if (!(this instanceof Outpoint))
return new Outpoint(hash, index);
this.hash = hash || constants.NULL_HASH;
this.hash = hash || encoding.NULL_HASH;
this.index = index != null ? index : 0xffffffff;
}
@ -61,7 +61,7 @@ Outpoint.fromOptions = function fromOptions(options) {
*/
Outpoint.prototype.isNull = function isNull() {
return this.index === 0xffffffff && this.hash === constants.NULL_HASH;
return this.index === 0xffffffff && this.hash === encoding.NULL_HASH;
};
/**

View File

@ -7,15 +7,15 @@
'use strict';
var assert = require('assert');
var util = require('../utils/util');
var constants = require('../protocol/constants');
var btcutils = require('../btc/utils');
var Amount = require('../btc/amount');
var Network = require('../protocol/network');
var Script = require('../script/script');
var StaticWriter = require('../utils/staticwriter');
var BufferReader = require('../utils/reader');
var assert = require('assert');
var consensus = require('../protocol/consensus');
var policy = require('../protocol/policy');
/**
* Represents a transaction output.
@ -78,7 +78,7 @@ Output.fromOptions = function fromOptions(options) {
*/
Output.prototype.getType = function getType() {
return constants.scriptTypesByVal[this.script.getType()].toLowerCase();
return Script.typesByVal[this.script.getType()].toLowerCase();
};
/**
@ -165,12 +165,9 @@ Output.prototype.getJSON = function getJSON(network) {
*/
Output.prototype.getDustThreshold = function getDustThreshold(rate) {
var scale = constants.WITNESS_SCALE_FACTOR;
var scale = consensus.WITNESS_SCALE_FACTOR;
var size;
if (rate == null)
rate = constants.tx.MIN_RELAY;
if (this.script.isUnspendable())
return 0;
@ -183,7 +180,7 @@ Output.prototype.getDustThreshold = function getDustThreshold(rate) {
size += 32 + 4 + 1 + 107 + 4;
}
return 3 * btcutils.getMinFee(size, rate);
return 3 * policy.getMinFee(size, rate);
};
/**

View File

@ -12,9 +12,7 @@ var util = require('../utils/util');
var encoding = require('../utils/encoding');
var co = require('../utils/co');
var crypto = require('../crypto/crypto');
var btcutils = require('../btc/utils');
var Amount = require('../btc/amount');
var constants = require('../protocol/constants');
var Network = require('../protocol/network');
var Script = require('../script/script');
var BufferReader = require('../utils/reader');
@ -26,6 +24,8 @@ var Outpoint = require('./outpoint');
var InvItem = require('./invitem');
var workerPool = require('../workers/workerpool').pool;
var Bloom = require('../utils/bloom');
var consensus = require('../protocol/consensus');
var policy = require('../protocol/policy');
/*
* Constants
@ -332,7 +332,7 @@ TX.prototype.getSizes = function getSizes() {
*/
TX.prototype.getVirtualSize = function getVirtualSize() {
var scale = constants.WITNESS_SCALE_FACTOR;
var scale = consensus.WITNESS_SCALE_FACTOR;
return (this.getWeight() + scale - 1) / scale | 0;
};
@ -344,8 +344,8 @@ TX.prototype.getVirtualSize = function getVirtualSize() {
*/
TX.prototype.getSigopsSize = function getSigopsSize(sigops) {
var scale = constants.WITNESS_SCALE_FACTOR;
var bytes = constants.tx.BYTES_PER_SIGOP;
var scale = consensus.WITNESS_SCALE_FACTOR;
var bytes = policy.BYTES_PER_SIGOP;
var weight = Math.max(this.getWeight(), sigops * bytes);
return (weight + scale - 1) / scale | 0;
};
@ -359,7 +359,7 @@ TX.prototype.getSigopsSize = function getSigopsSize(sigops) {
TX.prototype.getWeight = function getWeight() {
var raw = this.getSizes();
var base = raw.total - raw.witness;
return base * (constants.WITNESS_SCALE_FACTOR - 1) + raw.total;
return base * (consensus.WITNESS_SCALE_FACTOR - 1) + raw.total;
};
/**
@ -418,7 +418,7 @@ TX.prototype.hasWitness = function hasWitness() {
TX.prototype.signatureHash = function signatureHash(index, prev, value, type, version) {
if (typeof type === 'string')
type = constants.hashType[type.toUpperCase()];
type = Script.hashType[type.toUpperCase()];
assert(index >= 0 && index < this.inputs.length);
assert(prev instanceof Script);
@ -448,11 +448,11 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) {
var i, size, bw, input, output;
var hashType = type & 0x1f;
if (hashType === constants.hashType.SINGLE) {
if (hashType === Script.hashType.SINGLE) {
// Bitcoind used to return 1 as an error code:
// it ended up being treated like a hash.
if (index >= this.outputs.length)
return util.copy(constants.ONE_HASH);
return util.copy(encoding.ONE_HASH);
}
// Remove all code separators.
@ -466,7 +466,7 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) {
bw.writeU32(this.version);
// Serialize inputs.
if (type & constants.hashType.ANYONECANPAY) {
if (type & Script.hashType.ANYONECANPAY) {
bw.writeVarint(1);
// Serialize only the current
@ -501,8 +501,8 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) {
// Sequences are 0 if NONE or SINGLE.
switch (hashType) {
case constants.hashType.NONE:
case constants.hashType.SINGLE:
case Script.hashType.NONE:
case Script.hashType.SINGLE:
bw.writeU32(0);
break;
default:
@ -514,11 +514,11 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) {
// Serialize outputs.
switch (hashType) {
case constants.hashType.NONE:
case Script.hashType.NONE:
// No outputs if NONE.
bw.writeVarint(0);
break;
case constants.hashType.SINGLE:
case Script.hashType.SINGLE:
// Drop all outputs after the
// current input index if SINGLE.
bw.writeVarint(index + 1);
@ -569,7 +569,7 @@ TX.prototype.hashSize = function hashSize(index, prev, type) {
size += 4;
if (type & constants.hashType.ANYONECANPAY) {
if (type & Script.hashType.ANYONECANPAY) {
size += 1;
size += 36;
size += prev.getVarSize();
@ -583,10 +583,10 @@ TX.prototype.hashSize = function hashSize(index, prev, type) {
}
switch (type & 0x1f) {
case constants.hashType.NONE:
case Script.hashType.NONE:
size += 1;
break;
case constants.hashType.SINGLE:
case Script.hashType.SINGLE:
size += encoding.sizeVarint(index + 1);
size += 9 * index;
size += this.outputs[index].getSize();
@ -616,9 +616,12 @@ TX.prototype.hashSize = function hashSize(index, prev, type) {
*/
TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, value, type) {
var i, bw, size, input, output, prevouts, sequences, outputs;
var prevouts = encoding.ZERO_HASH;
var sequences = encoding.ZERO_HASH;
var outputs = encoding.ZERO_HASH;
var i, bw, size, input, output;
if (!(type & constants.hashType.ANYONECANPAY)) {
if (!(type & Script.hashType.ANYONECANPAY)) {
if (this._hashPrevouts) {
prevouts = this._hashPrevouts;
} else {
@ -634,13 +637,11 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, value, type
if (!this.mutable)
this._hashPrevouts = prevouts;
}
} else {
prevouts = util.copy(constants.ZERO_HASH);
}
if (!(type & constants.hashType.ANYONECANPAY)
&& (type & 0x1f) !== constants.hashType.SINGLE
&& (type & 0x1f) !== constants.hashType.NONE) {
if (!(type & Script.hashType.ANYONECANPAY)
&& (type & 0x1f) !== Script.hashType.SINGLE
&& (type & 0x1f) !== Script.hashType.NONE) {
if (this._hashSequence) {
sequences = this._hashSequence;
} else {
@ -656,12 +657,10 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, value, type
if (!this.mutable)
this._hashSequence = sequences;
}
} else {
sequences = util.copy(constants.ZERO_HASH);
}
if ((type & 0x1f) !== constants.hashType.SINGLE
&& (type & 0x1f) !== constants.hashType.NONE) {
if ((type & 0x1f) !== Script.hashType.SINGLE
&& (type & 0x1f) !== Script.hashType.NONE) {
if (this._hashOutputs) {
outputs = this._hashOutputs;
} else {
@ -684,11 +683,9 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, value, type
if (!this.mutable)
this._hashOutputs = outputs;
}
} else if ((type & 0x1f) === constants.hashType.SINGLE && index < this.outputs.length) {
} else if ((type & 0x1f) === Script.hashType.SINGLE && index < this.outputs.length) {
output = this.outputs[index];
outputs = crypto.hash256(output.toRaw());
} else {
outputs = util.copy(constants.ZERO_HASH);
}
input = this.inputs[index];
@ -1128,7 +1125,7 @@ TX.prototype.hasCoins = function hasCoins(view) {
*/
TX.prototype.isFinal = function isFinal(height, ts) {
var threshold = constants.LOCKTIME_THRESHOLD;
var threshold = consensus.LOCKTIME_THRESHOLD;
var i, input;
if (this.locktime === 0)
@ -1203,17 +1200,17 @@ TX.prototype.getScripthashSigops = function getScripthashSigops(view) {
*/
TX.prototype.getSigopsCost = function getSigopsCost(view, flags) {
var scale = constants.WITNESS_SCALE_FACTOR;
var scale = consensus.WITNESS_SCALE_FACTOR;
var cost = this.getLegacySigops() * scale;
var i, input, coin;
if (flags == null)
flags = constants.flags.STANDARD_VERIFY_FLAGS;
flags = Script.flags.STANDARD_VERIFY_FLAGS;
if (this.isCoinbase())
return cost;
if (flags & constants.flags.VERIFY_P2SH)
if (flags & Script.flags.VERIFY_P2SH)
cost += this.getScripthashSigops(view) * scale;
for (i = 0; i < this.inputs.length; i++) {
@ -1241,10 +1238,10 @@ TX.prototype.getSigopsCost = function getSigopsCost(view, flags) {
*/
TX.prototype.getSigops = function getSigops(view, flags) {
var scale = constants.WITNESS_SCALE_FACTOR;
var scale = consensus.WITNESS_SCALE_FACTOR;
if (flags == null)
flags = constants.flags.STANDARD_VERIFY_FLAGS;
flags = Script.flags.STANDARD_VERIFY_FLAGS;
return (this.getSigopsCost(view, flags) + scale - 1) / scale | 0;
};
@ -1278,7 +1275,7 @@ TX.prototype.isSane = function isSane(ret) {
return false;
}
if (this.getBaseSize() > constants.block.MAX_SIZE) {
if (this.getBaseSize() > consensus.MAX_BLOCK_SIZE) {
ret.reason = 'bad-txns-oversize';
ret.score = 100;
return false;
@ -1293,7 +1290,7 @@ TX.prototype.isSane = function isSane(ret) {
return false;
}
if (output.value > constants.MAX_MONEY) {
if (output.value > consensus.MAX_MONEY) {
ret.reason = 'bad-txns-vout-toolarge';
ret.score = 100;
return false;
@ -1301,7 +1298,7 @@ TX.prototype.isSane = function isSane(ret) {
total += output.value;
if (total < 0 || total > constants.MAX_MONEY) {
if (total < 0 || total > consensus.MAX_MONEY) {
ret.reason = 'bad-txns-txouttotal-toolarge';
ret.score = 100;
return false;
@ -1362,13 +1359,13 @@ TX.prototype.isStandard = function isStandard(ret) {
if (!ret)
ret = new VerifyResult();
if (this.version < 1 || this.version > constants.tx.MAX_VERSION) {
if (this.version < 1 || this.version > policy.MAX_TX_VERSION) {
ret.reason = 'version';
ret.score = 0;
return false;
}
if (this.getWeight() >= constants.tx.MAX_WEIGHT) {
if (this.getWeight() >= policy.MAX_TX_WEIGHT) {
ret.reason = 'tx-size';
ret.score = 0;
return false;
@ -1404,13 +1401,13 @@ TX.prototype.isStandard = function isStandard(ret) {
continue;
}
if (output.script.isMultisig() && !constants.tx.BARE_MULTISIG) {
if (output.script.isMultisig() && !policy.BARE_MULTISIG) {
ret.reason = 'bare-multisig';
ret.score = 0;
return false;
}
if (output.isDust(constants.tx.MIN_RELAY)) {
if (output.isDust(policy.MIN_RELAY)) {
ret.reason = 'dust';
ret.score = 0;
return false;
@ -1436,7 +1433,7 @@ TX.prototype.isStandard = function isStandard(ret) {
*/
TX.prototype.hasStandardInputs = function hasStandardInputs(view) {
var maxSigops = constants.script.MAX_SCRIPTHASH_SIGOPS;
var maxSigops = policy.MAX_SCRIPTHASH_SIGOPS;
var i, input, coin, redeem;
if (this.isCoinbase())
@ -1564,10 +1561,10 @@ TX.prototype.getWitnessStandard = function getWitnessStandard(view) {
redeem = input.witness.get(input.witness.length - 1);
if (redeem.length > constants.script.MAX_SIZE)
if (redeem.length > consensus.MAX_SCRIPT_SIZE)
return BAD_WITNESS;
if (redeem.length > constants.script.MAX_P2WSH_SIZE)
if (redeem.length > policy.MAX_P2WSH_SIZE)
ret = BAD_NONSTD_P2WSH;
hash = crypto.sha256(redeem);
@ -1579,14 +1576,14 @@ TX.prototype.getWitnessStandard = function getWitnessStandard(view) {
if (input.witness.length - 1 > 604)
return BAD_WITNESS;
if (input.witness.length - 1 > constants.script.MAX_P2WSH_STACK)
if (input.witness.length - 1 > policy.MAX_P2WSH_STACK)
ret = BAD_NONSTD_P2WSH;
for (j = 0; j < input.witness.length; j++) {
if (input.witness.get(j).length > constants.script.MAX_PUSH)
if (input.witness.get(j).length > consensus.MAX_SCRIPT_PUSH)
return BAD_WITNESS;
if (input.witness.get(j).length > constants.script.MAX_P2WSH_PUSH)
if (input.witness.get(j).length > policy.MAX_P2WSH_PUSH)
ret = BAD_NONSTD_P2WSH;
}
@ -1668,7 +1665,7 @@ TX.prototype.checkInputs = function checkInputs(view, height, ret) {
}
if (coins.coinbase) {
if (height - coins.height < constants.tx.COINBASE_MATURITY) {
if (height - coins.height < consensus.COINBASE_MATURITY) {
ret.reason = 'bad-txns-premature-spend-of-coinbase';
ret.score = 0;
return false;
@ -1677,7 +1674,7 @@ TX.prototype.checkInputs = function checkInputs(view, height, ret) {
coin = view.getOutput(input);
if (coin.value < 0 || coin.value > constants.MAX_MONEY) {
if (coin.value < 0 || coin.value > consensus.MAX_MONEY) {
ret.reason = 'bad-txns-inputvalues-outofrange';
ret.score = 100;
return false;
@ -1685,7 +1682,7 @@ TX.prototype.checkInputs = function checkInputs(view, height, ret) {
total += coin.value;
if (total < 0 || total > constants.MAX_MONEY) {
if (total < 0 || total > consensus.MAX_MONEY) {
ret.reason = 'bad-txns-inputvalues-outofrange';
ret.score = 100;
return false;
@ -1709,7 +1706,7 @@ TX.prototype.checkInputs = function checkInputs(view, height, ret) {
return false;
}
if (fee > constants.MAX_MONEY) {
if (fee > consensus.MAX_MONEY) {
ret.reason = 'bad-txns-fee-outofrange';
ret.score = 100;
return false;
@ -1840,7 +1837,7 @@ TX.prototype.getChainValue = function getChainValue(view, height) {
TX.prototype.isFree = function isFree(view, height, size) {
var priority = this.getPriority(view, height, size);
return priority > constants.tx.FREE_THRESHOLD;
return priority > policy.FREE_THRESHOLD;
};
/**
@ -1856,7 +1853,7 @@ TX.prototype.getMinFee = function getMinFee(size, rate) {
if (size == null)
size = this.getVirtualSize();
return btcutils.getMinFee(size, rate);
return policy.getMinFee(size, rate);
};
/**
@ -1873,7 +1870,7 @@ TX.prototype.getRoundFee = function getRoundFee(size, rate) {
if (size == null)
size = this.getVirtualSize();
return btcutils.getRoundFee(size, rate);
return policy.getRoundFee(size, rate);
};
/**
@ -1888,7 +1885,7 @@ TX.prototype.getRate = function getRate(view, size) {
if (size == null)
size = this.getVirtualSize();
return btcutils.getRate(size, this.getFee(view));
return policy.getRate(size, this.getFee(view));
};
/**
@ -2555,6 +2552,72 @@ TX.isTX = function isTX(obj) {
&& typeof obj.witnessHash === 'function';
};
/**
* Verify the nLockTime of a transaction.
* @param {Number} index - Index of input being verified.
* @param {Number} locktime - Locktime to verify against (max=u32).
* @returns {Boolean}
*/
TX.prototype.verifyLocktime = function verifyLocktime(index, locktime) {
var threshold = consensus.LOCKTIME_THRESHOLD;
var input = this.inputs[index];
if (!(
(this.locktime < threshold && locktime < threshold)
|| (this.locktime >= threshold && locktime >= threshold)
)) {
return false;
}
if (locktime > this.locktime)
return false;
if (input.sequence === 0xffffffff)
return false;
return true;
};
/**
* Verify the nSequence locktime of a transaction.
* @param {Number} index - Index of input being verified.
* @param {Number} sequence - Locktime to verify against (max=u32).
* @returns {Boolean}
*/
TX.prototype.verifySequence = function verifySequence(index, sequence) {
var input = this.inputs[index];
var mask, seq1, seq2;
if ((sequence & consensus.SEQUENCE_DISABLE_FLAG) !== 0)
return true;
if (this.version < 2)
return false;
if (input.sequence & consensus.SEQUENCE_DISABLE_FLAG)
return false;
mask = consensus.SEQUENCE_TYPE_FLAG | consensus.SEQUENCE_MASK;
seq1 = input.sequence & mask;
seq2 = sequence & mask;
if (!(
(seq1 < consensus.SEQUENCE_TYPE_FLAG
&& seq2 < consensus.SEQUENCE_TYPE_FLAG)
|| (seq1 >= consensus.SEQUENCE_TYPE_FLAG
&& seq2 >= consensus.SEQUENCE_TYPE_FLAG)
)) {
return false;
}
if (seq2 > seq1)
return false;
return true;
};
/*
* Helpers
*/

290
lib/protocol/consensus.js Normal file
View File

@ -0,0 +1,290 @@
/*!
* consensus.js - consensus constants and helpers for bcoin
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var assert = require('assert');
var BN = require('bn.js');
/**
* One bitcoin in satoshis.
* @const {Amount}
* @default
*/
exports.COIN = 100000000;
/**
* Maximum amount of money in satoshis:
* `21million * 1btc` (consensus).
* @const {Amount}
* @default
*/
exports.MAX_MONEY = 21000000 * exports.COIN;
/**
* Maximum block base size (consensus).
* @const {Number}
* @default
*/
exports.MAX_BLOCK_SIZE = 1000000;
/**
* Maximum block serialization size (protocol).
* @const {Number}
* @default
*/
exports.MAX_RAW_BLOCK_SIZE = 4000000;
/**
* Maximum block weight (consensus).
* @const {Number}
* @default
*/
exports.MAX_BLOCK_WEIGHT = 4000000;
/**
* Maximum block sigops (consensus).
* @const {Number}
* @default
*/
exports.MAX_BLOCK_SIGOPS = 1000000 / 50;
/**
* Maximum block sigops cost (consensus).
* @const {Number}
* @default
*/
exports.MAX_BLOCK_SIGOPS_COST = 80000;
/**
* Number of blocks before a coinbase
* spend can occur (consensus).
* @const {Number}
* @default
*/
exports.COINBASE_MATURITY = 100;
/**
* Amount to multiply base/non-witness sizes by.
* @const {Number}
* @default
*/
exports.WITNESS_SCALE_FACTOR = 4;
/**
* nLockTime threshold for differentiating
* between height and time (consensus).
* Tue Nov 5 00:53:20 1985 UTC
* @const {Number}
* @default
*/
exports.LOCKTIME_THRESHOLD = 500000000;
/**
* Highest nSequence bit -- disables
* sequence locktimes (consensus).
* @const {Number}
*/
exports.SEQUENCE_DISABLE_FLAG = (1 << 31) >>> 0;
/**
* Sequence time: height or time (consensus).
* @const {Number}
* @default
*/
exports.SEQUENCE_TYPE_FLAG = 1 << 22;
/**
* Sequence granularity for time (consensus).
* @const {Number}
* @default
*/
exports.SEQUENCE_GRANULARITY = 9;
/**
* Sequence mask (consensus).
* @const {Number}
* @default
*/
exports.SEQUENCE_MASK = 0x0000ffff;
/**
* Max serialized script size (consensus).
* @const {Number}
* @default
*/
exports.MAX_SCRIPT_SIZE = 10000;
/**
* Max stack size during execution (consensus).
* @const {Number}
* @default
*/
exports.MAX_SCRIPT_STACK = 1000;
/**
* Max script element size (consensus).
* @const {Number}
* @default
*/
exports.MAX_SCRIPT_PUSH = 520;
/**
* Max opcodes executed (consensus).
* @const {Number}
* @default
*/
exports.MAX_SCRIPT_OPS = 201;
/**
* Max `n` value for multisig (consensus).
* @const {Number}
* @default
*/
exports.MAX_MULTISIG_PUBKEYS = 20;
/**
* The date bip16 (p2sh) was activated (consensus).
* @const {Number}
* @default
*/
exports.BIP16_TIME = 1333238400;
/**
* Convert a compact number to a big number.
* Used for `block.bits` -> `target` conversion.
* @param {Number} compact
* @returns {BN}
*/
exports.fromCompact = function fromCompact(compact) {
var exponent = compact >>> 24;
var negative = (compact >>> 23) & 1;
var mantissa = compact & 0x7fffff;
var num;
if (compact === 0)
return new BN(0);
if (exponent <= 3) {
mantissa >>>= 8 * (3 - exponent);
num = new BN(mantissa);
} else {
num = new BN(mantissa);
num.iushln(8 * (exponent - 3));
}
if (negative)
num.ineg();
return num;
};
/**
* Convert a big number to a compact number.
* Used for `target` -> `block.bits` conversion.
* @param {BN} num
* @returns {Number}
*/
exports.toCompact = function toCompact(num) {
var mantissa, exponent, compact;
if (num.cmpn(0) === 0)
return 0;
exponent = num.byteLength();
if (exponent <= 3) {
mantissa = num.toNumber();
mantissa <<= 8 * (3 - exponent);
} else {
mantissa = num.ushrn(8 * (exponent - 3)).toNumber();
}
if (mantissa & 0x800000) {
mantissa >>= 8;
exponent++;
}
compact = (exponent << 24) | mantissa;
if (num.isNeg())
compact |= 0x800000;
compact >>>= 0;
return compact;
};
/**
* Verify proof-of-work.
* @param {Hash} hash
* @param {Number} bits
* @returns {Boolean}
*/
exports.verifyPOW = function verifyPOW(hash, bits) {
var target = exports.fromCompact(bits);
if (target.isNeg() || target.cmpn(0) === 0)
return false;
hash = new BN(hash, 'le');
if (hash.cmp(target) > 0)
return false;
return true;
};
/**
* Calculate block subsidy.
* @param {Number} height - Reward era by height.
* @returns {Amount}
*/
exports.getReward = function getReward(height, interval) {
var halvings = Math.floor(height / interval);
assert(height >= 0, 'Bad height for reward.');
// BIP 42 (well, our own version of it,
// since we can only handle 32 bit shifts).
// https://github.com/bitcoin/bips/blob/master/bip-0042.mediawiki
if (halvings >= 33)
return 0;
// We need to shift right by `halvings`,
// but 50 btc is a 33 bit number, so we
// cheat. We only start halving once the
// halvings are at least 1.
if (halvings === 0)
return 5000000000;
return 2500000000 >>> (halvings - 1);
};

View File

@ -8,761 +8,22 @@
'use strict';
/**
* @module constants
*/
var util = require('../utils/util');
/**
* Minimum protocol version we're willing to talk to.
* @const {Number}
* @default
*/
exports.MIN_VERSION = 70001;
/**
* BCoin's protocol version.
* @const {Number}
* @default
*/
exports.VERSION = 70014;
/**
* Max message size (~4mb with segwit, formerly 2mb)
* @const {Number}
* @default
*/
exports.MAX_MESSAGE = 4 * 1000 * 1000;
/**
* Service bits.
* @enum {Number}
* @default
*/
exports.services = {
/**
* Whether network services are enabled.
*/
NETWORK: (1 << 0),
/**
* Whether the peer supports the getutxos packet.
*/
GETUTXO: (1 << 1),
/**
* Whether the peer supports BIP37.
*/
BLOOM: (1 << 2),
/**
* Whether the peer supports segregated witness.
*/
WITNESS: (1 << 3)
};
/**
* BCoin's services (we support everything).
* @const {Number}
* @default
*/
exports.LOCAL_SERVICES = 0
| exports.services.NETWORK
| exports.services.GETUTXO
| exports.services.BLOOM
| exports.services.WITNESS;
/**
* Script opcodes.
* @enum {Number}
* @default
*/
exports.opcodes = {
OP_FALSE: 0x00,
OP_0: 0x00,
OP_PUSHDATA1: 0x4c,
OP_PUSHDATA2: 0x4d,
OP_PUSHDATA4: 0x4e,
OP_1NEGATE: 0x4f,
OP_RESERVED: 0x50,
OP_TRUE: 0x51,
OP_1: 0x51,
OP_2: 0x52,
OP_3: 0x53,
OP_4: 0x54,
OP_5: 0x55,
OP_6: 0x56,
OP_7: 0x57,
OP_8: 0x58,
OP_9: 0x59,
OP_10: 0x5a,
OP_11: 0x5b,
OP_12: 0x5c,
OP_13: 0x5d,
OP_14: 0x5e,
OP_15: 0x5f,
OP_16: 0x60,
OP_NOP: 0x61,
OP_VER: 0x62,
OP_IF: 0x63,
OP_NOTIF: 0x64,
OP_VERIF: 0x65,
OP_VERNOTIF: 0x66,
OP_ELSE: 0x67,
OP_ENDIF: 0x68,
OP_VERIFY: 0x69,
OP_RETURN: 0x6a,
OP_TOALTSTACK: 0x6b,
OP_FROMALTSTACK: 0x6c,
OP_2DROP: 0x6d,
OP_2DUP: 0x6e,
OP_3DUP: 0x6f,
OP_2OVER: 0x70,
OP_2ROT: 0x71,
OP_2SWAP: 0x72,
OP_IFDUP: 0x73,
OP_DEPTH: 0x74,
OP_DROP: 0x75,
OP_DUP: 0x76,
OP_NIP: 0x77,
OP_OVER: 0x78,
OP_PICK: 0x79,
OP_ROLL: 0x7a,
OP_ROT: 0x7b,
OP_SWAP: 0x7c,
OP_TUCK: 0x7d,
OP_CAT: 0x7e,
OP_SUBSTR: 0x7f,
OP_LEFT: 0x80,
OP_RIGHT: 0x81,
OP_SIZE: 0x82,
OP_INVERT: 0x83,
OP_AND: 0x84,
OP_OR: 0x85,
OP_XOR: 0x86,
OP_EQUAL: 0x87,
OP_EQUALVERIFY: 0x88,
OP_RESERVED1: 0x89,
OP_RESERVED2: 0x8a,
OP_1ADD: 0x8b,
OP_1SUB: 0x8c,
OP_2MUL: 0x8d,
OP_2DIV: 0x8e,
OP_NEGATE: 0x8f,
OP_ABS: 0x90,
OP_NOT: 0x91,
OP_0NOTEQUAL: 0x92,
OP_ADD: 0x93,
OP_SUB: 0x94,
OP_MUL: 0x95,
OP_DIV: 0x96,
OP_MOD: 0x97,
OP_LSHIFT: 0x98,
OP_RSHIFT: 0x99,
OP_BOOLAND: 0x9a,
OP_BOOLOR: 0x9b,
OP_NUMEQUAL: 0x9c,
OP_NUMEQUALVERIFY: 0x9d,
OP_NUMNOTEQUAL: 0x9e,
OP_LESSTHAN: 0x9f,
OP_GREATERTHAN: 0xa0,
OP_LESSTHANOREQUAL: 0xa1,
OP_GREATERTHANOREQUAL: 0xa2,
OP_MIN: 0xa3,
OP_MAX: 0xa4,
OP_WITHIN: 0xa5,
OP_RIPEMD160: 0xa6,
OP_SHA1: 0xa7,
OP_SHA256: 0xa8,
OP_HASH160: 0xa9,
OP_HASH256: 0xaa,
OP_CODESEPARATOR: 0xab,
OP_CHECKSIG: 0xac,
OP_CHECKSIGVERIFY: 0xad,
OP_CHECKMULTISIG: 0xae,
OP_CHECKMULTISIGVERIFY: 0xaf,
OP_EVAL: 0xb0,
OP_NOP1: 0xb0,
OP_NOP2: 0xb1,
OP_CHECKLOCKTIMEVERIFY: 0xb1,
OP_NOP3: 0xb2,
OP_CHECKSEQUENCEVERIFY: 0xb2,
OP_NOP4: 0xb3,
OP_NOP5: 0xb4,
OP_NOP6: 0xb5,
OP_NOP7: 0xb6,
OP_NOP8: 0xb7,
OP_NOP9: 0xb8,
OP_NOP10: 0xb9,
OP_PUBKEYHASH: 0xfd,
OP_PUBKEY: 0xfe,
OP_INVALIDOPCODE: 0xff
};
/**
* Opcodes by value.
* @const {RevMap}
*/
exports.opcodesByVal = util.revMap(exports.opcodes);
/**
* One bitcoin in satoshis.
* @const {Amount}
* @default
*/
exports.COIN = 100000000;
/**
* One bitcoin / 100.
* @const {Amount}
* @default
*/
exports.CENT = 1000000;
/**
* Maximum amount of money in satoshis (1btc * 21million)
* @const {Amount}
* @default
*/
exports.MAX_MONEY = 21000000 * exports.COIN;
/**
* Sighash Types.
* @enum {SighashType}
* @default
*/
exports.hashType = {
/**
* Sign all outputs.
*/
ALL: 1,
/**
* Do not sign outputs (zero sequences).
*/
NONE: 2,
/**
* Sign output at the same index (zero sequences).
*/
SINGLE: 3,
/**
* Sign only the current input (mask).
*/
ANYONECANPAY: 0x80
};
/**
* Sighash types by value.
* @const {RevMap}
*/
exports.hashTypeByVal = util.revMap(exports.hashType);
/**
* Amount to multiply base/non-witness sizes by.
* @const {Number}
* @default
*/
exports.WITNESS_SCALE_FACTOR = 4;
/**
* Block-related constants.
* @enum {Number}
* @default
*/
exports.block = {
MAX_SIZE: 1000000,
MAX_RAW_SIZE: 4000000,
MAX_WEIGHT: 4000000,
MAX_SIGOPS: 1000000 / 50,
MAX_SIGOPS_COST: 80000,
MEDIAN_TIMESPAN: 11,
BIP16_TIME: 1333238400,
SIGHASH_LIMIT: 1300000000
};
/**
* Map of historical blocks which create duplicate transactions hashes.
* @see https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki
* @const {Object}
* @default
*/
exports.bip30 = {
91842: 'eccae000e3c8e4e093936360431f3b7603c563c1ff6181390a4d0a0000000000',
91880: '21d77ccb4c08386a04ac0196ae10f6a1d2c2a377558ca190f143070000000000'
};
/**
* TX-related constants.
* @enum {Number}
* @default
*/
exports.tx = {
MAX_VERSION: 2,
MAX_SIZE: 100000,
MAX_WEIGHT: 400000,
MIN_FEE: 10000,
MAX_FEE: exports.COIN / 10,
MIN_RELAY: 1000,
BARE_MULTISIG: true,
FREE_THRESHOLD: exports.COIN * 144 / 250,
MAX_SIGOPS: exports.block.MAX_SIGOPS / 5,
MAX_SIGOPS_COST: exports.block.MAX_SIGOPS_COST / 5,
BYTES_PER_SIGOP: 20,
COINBASE_MATURITY: 100
};
/**
* Script-related constants.
* @enum {Number}
* @default
*/
exports.script = {
MAX_SIZE: 10000,
MAX_STACK: 1000,
MAX_PUSH: 520,
MAX_OPS: 201,
MAX_MULTISIG_PUBKEYS: 20,
MAX_SCRIPTHASH_SIGOPS: 15,
MAX_OP_RETURN_BYTES: 83,
MAX_OP_RETURN: 80,
BYTES_PER_SIGOP: 20,
MAX_P2WSH_STACK: 100,
MAX_P2WSH_PUSH: 80,
MAX_P2WSH_SIZE: 3600
};
/**
* Mempool-related constants.
* @enum {Number}
* @default
*/
exports.mempool = {
/**
* Ancestor limit.
*/
ANCESTOR_LIMIT: 25,
/**
* Maximum mempool size in bytes.
*/
MAX_MEMPOOL_SIZE: 100 * 1000000,
/**
* The time at which transactions
* fall out of the mempool.
*/
MEMPOOL_EXPIRY: 72 * 60 * 60,
/**
* Maximum number of orphan transactions.
*/
MAX_ORPHAN_TX: 100
};
/**
* Reject codes. Note that `internal` and higher
* are not meant for use on the p2p network.
* @enum {Number}
* @default
*/
exports.reject = {
MALFORMED: 0x01,
INVALID: 0x10,
OBSOLETE: 0x11,
DUPLICATE: 0x12,
NONSTANDARD: 0x40,
DUST: 0x41,
INSUFFICIENTFEE: 0x42,
CHECKPOINT: 0x43,
// Internal codes (NOT FOR USE ON NETWORK)
INTERNAL: 0x100,
HIGHFEE: 0x100,
ALREADYKNOWN: 0x101,
CONFLICT: 0x102
};
/**
* Reject codes by value.
* @const {RevMap}
*/
exports.rejectByVal = util.revMap(exports.reject);
/**
* HD-related constants.
* @const {Object}
* @default
*/
exports.hd = {
HARDENED: 0x80000000,
MAX_INDEX: 0x100000000,
MIN_ENTROPY: 128,
MAX_ENTROPY: 512
};
/**
* nLockTime threshold for differentiating
* between height and time.
* Tue Nov 5 00:53:20 1985 UTC
* @const {Number}
* @default
*/
exports.LOCKTIME_THRESHOLD = 500000000;
/**
* Sequence locktime-related constants.
* @enum {Number}
* @default
*/
exports.sequence = {
/**
* Highest nSequence bit (disables sequence locktimes).
*/
DISABLE_FLAG: (1 << 31) >>> 0,
/**
* Type (height or time).
*/
TYPE_FLAG: 1 << 22,
/**
* Sequence granularity.
*/
GRANULARITY: 9,
/**
* Mask.
*/
MASK: 0x0000ffff
};
/**
* A hash of all zeroes with a `1` at the
* end (used for the SIGHASH_SINGLE bug).
* @const {Buffer}
* @default
*/
exports.ONE_HASH = new Buffer(
'0100000000000000000000000000000000000000000000000000000000000000',
'hex'
);
/**
* A hash of all zeroes.
* @const {Buffer}
* @default
*/
exports.ZERO_HASH = new Buffer(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'
);
/**
* A hash of all 0xff.
* @const {Buffer}
* @default
*/
exports.MAX_HASH = new Buffer(
'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
'hex'
);
/**
* A hash of all zeroes.
* @const {String}
* @default
*/
exports.NULL_HASH =
'0000000000000000000000000000000000000000000000000000000000000000';
/**
* A hash of all 0xff.
* @const {String}
* @default
*/
exports.HIGH_HASH =
'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff';
/**
* A hash of all zeroes.
* @const {Buffer}
* @default
*/
exports.ZERO_HASH160 = new Buffer(
'0000000000000000000000000000000000000000',
'hex'
);
/**
* A hash of all 0xff.
* @const {String}
* @default
*/
exports.MAX_HASH160 = new Buffer(
'ffffffffffffffffffffffffffffffffffffffff',
'hex'
);
/**
* A hash of all zeroes.
* @const {String}
* @default
*/
exports.NULL_HASH160 = '0000000000000000000000000000000000000000';
/**
* A hash of all 0xff.
* @const {String}
* @default
*/
exports.HIGH_HASH160 = 'ffffffffffffffffffffffffffffffffffffffff';
/**
* A compressed pubkey of all zeroes.
* @const {Buffer}
* @default
*/
exports.ZERO_KEY = new Buffer(
'000000000000000000000000000000000000000000000000000000000000000000',
'hex'
);
/**
* A 73 byte signature of all zeroes.
* @const {Buffer}
* @default
*/
exports.ZERO_SIG = new Buffer(''
+ '0000000000000000000000000000000000000000000000000000000000000000'
+ '0000000000000000000000000000000000000000000000000000000000000000'
+ '000000000000000000',
'hex'
);
/**
* A 64 byte signature of all zeroes.
* @const {Buffer}
* @default
*/
exports.ZERO_SIG64 = new Buffer(''
+ '0000000000000000000000000000000000000000000000000000000000000000'
+ '0000000000000000000000000000000000000000000000000000000000000000',
'hex'
);
/**
* 4 zero bytes.
* @const {Buffer}
* @default
*/
exports.ZERO_U32 = new Buffer('00000000', 'hex');
/**
* 8 zero bytes.
* @const {Buffer}
* @default
*/
exports.ZERO_U64 = new Buffer('0000000000000000', 'hex');
/**
* BCoin version.
* @const {String}
* @default
*/
exports.USER_VERSION = require('../../package.json').version;
/**
* BCoin user agent: `/bcoin:{version}/`.
* @const {String}
* @default
*/
exports.USER_AGENT = '/bcoin:' + exports.USER_VERSION + '/';
/**
* Amount of time to ban misbheaving peers.
* @const {Number}
* @default
*/
exports.BAN_TIME = 24 * 60 * 60;
/**
* Ban score threshold before ban is placed in effect.
* @const {Number}
* @default
*/
exports.BAN_SCORE = 100;
/**
* Output script types.
* Locktime flags.
* @enum {Number}
*/
exports.scriptTypes = {
NONSTANDARD: 0,
PUBKEY: 1,
PUBKEYHASH: 2,
SCRIPTHASH: 3,
MULTISIG: 4,
NULLDATA: 5,
WITNESSMALFORMED: 0x80 | 0,
WITNESSSCRIPTHASH: 0x80 | 1,
WITNESSPUBKEYHASH: 0x80 | 2,
WITNESSMASTHASH: 0x80 | 3
exports.lockFlags = {
VERIFY_SEQUENCE: 1 << 0,
MEDIAN_TIME_PAST: 1 << 1
};
/**
* Output script types by value.
* @const {RevMap}
*/
exports.scriptTypesByVal = util.revMap(exports.scriptTypes);
/**
* Script and locktime flags. See {@link VerifyFlags}.
* @enum {Number}
*/
exports.flags = {
VERIFY_NONE: 0,
VERIFY_P2SH: (1 << 0),
VERIFY_STRICTENC: (1 << 1),
VERIFY_DERSIG: (1 << 2),
VERIFY_LOW_S: (1 << 3),
VERIFY_NULLDUMMY: (1 << 4),
VERIFY_SIGPUSHONLY: (1 << 5),
VERIFY_MINIMALDATA: (1 << 6),
VERIFY_DISCOURAGE_UPGRADABLE_NOPS: (1 << 7),
VERIFY_CLEANSTACK: (1 << 8),
VERIFY_CHECKLOCKTIMEVERIFY: (1 << 9),
VERIFY_CHECKSEQUENCEVERIFY: (1 << 10),
VERIFY_WITNESS: (1 << 11),
VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: (1 << 12),
VERIFY_MINIMALIF: (1 << 13),
VERIFY_NULLFAIL: (1 << 14),
VERIFY_WITNESS_PUBKEYTYPE: (1 << 15),
VERIFY_MAST: (1 << 16), // should be 1 << 13
VERIFY_SEQUENCE: (1 << 0),
MEDIAN_TIME_PAST: (1 << 1)
};
/**
* Consensus verify flags (used for block validation).
* @const {VerifyFlags}
* @default
*/
exports.flags.MANDATORY_VERIFY_FLAGS = exports.flags.VERIFY_P2SH;
/**
* Standard verify flags (used for mempool validation).
* @const {VerifyFlags}
* @default
*/
exports.flags.STANDARD_VERIFY_FLAGS = 0
| exports.flags.MANDATORY_VERIFY_FLAGS
| exports.flags.VERIFY_DERSIG
| exports.flags.VERIFY_STRICTENC
| exports.flags.VERIFY_MINIMALDATA
| exports.flags.VERIFY_NULLDUMMY
| exports.flags.VERIFY_DISCOURAGE_UPGRADABLE_NOPS
| exports.flags.VERIFY_CLEANSTACK
| exports.flags.VERIFY_MINIMALIF
| exports.flags.VERIFY_NULLFAIL
| exports.flags.VERIFY_CHECKLOCKTIMEVERIFY
| exports.flags.VERIFY_CHECKSEQUENCEVERIFY
| exports.flags.VERIFY_LOW_S
| exports.flags.VERIFY_WITNESS
| exports.flags.VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM
| exports.flags.VERIFY_WITNESS_PUBKEYTYPE;
/**
* Standard-not-mandatory flags.
* @const {VerifyFlags}
* @default
*/
exports.flags.UNSTANDARD_VERIFY_FLAGS =
exports.flags.STANDARD_VERIFY_FLAGS & ~exports.flags.MANDATORY_VERIFY_FLAGS;
/**
* Consensus locktime flags (used for block validation).
* @const {LockFlags}
* @default
*/
exports.flags.MANDATORY_LOCKTIME_FLAGS = 0;
exports.lockFlags.MANDATORY_LOCKTIME_FLAGS = 0;
/**
* Standard locktime flags (used for mempool validation).
@ -770,9 +31,9 @@ exports.flags.MANDATORY_LOCKTIME_FLAGS = 0;
* @default
*/
exports.flags.STANDARD_LOCKTIME_FLAGS = 0
| exports.flags.VERIFY_SEQUENCE
| exports.flags.MEDIAN_TIME_PAST;
exports.lockFlags.STANDARD_LOCKTIME_FLAGS = 0
| exports.lockFlags.VERIFY_SEQUENCE
| exports.lockFlags.MEDIAN_TIME_PAST;
/**
* Versionbits constants.
@ -813,11 +74,3 @@ exports.thresholdStates = {
ACTIVE: 3,
FAILED: 4
};
/**
* The name of our currency.
* @const {String}
* @default
*/
exports.CURRENCY_UNIT = 'BTC';

View File

@ -37,6 +37,7 @@ function Network(options) {
this.genesisBlock = options.genesisBlock;
this.pow = options.pow;
this.block = options.block;
this.bip30 = options.bip30;
this.witness = options.witness;
this.oldWitness = options.oldWitness;
this.activationThreshold = options.activationThreshold;

View File

@ -293,6 +293,18 @@ main.block = {
slowHeight: 325000
};
/**
* Map of historical blocks which create duplicate transactions hashes.
* @see https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki
* @const {Object}
* @default
*/
main.bip30 = {
91842: 'eccae000e3c8e4e093936360431f3b7603c563c1ff6181390a4d0a0000000000',
91880: '21d77ccb4c08386a04ac0196ae10f6a1d2c2a377558ca190f143070000000000'
};
/**
* Whether this is a segwit-enabled network.
* @const {Boolean}
@ -568,6 +580,8 @@ testnet.block = {
slowHeight: 750000
};
testnet.bip30 = {};
testnet.witness = true;
testnet.oldWitness = false;
@ -726,6 +740,8 @@ regtest.block = {
slowHeight: 0x7fffffff
};
regtest.bip30 = {};
regtest.witness = false;
regtest.oldWitness = false;
@ -885,6 +901,8 @@ segnet3.block = {
slowHeight: 0x7fffffff
};
segnet3.bip30 = {};
segnet3.witness = true;
segnet3.oldWitness = true;
@ -1008,6 +1026,8 @@ segnet4.block = {
slowHeight: 0x7fffffff
};
segnet4.bip30 = {};
segnet4.witness = true;
segnet4.oldWitness = false;
@ -1159,6 +1179,8 @@ simnet.block = {
slowHeight: 0
};
simnet.bip30 = {};
simnet.witness = false;
simnet.oldWitness = false;

235
lib/protocol/policy.js Normal file
View File

@ -0,0 +1,235 @@
/*!
* policy.js - bitcoin constants for bcoin
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
var consensus = require('./consensus');
/**
* Maximum transaction version (policy).
* @const {Number}
* @default
*/
exports.MAX_TX_VERSION = 2;
/**
* Maximum transaction base size (policy).
* @const {Number}
* @default
*/
exports.MAX_TX_SIZE = consensus.MAX_BLOCK_SIZE / 10;
/**
* Maximum transaction weight (policy).
* @const {Number}
* @default
*/
exports.MAX_TX_WEIGHT = consensus.MAX_BLOCK_WEIGHT / 10;
/**
* Maximum number of transaction sigops (policy).
* @const {Number}
* @default
*/
exports.MAX_TX_SIGOPS = consensus.MAX_BLOCK_SIGOPS / 5;
/**
* Maximum cost of transaction sigops (policy).
* @const {Number}
* @default
*/
exports.MAX_TX_SIGOPS_COST = consensus.MAX_BLOCK_SIGOPS_COST / 5;
/**
* How much weight a sigop should
* add to virtual size (policy).
* @const {Number}
* @default
*/
exports.BYTES_PER_SIGOP = 20;
/**
* Minimum relay fee rate (policy).
* @const {Rate}
*/
exports.MIN_RELAY = 1000;
/**
* Whether bare multisig outputs
* should be relayed (policy).
* @const {Boolean}
* @default
*/
exports.BARE_MULTISIG = true;
/**
* Priority threshold for
* free transactions (policy).
* @const {Number}
* @default
*/
exports.FREE_THRESHOLD = consensus.COIN * 144 / 250;
/**
* Max sigops per redeem script (policy).
* @const {Number}
* @default
*/
exports.MAX_SCRIPTHASH_SIGOPS = 15;
/**
* Max serialized nulldata size (policy).
* @const {Number}
* @default
*/
exports.MAX_OP_RETURN_BYTES = 83;
/**
* Max pushdata size in nulldata (policy).
* @const {Number}
* @default
*/
exports.MAX_OP_RETURN = 80;
/**
* Max p2wsh stack size. Used for
* witness malleation checks (policy).
* @const {Number}
* @default
*/
exports.MAX_P2WSH_STACK = 100;
/**
* Max p2wsh push size. Used for
* witness malleation checks (policy).
* @const {Number}
* @default
*/
exports.MAX_P2WSH_PUSH = 80;
/**
* Max serialized p2wsh size. Used for
* witness malleation checks (policy).
* @const {Number}
* @default
*/
exports.MAX_P2WSH_SIZE = 3600;
/**
* Mempool ancestor limit.
* @const {Number}
* @default
*/
exports.ANCESTOR_LIMIT = 25;
/**
* Block weight to be reached before
* rejecting free transactions during
* mining.
* @const {Number}
* @default
*/
exports.MIN_BLOCK_WEIGHT = 0;
/**
* Maximum block weight to be mined.
* @const {Number}
* @default
*/
exports.MAX_BLOCK_WEIGHT = 750000 * consensus.WITNESS_SCALE_FACTOR;
/**
* Bottom priority threshold to be seen
* before ignoring priority transactions
* during mining.
* @const {Number}
* @default
*/
exports.MIN_BLOCK_PRIORITY = 50000 * consensus.WITNESS_SCALE_FACTOR;
/**
* Weight to be reached before ignoring
* priority transactions during mining.
* @const {Number}
* @default
*/
exports.PRIORITY_BLOCK_WEIGHT = exports.FREE_THRESHOLD;
/**
* Calculate minimum fee based on rate and size.
* @param {Number?} size
* @param {Rate?} rate - Rate of satoshi per kB.
* @returns {Amount} fee
*/
exports.getMinFee = function getMinFee(size, rate) {
var fee;
if (rate == null)
rate = exports.MIN_RELAY;
fee = Math.floor(rate * size / 1000);
if (fee === 0 && rate > 0)
fee = rate;
return fee;
};
/**
* Calculate the minimum fee in order for the transaction
* to be relayable, but _round to the nearest kilobyte
* when taking into account size.
* @param {Number?} size
* @param {Rate?} rate - Rate of satoshi per kB.
* @returns {Amount} fee
*/
exports.getRoundFee = function getRoundFee(size, rate) {
var fee;
if (rate == null)
rate = exports.MIN_RELAY;
fee = rate * Math.ceil(size / 1000);
if (fee === 0 && rate > 0)
fee = rate;
return fee;
};
/**
* Calculate a fee rate based on size and fees.
* @param {Number} size
* @param {Amount} fee
* @returns {Rate}
*/
exports.getRate = function getRate(size, fee) {
return Math.floor(fee * 1000 / size);
};

View File

@ -7,13 +7,308 @@
'use strict';
var BN = require('bn.js');
var constants = require('../protocol/constants');
var util = require('../utils/util');
var assert = require('assert');
var opcodes = constants.opcodes;
var STACK_FALSE = new Buffer(0);
var ScriptError = require('../btc/errors').ScriptError;
var BN = require('bn.js');
var util = require('../utils/util');
/**
* Script opcodes.
* @enum {Number}
* @default
*/
exports.opcodes = {
OP_FALSE: 0x00,
OP_0: 0x00,
OP_PUSHDATA1: 0x4c,
OP_PUSHDATA2: 0x4d,
OP_PUSHDATA4: 0x4e,
OP_1NEGATE: 0x4f,
OP_RESERVED: 0x50,
OP_TRUE: 0x51,
OP_1: 0x51,
OP_2: 0x52,
OP_3: 0x53,
OP_4: 0x54,
OP_5: 0x55,
OP_6: 0x56,
OP_7: 0x57,
OP_8: 0x58,
OP_9: 0x59,
OP_10: 0x5a,
OP_11: 0x5b,
OP_12: 0x5c,
OP_13: 0x5d,
OP_14: 0x5e,
OP_15: 0x5f,
OP_16: 0x60,
OP_NOP: 0x61,
OP_VER: 0x62,
OP_IF: 0x63,
OP_NOTIF: 0x64,
OP_VERIF: 0x65,
OP_VERNOTIF: 0x66,
OP_ELSE: 0x67,
OP_ENDIF: 0x68,
OP_VERIFY: 0x69,
OP_RETURN: 0x6a,
OP_TOALTSTACK: 0x6b,
OP_FROMALTSTACK: 0x6c,
OP_2DROP: 0x6d,
OP_2DUP: 0x6e,
OP_3DUP: 0x6f,
OP_2OVER: 0x70,
OP_2ROT: 0x71,
OP_2SWAP: 0x72,
OP_IFDUP: 0x73,
OP_DEPTH: 0x74,
OP_DROP: 0x75,
OP_DUP: 0x76,
OP_NIP: 0x77,
OP_OVER: 0x78,
OP_PICK: 0x79,
OP_ROLL: 0x7a,
OP_ROT: 0x7b,
OP_SWAP: 0x7c,
OP_TUCK: 0x7d,
OP_CAT: 0x7e,
OP_SUBSTR: 0x7f,
OP_LEFT: 0x80,
OP_RIGHT: 0x81,
OP_SIZE: 0x82,
OP_INVERT: 0x83,
OP_AND: 0x84,
OP_OR: 0x85,
OP_XOR: 0x86,
OP_EQUAL: 0x87,
OP_EQUALVERIFY: 0x88,
OP_RESERVED1: 0x89,
OP_RESERVED2: 0x8a,
OP_1ADD: 0x8b,
OP_1SUB: 0x8c,
OP_2MUL: 0x8d,
OP_2DIV: 0x8e,
OP_NEGATE: 0x8f,
OP_ABS: 0x90,
OP_NOT: 0x91,
OP_0NOTEQUAL: 0x92,
OP_ADD: 0x93,
OP_SUB: 0x94,
OP_MUL: 0x95,
OP_DIV: 0x96,
OP_MOD: 0x97,
OP_LSHIFT: 0x98,
OP_RSHIFT: 0x99,
OP_BOOLAND: 0x9a,
OP_BOOLOR: 0x9b,
OP_NUMEQUAL: 0x9c,
OP_NUMEQUALVERIFY: 0x9d,
OP_NUMNOTEQUAL: 0x9e,
OP_LESSTHAN: 0x9f,
OP_GREATERTHAN: 0xa0,
OP_LESSTHANOREQUAL: 0xa1,
OP_GREATERTHANOREQUAL: 0xa2,
OP_MIN: 0xa3,
OP_MAX: 0xa4,
OP_WITHIN: 0xa5,
OP_RIPEMD160: 0xa6,
OP_SHA1: 0xa7,
OP_SHA256: 0xa8,
OP_HASH160: 0xa9,
OP_HASH256: 0xaa,
OP_CODESEPARATOR: 0xab,
OP_CHECKSIG: 0xac,
OP_CHECKSIGVERIFY: 0xad,
OP_CHECKMULTISIG: 0xae,
OP_CHECKMULTISIGVERIFY: 0xaf,
OP_EVAL: 0xb0,
OP_NOP1: 0xb0,
OP_NOP2: 0xb1,
OP_CHECKLOCKTIMEVERIFY: 0xb1,
OP_NOP3: 0xb2,
OP_CHECKSEQUENCEVERIFY: 0xb2,
OP_NOP4: 0xb3,
OP_NOP5: 0xb4,
OP_NOP6: 0xb5,
OP_NOP7: 0xb6,
OP_NOP8: 0xb7,
OP_NOP9: 0xb8,
OP_NOP10: 0xb9,
OP_PUBKEYHASH: 0xfd,
OP_PUBKEY: 0xfe,
OP_INVALIDOPCODE: 0xff
};
/**
* Opcodes by value.
* @const {RevMap}
*/
exports.opcodesByVal = util.revMap(exports.opcodes);
/**
* Script and locktime flags. See {@link VerifyFlags}.
* @enum {Number}
*/
exports.flags = {
VERIFY_NONE: 0,
VERIFY_P2SH: 1 << 0,
VERIFY_STRICTENC: 1 << 1,
VERIFY_DERSIG: 1 << 2,
VERIFY_LOW_S: 1 << 3,
VERIFY_NULLDUMMY: 1 << 4,
VERIFY_SIGPUSHONLY: 1 << 5,
VERIFY_MINIMALDATA: 1 << 6,
VERIFY_DISCOURAGE_UPGRADABLE_NOPS: 1 << 7,
VERIFY_CLEANSTACK: 1 << 8,
VERIFY_CHECKLOCKTIMEVERIFY: 1 << 9,
VERIFY_CHECKSEQUENCEVERIFY: 1 << 10,
VERIFY_WITNESS: 1 << 11,
VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: 1 << 12,
VERIFY_MINIMALIF: 1 << 13,
VERIFY_NULLFAIL: 1 << 14,
VERIFY_WITNESS_PUBKEYTYPE: 1 << 15,
VERIFY_MAST: 1 << 16
};
/**
* Consensus verify flags (used for block validation).
* @const {VerifyFlags}
* @default
*/
exports.flags.MANDATORY_VERIFY_FLAGS = exports.flags.VERIFY_P2SH;
/**
* Standard verify flags (used for mempool validation).
* @const {VerifyFlags}
* @default
*/
exports.flags.STANDARD_VERIFY_FLAGS = 0
| exports.flags.MANDATORY_VERIFY_FLAGS
| exports.flags.VERIFY_DERSIG
| exports.flags.VERIFY_STRICTENC
| exports.flags.VERIFY_MINIMALDATA
| exports.flags.VERIFY_NULLDUMMY
| exports.flags.VERIFY_DISCOURAGE_UPGRADABLE_NOPS
| exports.flags.VERIFY_CLEANSTACK
| exports.flags.VERIFY_MINIMALIF
| exports.flags.VERIFY_NULLFAIL
| exports.flags.VERIFY_CHECKLOCKTIMEVERIFY
| exports.flags.VERIFY_CHECKSEQUENCEVERIFY
| exports.flags.VERIFY_LOW_S
| exports.flags.VERIFY_WITNESS
| exports.flags.VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM
| exports.flags.VERIFY_WITNESS_PUBKEYTYPE;
/**
* Standard flags without mandatory bits.
* @const {VerifyFlags}
* @default
*/
exports.flags.UNSTANDARD_VERIFY_FLAGS =
exports.flags.STANDARD_VERIFY_FLAGS & ~exports.flags.MANDATORY_VERIFY_FLAGS;
/**
* Sighash Types.
* @enum {SighashType}
* @default
*/
exports.hashType = {
/*
* Sign all outputs.
*/
ALL: 1,
/*
* Do not sign outputs (zero sequences).
*/
NONE: 2,
/*
* Sign output at the same index (zero sequences).
*/
SINGLE: 3,
/*
* Sign only the current input (mask).
*/
ANYONECANPAY: 0x80
};
/**
* Sighash types by value.
* @const {RevMap}
*/
exports.hashTypeByVal = util.revMap(exports.hashType);
/**
* Output script types.
* @enum {Number}
*/
exports.types = {
NONSTANDARD: 0,
PUBKEY: 1,
PUBKEYHASH: 2,
SCRIPTHASH: 3,
MULTISIG: 4,
NULLDATA: 5,
WITNESSMALFORMED: 0x80 | 0,
WITNESSSCRIPTHASH: 0x80 | 1,
WITNESSPUBKEYHASH: 0x80 | 2,
WITNESSMASTHASH: 0x80 | 3
};
/**
* Output script types by value.
* @const {RevMap}
*/
exports.typesByVal = util.revMap(exports.types);
/**
* False stack return value.
* @const {Buffer}
*/
exports.STACK_FALSE = new Buffer([]);
/**
* True stack return value.
* @const {Buffer}
*/
exports.STACK_TRUE = new Buffer([0x01]);
/**
* -1 stack return value.
* @const {Buffer}
*/
exports.STACK_NEGATE = new Buffer([0x81]);
/**
* Test whether the data element is a ripemd160 hash.
@ -228,7 +523,7 @@ exports.formatCode = function formatCode(code) {
while (size.length % 2 !== 0)
size = '0' + size;
if (!constants.opcodesByVal[value]) {
if (!exports.opcodesByVal[value]) {
value = value.toString(16);
if (value.length < 2)
value = '0' + value;
@ -237,7 +532,7 @@ exports.formatCode = function formatCode(code) {
continue;
}
value = constants.opcodesByVal[value];
value = exports.opcodesByVal[value];
value = value + ' 0x' + size + ' 0x' + data.toString('hex');
out.push(value);
continue;
@ -245,8 +540,8 @@ exports.formatCode = function formatCode(code) {
assert(typeof value === 'number');
if (constants.opcodesByVal[value]) {
value = constants.opcodesByVal[value];
if (exports.opcodesByVal[value]) {
value = exports.opcodesByVal[value];
out.push(value);
continue;
}
@ -279,7 +574,7 @@ exports.formatItem = function formatItem(data, decode) {
var symbol, type;
if (data.length <= 4) {
data = exports.num(data, constants.flags.VERIFY_NONE);
data = exports.num(data, exports.flags.VERIFY_NONE);
return data.toString(10);
}
@ -287,9 +582,9 @@ exports.formatItem = function formatItem(data, decode) {
symbol = '';
if (exports.isSignatureEncoding(data)) {
type = data[data.length - 1];
symbol = constants.hashTypeByVal[type & 0x1f] || '';
symbol = exports.hashTypeByVal[type & 0x1f] || '';
if (symbol) {
if (type & constants.hashType.ANYONECANPAY)
if (type & exports.hashType.ANYONECANPAY)
symbol += '|ANYONECANPAY';
symbol = '[' + symbol + ']';
}
@ -312,7 +607,7 @@ exports.formatASM = function formatASM(code, decode) {
var out = [];
var i, op, data, value;
if (code.length > 0 && code[0].value === opcodes.OP_RETURN)
if (code.length > 0 && code[0].value === exports.opcodes.OP_RETURN)
decode = false;
for (i = 0; i < code.length; i++) {
@ -331,7 +626,7 @@ exports.formatASM = function formatASM(code, decode) {
continue;
}
value = constants.opcodesByVal[value] || 'OP_UNKNOWN';
value = exports.opcodesByVal[value] || 'OP_UNKNOWN';
out.push(value);
}
@ -374,15 +669,15 @@ exports.num = function num(value, flags, size) {
assert(Buffer.isBuffer(value));
if (flags == null)
flags = constants.flags.STANDARD_VERIFY_FLAGS;
flags = exports.flags.STANDARD_VERIFY_FLAGS;
if (size == null)
size = 4;
if (value.length > size)
throw new ScriptError('UNKNOWN_ERROR', 'Script number overflow.');
throw new exports.ScriptError('UNKNOWN_ERROR', 'Script number overflow.');
if ((flags & constants.flags.VERIFY_MINIMALDATA) && value.length > 0) {
if ((flags & exports.flags.VERIFY_MINIMALDATA) && value.length > 0) {
// If the low bits on the last byte are unset,
// fail if the value's second to last byte does
// not have the high bit set. A number can't
@ -393,7 +688,7 @@ exports.num = function num(value, flags, size) {
// zero).
if (!(value[value.length - 1] & 0x7f)) {
if (value.length === 1 || !(value[value.length - 2] & 0x80)) {
throw new ScriptError(
throw new exports.ScriptError(
'UNKNOWN_ERROR',
'Non-minimally encoded Script number.');
}
@ -438,7 +733,7 @@ exports.array = function(value) {
assert(BN.isBN(value));
if (value.cmpn(0) === 0)
return STACK_FALSE;
return exports.STACK_FALSE;
// If the most significant byte is >= 0x80
// and the value is positive, push a new
@ -466,3 +761,53 @@ exports.array = function(value) {
return new Buffer(result);
};
/**
* An error thrown from the scripting system,
* potentially pertaining to Script execution.
* @exports ScriptError
* @constructor
* @extends Error
* @param {String} code - Error code.
* @param {(Number|String)?} op - Opcode.
* @param {Number?} ip - Instruction pointer.
* @property {String} message - Error message.
* @property {String} code - Original code passed in.
* @property {String?} op - Symbolic opcode.
* @property {Number?} ip - Instruction pointer.
*/
exports.ScriptError = function ScriptError(code, op, ip) {
Error.call(this);
if (Error.captureStackTrace)
Error.captureStackTrace(this, ScriptError);
this.type = 'ScriptError';
this.code = code;
if (typeof op !== 'string') {
if (op || ip != null) {
code += ' (';
if (op) {
op = exports.opcodesByVal[op] || op;
code += 'op=' + op;
if (ip != null)
code += ', ';
}
if (ip != null)
code += 'ip=' + ip;
code += ')';
}
this.message = code;
this.op = op || '';
this.ip = ip != null ? ip : -1;
} else {
this.message = op;
this.op = '';
this.ip = -1;
}
};
util.inherits(exports.ScriptError, Error);

View File

@ -9,12 +9,11 @@
var assert = require('assert');
var BN = require('bn.js');
var constants = require('../protocol/constants');
var util = require('../utils/util');
var encoding = require('./encoding');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var opcodes = constants.opcodes;
var opcodes = encoding.opcodes;
/**
* A simple struct which contains
@ -347,7 +346,7 @@ Opcode.fromSymbol = function fromSymbol(name) {
if (!util.startsWith(name, 'OP_'))
name = 'OP_' + name;
op = constants.opcodes[name];
op = encoding.opcodes[name];
assert(op != null, 'Unknown opcode.');
return Opcode.fromOp(op);

View File

@ -7,10 +7,10 @@
'use strict';
var constants = require('../protocol/constants');
var util = require('../utils/util');
var assert = require('assert');
var scriptTypes = constants.scriptTypes;
var util = require('../utils/util');
var encoding = require('./encoding');
var scriptTypes = encoding.types;
/**
* Witness Program
@ -96,7 +96,7 @@ Program.prototype.inspect = function inspect() {
return '<Program:'
+ ' version=' + this.version
+ ' data=' + this.data.toString('hex')
+ ' type=' + constants.scriptTypesByVal[this.getType()].toLowerCase()
+ ' type=' + encoding.typesByVal[this.getType()].toLowerCase()
+ '>';
};

View File

@ -7,20 +7,15 @@
'use strict';
var assert = require('assert');
var BN = require('bn.js');
var constants = require('../protocol/constants');
var consensus = require('../protocol/consensus');
var policy = require('../protocol/policy');
var util = require('../utils/util');
var crypto = require('../crypto/crypto');
var assert = require('assert');
var BufferWriter = require('../utils/writer');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var opcodes = constants.opcodes;
var STACK_TRUE = new Buffer([1]);
var STACK_FALSE = new Buffer(0);
var STACK_NEGATE = new Buffer([0x81]);
var ScriptError = require('../btc/errors').ScriptError;
var scriptTypes = constants.scriptTypes;
var Program = require('./program');
var Opcode = require('./opcode');
var Stack = require('./stack');
@ -29,6 +24,12 @@ var encoding = require('./encoding');
var enc = require('../utils/encoding');
var ec = require('../crypto/ec');
var Address = require('../primitives/address');
var opcodes = encoding.opcodes;
var scriptTypes = encoding.types;
var ScriptError = encoding.ScriptError;
var STACK_TRUE = encoding.STACK_TRUE;
var STACK_FALSE = encoding.STACK_FALSE;
var STACK_NEGATE = encoding.STACK_NEGATE;
/**
* Represents a input or output script.
@ -53,10 +54,77 @@ function Script(options) {
this.fromOptions(options);
}
/**
* Script opcodes.
* @enum {Number}
* @default
*/
Script.opcodes = encoding.opcodes;
/**
* Opcodes by value.
* @const {RevMap}
*/
Script.opcodesByVal = encoding.opcodesByVal;
/**
* Script and locktime flags. See {@link VerifyFlags}.
* @enum {Number}
*/
Script.flags = encoding.flags;
/**
* Sighash Types.
* @enum {SighashType}
* @default
*/
Script.hashType = encoding.hashType;
/**
* Sighash types by value.
* @const {RevMap}
*/
Script.hashTypeByVal = encoding.hashTypeByVal;
/**
* Output script types.
* @enum {Number}
*/
Script.types = encoding.types;
/**
* Output script types by value.
* @const {RevMap}
*/
Script.typesByVal = encoding.typesByVal;
/**
* Getter to retrieve code length.
* @function
* @name length(get)
* @memberof Script#
* @returns {Number}
*/
Script.prototype.__defineGetter__('length', function() {
return this.code.length;
});
/**
* Setter to set code length.
* @function
* @name length(set)
* @memberof Script#
* @returns {Number}
*/
Script.prototype.__defineSetter__('length', function(length) {
return this.code.length = length;
});
@ -234,7 +302,7 @@ Script.prototype.inspect = function inspect() {
*/
Script.prototype.toString = function toString() {
return Script.format(this.code);
return encoding.formatCode(this.code);
};
/**
@ -244,7 +312,7 @@ Script.prototype.toString = function toString() {
*/
Script.prototype.toASM = function toASM(decode) {
return Script.formatASM(this.code, decode);
return encoding.formatASM(this.code, decode);
};
/**
@ -410,9 +478,9 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
var i, j, res, locktime;
if (flags == null)
flags = constants.flags.STANDARD_VERIFY_FLAGS;
flags = Script.flags.STANDARD_VERIFY_FLAGS;
if (this.getSize() > constants.script.MAX_SIZE)
if (this.getSize() > consensus.MAX_SCRIPT_SIZE)
throw new ScriptError('SCRIPT_SIZE');
for (ip = 0; ip < this.code.length; ip++) {
@ -424,7 +492,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
throw new ScriptError('BAD_OPCODE', op, ip);
if (data) {
if (data.length > constants.script.MAX_PUSH)
if (data.length > consensus.MAX_SCRIPT_PUSH)
throw new ScriptError('PUSH_SIZE', op, ip);
// Note that minimaldata is not checked
@ -438,7 +506,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
continue;
}
if (op > opcodes.OP_16 && ++opCount > constants.script.MAX_OPS)
if (op > opcodes.OP_16 && ++opCount > consensus.MAX_SCRIPT_OPS)
throw new ScriptError('OP_COUNT', op, ip);
// It's very important to make a distiction
@ -477,7 +545,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
val = stack.top(-1);
if (version === 1 && (flags & constants.flags.VERIFY_MINIMALIF)) {
if (version === 1 && (flags & Script.flags.VERIFY_MINIMALIF)) {
if (val.length > 1)
throw new ScriptError('MINIMALIF');
@ -569,8 +637,8 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
}
case opcodes.OP_CHECKLOCKTIMEVERIFY: {
// OP_CHECKLOCKTIMEVERIFY = OP_NOP2
if (!(flags & constants.flags.VERIFY_CHECKLOCKTIMEVERIFY)) {
if (flags & constants.flags.VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
if (!(flags & Script.flags.VERIFY_CHECKLOCKTIMEVERIFY)) {
if (flags & Script.flags.VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
throw new ScriptError('DISCOURAGE_UPGRADABLE_NOPS', op, ip);
break;
}
@ -588,15 +656,15 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
locktime = locktime.toNumber();
if (!Script.checkLocktime(locktime, tx, index))
if (!tx.verifyLocktime(index, locktime))
throw new ScriptError('UNSATISFIED_LOCKTIME', op, ip);
break;
}
case opcodes.OP_CHECKSEQUENCEVERIFY: {
// OP_CHECKSEQUENCEVERIFY = OP_NOP3
if (!(flags & constants.flags.VERIFY_CHECKSEQUENCEVERIFY)) {
if (flags & constants.flags.VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
if (!(flags & Script.flags.VERIFY_CHECKSEQUENCEVERIFY)) {
if (flags & Script.flags.VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
throw new ScriptError('DISCOURAGE_UPGRADABLE_NOPS', op, ip);
break;
}
@ -614,10 +682,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
locktime = locktime.toNumber();
if ((locktime & constants.sequence.DISABLE_FLAG) !== 0)
break;
if (!Script.checkSequence(locktime, tx, index))
if (!tx.verifySequence(index, locktime))
throw new ScriptError('UNSATISFIED_LOCKTIME', op, ip);
break;
@ -630,7 +695,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
case opcodes.OP_NOP8:
case opcodes.OP_NOP9:
case opcodes.OP_NOP10: {
if (flags & constants.flags.VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
if (flags & Script.flags.VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
throw new ScriptError('DISCOURAGE_UPGRADABLE_NOPS', op, ip);
break;
}
@ -1086,7 +1151,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
res = Script.checksig(hash, sig, key, flags);
}
if (!res && (flags & constants.flags.VERIFY_NULLFAIL)) {
if (!res && (flags & Script.flags.VERIFY_NULLFAIL)) {
if (sig.length !== 0)
throw new ScriptError('NULLFAIL', op, ip);
}
@ -1116,12 +1181,12 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
n = Script.num(stack.top(-i), flags).toNumber();
ikey2 = n + 2;
if (!(n >= 0 && n <= constants.script.MAX_MULTISIG_PUBKEYS))
if (!(n >= 0 && n <= consensus.MAX_MULTISIG_PUBKEYS))
throw new ScriptError('PUBKEY_COUNT', op, ip);
opCount += n;
if (opCount > constants.script.MAX_OPS)
if (opCount > consensus.MAX_SCRIPT_OPS)
throw new ScriptError('OP_COUNT', op, ip);
i++;
@ -1177,7 +1242,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
}
while (i-- > 1) {
if (!res && (flags & constants.flags.VERIFY_NULLFAIL)) {
if (!res && (flags & Script.flags.VERIFY_NULLFAIL)) {
if (ikey2 === 0 && stack.top(-1).length !== 0)
throw new ScriptError('NULLFAIL', op, ip);
}
@ -1189,7 +1254,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
if (stack.length < 1)
throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
if (flags & constants.flags.VERIFY_NULLDUMMY) {
if (flags & Script.flags.VERIFY_NULLDUMMY) {
if (!Script.isDummy(stack.top(-1)))
throw new ScriptError('SIG_NULLDUMMY', op, ip);
}
@ -1324,7 +1389,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
}
}
if (stack.length + alt.length > constants.script.MAX_STACK)
if (stack.length + alt.length > consensus.MAX_SCRIPT_STACK)
throw new ScriptError('STACK_SIZE', op, ip);
if (state.length !== 0)
@ -1333,71 +1398,6 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
return true;
};
/**
* Verify the nLockTime of a transaction.
* @param {Number} locktime - Locktime to verify against (max=u32).
* @param {TX} tx - Transaction to verify.
* @param {Number} index - Index of input being verified (for IsFinal).
* @returns {Boolean}
*/
Script.checkLocktime = function checkLocktime(locktime, tx, i) {
var threshold = constants.LOCKTIME_THRESHOLD;
if (!(
(tx.locktime < threshold && locktime < threshold)
|| (tx.locktime >= threshold && locktime >= threshold)
)) {
return false;
}
if (locktime > tx.locktime)
return false;
if (tx.inputs[i].sequence === 0xffffffff)
return false;
return true;
};
/**
* Verify the nSequence locktime of a transaction.
* @param {Number} sequence - Locktime to verify against (max=u32).
* @param {TX} tx - Transaction to verify.
* @param {Number} index - Index of input being verified.
* @returns {Boolean}
*/
Script.checkSequence = function checkSequence(sequence, tx, i) {
var txSequence = tx.inputs[i].sequence;
var locktimeMask, txSequenceMasked, sequenceMasked;
if (tx.version < 2)
return false;
if (txSequence & constants.sequence.DISABLE_FLAG)
return false;
locktimeMask = constants.sequence.TYPE_FLAG
| constants.sequence.MASK;
txSequenceMasked = txSequence & locktimeMask;
sequenceMasked = sequence & locktimeMask;
if (!(
(txSequenceMasked < constants.sequence.TYPE_FLAG
&& sequenceMasked < constants.sequence.TYPE_FLAG)
|| (txSequenceMasked >= constants.sequence.TYPE_FLAG
&& sequenceMasked >= constants.sequence.TYPE_FLAG)
)) {
return false;
}
if (sequenceMasked > txSequenceMasked)
return false;
return true;
};
/**
* Cast a big number or Buffer to a bool.
* @see CastToBool
@ -1542,9 +1542,9 @@ Script.prototype.indexOf = function indexOf(data) {
Script.isMinimal = function isMinimal(data, opcode, flags) {
if (flags == null)
flags = constants.flags.STANDARD_VERIFY_FLAGS;
flags = Script.flags.STANDARD_VERIFY_FLAGS;
if (!(flags & constants.flags.VERIFY_MINIMALDATA))
if (!(flags & Script.flags.VERIFY_MINIMALDATA))
return true;
if (!data)
@ -1754,7 +1754,7 @@ Script.fromScripthash = function fromScripthash(hash) {
Script.prototype.fromNulldata = function fromNulldata(flags) {
assert(Buffer.isBuffer(flags));
assert(flags.length <= constants.script.MAX_OP_RETURN, 'Nulldata too large.');
assert(flags.length <= policy.MAX_OP_RETURN, 'Nulldata too large.');
this.push(opcodes.OP_RETURN);
this.push(flags);
this.compile();
@ -1953,7 +1953,7 @@ Script.prototype.isStandard = function isStandard() {
return true;
case scriptTypes.NULLDATA:
if (this.raw.length > constants.script.MAX_OP_RETURN_BYTES)
if (this.raw.length > policy.MAX_OP_RETURN_BYTES)
return false;
return true;
default:
@ -2146,7 +2146,7 @@ Script.prototype.isNulldata = function isNulldata(minimal) {
return true;
if (minimal) {
if (this.raw.length > constants.script.MAX_OP_RETURN_BYTES)
if (this.raw.length > policy.MAX_OP_RETURN_BYTES)
return false;
if (this.raw.length === 2)
@ -2306,7 +2306,7 @@ Script.prototype.isWitnessMasthash = function isWitnessMasthash() {
*/
Script.prototype.isUnspendable = function isUnspendable() {
if (this.raw.length > constants.script.MAX_SIZE)
if (this.raw.length > consensus.MAX_SCRIPT_SIZE)
return true;
return this.raw.length > 0 && this.raw[0] === opcodes.OP_RETURN;
@ -2478,7 +2478,7 @@ Script.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
*/
Script.getCoinbaseHeight = function getCoinbaseHeight(raw) {
var flags = constants.flags.STANDARD_VERIFY_FLAGS;
var flags = Script.flags.STANDARD_VERIFY_FLAGS;
var data, height, op;
if (raw.length === 0)
@ -2694,7 +2694,7 @@ Script.prototype.getNumber = function getNumber(i) {
if (!op || !op.data || op.data.length > 5)
return;
return Script.num(op.data, constants.flags.VERIFY_NONE, 5);
return Script.num(op.data, Script.flags.VERIFY_NONE, 5);
};
/**
@ -2781,17 +2781,17 @@ Script.isDummy = function isDummy(data) {
Script.validateKey = function validateKey(key, flags, version) {
if (flags == null)
flags = constants.flags.STANDARD_VERIFY_FLAGS;
flags = Script.flags.STANDARD_VERIFY_FLAGS;
assert(Buffer.isBuffer(key));
if (flags & constants.flags.VERIFY_STRICTENC) {
if (flags & Script.flags.VERIFY_STRICTENC) {
if (!Script.isKeyEncoding(key))
throw new ScriptError('PUBKEYTYPE');
}
if (version === 1) {
if (flags & constants.flags.VERIFY_WITNESS_PUBKEYTYPE) {
if (flags & Script.flags.VERIFY_WITNESS_PUBKEYTYPE) {
if (!Script.isCompressedEncoding(key))
throw new ScriptError('WITNESS_PUBKEYTYPE');
}
@ -2834,7 +2834,7 @@ Script.isKeyEncoding = function isKeyEncoding(key) {
Script.validateSignature = function validateSignature(sig, flags) {
if (flags == null)
flags = constants.flags.STANDARD_VERIFY_FLAGS;
flags = Script.flags.STANDARD_VERIFY_FLAGS;
assert(Buffer.isBuffer(sig));
@ -2842,19 +2842,19 @@ Script.validateSignature = function validateSignature(sig, flags) {
if (sig.length === 0)
return true;
if ((flags & constants.flags.VERIFY_DERSIG)
|| (flags & constants.flags.VERIFY_LOW_S)
|| (flags & constants.flags.VERIFY_STRICTENC)) {
if ((flags & Script.flags.VERIFY_DERSIG)
|| (flags & Script.flags.VERIFY_LOW_S)
|| (flags & Script.flags.VERIFY_STRICTENC)) {
if (!Script.isSignatureEncoding(sig))
throw new ScriptError('SIG_DER');
}
if (flags & constants.flags.VERIFY_LOW_S) {
if (flags & Script.flags.VERIFY_LOW_S) {
if (!Script.isLowDER(sig))
throw new ScriptError('SIG_HIGH_S');
}
if (flags & constants.flags.VERIFY_STRICTENC) {
if (flags & Script.flags.VERIFY_STRICTENC) {
if (!Script.isHashType(sig))
throw new ScriptError('SIG_HASHTYPE');
}
@ -2887,9 +2887,9 @@ Script.isHashType = function isHashType(sig) {
if (sig.length === 0)
return false;
type = sig[sig.length - 1] & ~constants.hashType.ANYONECANPAY;
type = sig[sig.length - 1] & ~Script.hashType.ANYONECANPAY;
if (!(type >= constants.hashType.ALL && type <= constants.hashType.SINGLE))
if (!(type >= Script.hashType.ALL && type <= Script.hashType.SINGLE))
return false;
return true;
@ -2908,27 +2908,6 @@ Script.isLowDER = function isLowDER(sig) {
return ec.isLowS(sig.slice(0, -1));
};
/**
* Format script code into a human readable-string.
* @param {Array} code
* @returns {String} Human-readable string.
*/
Script.format = function format(code) {
return encoding.formatCode(code);
};
/**
* Format script code into bitcoind asm format.
* @param {Array} code
* @param {Boolean?} decode - Attempt to decode hash types.
* @returns {String} Human-readable string.
*/
Script.formatASM = function formatASM(code, decode) {
return encoding.formatASM(code, decode);
};
/**
* Test the script to see if it contains only push ops.
* Push ops are: OP_1NEGATE, OP_0-OP_16 and all PUSHDATAs.
@ -2985,7 +2964,7 @@ Script.prototype.getSigops = function getSigops(accurate) {
if (accurate && lastOp >= opcodes.OP_1 && lastOp <= opcodes.OP_16)
total += lastOp - 0x50;
else
total += constants.script.MAX_MULTISIG_PUBKEYS;
total += consensus.MAX_MULTISIG_PUBKEYS;
break;
}
@ -3043,7 +3022,7 @@ Script.witnessSigops = function witnessSigops(program, witness, flags) {
var redeem;
if (flags == null)
flags = constants.flags.STANDARD_VERIFY_FLAGS;
flags = Script.flags.STANDARD_VERIFY_FLAGS;
if (program.version === 0) {
if (program.data.length === 20)
@ -3071,12 +3050,12 @@ Script.getWitnessSigops = function getWitnessSigops(input, output, witness, flag
var redeem;
if (flags == null)
flags = constants.flags.STANDARD_VERIFY_FLAGS;
flags = Script.flags.STANDARD_VERIFY_FLAGS;
if ((flags & constants.flags.VERIFY_WITNESS) === 0)
if ((flags & Script.flags.VERIFY_WITNESS) === 0)
return 0;
assert((flags & constants.flags.VERIFY_P2SH) !== 0);
assert((flags & Script.flags.VERIFY_P2SH) !== 0);
if (output.isProgram())
return Script.witnessSigops(output.toProgram(), witness, flags);
@ -3203,9 +3182,9 @@ Script.verify = function verify(input, witness, output, tx, i, value, flags) {
var stack, copy, raw, redeem, hadWitness;
if (flags == null)
flags = constants.flags.STANDARD_VERIFY_FLAGS;
flags = Script.flags.STANDARD_VERIFY_FLAGS;
if (flags & constants.flags.VERIFY_SIGPUSHONLY) {
if (flags & Script.flags.VERIFY_SIGPUSHONLY) {
if (!input.isPushOnly())
throw new ScriptError('SIG_PUSHONLY');
}
@ -3217,7 +3196,7 @@ Script.verify = function verify(input, witness, output, tx, i, value, flags) {
input.execute(stack, flags, tx, i, value, 0);
// Copy the stack for P2SH
if (flags & constants.flags.VERIFY_P2SH)
if (flags & Script.flags.VERIFY_P2SH)
copy = stack.clone();
// Execute the previous output script.
@ -3227,7 +3206,7 @@ Script.verify = function verify(input, witness, output, tx, i, value, flags) {
if (stack.length === 0 || !Script.bool(stack.top(-1)))
throw new ScriptError('EVAL_FALSE');
if ((flags & constants.flags.VERIFY_WITNESS) && output.isProgram()) {
if ((flags & Script.flags.VERIFY_WITNESS) && output.isProgram()) {
hadWitness = true;
// Input script must be empty.
@ -3242,7 +3221,7 @@ Script.verify = function verify(input, witness, output, tx, i, value, flags) {
}
// If the script is P2SH, execute the real output script
if ((flags & constants.flags.VERIFY_P2SH) && output.isScripthash()) {
if ((flags & Script.flags.VERIFY_P2SH) && output.isScripthash()) {
// P2SH can only have push ops in the scriptSig
if (!input.isPushOnly())
throw new ScriptError('SIG_PUSHONLY');
@ -3265,7 +3244,7 @@ Script.verify = function verify(input, witness, output, tx, i, value, flags) {
if (stack.length === 0 || !Script.bool(stack.top(-1)))
throw new ScriptError('EVAL_FALSE');
if ((flags & constants.flags.VERIFY_WITNESS) && redeem.isProgram()) {
if ((flags & Script.flags.VERIFY_WITNESS) && redeem.isProgram()) {
hadWitness = true;
// Input script must be exactly one push of the redeem script.
@ -3281,15 +3260,15 @@ Script.verify = function verify(input, witness, output, tx, i, value, flags) {
}
// Ensure there is nothing left on the stack.
if (flags & constants.flags.VERIFY_CLEANSTACK) {
assert((flags & constants.flags.VERIFY_P2SH) !== 0);
if (flags & Script.flags.VERIFY_CLEANSTACK) {
assert((flags & Script.flags.VERIFY_P2SH) !== 0);
if (stack.length !== 1)
throw new ScriptError('CLEANSTACK');
}
// If we had a witness but no witness program, fail.
if (flags & constants.flags.VERIFY_WITNESS) {
assert((flags & constants.flags.VERIFY_P2SH) !== 0);
if (flags & Script.flags.VERIFY_WITNESS) {
assert((flags & Script.flags.VERIFY_P2SH) !== 0);
if (!hadWitness && witness.items.length > 0)
throw new ScriptError('WITNESS_UNEXPECTED');
}
@ -3316,7 +3295,7 @@ Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i, val
var j, witnessScript, redeem;
assert(program, 'verifyProgram called on non-witness-program.');
assert((flags & constants.flags.VERIFY_WITNESS) !== 0);
assert((flags & Script.flags.VERIFY_WITNESS) !== 0);
if (program.version === 0) {
if (program.data.length === 32) {
@ -3338,7 +3317,7 @@ Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i, val
// Failure on version=0 (bad program data length).
throw new ScriptError('WITNESS_PROGRAM_WRONG_LENGTH');
}
} else if ((flags & constants.flags.VERIFY_MAST) && program.version === 1) {
} else if ((flags & Script.flags.VERIFY_MAST) && program.version === 1) {
return Script.verifyMast(program, stack, output, flags, tx, i);
} else {
// Anyone can spend (we can return true here
@ -3348,14 +3327,14 @@ Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i, val
// we can use the regalar output script which will
// succeed in a block, but fail in the mempool
// due to VERIFY_CLEANSTACK.
if (flags & constants.flags.VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)
if (flags & Script.flags.VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)
throw new ScriptError('DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM');
return true;
}
// Witnesses still have push limits.
for (j = 0; j < stack.length; j++) {
if (stack.get(j).length > constants.script.MAX_PUSH)
if (stack.get(j).length > consensus.MAX_SCRIPT_PUSH)
throw new ScriptError('PUSH_SIZE');
}
@ -3391,7 +3370,7 @@ Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i, va
var j;
assert(program.version === 1);
assert((flags & constants.flags.VERIFY_MAST) !== 0);
assert((flags & Script.flags.VERIFY_MAST) !== 0);
if (stack.length < 4)
throw new ScriptError('INVALID_MAST_STACK');
@ -3417,7 +3396,7 @@ Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i, va
version += 0x100000000;
if (version > 0) {
if (flags & constants.flags.DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)
if (flags & Script.flags.DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)
throw new ScriptError('DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM');
}
@ -3435,7 +3414,7 @@ Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i, va
ops += depth;
if (version === 0) {
if (ops > constants.script.MAX_OPS)
if (ops > consensus.MAX_SCRIPT_OPS)
throw new ScriptError('OP_COUNT');
}
@ -3471,7 +3450,7 @@ Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i, va
for (j = 0; j < subscripts; j++) {
script = stack.top(-(4 + j));
if (version === 0) {
if ((scripts.written + script.length) > constants.script.MAX_SIZE)
if ((scripts.written + script.length) > consensus.MAX_SCRIPT_SIZE)
throw new ScriptError('SCRIPT_SIZE');
}
scriptRoot.writeBytes(crypto.hash256(script));
@ -3491,7 +3470,7 @@ Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i, va
stack.length -= 3 + subscripts;
for (j = 0; j < stack.length; j++) {
if (stack.get(j).length > constants.script.MAX_PUSH)
if (stack.get(j).length > consensus.MAX_SCRIPT_PUSH)
throw new ScriptError('PUSH_SIZE');
}
@ -3523,19 +3502,19 @@ Script.checksig = function checksig(msg, sig, key, flags) {
var high = false;
if (flags == null)
flags = constants.flags.STANDARD_VERIFY_FLAGS;
flags = Script.flags.STANDARD_VERIFY_FLAGS;
// Attempt to normalize the signature
// length before passing to elliptic.
// Note: We only do this for historical data!
// https://github.com/indutny/elliptic/issues/78
if (!((flags & constants.flags.VERIFY_DERSIG)
|| (flags & constants.flags.VERIFY_LOW_S)
|| (flags & constants.flags.VERIFY_STRICTENC))) {
if (!((flags & Script.flags.VERIFY_DERSIG)
|| (flags & Script.flags.VERIFY_LOW_S)
|| (flags & Script.flags.VERIFY_STRICTENC))) {
historical = true;
}
if (!(flags & constants.flags.VERIFY_LOW_S))
if (!(flags & Script.flags.VERIFY_LOW_S))
high = true;
return sigcache.verify(msg, sig.slice(0, -1), key, historical, high);
@ -3612,26 +3591,6 @@ Script.fromRaw = function fromRaw(data, enc) {
return new Script().fromRaw(data);
};
/**
* Calculate the size (including
* the opcode) of a pushdata.
* @param {Number} num - Pushdata data length.
* @returns {Number} size
*/
Script.sizePush = function sizePush(num) {
if (num <= 0x4b)
return 1;
if (num <= 0xff)
return 2;
if (num <= 0xffff)
return 3;
return 5;
};
/**
* Test whether an object a Script.
* @param {Object} obj
@ -3658,12 +3617,4 @@ function sortKeys(keys) {
* Expose
*/
exports = Script;
exports.opcodes = constants.opcodes;
exports.opcodesByVal = constants.opcodesByVal;
exports.types = scriptTypes;
exports.typesByVal = constants.scriptTypesByVal;
exports.flags = constants.flags;
module.exports = exports;
module.exports = Script;

View File

@ -7,7 +7,7 @@
'use strict';
var assert = require('assert');
var ScriptError = require('../btc/errors').ScriptError;
var ScriptError = require('./common').ScriptError;
var EMPTY_ARRAY = new Buffer(0);
/**

View File

@ -7,14 +7,9 @@
'use strict';
var BN = require('bn.js');
var constants = require('../protocol/constants');
var util = require('../utils/util');
var assert = require('assert');
var opcodes = constants.opcodes;
var STACK_FALSE = new Buffer(0);
var STACK_NEGATE = new Buffer([0x81]);
var scriptTypes = constants.scriptTypes;
var BN = require('bn.js');
var util = require('../utils/util');
var Script = require('./script');
var encoding = require('./encoding');
var enc = require('../utils/encoding');
@ -23,6 +18,10 @@ var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var Address = require('../primitives/address');
var Stack = require('./stack');
var opcodes = encoding.opcodes;
var scriptTypes = encoding.types;
var STACK_FALSE = encoding.STACK_FALSE;
var STACK_NEGATE = encoding.STACK_NEGATE;
/**
* Refers to the witness field of segregated witness transactions.
@ -45,10 +44,26 @@ function Witness(options) {
this.fromOptions(options);
}
/**
* Getter to retrieve items length.
* @function
* @name length(get)
* @memberof Witness#
* @returns {Number}
*/
Witness.prototype.__defineGetter__('length', function() {
return this.items.length;
});
/**
* Setter to set items length.
* @function
* @name length(set)
* @memberof Witness#
* @returns {Number}
*/
Witness.prototype.__defineSetter__('length', function(length) {
return this.items.length = length;
});
@ -485,7 +500,7 @@ Witness.prototype.getNumber = function getNumber(i) {
var item = this.items[i];
if (!item || item.length > 5)
return;
return encoding.num(item, constants.flags.VERIFY_NONE, 5);
return encoding.num(item, encoding.flags.VERIFY_NONE, 5);
};
/**

View File

@ -8,7 +8,6 @@
'use strict';
var assert = require('assert');
var constants = require('../protocol/constants');
var murmur3 = require('./murmur3');
var BufferReader = require('./reader');
var StaticWriter = require('./staticwriter');

View File

@ -42,6 +42,156 @@ encoding.MAX_SAFE_INTEGER = 0x1fffffffffffff;
encoding.MAX_SAFE_ADDITION = 0xfffffffffffff;
/**
* An empty buffer.
* @const {Buffer}
* @default
*/
encoding.DUMMY = new Buffer([0]);
/**
* A hash of all zeroes with a `1` at the
* end (used for the SIGHASH_SINGLE bug).
* @const {Buffer}
* @default
*/
encoding.ONE_HASH = new Buffer(
'0100000000000000000000000000000000000000000000000000000000000000',
'hex'
);
/**
* A hash of all zeroes.
* @const {Buffer}
* @default
*/
encoding.ZERO_HASH = new Buffer(
'0000000000000000000000000000000000000000000000000000000000000000',
'hex'
);
/**
* A hash of all 0xff.
* @const {Buffer}
* @default
*/
encoding.MAX_HASH = new Buffer(
'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
'hex'
);
/**
* A hash of all zeroes.
* @const {String}
* @default
*/
encoding.NULL_HASH =
'0000000000000000000000000000000000000000000000000000000000000000';
/**
* A hash of all 0xff.
* @const {String}
* @default
*/
encoding.HIGH_HASH =
'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff';
/**
* A hash of all zeroes.
* @const {Buffer}
* @default
*/
encoding.ZERO_HASH160 = new Buffer(
'0000000000000000000000000000000000000000',
'hex'
);
/**
* A hash of all 0xff.
* @const {String}
* @default
*/
encoding.MAX_HASH160 = new Buffer(
'ffffffffffffffffffffffffffffffffffffffff',
'hex'
);
/**
* A hash of all zeroes.
* @const {String}
* @default
*/
encoding.NULL_HASH160 = '0000000000000000000000000000000000000000';
/**
* A hash of all 0xff.
* @const {String}
* @default
*/
encoding.HIGH_HASH160 = 'ffffffffffffffffffffffffffffffffffffffff';
/**
* A compressed pubkey of all zeroes.
* @const {Buffer}
* @default
*/
encoding.ZERO_KEY = new Buffer(
'000000000000000000000000000000000000000000000000000000000000000000',
'hex'
);
/**
* A 73 byte signature of all zeroes.
* @const {Buffer}
* @default
*/
encoding.ZERO_SIG = new Buffer(''
+ '0000000000000000000000000000000000000000000000000000000000000000'
+ '0000000000000000000000000000000000000000000000000000000000000000'
+ '000000000000000000',
'hex'
);
/**
* A 64 byte signature of all zeroes.
* @const {Buffer}
* @default
*/
encoding.ZERO_SIG64 = new Buffer(''
+ '0000000000000000000000000000000000000000000000000000000000000000'
+ '0000000000000000000000000000000000000000000000000000000000000000',
'hex'
);
/**
* 4 zero bytes.
* @const {Buffer}
* @default
*/
encoding.ZERO_U32 = new Buffer('00000000', 'hex');
/**
* 8 zero bytes.
* @const {Buffer}
* @default
*/
encoding.ZERO_U64 = new Buffer('0000000000000000', 'hex');
/**
* Read uint64 as a js number.
* @private

View File

@ -24,3 +24,79 @@ common.isName = function isName(key) {
return key.length >= 1 && key.length <= 40;
};
/**
* Sort an array of transactions in dependency order.
* @param {TX[]} txs
* @returns {TX[]}
*/
common.sortTX = function sortTX(txs) {
var depMap = {};
var count = {};
var result = [];
var top = [];
var map = txs;
var i, j, tx, hash, input;
var prev, hasDeps, deps;
if (Array.isArray(txs)) {
map = {};
for (i = 0; i < txs.length; i++) {
tx = txs[i];
hash = tx.hash('hex');
map[hash] = tx;
}
}
for (i = 0; i < txs.length; i++) {
tx = txs[i];
hash = tx.hash('hex');
hasDeps = false;
count[hash] = 0;
for (j = 0; j < tx.inputs.length; j++) {
input = tx.inputs[j];
prev = input.prevout.hash;
if (!map[prev])
continue;
count[hash] += 1;
hasDeps = true;
if (!depMap[prev])
depMap[prev] = [];
depMap[prev].push(tx);
}
if (hasDeps)
continue;
top.push(tx);
}
for (i = 0; i < top.length; i++) {
tx = top[i];
hash = tx.hash('hex');
result.push(tx);
deps = depMap[hash];
if (!deps)
continue;
for (j = 0; j < deps.length; j++) {
tx = deps[j];
hash = tx.hash('hex');
if (--count[hash] === 0)
top.push(tx);
}
}
return result;
};

View File

@ -8,7 +8,7 @@
var assert = require('assert');
var util = require('../utils/util');
var constants = require('../protocol/constants');
var encoding = require('../utils/encoding');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var TX = require('../primitives/tx');
@ -23,7 +23,7 @@ function ChainState() {
return new ChainState();
this.startHeight = -1;
this.startHash = constants.NULL_HASH;
this.startHash = encoding.NULL_HASH;
this.height = -1;
this.marked = false;
}
@ -101,7 +101,7 @@ function BlockMeta(hash, height, ts) {
if (!(this instanceof BlockMeta))
return new BlockMeta(hash, height, ts);
this.hash = hash || constants.NULL_HASH;
this.hash = hash || encoding.NULL_HASH;
this.height = height != null ? height : -1;
this.ts = ts || 0;
}
@ -365,7 +365,7 @@ BlockMapRecord.prototype.remove = function remove(hash, wid) {
*/
function TXMapRecord(hash, wids) {
this.hash = hash || constants.NULL_HASH;
this.hash = hash || encoding.NULL_HASH;
this.wids = wids || [];
this.id = TXMapRecord.id++;
}
@ -416,7 +416,7 @@ TXMapRecord.fromRaw = function fromRaw(hash, data) {
*/
function OutpointMapRecord(hash, index, wids) {
this.hash = hash || constants.NULL_HASH;
this.hash = hash || encoding.NULL_HASH;
this.index = index != null ? index : -1;
this.wids = wids || [];
}
@ -465,7 +465,7 @@ OutpointMapRecord.fromRaw = function fromRaw(hash, index, data) {
*/
function PathMapRecord(hash, wids) {
this.hash = hash || constants.NULL_HASH;
this.hash = hash || encoding.NULL_HASH;
this.wids = wids || [];
}

View File

@ -11,16 +11,17 @@ var util = require('../utils/util');
var LRU = require('../utils/lru');
var co = require('../utils/co');
var assert = require('assert');
var constants = require('../protocol/constants');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var btcutils = require('../btc/utils');
var Amount = require('../btc/amount');
var CoinView = require('../coins/coinview');
var Coin = require('../primitives/coin');
var Outpoint = require('../primitives/outpoint');
var records = require('./records');
var layout = require('./layout').txdb;
var encoding = require('../utils/encoding');
var policy = require('../protocol/policy');
var Script = require('../script/script');
var BlockMapRecord = records.BlockMapRecord;
var OutpointMapRecord = records.OutpointMapRecord;
var TXRecord = records.TXRecord;
@ -1556,7 +1557,7 @@ TXDB.prototype.removeConflicts = co(function* removeConflicts(tx, conf) {
*/
TXDB.prototype.verifyInput = co(function* verifyInput(tx, index, coin) {
var flags = constants.flags.MANDATORY_VERIFY_FLAGS;
var flags = Script.flags.MANDATORY_VERIFY_FLAGS;
if (!this.options.verify)
return true;
return yield tx.verifyInputAsync(index, coin, flags);
@ -1672,8 +1673,8 @@ TXDB.prototype.getLocked = function getLocked() {
TXDB.prototype.getAccountHistoryHashes = function getHistoryHashes(account) {
return this.keys({
gte: layout.T(account, constants.NULL_HASH),
lte: layout.T(account, constants.HIGH_HASH),
gte: layout.T(account, encoding.NULL_HASH),
lte: layout.T(account, encoding.HIGH_HASH),
parse: function(key) {
key = layout.Tt(key);
return key[1];
@ -1692,8 +1693,8 @@ TXDB.prototype.getHistoryHashes = function getHistoryHashes(account) {
return this.getAccountHistoryHashes(account);
return this.keys({
gte: layout.t(constants.NULL_HASH),
lte: layout.t(constants.HIGH_HASH),
gte: layout.t(encoding.NULL_HASH),
lte: layout.t(encoding.HIGH_HASH),
parse: layout.tt
});
};
@ -1706,8 +1707,8 @@ TXDB.prototype.getHistoryHashes = function getHistoryHashes(account) {
TXDB.prototype.getAccountPendingHashes = function getAccountPendingHashes(account) {
return this.keys({
gte: layout.P(account, constants.NULL_HASH),
lte: layout.P(account, constants.HIGH_HASH),
gte: layout.P(account, encoding.NULL_HASH),
lte: layout.P(account, encoding.HIGH_HASH),
parse: function(key) {
key = layout.Pp(key);
return key[1];
@ -1726,8 +1727,8 @@ TXDB.prototype.getPendingHashes = function getPendingHashes(account) {
return this.getAccountPendingHashes(account);
return this.keys({
gte: layout.p(constants.NULL_HASH),
lte: layout.p(constants.HIGH_HASH),
gte: layout.p(encoding.NULL_HASH),
lte: layout.p(encoding.HIGH_HASH),
parse: layout.pp
});
};
@ -1740,8 +1741,8 @@ TXDB.prototype.getPendingHashes = function getPendingHashes(account) {
TXDB.prototype.getAccountOutpoints = function getAccountOutpoints(account) {
return this.keys({
gte: layout.C(account, constants.NULL_HASH, 0),
lte: layout.C(account, constants.HIGH_HASH, 0xffffffff),
gte: layout.C(account, encoding.NULL_HASH, 0),
lte: layout.C(account, encoding.HIGH_HASH, 0xffffffff),
parse: function(key) {
key = layout.Cc(key);
return new Outpoint(key[1], key[2]);
@ -1760,8 +1761,8 @@ TXDB.prototype.getOutpoints = function getOutpoints(account) {
return this.getAccountOutpoints(account);
return this.keys({
gte: layout.c(constants.NULL_HASH, 0),
lte: layout.c(constants.HIGH_HASH, 0xffffffff),
gte: layout.c(encoding.NULL_HASH, 0),
lte: layout.c(encoding.HIGH_HASH, 0xffffffff),
parse: function(key) {
key = layout.cc(key);
return new Outpoint(key[0], key[1]);
@ -1785,8 +1786,8 @@ TXDB.prototype.getAccountHeightRangeHashes = function getAccountHeightRangeHashe
var end = options.end || 0xffffffff;
return this.keys({
gte: layout.H(account, start, constants.NULL_HASH),
lte: layout.H(account, end, constants.HIGH_HASH),
gte: layout.H(account, start, encoding.NULL_HASH),
lte: layout.H(account, end, encoding.HIGH_HASH),
limit: options.limit,
reverse: options.reverse,
parse: function(key) {
@ -1822,8 +1823,8 @@ TXDB.prototype.getHeightRangeHashes = function getHeightRangeHashes(account, opt
end = options.end || 0xffffffff;
return this.keys({
gte: layout.h(start, constants.NULL_HASH),
lte: layout.h(end, constants.HIGH_HASH),
gte: layout.h(start, encoding.NULL_HASH),
lte: layout.h(end, encoding.HIGH_HASH),
limit: options.limit,
reverse: options.reverse,
parse: function(key) {
@ -1859,8 +1860,8 @@ TXDB.prototype.getAccountRangeHashes = function getAccountRangeHashes(account, o
var end = options.end || 0xffffffff;
return this.keys({
gte: layout.M(account, start, constants.NULL_HASH),
lte: layout.M(account, end, constants.HIGH_HASH),
gte: layout.M(account, start, encoding.NULL_HASH),
lte: layout.M(account, end, encoding.HIGH_HASH),
limit: options.limit,
reverse: options.reverse,
parse: function(key) {
@ -1896,8 +1897,8 @@ TXDB.prototype.getRangeHashes = function getRangeHashes(account, options) {
end = options.end || 0xffffffff;
return this.keys({
gte: layout.m(start, constants.NULL_HASH),
lte: layout.m(end, constants.HIGH_HASH),
gte: layout.m(start, encoding.NULL_HASH),
lte: layout.m(end, encoding.HIGH_HASH),
limit: options.limit,
reverse: options.reverse,
parse: function(key) {
@ -1971,8 +1972,8 @@ TXDB.prototype.getHistory = function getHistory(account) {
// Fast case
return this.values({
gte: layout.t(constants.NULL_HASH),
lte: layout.t(constants.HIGH_HASH),
gte: layout.t(encoding.NULL_HASH),
lte: layout.t(encoding.HIGH_HASH),
parse: TXRecord.fromRaw
});
};
@ -2040,8 +2041,8 @@ TXDB.prototype.getCredits = function getCredits(account) {
// Fast case
return this.range({
gte: layout.c(constants.NULL_HASH, 0x00000000),
lte: layout.c(constants.HIGH_HASH, 0xffffffff),
gte: layout.c(encoding.NULL_HASH, 0x00000000),
lte: layout.c(encoding.HIGH_HASH, 0xffffffff),
parse: function(key, value) {
var parts = layout.cc(key);
var hash = parts[0];
@ -3029,7 +3030,7 @@ Details.prototype.getFee = function getFee() {
*/
Details.prototype.getRate = function getRate(fee) {
return btcutils.getRate(this.vsize, fee);
return policy.getRate(this.vsize, fee);
};
/**
@ -3127,7 +3128,7 @@ function BlockRecord(hash, height, ts) {
if (!(this instanceof BlockRecord))
return new BlockRecord(hash, height, ts);
this.hash = hash || constants.NULL_HASH;
this.hash = hash || encoding.NULL_HASH;
this.height = height != null ? height : -1;
this.ts = ts || 0;
this.hashes = [];

View File

@ -9,14 +9,12 @@
var assert = require('assert');
var EventEmitter = require('events').EventEmitter;
var constants = require('../protocol/constants');
var Network = require('../protocol/network');
var util = require('../utils/util');
var encoding = require('../utils/encoding');
var Locker = require('../utils/locker');
var co = require('../utils/co');
var crypto = require('../crypto/crypto');
var btcutils = require('../btc/utils');
var BufferReader = require('../utils/reader');
var StaticWriter = require('../utils/staticwriter');
var base58 = require('../utils/base58');
@ -31,6 +29,8 @@ var Output = require('../primitives/output');
var Account = require('./account');
var MasterKey = require('./masterkey');
var LRU = require('../utils/lru');
var policy = require('../protocol/policy');
var consensus = require('../protocol/consensus');
/**
* BIP44 Wallet
@ -81,7 +81,7 @@ function Wallet(db, options) {
this.initialized = false;
this.watchOnly = false;
this.accountDepth = 0;
this.token = constants.ZERO_HASH;
this.token = encoding.ZERO_HASH;
this.tokenDepth = 0;
this.master = new MasterKey();
@ -1473,7 +1473,7 @@ Wallet.prototype.getAccountByAddress = co(function* getAccountByAddress(address)
*/
Wallet.prototype.estimate = co(function* estimate(prev) {
var scale = constants.WITNESS_SCALE_FACTOR;
var scale = consensus.WITNESS_SCALE_FACTOR;
var address = prev.getAddress();
var account = yield this.getAccountByAddress(address);
var size = 0;
@ -1630,15 +1630,15 @@ Wallet.prototype._send = co(function* send(options, passphrase) {
if (!mtx.isSigned())
throw new Error('TX could not be fully signed.');
assert(mtx.getFee() <= constants.tx.MAX_FEE, 'TX exceeds maxfee.');
assert(mtx.getFee() <= MTX.MAX_FEE, 'TX exceeds maxfee.');
tx = mtx.toTX();
// Sanity checks.
if (tx.getSigopsCost(mtx.view) > constants.tx.MAX_SIGOPS_COST)
if (tx.getSigopsCost(mtx.view) > policy.MAX_TX_SIGOPS_COST)
throw new Error('TX exceeds policy sigops.');
if (tx.getWeight() > constants.tx.MAX_WEIGHT)
if (tx.getWeight() > policy.MAX_TX_WEIGHT)
throw new Error('TX exceeds policy weight.');
yield this.db.addTX(tx);
@ -1682,8 +1682,8 @@ Wallet.prototype.increaseFee = co(function* increaseFee(hash, rate, passphrase)
oldFee = tx.getFee(view);
fee = tx.getMinFee(null, rate);
if (fee > constants.tx.MAX_FEE)
fee = constants.tx.MAX_FEE;
if (fee > MTX.MAX_FEE)
fee = MTX.MAX_FEE;
if (oldFee >= fee)
throw new Error('Fee is not increasing.');
@ -1758,7 +1758,7 @@ Wallet.prototype.resend = co(function* resend() {
if (txs.length > 0)
this.logger.info('Rebroadcasting %d transactions.', txs.length);
txs = btcutils.sortTX(txs);
txs = common.sortTX(txs);
for (i = 0; i < txs.length; i++)
yield this.db.send(txs[i]);

View File

@ -15,8 +15,6 @@ var Locker = require('../utils/locker');
var LRU = require('../utils/lru');
var encoding = require('../utils/encoding');
var crypto = require('../crypto/crypto');
var btcutils = require('../btc/utils');
var constants = require('../protocol/constants');
var Network = require('../protocol/network');
var Path = require('./path');
var common = require('./common');
@ -299,8 +297,8 @@ WalletDB.prototype.watch = co(function* watch() {
var iter, item, data, outpoint, items;
iter = this.db.iterator({
gte: layout.p(constants.NULL_HASH),
lte: layout.p(constants.HIGH_HASH)
gte: layout.p(encoding.NULL_HASH),
lte: layout.p(encoding.HIGH_HASH)
});
for (;;) {
@ -321,8 +319,8 @@ WalletDB.prototype.watch = co(function* watch() {
}
iter = this.db.iterator({
gte: layout.o(constants.NULL_HASH, 0),
lte: layout.o(constants.HIGH_HASH, 0xffffffff)
gte: layout.o(encoding.NULL_HASH, 0),
lte: layout.o(encoding.HIGH_HASH, 0xffffffff)
});
for (;;) {
@ -1241,8 +1239,8 @@ WalletDB.prototype.hasPath = function hasPath(wid, hash) {
WalletDB.prototype.getHashes = function getHashes() {
return this.db.keys({
gte: layout.p(constants.NULL_HASH),
lte: layout.p(constants.HIGH_HASH),
gte: layout.p(encoding.NULL_HASH),
lte: layout.p(encoding.HIGH_HASH),
parse: layout.pp
});
};
@ -1254,8 +1252,8 @@ WalletDB.prototype.getHashes = function getHashes() {
WalletDB.prototype.getOutpoints = function getOutpoints() {
return this.db.keys({
gte: layout.o(constants.NULL_HASH, 0),
lte: layout.o(constants.HIGH_HASH, 0xffffffff),
gte: layout.o(encoding.NULL_HASH, 0),
lte: layout.o(encoding.HIGH_HASH, 0xffffffff),
parse: function(key) {
var items = layout.oo(key);
return new Outpoint(items[0], items[1]);
@ -1271,8 +1269,8 @@ WalletDB.prototype.getOutpoints = function getOutpoints() {
WalletDB.prototype.getWalletHashes = function getWalletHashes(wid) {
return this.db.keys({
gte: layout.P(wid, constants.NULL_HASH),
lte: layout.P(wid, constants.HIGH_HASH),
gte: layout.P(wid, encoding.NULL_HASH),
lte: layout.P(wid, encoding.HIGH_HASH),
parse: layout.Pp
});
};
@ -1286,8 +1284,8 @@ WalletDB.prototype.getWalletHashes = function getWalletHashes(wid) {
WalletDB.prototype.getAccountHashes = function getAccountHashes(wid, account) {
return this.db.keys({
gte: layout.r(wid, account, constants.NULL_HASH),
lte: layout.r(wid, account, constants.HIGH_HASH),
gte: layout.r(wid, account, encoding.NULL_HASH),
lte: layout.r(wid, account, encoding.HIGH_HASH),
parse: layout.rr
});
};
@ -1302,8 +1300,8 @@ WalletDB.prototype.getWalletPaths = co(function* getWalletPaths(wid) {
var i, item, items, hash, path;
items = yield this.db.range({
gte: layout.P(wid, constants.NULL_HASH),
lte: layout.P(wid, constants.HIGH_HASH)
gte: layout.P(wid, encoding.NULL_HASH),
lte: layout.P(wid, encoding.HIGH_HASH)
});
for (i = 0; i < items.length; i++) {
@ -1492,7 +1490,7 @@ WalletDB.prototype.resend = co(function* resend() {
txs.push(wtx.tx);
}
txs = btcutils.sortTX(txs);
txs = common.sortTX(txs);
for (i = 0; i < txs.length; i++)
yield this.send(txs[i]);

View File

@ -7,10 +7,10 @@
'use strict';
var constants = require('../protocol/constants');
var KeyRing = require('../primitives/keyring');
var util = require('../utils/util');
var Path = require('./path');
var Script = require('../script/script');
/**
* Represents a key ring which amounts to an address.
@ -132,7 +132,7 @@ WalletKey.prototype.toJSON = function toJSON() {
publicKey: this.publicKey.toString('hex'),
script: this.script ? this.script.toRaw().toString('hex') : null,
program: this.witness ? this.getProgram().toRaw().toString('hex') : null,
type: constants.scriptTypesByVal[this.getType()].toLowerCase(),
type: Script.typesByVal[this.getType()].toLowerCase(),
address: this.getAddress('base58')
};
};

View File

@ -1,5 +1,6 @@
var assert = require('assert');
var constants = require('../lib/protocol/constants');
var encoding = require('../lib/utils/encoding');
var networks = require('../lib/protocol/networks');
var co = require('../lib/utils/co');
var BufferWriter = require('../lib/utils/writer');
@ -65,8 +66,8 @@ var updateVersion = co(function* updateVersion() {
var checkTipIndex = co(function* checkTipIndex() {
var keys = yield db.keys({
gte: pair('p', constants.ZERO_HASH),
lte: pair('p', constants.MAX_HASH)
gte: pair('p', encoding.ZERO_HASH),
lte: pair('p', encoding.MAX_HASH)
});
if (keys.length === 0) {
@ -119,8 +120,8 @@ var reserializeCoins = co(function* reserializeCoins() {
var i, iter, item, hash, old, coins, coin, output;
iter = db.iterator({
gte: pair('c', constants.ZERO_HASH),
lte: pair('c', constants.MAX_HASH),
gte: pair('c', encoding.ZERO_HASH),
lte: pair('c', encoding.MAX_HASH),
values: true
});
@ -171,8 +172,8 @@ var reserializeUndo = co(function* reserializeUndo() {
var iter, item, br, undo;
iter = db.iterator({
gte: pair('u', constants.ZERO_HASH),
lte: pair('u', constants.MAX_HASH),
gte: pair('u', encoding.ZERO_HASH),
lte: pair('u', encoding.MAX_HASH),
values: true
});

View File

@ -9,6 +9,7 @@
var assert = require('assert');
var util = require('../lib/utils/util');
var constants = require('../lib/protocol/constants');
var encoding = require('../lib/utils/encoding');
var Coin = require('../lib/primitives/coin');
var Output = require('../lib/primitives/output');
var BufferReader = require('../lib/utils/reader');
@ -35,7 +36,7 @@ function Coins(options) {
return new Coins(options);
this.version = 1;
this.hash = constants.NULL_HASH;
this.hash = encoding.NULL_HASH;
this.height = -1;
this.coinbase = true;
this.outputs = [];

View File

@ -1,5 +1,6 @@
var assert = require('assert');
var constants = require('../lib/protocol/constants');
var encoding = require('../lib/utils/encoding');
var co = require('../lib/utils/co');
var BufferWriter = require('../lib/utils/writer');
var BufferReader = require('../lib/utils/reader');
@ -62,8 +63,8 @@ function entryFromRaw(data) {
function getEntries() {
return db.values({
gte: pair('e', constants.ZERO_HASH),
lte: pair('e', constants.MAX_HASH),
gte: pair('e', encoding.ZERO_HASH),
lte: pair('e', encoding.MAX_HASH),
parse: entryFromRaw
});
}

View File

@ -1,6 +1,7 @@
var bcoin = require('../');
var walletdb = require('../lib/wallet/walletdb');
var constants = require('../lib/protocol/constants');
var encoding = require('../lib/utils/encoding');
var Path = require('../lib/wallet/path');
var MasterKey = require('../lib/wallet/masterkey');
var Account = require('../lib/wallet/account');
@ -55,8 +56,8 @@ var updatePathMap = co(function* updatePathMap() {
var hash, path, keys, key, ring;
iter = db.iterator({
gte: layout.p(constants.NULL_HASH),
lte: layout.p(constants.HIGH_HASH),
gte: layout.p(encoding.NULL_HASH),
lte: layout.p(encoding.HIGH_HASH),
values: true
});
@ -171,8 +172,8 @@ var updateTXMap = co(function* updateTXMap() {
var iter, item, wallets;
iter = db.iterator({
gte: layout.e(constants.NULL_HASH),
lte: layout.e(constants.HIGH_HASH),
gte: layout.e(encoding.NULL_HASH),
lte: layout.e(encoding.HIGH_HASH),
values: true
});

View File

@ -1,6 +1,7 @@
var assert = require('assert');
var bcoin = require('../');
var constants = require('../lib/protocol/constants');
var encoding = require('../lib/utils/encoding');
var WalletDB = require('../lib/wallet/walletdb');
var TXDB = require('../lib/wallet/txdb');
var BufferWriter = require('../lib/utils/writer');
@ -107,7 +108,7 @@ function fromExtended(data, saveCoins) {
tx.ts = p.readU32();
tx.ps = p.readU32();
if (tx.block === constants.NULL_HASH)
if (tx.block === encoding.NULL_HASH)
tx.block = null;
if (tx.height === 0x7fffffff)

View File

@ -1,6 +1,7 @@
var assert = require('assert');
var bcoin = require('../');
var constants = require('../lib/protocol/constants');
var encoding = require('../lib/utils/encoding');
var BufferWriter = require('../lib/utils/writer');
var BufferReader = require('../lib/utils/reader');
var util = require('../lib/utils/util');
@ -97,8 +98,8 @@ var indexPaths = co(function* indexPaths() {
var i, items, item, wid, index, hash;
items = yield db.range({
gte: new Buffer('5000000000' + constants.NULL_HASH, 'hex'), // P
lte: new Buffer('50ffffffff' + constants.HIGH_HASH, 'hex') // P
gte: new Buffer('5000000000' + encoding.NULL_HASH, 'hex'), // P
lte: new Buffer('50ffffffff' + encoding.HIGH_HASH, 'hex') // P
});
for (i = 0; i < items.length; i++) {
@ -115,8 +116,8 @@ var patchPathMaps = co(function* patchPathMaps() {
var i, items, item, hash, wids;
items = yield db.range({
gte: new Buffer('70' + constants.NULL_HASH, 'hex'), // p
lte: new Buffer('70' + constants.HIGH_HASH, 'hex') // p
gte: new Buffer('70' + encoding.NULL_HASH, 'hex'), // p
lte: new Buffer('70' + encoding.HIGH_HASH, 'hex') // p
});
for (i = 0; i < items.length; i++) {

View File

@ -2,12 +2,13 @@
var BN = require('bn.js');
var util = require('../lib/utils/util');
var constants = require('../lib/protocol/constants');
var consensus = require('../lib/protocol/consensus');
var encoding = require('../lib/utils/encoding');
var TX = require('../lib/primitives/tx');
var Block = require('../lib/primitives/block');
var Script = require('../lib/script/script');
var Opcode = require('../lib/script/opcode');
var opcodes = constants.opcodes;
var opcodes = Script.opcodes;
var main, testnet, regtest, segnet3, segnet4, btcd;
function createGenesisBlock(options) {
@ -32,14 +33,14 @@ function createGenesisBlock(options) {
}
if (!reward)
reward = 50 * constants.COIN;
reward = 50 * consensus.COIN;
tx = new TX({
version: 1,
flag: 1,
inputs: [{
prevout: {
hash: constants.NULL_HASH,
hash: encoding.NULL_HASH,
index: 0xffffffff
},
script: [
@ -58,7 +59,7 @@ function createGenesisBlock(options) {
block = new Block({
version: options.version,
prevBlock: constants.NULL_HASH,
prevBlock: encoding.NULL_HASH,
merkleRoot: tx.hash('hex'),
ts: options.ts,
bits: options.bits,

View File

@ -2,14 +2,15 @@
var fs = require('fs');
var assert = require('assert');
var btcutils = require('../lib/btc/utils');
var Bloom = require('../lib/utils/bloom');
var Block = require('../lib/primitives/block');
var Headers = require('../lib/primitives/headers');
var MerkleBlock = require('../lib/primitives/merkleblock');
var CoinView = require('../lib/coins/coinview');
var Coin = require('../lib/primitives/coin');
var constants = require('../lib/protocol/constants');
var consensus = require('../lib/protocol/consensus');
var Script = require('../lib/script/script');
var encoding = require('../lib/utils/encoding');
var bip152 = require('../lib/net/bip152');
var block300025 = require('./data/block300025.json');
@ -111,8 +112,8 @@ describe('Block', function() {
var reward;
for (;;) {
reward = btcutils.getReward(height, 210000);
assert(reward <= constants.COIN * 50);
reward = consensus.getReward(height, 210000);
assert(reward <= consensus.COIN * 50);
total += reward;
if (reward === 0)
break;
@ -172,7 +173,7 @@ describe('Block', function() {
assert(!block.hasWitness());
assert.equal(block.getWeight(), 1136924);
flags = constants.flags.VERIFY_P2SH | constants.flags.VERIFY_DERSIG;
flags = Script.flags.VERIFY_P2SH | Script.flags.VERIFY_DERSIG;
for (i = 1; i < block.txs.length; i++) {
tx = block.txs[i];
@ -193,7 +194,7 @@ describe('Block', function() {
var block2 = new Block(block);
var ret = {};
block2.hash();
block2.merkleRoot = constants.NULL_HASH;
block2.merkleRoot = encoding.NULL_HASH;
block2._validHeaders = null;
assert(!block2.verify(ret));
assert.equal(ret.reason, 'bad-txnmrklroot');
@ -206,7 +207,7 @@ describe('Block', function() {
var mblock2 = new MerkleBlock(mblock);
var ret = {};
mblock2.hash();
mblock2.merkleRoot = constants.NULL_HASH;
mblock2.merkleRoot = encoding.NULL_HASH;
assert(!mblock2.verify(ret));
assert.equal(ret.reason, 'bad-txnmrklroot');
mblock2.merkleRoot = mblock.merkleRoot;

View File

@ -1,7 +1,6 @@
'use strict';
var assert = require('assert');
var constants = require('../lib/protocol/constants');
var Bloom = require('../lib/utils/bloom');
var murmur3 = require('../lib/utils/murmur3');

View File

@ -2,7 +2,7 @@
var assert = require('assert');
var BN = require('bn.js');
var constants = require('../lib/protocol/constants');
var consensus = require('../lib/protocol/consensus');
var co = require('../lib/utils/co');
var Coin = require('../lib/primitives/coin');
var Script = require('../lib/script/script');
@ -57,7 +57,7 @@ describe('Chain', function() {
it('should open chain and miner', cob(function* () {
miner.mempool = null;
constants.tx.COINBASE_MATURITY = 0;
consensus.COINBASE_MATURITY = 0;
yield node.open();
}));
@ -321,7 +321,7 @@ describe('Chain', function() {
redeemer.addOutput({
script: [
Script.array(new BN(1)),
constants.opcodes.OP_CHECKSEQUENCEVERIFY
Script.opcodes.OP_CHECKSEQUENCEVERIFY
],
value: 10 * 1e8
});
@ -351,7 +351,7 @@ describe('Chain', function() {
redeemer.addOutput({
script: [
Script.array(new BN(2)),
constants.opcodes.OP_CHECKSEQUENCEVERIFY
Script.opcodes.OP_CHECKSEQUENCEVERIFY
],
value: 10 * 1e8
});
@ -377,7 +377,7 @@ describe('Chain', function() {
redeemer.addOutput({
script: [
Script.array(new BN(1)),
constants.opcodes.OP_CHECKSEQUENCEVERIFY
Script.opcodes.OP_CHECKSEQUENCEVERIFY
],
value: 10 * 1e8
});
@ -421,7 +421,7 @@ describe('Chain', function() {
redeemer.addOutput({
script: [
Script.array(new BN(2)),
constants.opcodes.OP_CHECKSEQUENCEVERIFY
Script.opcodes.OP_CHECKSEQUENCEVERIFY
],
value: 10 * 1e8
});
@ -451,7 +451,7 @@ describe('Chain', function() {
}));
it('should cleanup', cob(function* () {
constants.tx.COINBASE_MATURITY = 100;
consensus.COINBASE_MATURITY = 100;
yield node.close();
}));
});

View File

@ -1,17 +1,19 @@
'use strict';
var assert = require('assert');
var constants = require('../lib/protocol/constants');
var consensus = require('../lib/protocol/consensus');
var encoding = require('../lib/utils/encoding');
var co = require('../lib/utils/co');
var Amount = require('../lib/btc/amount');
var MTX = require('../lib/primitives/mtx');
var HTTP = require('../lib/http');
var FullNode = require('../lib/node/fullnode');
var USER_VERSION = require('../package.json').version;
var cob = co.cob;
var dummyInput = {
prevout: {
hash: constants.NULL_HASH,
hash: encoding.NULL_HASH,
index: 0
}
};
@ -36,7 +38,7 @@ describe('HTTP', function() {
this.timeout(15000);
it('should open node', cob(function* () {
constants.tx.COINBASE_MATURITY = 0;
consensus.COINBASE_MATURITY = 0;
yield node.open();
}));
@ -48,8 +50,8 @@ describe('HTTP', function() {
it('should get info', cob(function* () {
var info = yield wallet.client.getInfo();
assert.equal(info.network, node.network.type);
assert.equal(info.version, constants.USER_VERSION);
assert.equal(info.agent, constants.USER_AGENT);
assert.equal(info.version, USER_VERSION);
assert.equal(info.agent, node.pool.userAgent);
assert.equal(typeof info.chain, 'object');
assert.equal(info.chain.height, 0);
}));
@ -155,7 +157,7 @@ describe('HTTP', function() {
}));
it('should cleanup', cob(function* () {
constants.tx.COINBASE_MATURITY = 100;
consensus.COINBASE_MATURITY = 100;
yield wallet.close();
yield node.close();
}));

View File

@ -1,7 +1,7 @@
'use strict';
var assert = require('assert');
var constants = require('../lib/protocol/constants');
var encoding = require('../lib/utils/encoding');
var crypto = require('../lib/crypto/crypto');
var co = require('../lib/utils/co');
var MempoolEntry = require('../lib/mempool/mempoolentry');
@ -15,7 +15,7 @@ var Address = require('../lib/primitives/address');
var Script = require('../lib/script/script');
var Witness = require('../lib/script/witness');
var Block = require('../lib/primitives/block');
var opcodes = constants.opcodes;
var opcodes = Script.opcodes;
var cob = co.cob;
describe('Mempool', function() {
@ -45,7 +45,7 @@ describe('Mempool', function() {
var coin, entry;
if (!prevHash)
prevHash = constants.ONE_HASH.toString('hex');
prevHash = encoding.ONE_HASH.toString('hex');
coin = new Coin({
version: 1,
@ -70,7 +70,7 @@ describe('Mempool', function() {
it('should open mempool', cob(function* () {
yield mempool.open();
chain.state.flags |= constants.flags.VERIFY_WITNESS;
chain.state.flags |= Script.flags.VERIFY_WITNESS;
}));
it('should open walletdb', cob(function* () {
@ -143,7 +143,7 @@ describe('Mempool', function() {
yield w.template(fake);
// Fake signature
fake.inputs[0].script.set(0, constants.ZERO_SIG);
fake.inputs[0].script.set(0, encoding.ZERO_SIG);
fake.inputs[0].script.compile();
fake = fake.toTX();
// balance: 11000
@ -365,7 +365,7 @@ describe('Mempool', function() {
input = {
prevout: {
hash: constants.NULL_HASH,
hash: encoding.NULL_HASH,
index: 0xffffffff
}
};

View File

@ -2,7 +2,6 @@
var fs = require('fs');
var assert = require('assert');
var constants = require('../lib/protocol/constants');
var Network = require('../lib/protocol/network');
var util = require('../lib/utils/util');
var BufferReader = require('../lib/utils/reader');
@ -38,38 +37,38 @@ describe('Protocol', function() {
}
v1 = packets.VersionPacket.fromOptions({
version: constants.VERSION,
services: constants.LOCAL_SERVICES,
version: 300,
services: 1,
ts: network.now(),
remote: new NetAddress(),
local: new NetAddress(),
nonce: util.nonce(),
agent: constants.USER_AGENT,
agent: agent,
height: 0,
noRelay: false
});
packetTest('version', v1, function(payload) {
assert.equal(payload.version, constants.VERSION);
assert.equal(payload.version, 300);
assert.equal(payload.agent, agent);
assert.equal(payload.height, 0);
assert.equal(payload.noRelay, false);
});
v2 = packets.VersionPacket.fromOptions({
version: constants.VERSION,
services: constants.LOCAL_SERVICES,
version: 300,
services: 1,
ts: network.now(),
remote: new NetAddress(),
local: new NetAddress(),
nonce: util.nonce(),
agent: constants.USER_AGENT,
agent: agent,
height: 10,
noRelay: true
});
packetTest('version', v2, function(payload) {
assert.equal(payload.version, constants.VERSION);
assert.equal(payload.version, 300);
assert.equal(payload.agent, agent);
assert.equal(payload.height, 10);
assert.equal(payload.noRelay, true);
@ -80,13 +79,13 @@ describe('Protocol', function() {
hosts = [
new NetAddress({
services: constants.LOCAL_SERVICES,
services: 1,
host: '127.0.0.1',
port: 8333,
ts: util.now()
}),
new NetAddress({
services: constants.LOCAL_SERVICES,
services: 1,
host: '::123:456:789a',
port: 18333,
ts: util.now()
@ -98,12 +97,12 @@ describe('Protocol', function() {
assert.equal(payload.items.length, 2);
assert.equal(typeof payload.items[0].ts, 'number');
assert.equal(payload.items[0].services, constants.LOCAL_SERVICES);
assert.equal(payload.items[0].services, 1);
assert.equal(payload.items[0].host, hosts[0].host);
assert.equal(payload.items[0].port, hosts[0].port);
assert.equal(typeof payload.items[1].ts, 'number');
assert.equal(payload.items[1].services, constants.LOCAL_SERVICES);
assert.equal(payload.items[1].services, 1);
assert.equal(payload.items[1].host, hosts[1].host);
assert.equal(payload.items[1].port, hosts[1].port);
});

View File

@ -5,8 +5,8 @@ var Script = require('../lib/script/script');
var Witness = require('../lib/script/witness');
var Stack = require('../lib/script/stack');
var TX = require('../lib/primitives/tx');
var constants = require('../lib/protocol/constants');
var opcodes = constants.opcodes;
var encoding = require('../lib/utils/encoding');
var opcodes = Script.opcodes;
var scripts = require('./data/script_tests');
@ -256,8 +256,8 @@ describe('Script', function() {
for (i = 0; i < flags.length; i++) {
name = 'VERIFY_' + flags[i];
assert(constants.flags[name] != null, 'Unknown flag.');
flag |= constants.flags[name];
assert(Script.flags[name] != null, 'Unknown flag.');
flag |= Script.flags[name];
}
flags = flag;
@ -273,7 +273,7 @@ describe('Script', function() {
flag: 1,
inputs: [{
prevout: {
hash: constants.NULL_HASH,
hash: encoding.NULL_HASH,
index: 0xffffffff
},
script: new Script([opcodes.OP_0, opcodes.OP_0]),

View File

@ -5,7 +5,7 @@ var assert = require('assert');
var util = require('../lib/utils/util');
var encoding = require('../lib/utils/encoding');
var crypto = require('../lib/crypto/crypto');
var constants = require('../lib/protocol/constants');
var consensus = require('../lib/protocol/consensus');
var Network = require('../lib/protocol/network');
var TX = require('../lib/primitives/tx');
var Block = require('../lib/primitives/block');
@ -59,8 +59,8 @@ function parseTest(data) {
for (i = 0; i < flags.length; i++) {
name = 'VERIFY_' + flags[i];
assert(constants.flags[name] != null, 'Unknown flag.');
flag |= constants.flags[name];
assert(Script.flags[name] != null, 'Unknown flag.');
flag |= Script.flags[name];
}
flags = flag;
@ -163,29 +163,29 @@ describe('TX', function() {
it('should verify non-minimal output' + suffix, function() {
clearCache(tx1.tx, noCache);
assert(tx1.tx.verify(tx1.view, constants.flags.VERIFY_P2SH));
assert(tx1.tx.verify(tx1.view, Script.flags.VERIFY_P2SH));
});
it('should verify tx.version == 0' + suffix, function() {
clearCache(tx2.tx, noCache);
assert(tx2.tx.verify(tx2.view, constants.flags.VERIFY_P2SH));
assert(tx2.tx.verify(tx2.view, Script.flags.VERIFY_P2SH));
});
it('should verify sighash_single bug w/ findanddelete' + suffix, function() {
clearCache(tx3.tx, noCache);
assert(tx3.tx.verify(tx3.view, constants.flags.VERIFY_P2SH));
assert(tx3.tx.verify(tx3.view, Script.flags.VERIFY_P2SH));
});
it('should verify high S value with only DERSIG enabled' + suffix, function() {
var coin = tx4.view.getOutput(tx4.tx.inputs[0]);
var flags = constants.flags.VERIFY_P2SH | constants.flags.VERIFY_DERSIG;
var flags = Script.flags.VERIFY_P2SH | Script.flags.VERIFY_DERSIG;
clearCache(tx4.tx, noCache);
assert(tx4.tx.verifyInput(0, coin, flags));
});
it('should verify the coolest tx ever sent' + suffix, function() {
clearCache(coolest.tx, noCache);
assert(coolest.tx.verify(coolest.view, constants.flags.VERIFY_NONE));
assert(coolest.tx.verify(coolest.view, Script.flags.VERIFY_NONE));
});
it('should parse witness tx properly' + suffix, function() {
@ -344,10 +344,10 @@ describe('TX', function() {
var tx = new TX({
version: 1,
flag: 1,
inputs: [createInput(constants.MAX_MONEY + 1, view)],
inputs: [createInput(consensus.MAX_MONEY + 1, view)],
outputs: [{
script: [],
value: constants.MAX_MONEY
value: consensus.MAX_MONEY
}],
locktime: 0
});
@ -360,10 +360,10 @@ describe('TX', function() {
var tx = new TX({
version: 1,
flag: 1,
inputs: [createInput(constants.MAX_MONEY, view)],
inputs: [createInput(consensus.MAX_MONEY, view)],
outputs: [{
script: [],
value: constants.MAX_MONEY
value: consensus.MAX_MONEY
}],
locktime: 0
});
@ -376,10 +376,10 @@ describe('TX', function() {
var tx = new TX({
version: 1,
flag: 1,
inputs: [createInput(constants.MAX_MONEY, view)],
inputs: [createInput(consensus.MAX_MONEY, view)],
outputs: [{
script: [],
value: constants.MAX_MONEY + 1
value: consensus.MAX_MONEY + 1
}],
locktime: 0
});
@ -392,10 +392,10 @@ describe('TX', function() {
var tx = new TX({
version: 1,
flag: 1,
inputs: [createInput(constants.MAX_MONEY, view)],
inputs: [createInput(consensus.MAX_MONEY, view)],
outputs: [{
script: [],
value: constants.MAX_MONEY
value: consensus.MAX_MONEY
}],
locktime: 0
});
@ -408,7 +408,7 @@ describe('TX', function() {
var tx = new TX({
version: 1,
flag: 1,
inputs: [createInput(constants.MAX_MONEY + 1, view)],
inputs: [createInput(consensus.MAX_MONEY + 1, view)],
outputs: [{
script: [],
value: 0
@ -425,13 +425,13 @@ describe('TX', function() {
version: 1,
flag: 1,
inputs: [
createInput(Math.floor(constants.MAX_MONEY / 2), view),
createInput(Math.floor(constants.MAX_MONEY / 2), view),
createInput(Math.floor(constants.MAX_MONEY / 2), view)
createInput(Math.floor(consensus.MAX_MONEY / 2), view),
createInput(Math.floor(consensus.MAX_MONEY / 2), view),
createInput(Math.floor(consensus.MAX_MONEY / 2), view)
],
outputs: [{
script: [],
value: constants.MAX_MONEY
value: consensus.MAX_MONEY
}],
locktime: 0
});
@ -444,19 +444,19 @@ describe('TX', function() {
var tx = new TX({
version: 1,
flag: 1,
inputs: [createInput(constants.MAX_MONEY, view)],
inputs: [createInput(consensus.MAX_MONEY, view)],
outputs: [
{
script: [],
value: Math.floor(constants.MAX_MONEY / 2)
value: Math.floor(consensus.MAX_MONEY / 2)
},
{
script: [],
value: Math.floor(constants.MAX_MONEY / 2)
value: Math.floor(consensus.MAX_MONEY / 2)
},
{
script: [],
value: Math.floor(constants.MAX_MONEY / 2)
value: Math.floor(consensus.MAX_MONEY / 2)
}
],
locktime: 0
@ -471,9 +471,9 @@ describe('TX', function() {
version: 1,
flag: 1,
inputs: [
createInput(Math.floor(constants.MAX_MONEY / 2), view),
createInput(Math.floor(constants.MAX_MONEY / 2), view),
createInput(Math.floor(constants.MAX_MONEY / 2), view)
createInput(Math.floor(consensus.MAX_MONEY / 2), view),
createInput(Math.floor(consensus.MAX_MONEY / 2), view),
createInput(Math.floor(consensus.MAX_MONEY / 2), view)
],
outputs: [{
script: [],
@ -496,7 +496,7 @@ describe('TX', function() {
version: 1,
flag: 1,
inputs: [
createInput(Math.floor(constants.MAX_MONEY / 2), view)
createInput(Math.floor(consensus.MAX_MONEY / 2), view)
],
outputs: [{
script: [],
@ -519,7 +519,7 @@ describe('TX', function() {
version: 1,
flag: 1,
inputs: [
createInput(Math.floor(constants.MAX_MONEY / 2), view)
createInput(Math.floor(consensus.MAX_MONEY / 2), view)
],
outputs: [{
script: [],
@ -555,7 +555,7 @@ describe('TX', function() {
inputs: [createInput(util.MAX_SAFE_INTEGER, view)],
outputs: [{
script: [],
value: constants.MAX_MONEY
value: consensus.MAX_MONEY
}],
locktime: 0
});
@ -568,7 +568,7 @@ describe('TX', function() {
var tx = new TX({
version: 1,
flag: 1,
inputs: [createInput(constants.MAX_MONEY, view)],
inputs: [createInput(consensus.MAX_MONEY, view)],
outputs: [{
script: [],
value: util.MAX_SAFE_INTEGER
@ -608,7 +608,7 @@ describe('TX', function() {
],
outputs: [{
script: [],
value: constants.MAX_MONEY
value: consensus.MAX_MONEY
}],
locktime: 0
});
@ -621,7 +621,7 @@ describe('TX', function() {
var tx = new TX({
version: 1,
flag: 1,
inputs: [createInput(constants.MAX_MONEY, view)],
inputs: [createInput(consensus.MAX_MONEY, view)],
outputs: [
{
script: [],

View File

@ -3,12 +3,12 @@
var assert = require('assert');
var BN = require('bn.js');
var ec = require('../lib/crypto/ec');
var btcutils = require('../lib/btc/utils');
var base58 = require('../lib/utils/base58');
var encoding = require('../lib/utils/encoding');
var crypto = require('../lib/crypto/crypto');
var schnorr = require('../lib/crypto/schnorr');
var Amount = require('../lib/btc/amount');
var consensus = require('../lib/protocol/consensus');
describe('Utils', function() {
var vectors, signed, unsigned;
@ -53,7 +53,7 @@ describe('Utils', function() {
'hex'
);
assert(btcutils.verifyPOW(hash, bits));
assert(consensus.verifyPOW(hash, bits));
});
it('should convert satoshi to btc', function() {

View File

@ -1,7 +1,7 @@
'use strict';
var assert = require('assert');
var constants = require('../lib/protocol/constants');
var consensus = require('../lib/protocol/consensus');
var util = require('../lib/utils/util');
var encoding = require('../lib/utils/encoding');
var crypto = require('../lib/crypto/crypto');
@ -14,7 +14,7 @@ var KeyRing = require('../lib/primitives/keyring');
var Address = require('../lib/primitives/address');
var Script = require('../lib/script/script');
var HD = require('../lib/hd');
var scriptTypes = constants.scriptTypes;
var scriptTypes = Script.types;
var cob = co.cob;
var KEY1 = 'xprv9s21ZrQH143K3Aj6xQBymM31Zb4BVc7wxqfUhMZrzewdDVCt'
@ -40,7 +40,7 @@ function nextBlock(height) {
height: height,
prevBlock: prev,
ts: globalTime + height,
merkleRoot: constants.NULL_HASH,
merkleRoot: encoding.NULL_HASH,
nonce: 0,
bits: 0
};
@ -72,7 +72,7 @@ describe('Wallet', function() {
this.timeout(5000);
it('should open walletdb', cob(function* () {
constants.tx.COINBASE_MATURITY = 0;
consensus.COINBASE_MATURITY = 0;
yield walletdb.open();
}));
@ -108,11 +108,11 @@ describe('Wallet', function() {
}));
p2pkh = co(function* p2pkh(witness, bullshitNesting) {
var flags = constants.flags.STANDARD_VERIFY_FLAGS;
var flags = Script.flags.STANDARD_VERIFY_FLAGS;
var w, addr, src, tx;
if (witness)
flags |= constants.flags.VERIFY_WITNESS;
flags |= Script.flags.VERIFY_WITNESS;
w = yield walletdb.create({ witness: witness });
@ -261,7 +261,7 @@ describe('Wallet', function() {
// Script inputs but do not sign
yield w.template(fake);
// Fake signature
fake.inputs[0].script.set(0, constants.ZERO_SIG);
fake.inputs[0].script.set(0, encoding.ZERO_SIG);
fake.inputs[0].script.compile();
// balance: 11000
fake = fake.toTX();
@ -410,7 +410,7 @@ describe('Wallet', function() {
// Script inputs but do not sign
// yield w.template(fake);
// Fake signature
// fake.inputs[0].script.set(0, constants.ZERO_SIG);
// fake.inputs[0].script.set(0, encoding.ZERO_SIG);
// fake.inputs[0].script.compile();
// balance: 11000
// fake = fake.toTX();
@ -533,7 +533,7 @@ describe('Wallet', function() {
.addOutput(w1.getAddress(), 5460)
.addOutput(w1.getAddress(), 5460);
t1.addInput(dummy(constants.NULL_HASH));
t1.addInput(dummy(encoding.NULL_HASH));
t1 = t1.toTX();
yield walletdb.addTX(t1);
@ -613,7 +613,7 @@ describe('Wallet', function() {
tx.addOutput(to.getAddress(), 5460);
cost = tx.getOutputValue();
total = cost * constants.tx.MIN_FEE;
total = cost * MTX.MIN_FEE;
coins1 = yield w1.getCoins();
coins2 = yield w2.getCoins();
@ -627,10 +627,6 @@ describe('Wallet', function() {
tx.addInput(coins2[0]);
left = tx.getInputValue() - total;
if (left < constants.tx.DUST_THRESHOLD) {
tx.outputs[tx.outputs.length - 2].value += left;
left = 0;
}
if (left === 0)
tx.outputs.pop();
else
@ -663,14 +659,14 @@ describe('Wallet', function() {
}));
multisig = co(function* multisig(witness, bullshitNesting, cb) {
var flags = constants.flags.STANDARD_VERIFY_FLAGS;
var flags = Script.flags.STANDARD_VERIFY_FLAGS;
var options, w1, w2, w3, receive, b58, addr, paddr, utx, send, change;
var rec = bullshitNesting ? 'nested' : 'receive';
var depth = bullshitNesting ? 'nestedDepth' : 'receiveDepth';
var view, block;
if (witness)
flags |= constants.flags.VERIFY_WITNESS;
flags |= Script.flags.VERIFY_WITNESS;
// Create 3 2-of-3 wallets with our pubkeys as "shared keys"
options = {
@ -1345,6 +1341,6 @@ describe('Wallet', function() {
}));
it('should cleanup', function() {
constants.tx.COINBASE_MATURITY = 100;
consensus.COINBASE_MATURITY = 100;
});
});