refactor. work.
This commit is contained in:
parent
42fbef82ed
commit
df420a4a8b
@ -216,63 +216,79 @@ Block.prototype.getMerkleRoot = function getMerkleRoot() {
|
||||
return merkleTree[merkleTree.length - 1];
|
||||
};
|
||||
|
||||
// This mimics the behavior of CheckBlockHeader()
|
||||
// and CheckBlock() in bitcoin/src/main.cpp.
|
||||
Block.prototype._verify = function _verify() {
|
||||
var uniq = {};
|
||||
var i, tx, hash;
|
||||
|
||||
// Check proof of work matches claimed amount
|
||||
if (!utils.testTarget(this.bits, this.hash()))
|
||||
// Check proof of work
|
||||
if (!utils.testTarget(this.bits, this.hash())) {
|
||||
this.chain.emit('debug', 'Block failed POW test: %s', this.rhash);
|
||||
return false;
|
||||
|
||||
// Check timestamp
|
||||
if (this.ts > utils.now() + 2 * 60 * 60)
|
||||
return false;
|
||||
|
||||
if (this.subtype === 'merkleblock') {
|
||||
if (!this._verifyPartial())
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check timestamp against now + 2 hours
|
||||
if (this.ts > utils.now() + 2 * 60 * 60) {
|
||||
this.chain.emit('debug', 'Block timestamp is too high: %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify the partial merkle tree if we are a merkleblock.
|
||||
if (this.subtype === 'merkleblock') {
|
||||
if (!this._verifyPartial()) {
|
||||
this.chain.emit('debug', 'Block failed merkle test: %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Merkleblock and headers cannot do anymore tests.
|
||||
if (this.subtype !== 'block')
|
||||
return true;
|
||||
|
||||
// Size can't be bigger than MAX_BLOCK_SIZE
|
||||
if (this.txs.length > constants.block.maxSize
|
||||
|| this.size() > constants.block.maxSize) {
|
||||
this.chain.emit('debug', 'Block is too large: %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
|
||||
// First TX must be a coinbase
|
||||
if (!this.txs.length || !this.txs[0].isCoinbase())
|
||||
if (!this.txs.length || !this.txs[0].isCoinbase()) {
|
||||
this.chain.emit('debug', 'Block has no coinbase: %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test all txs
|
||||
for (i = 0; i < this.txs.length; i++) {
|
||||
tx = this.txs[i];
|
||||
|
||||
// The rest of the txs must not be coinbases
|
||||
if (i > 0 && tx.isCoinbase())
|
||||
if (i > 0 && tx.isCoinbase()) {
|
||||
this.chain.emit('debug', 'Block more than one coinbase: %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for duplicate txids
|
||||
hash = tx.hash('hex');
|
||||
if (uniq[hash])
|
||||
if (uniq[hash]) {
|
||||
this.chain.emit('debug', 'Block has duplicate txids: %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
uniq[hash] = true;
|
||||
}
|
||||
|
||||
// Check merkle root
|
||||
if (this.getMerkleRoot() !== this.merkleRoot)
|
||||
if (this.getMerkleRoot() !== this.merkleRoot) {
|
||||
this.chain.emit('debug', 'Block failed merkleroot test: %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
Block.prototype.postVerify = function postVerify() {
|
||||
var flags = {};
|
||||
var prev, height, i, j, tx, cb, sigops, input;
|
||||
var sigops = 0;
|
||||
var prev, height, ts, i, j, tx, cb, input;
|
||||
|
||||
if (this.subtype !== 'block')
|
||||
return true;
|
||||
@ -284,96 +300,121 @@ Block.prototype.postVerify = function postVerify() {
|
||||
return true;
|
||||
|
||||
prev = this.chain.getBlock(this.prevBlock);
|
||||
height = prev.height + 1;
|
||||
|
||||
// Ensure it's not an orphan
|
||||
if (!prev) {
|
||||
console.log('NO PREV: %s', height);
|
||||
this.chain.emit('debug', 'Block has no previous entry: %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
|
||||
height = prev.height + 1;
|
||||
|
||||
// Ensure the timestamp is correct
|
||||
if (this.ts <= prev.getMedianTime()) {
|
||||
console.log('BAD TIME: %s', height);
|
||||
this.chain.emit('debug', 'Block time is lower than median: %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test all txs
|
||||
for (i = 0; i < this.txs.length; i++) {
|
||||
tx = this.txs[i];
|
||||
|
||||
// TXs must be finalized with regards to seq and locktime
|
||||
if (!tx.isFinal(this, prev)) {
|
||||
console.log('IS NOT FINAL: %s', height);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the miner's target is equal to what we expect
|
||||
if (this.bits !== this.chain.target(prev, this)) {
|
||||
console.log('BAD TARGET: %s', height);
|
||||
this.chain.emit('debug', 'Block is using wrong target: %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only allow version 2 blocks (coinbase height)
|
||||
// once the majority of blocks are using it.
|
||||
if (this.version < 2 && prev.isOutdated(2)) {
|
||||
console.log('OUTDATED 2: %s', height);
|
||||
this.chain.emit('debug', 'Block is outdated (v2): %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only allow version 3 blocks (sig validation)
|
||||
// once the majority of blocks are using it.
|
||||
if (this.version < 3 && prev.isOutdated(3)) {
|
||||
console.log('OUTDATED 3: %s', height);
|
||||
this.chain.emit('debug', 'Block is outdated (v3): %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only allow version 4 blocks (checklocktimeverify)
|
||||
// once the majority of blocks are using it.
|
||||
if (this.version < 4 && prev.isOutdated(4)) {
|
||||
console.log('OUTDATED 4: %s', height);
|
||||
this.chain.emit('debug', 'Block is outdated (v4): %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the height contained in the
|
||||
// coinbase is correct.
|
||||
// Only allow version 8 blocks (locktime median past)
|
||||
// once the majority of blocks are using it.
|
||||
// if (this.version < 8 && prev.isOutdated(8)) {
|
||||
// this.chain.emit('debug', 'Block is outdated (v8): %s', this.rhash);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// Make sure the height contained in the coinbase is correct.
|
||||
if (this.version >= 2 && prev.isUpgraded(2)) {
|
||||
cb = bcoin.script.isCoinbase(this.txs[0].inputs[0].script, this);
|
||||
|
||||
// Make sure the coinbase is parseable.
|
||||
if (!cb) {
|
||||
console.log('BAD COINBASE: %s', height);
|
||||
this.chain.emit('debug', 'Block has malformed coinbase: %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure coinbase height is equal to the actual height.
|
||||
if (cb.height !== height) {
|
||||
console.log('BAD COINBASE HEIGHT: %s', height);
|
||||
this.chain.emit('debug', 'Block has bad coinbase height: %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Signature validation is now enforced (bip66)
|
||||
if (this.version >= 3 && prev.isUpgraded(3))
|
||||
flags.strictder = true;
|
||||
if (!(this.version >= 3 && prev.isUpgraded(3)))
|
||||
flags.strictder = false;
|
||||
|
||||
// CHECKLOCKTIMEVERIFY is now usable (bip65)
|
||||
if (this.version >= 4 && prev.isUpgraded(4))
|
||||
flags.cltv = true;
|
||||
if (!(this.version >= 4 && prev.isUpgraded(4)))
|
||||
flags.cltv = false;
|
||||
|
||||
// Check for sigops limits
|
||||
sigops = 0;
|
||||
// Use nLockTime median past (bip113)
|
||||
// https://github.com/btcdrak/bips/blob/d4c9a236ecb947866c61aefb868b284498489c2b/bip-0113.mediawiki
|
||||
// Support version bits:
|
||||
// https://gist.github.com/sipa/bf69659f43e763540550
|
||||
// http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-August/010396.html
|
||||
// if (this.version >= 8 && prev.isUpgraded(8))
|
||||
// flags.locktimeMedian = true;
|
||||
|
||||
// If we are an ancestor of a checkpoint, we can
|
||||
// skip the input verification.
|
||||
if (height < network.checkpoints.lastHeight && !network.checkpoints[height])
|
||||
flags.scriptChecks = false;
|
||||
|
||||
// Get timestamp for tx.isFinal().
|
||||
ts = flags.locktimeMedian
|
||||
? prev.getMedianTime()
|
||||
: this.ts;
|
||||
|
||||
// Check all transactions
|
||||
for (i = 0; i < this.txs.length; i++) {
|
||||
tx = this.txs[i];
|
||||
|
||||
// Transactions must be finalized with
|
||||
// regards to nSequence and nLockTime.
|
||||
if (!tx.isFinal(height, ts)) {
|
||||
this.chain.emit('debug', 'TX is not final: %s (%s)', this.rhash, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for tx sigops limits
|
||||
// Bitcoind does not check for this when accepting
|
||||
// a block even though it probably should.
|
||||
// if (tx.sigops(true) > constants.script.maxTxSigops) {
|
||||
// // Block 71036 abused checksig to
|
||||
// // include a huge number of sigops.
|
||||
// this.chain.emit('debug', 'Block TX has too many sigops: %s', this.rhash);
|
||||
// if (!(network.type === 'main' && height === 71036))
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// Check for block sigops limits
|
||||
// Start counting P2SH sigops once block
|
||||
// timestamps reach March 31st, 2012.
|
||||
if (this.ts >= constants.block.bip16time)
|
||||
@ -382,50 +423,46 @@ Block.prototype.postVerify = function postVerify() {
|
||||
sigops += tx.sigops();
|
||||
|
||||
if (sigops > constants.script.maxBlockSigops) {
|
||||
console.log('BAD SIGOPS: %s', height);
|
||||
this.chain.emit('debug', 'Block has too many sigops: %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// BIP30 - Ensure there are no duplicate txids
|
||||
for (i = 0; i < this.txs.length; i++) {
|
||||
tx = this.txs[i];
|
||||
// BIP30 - Ensure there are no duplicate txids
|
||||
if (this.chain.index[tx.hash('hex')]) {
|
||||
// Blocks 91842 and 91880 created duplicate
|
||||
// txids by carefully crafting the coinbases.
|
||||
if (!(network.type === 'main' && height === 91842 && height === 91880))
|
||||
this.chain.emit('debug', 'Block is overwriting txids: %s', this.rhash);
|
||||
if (!(network.type === 'main' && (height === 91842 || height === 91880)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If we are an ancestor of a checkpoint,
|
||||
// we can skip the input verification.
|
||||
if (height < network.checkpoints.lastHeight && !network.checkpoints[height])
|
||||
flags.noScriptChecks = true;
|
||||
|
||||
// Verify the inputs of every tx (CheckInputs)
|
||||
for (i = 0; i < this.txs.length; i++) {
|
||||
tx = this.txs[i];
|
||||
|
||||
if (tx.isCoinbase())
|
||||
continue;
|
||||
|
||||
if (flags.noScriptChecks)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < tx.inputs.length; j++) {
|
||||
input = tx.inputs[j];
|
||||
|
||||
if (!input.out.tx)
|
||||
// Verify the inputs of every tx (CheckInputs)
|
||||
if (flags.scriptChecks !== false) {
|
||||
if (tx.isCoinbase())
|
||||
continue;
|
||||
|
||||
assert(input.out.tx);
|
||||
for (j = 0; j < tx.inputs.length; j++) {
|
||||
input = tx.inputs[j];
|
||||
|
||||
if (!tx.verify(j, true, flags))
|
||||
return false;
|
||||
// We need the previous output in order
|
||||
// to verify the script.
|
||||
if (!input.out.tx)
|
||||
continue;
|
||||
|
||||
// if (this.chain.isSpent(input.out.hash, input.out.index))
|
||||
// return false;
|
||||
assert(input.out.tx);
|
||||
|
||||
// Verify the script
|
||||
if (!tx.verify(j, true, flags)) {
|
||||
this.chain.emit('debug', 'Block has invalid inputs: %s', this.rhash);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure tx is not double spending an output
|
||||
// if (this.chain.isSpent(input.out.hash, input.out.index)) {
|
||||
// this.chain.emit('debug', 'Block is using spent inputs: %s', this.rhash);
|
||||
// return false;
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -50,6 +50,12 @@ function Chain(options) {
|
||||
|
||||
this.request = new utils.RequestCache();
|
||||
|
||||
this.fromJSON(require('./protocol/preload-full'));
|
||||
this.storage = null;
|
||||
//this.resetHeight(133000);
|
||||
this.resetHeight(145000);
|
||||
|
||||
if (0)
|
||||
this.fromJSON({
|
||||
v: 2,
|
||||
type: 'chain',
|
||||
@ -608,7 +614,10 @@ Chain.prototype.height = function height() {
|
||||
return this.getTip().height;
|
||||
};
|
||||
|
||||
// /home/chjj/bitcoin/src/pow.cpp
|
||||
Chain.prototype.currentTarget = function currentTarget() {
|
||||
return this.target(this.getTip());
|
||||
};
|
||||
|
||||
Chain.prototype.target = function target(last, block) {
|
||||
var powLimit = utils.toCompact(network.powLimit);
|
||||
var ts, first, i;
|
||||
|
||||
@ -139,7 +139,9 @@ Miner.prototype.addBlock = function addBlock(block) {
|
||||
};
|
||||
|
||||
Miner.prototype.addTX = function addTX(tx) {
|
||||
var full = this.index.inputs.every(function(input) {
|
||||
var full, ts;
|
||||
|
||||
full = this.index.inputs.every(function(input) {
|
||||
return !!input.out.tx;
|
||||
});
|
||||
|
||||
@ -160,7 +162,12 @@ Miner.prototype.addTX = function addTX(tx) {
|
||||
if (tx.isCoinbase())
|
||||
return;
|
||||
|
||||
if (!tx.isFinal(this.block, this.last))
|
||||
// Get timestamp for tx.isFinal() - bip113
|
||||
ts = this.block.version === 8
|
||||
? this.last.getMedianTime()
|
||||
: this.block.ts;
|
||||
|
||||
if (!tx.isFinal(this.last.height + 1, ts))
|
||||
return;
|
||||
|
||||
// Deliver me from the block size debate, please
|
||||
|
||||
@ -548,6 +548,10 @@ Peer.prototype.loadHeaders = function loadHeaders(hashes, stop) {
|
||||
this.emit('debug',
|
||||
'Requesting headers packet from %s with getheaders',
|
||||
this.host);
|
||||
this.pool.emit('debug', 'Height: %s, Hash: %s, Stop: %s',
|
||||
this.pool.chain.getHeight(hashes[0]),
|
||||
hashes ? utils.revHex(hashes[0]) : 0,
|
||||
stop ? utils.revHex(stop) : 0);
|
||||
this._write(this.framer.getHeaders(hashes, stop));
|
||||
};
|
||||
|
||||
@ -555,6 +559,10 @@ Peer.prototype.loadBlocks = function loadBlocks(hashes, stop) {
|
||||
this.emit('debug',
|
||||
'Requesting inv packet from %s with getblocks',
|
||||
this.host);
|
||||
this.pool.emit('debug', 'Height: %s, Hash: %s, Stop: %s',
|
||||
this.pool.chain.getHeight(hashes[0]),
|
||||
hashes ? utils.revHex(hashes[0]) : 0,
|
||||
stop ? utils.revHex(stop) : 0);
|
||||
this._write(this.framer.getBlocks(hashes, stop));
|
||||
};
|
||||
|
||||
@ -571,6 +579,13 @@ Peer.prototype.loadMempool = function loadMempool() {
|
||||
this._write(this.framer.mempool());
|
||||
};
|
||||
|
||||
Peer.prototype.reject = function reject(details) {
|
||||
this.emit('debug',
|
||||
'Sending reject packet to %s',
|
||||
this.host);
|
||||
this._write(this.framer.reject(details));
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
@ -42,7 +42,7 @@ function Pool(options) {
|
||||
this.destroyed = false;
|
||||
this.size = options.size || 32;
|
||||
this.parallel = options.parallel || 2000;
|
||||
this.redundancy = options.redundancy || 2;
|
||||
this.redundancy = options.redundancy || 1;
|
||||
this.seeds = options.seeds
|
||||
? options.seeds.slice()
|
||||
: network.seeds.slice();
|
||||
@ -320,10 +320,14 @@ Pool.prototype._addLoader = function _addLoader() {
|
||||
});
|
||||
|
||||
peer.on('merkleblock', function(block) {
|
||||
self._startInterval();
|
||||
self._startTimer();
|
||||
self._handleBlock(block, peer);
|
||||
});
|
||||
|
||||
peer.on('block', function(block) {
|
||||
self._startInterval();
|
||||
self._startTimer();
|
||||
self._handleBlock(block, peer);
|
||||
});
|
||||
|
||||
@ -346,7 +350,6 @@ Pool.prototype._addLoader = function _addLoader() {
|
||||
};
|
||||
|
||||
Pool.prototype._handleHeaders = function _handleHeaders(headers, peer) {
|
||||
var reqs = 0;
|
||||
var i, header, last, block;
|
||||
|
||||
assert(this.options.headers);
|
||||
@ -375,10 +378,8 @@ Pool.prototype._handleHeaders = function _handleHeaders(headers, peer) {
|
||||
if (!block.verify())
|
||||
break;
|
||||
|
||||
if (!this.chain.has(block)) {
|
||||
if (!this.chain.has(block))
|
||||
this._request(this.block.type, block.hash('hex'));
|
||||
reqs++;
|
||||
}
|
||||
|
||||
last = block;
|
||||
}
|
||||
@ -401,15 +402,9 @@ Pool.prototype._handleHeaders = function _handleHeaders(headers, peer) {
|
||||
|
||||
// Reset timeout to avoid killing the loader
|
||||
this._startTimer();
|
||||
|
||||
this.emit('debug',
|
||||
'Requesting %s block packets from %s with getdata',
|
||||
reqs, peer.host
|
||||
);
|
||||
};
|
||||
|
||||
Pool.prototype._handleBlocks = function _handleBlocks(hashes, peer) {
|
||||
var reqs = 0;
|
||||
var i, hash;
|
||||
|
||||
assert(!this.options.headers);
|
||||
@ -435,7 +430,6 @@ Pool.prototype._handleBlocks = function _handleBlocks(hashes, peer) {
|
||||
// Request block if we don't have it
|
||||
if (!this.chain.has(hash)) {
|
||||
this._request(this.block.type, hash);
|
||||
reqs++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -457,11 +451,6 @@ Pool.prototype._handleBlocks = function _handleBlocks(hashes, peer) {
|
||||
|
||||
// Reset timeout to avoid killing the loader
|
||||
this._startTimer();
|
||||
|
||||
this.emit('debug',
|
||||
'Requesting %s block packets from %s with getdata',
|
||||
reqs, peer.host
|
||||
);
|
||||
};
|
||||
|
||||
Pool.prototype._handleInv = function _handleInv(hashes, peer) {
|
||||
@ -490,10 +479,6 @@ Pool.prototype._handleBlock = function _handleBlock(block, peer) {
|
||||
|
||||
var requested = this._response(block);
|
||||
|
||||
// Someone is sending us blocks without us requesting them.
|
||||
if (!requested)
|
||||
return;
|
||||
|
||||
// Emulate bip37 - emit all the "watched" txs
|
||||
if (this.options.fullNode && this.listeners('watched').length > 0) {
|
||||
block.txs.forEach(function(tx) {
|
||||
@ -503,15 +488,21 @@ Pool.prototype._handleBlock = function _handleBlock(block, peer) {
|
||||
}
|
||||
|
||||
// Ignore if we already have
|
||||
if (this.chain.has(block))
|
||||
if (this.chain.has(block)) {
|
||||
this.emit('debug', 'Already have block %s (%s)', block.height, peer.host);
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure the block is valid
|
||||
if (!block.verify()) {
|
||||
this.emit('debug', 'Block verification failed for %s', block.hash('hex'));
|
||||
this.emit('debug', 'Block verification failed for %s (%s)', block.rhash, peer.host);
|
||||
return;
|
||||
}
|
||||
|
||||
// Someone is sending us blocks without us requesting them.
|
||||
if (!requested)
|
||||
this.emit('debug', 'Recieved unrequested block: %s (%s)', block.rhash, peer.host);
|
||||
|
||||
// Resolve orphan chain
|
||||
if (!this.options.headers) {
|
||||
if (!this.chain.hasBlock(block.prevBlock)) {
|
||||
@ -521,10 +512,11 @@ Pool.prototype._handleBlock = function _handleBlock(block, peer) {
|
||||
// the height until later.
|
||||
if (this._addIndex(block, peer))
|
||||
this.emit('pool block', block, peer);
|
||||
peer.loadBlocks(
|
||||
this.peers.load.loadBlocks(
|
||||
this.chain.locatorHashes(),
|
||||
this.chain.getOrphanRoot(block)
|
||||
);
|
||||
this.emit('debug', 'Handled orphan %s (%s)', block.rhash, peer.host);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -786,11 +778,6 @@ Pool.prototype._removePeer = function _removePeer(peer) {
|
||||
if (this.peers.load === peer) {
|
||||
this.emit('debug', 'Removed loader peer (%s).', peer.host);
|
||||
this.peers.load = null;
|
||||
// i = this.seeds.indexOf(peer.host);
|
||||
// if (i === -1)
|
||||
// i = this.seeds.indexOf(peer.host + ':' + peer.port);
|
||||
// if (i !== -1)
|
||||
// this.seeds.splice(i, 1);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1236,6 +1223,9 @@ Pool.prototype._doRequests = function _doRequests() {
|
||||
if (above && below && this.load.hiReached)
|
||||
this._load();
|
||||
|
||||
if (items.length === 0)
|
||||
return;
|
||||
|
||||
if (this.options.multiplePeers) {
|
||||
mapReq = function(item) {
|
||||
return item.start(this.peers.block[i]);
|
||||
@ -1258,6 +1248,12 @@ Pool.prototype._doRequests = function _doRequests() {
|
||||
return item.start(this.peers.load);
|
||||
}, this);
|
||||
|
||||
this.emit('debug',
|
||||
'Requesting %s/%s items from %s with getdata',
|
||||
req.length,
|
||||
this.request.queue.length,
|
||||
this.peers.load.host);
|
||||
|
||||
this.peers.load.getData(req);
|
||||
};
|
||||
|
||||
@ -1506,16 +1502,17 @@ LoadRequest.prototype.start = function start(peer) {
|
||||
var reqType;
|
||||
|
||||
assert(!this.active);
|
||||
assert(!this.timer);
|
||||
assert(!this.peer);
|
||||
|
||||
this.active = true;
|
||||
this.pool.request.active++;
|
||||
|
||||
assert(!this.timer);
|
||||
this.timer = setTimeout(function() {
|
||||
self.timer = null;
|
||||
self.retry();
|
||||
}, this.pool.requestTimeout);
|
||||
// this.timer = setTimeout(function() {
|
||||
// self.timer = null;
|
||||
// self.retry();
|
||||
// }, this.pool.requestTimeout);
|
||||
|
||||
assert(!this.peer);
|
||||
this.peer = peer;
|
||||
this.peer.once('close', this.onclose);
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
var bcoin = require('../../bcoin');
|
||||
var bn = require('bn.js');
|
||||
var utils = bcoin.utils;
|
||||
|
||||
var i;
|
||||
@ -219,3 +220,7 @@ exports.zeroHash = utils.toArray(
|
||||
|
||||
exports.userVersion = require('../../../package.json').version;
|
||||
exports.userAgent = '/bcoin:' + exports.userVersion + '/';
|
||||
|
||||
exports.coin = new bn(10000000).muln(10);
|
||||
exports.cent = new bn(1000000);
|
||||
exports.maxMoney = new bn(21000000).mul(exports.coin);
|
||||
|
||||
@ -357,6 +357,32 @@ Framer.prototype.merkleBlock = function merkleBlock(block) {
|
||||
return this.packet('merkleblock', Framer.block(block, 'merkleblock'));
|
||||
};
|
||||
|
||||
Framer.prototype.reject = function reject(details) {
|
||||
var p = [];
|
||||
var off = 0;
|
||||
|
||||
var message = details.message || '';
|
||||
var ccode = constants.reject[details.ccode] || constants.reject.malformed;
|
||||
var reason = details.reason || '';
|
||||
var data = details.data || [];
|
||||
|
||||
off += utils.writeIntv(p, message.length, off);
|
||||
utils.writeAscii(p, message, off);
|
||||
off += message.length;
|
||||
|
||||
p[off] = ccode;
|
||||
off++;
|
||||
|
||||
off += utils.writeIntv(p, reason.length, off);
|
||||
utils.writeAscii(p, reason, off);
|
||||
off += reason.length;
|
||||
|
||||
utils.copy(data, p, off, true);
|
||||
off += data.length;
|
||||
|
||||
return this.packet('reject', p);
|
||||
};
|
||||
|
||||
Framer.prototype.addr = function addr(peers) {
|
||||
var p = [];
|
||||
var off = 0;
|
||||
|
||||
@ -295,12 +295,12 @@ Parser.prototype.parseBlock = function parseBlock(p) {
|
||||
off = result.off;
|
||||
totalTX = result.r;
|
||||
|
||||
if (p.length >= off + 10) {
|
||||
for (i = 0; i < totalTX; i++) {
|
||||
tx = this.parseTX(p.slice(off));
|
||||
off += tx._off;
|
||||
txs.push(tx);
|
||||
}
|
||||
for (i = 0; i < totalTX; i++) {
|
||||
tx = this.parseTX(p.slice(off));
|
||||
if (!tx)
|
||||
return this._error('Invalid tx count for block');
|
||||
off += tx._off;
|
||||
txs.push(tx);
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@ -686,8 +686,13 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
||||
if (!constants.hashTypeByVal[type & 0x1f])
|
||||
return false;
|
||||
|
||||
if (!script.isValidSig(sig))
|
||||
return false;
|
||||
if (flags.strictder !== false) {
|
||||
if (!script.isValidSig(sig))
|
||||
return false;
|
||||
} else {
|
||||
if (!script.isSig(sig))
|
||||
return false;
|
||||
}
|
||||
|
||||
subscript = script.subscript(s, lastSep);
|
||||
hash = tx.subscriptHash(index, subscript, type);
|
||||
@ -743,8 +748,13 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
||||
if (!constants.hashTypeByVal[type & 0x1f])
|
||||
return false;
|
||||
|
||||
if (!script.isValidSig(sig))
|
||||
return false;
|
||||
if (flags.strictder !== false) {
|
||||
if (!script.isValidSig(sig))
|
||||
return false;
|
||||
} else {
|
||||
if (!script.isSig(sig))
|
||||
return false;
|
||||
}
|
||||
|
||||
hash = tx.subscriptHash(index, subscript, type);
|
||||
|
||||
@ -775,6 +785,9 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
||||
}
|
||||
case 'checklocktimeverify': {
|
||||
// OP_CHECKLOCKTIMEVERIFY = OP_NOP2
|
||||
if (flags.cltv === false)
|
||||
break;
|
||||
|
||||
if (!tx || stack.length === 0)
|
||||
return false;
|
||||
|
||||
@ -1298,6 +1311,16 @@ script.isCoinbase = function isCoinbase(s, block) {
|
||||
return coinbase;
|
||||
};
|
||||
|
||||
script.isSig = function isSig(sig, allowZero) {
|
||||
if (!Array.isArray(sig))
|
||||
return false;
|
||||
|
||||
if (allowZero && sig.length === 0)
|
||||
return true;
|
||||
|
||||
return 9 <= sig.length && sig.length <= 73;
|
||||
};
|
||||
|
||||
// https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki
|
||||
/**
|
||||
* A canonical signature exists of: <30> <total len> <02> <len R> <R> <02> <len S> <S> <hashtype>
|
||||
|
||||
@ -838,29 +838,29 @@ TX.prototype.funds = function funds(side) {
|
||||
// Used for postVerify/ContextualBlockCheck and miner isFinalTx call.
|
||||
// BIP113 will require that time-locked transactions have nLockTime set to
|
||||
// less than the median time of the previous block they're contained in.
|
||||
TX.prototype.isFinal = function isFinal(block, prev) {
|
||||
TX.prototype.isFinalBlock = function isFinalBlock(block, prev, useMedian) {
|
||||
var height = prev.height + 1;
|
||||
var ts = this.locktimeMedian ? prev.getMedianTime() : block.ts;
|
||||
return this._isFinal(height, ts);
|
||||
var ts = useMedian ? prev.getMedianTime() : block.ts;
|
||||
return this.isFinal(height, ts);
|
||||
};
|
||||
|
||||
// Used in AcceptToMemoryPool
|
||||
TX.prototype.isFinalAccept = function isFinalAccept() {
|
||||
TX.prototype.isFinalMempool = function isFinalMempool(useMedian) {
|
||||
var height = this.chain.height() + 1;
|
||||
var ts = this.lockTimeMedian
|
||||
var ts = useMedian
|
||||
? this.chain.getTip().getMedianTime()
|
||||
: utils.now();
|
||||
return this._isFinalTx(height, ts);
|
||||
return this.isFinal(height, ts);
|
||||
};
|
||||
|
||||
// Used in the original bitcoind code for AcceptBlock
|
||||
TX.prototype._isFinalOriginal = function _isFinalOriginal(block) {
|
||||
TX.prototype.isFinalLegacy = function isFinalLegacy(block) {
|
||||
var ts = block ? block.ts : utils.now();
|
||||
var height = this.chain.height();
|
||||
return this._isFinalTx(height, ts);
|
||||
return this.isFinal(height, ts);
|
||||
};
|
||||
|
||||
TX.prototype._isFinal = function _isFinal(height, ts) {
|
||||
TX.prototype.isFinal = function isFinal(height, ts) {
|
||||
var threshold = constants.locktimeThreshold;
|
||||
var i;
|
||||
|
||||
|
||||
@ -81,7 +81,7 @@ function Wallet(options, passphrase) {
|
||||
this.m = 1;
|
||||
this.n = 1;
|
||||
|
||||
this.prefix = 'bt/' + this.getOwnAddress() + '/';
|
||||
this.prefix = 'bt/wallet/' + this.getOwnAddress() + '/';
|
||||
|
||||
this.multisig(options.multisig || {});
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user