refactor: move constants around.
This commit is contained in:
parent
d1a4e53896
commit
5caf6210b9
@ -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) {
|
||||
|
||||
@ -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: [
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
});
|
||||
|
||||
@ -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;
|
||||
|
||||
324
lib/btc/utils.js
324
lib/btc/utils.js
@ -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;
|
||||
};
|
||||
@ -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 = [];
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@ -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
|
||||
});
|
||||
});
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
112
lib/net/common.js
Normal 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;
|
||||
@ -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');
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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();
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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');
|
||||
|
||||
@ -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')
|
||||
};
|
||||
};
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
*/
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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
290
lib/protocol/consensus.js
Normal 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);
|
||||
};
|
||||
@ -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';
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
235
lib/protocol/policy.js
Normal 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);
|
||||
};
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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()
|
||||
+ '>';
|
||||
};
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
/**
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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');
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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 || [];
|
||||
}
|
||||
|
||||
|
||||
@ -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 = [];
|
||||
|
||||
@ -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]);
|
||||
|
||||
@ -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]);
|
||||
|
||||
@ -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')
|
||||
};
|
||||
};
|
||||
|
||||
@ -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
|
||||
});
|
||||
|
||||
|
||||
@ -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 = [];
|
||||
|
||||
@ -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
|
||||
});
|
||||
}
|
||||
|
||||
@ -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
|
||||
});
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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++) {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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');
|
||||
|
||||
|
||||
@ -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();
|
||||
}));
|
||||
});
|
||||
|
||||
@ -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();
|
||||
}));
|
||||
|
||||
@ -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
|
||||
}
|
||||
};
|
||||
|
||||
@ -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);
|
||||
});
|
||||
|
||||
@ -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]),
|
||||
|
||||
@ -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: [],
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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;
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user