more chainblock refactoring.
This commit is contained in:
parent
27214676bc
commit
9f56efe0d7
@ -1848,7 +1848,7 @@ Chain.prototype.getTarget = function getTarget(last, block) {
|
||||
return powLimit;
|
||||
|
||||
i = 1;
|
||||
prev = last.previous;
|
||||
prev = last.ancestors;
|
||||
while (prev[i]
|
||||
&& last.height % network.powDiffInterval !== 0
|
||||
&& last.bits === powLimit) {
|
||||
@ -1861,7 +1861,7 @@ Chain.prototype.getTarget = function getTarget(last, block) {
|
||||
}
|
||||
|
||||
// Back 2 weeks
|
||||
first = last.previous[network.powDiffInterval - 1];
|
||||
first = last.ancestors[network.powDiffInterval - 1];
|
||||
|
||||
assert(first);
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@ function ChainBlock(chain, data, prev) {
|
||||
return new ChainBlock(chain, data);
|
||||
|
||||
this.chain = chain;
|
||||
|
||||
this.hash = data.hash;
|
||||
this.version = data.version;
|
||||
this.prevBlock = data.prevBlock;
|
||||
@ -32,14 +33,9 @@ function ChainBlock(chain, data, prev) {
|
||||
this.nonce = data.nonce;
|
||||
this.height = data.height;
|
||||
this.chainwork = data.chainwork || this.getChainwork(prev);
|
||||
|
||||
assert(this.chainwork);
|
||||
|
||||
this.previous = [];
|
||||
this.ancestors = [];
|
||||
}
|
||||
|
||||
ChainBlock.BLOCK_SIZE = 116;
|
||||
|
||||
ChainBlock.prototype.getProof = function getProof() {
|
||||
var target = utils.fromCompact(this.bits);
|
||||
if (target.isNeg() || target.cmpn(0) === 0)
|
||||
@ -55,104 +51,6 @@ ChainBlock.prototype.isGenesis = function isGenesis() {
|
||||
return this.hash === network.genesis.hash;
|
||||
};
|
||||
|
||||
ChainBlock.prototype.toJSON = function toJSON() {
|
||||
return {
|
||||
hash: this.hash,
|
||||
version: this.version,
|
||||
prevBlock: this.prevBlock,
|
||||
merkleRoot: this.merkleRoot,
|
||||
ts: this.ts,
|
||||
bits: this.bits,
|
||||
nonce: this.nonce,
|
||||
height: this.height
|
||||
};
|
||||
};
|
||||
|
||||
ChainBlock.fromJSON = function fromJSON(chain, json) {
|
||||
return new ChainBlock(chain, json);
|
||||
};
|
||||
|
||||
ChainBlock.prototype.toRaw = function toRaw() {
|
||||
var res = new Buffer(ChainBlock.BLOCK_SIZE);
|
||||
|
||||
utils.write32(res, this.version, 0);
|
||||
utils.copy(new Buffer(this.prevBlock, 'hex'), res, 4);
|
||||
utils.copy(new Buffer(this.merkleRoot, 'hex'), res, 36);
|
||||
utils.writeU32(res, this.ts, 68);
|
||||
utils.writeU32(res, this.bits, 72);
|
||||
utils.writeU32(res, this.nonce, 76);
|
||||
utils.writeU32(res, this.height, 80);
|
||||
utils.copy(new Buffer(this.chainwork.toArray('le', 32)), res, 84);
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
ChainBlock.fromRaw = function fromRaw(chain, p) {
|
||||
return new ChainBlock(chain, {
|
||||
hash: utils.toHex(utils.dsha256(p.slice(0, 80))),
|
||||
version: utils.read32(p, 0),
|
||||
prevBlock: utils.toHex(p.slice(4, 36)),
|
||||
merkleRoot: utils.toHex(p.slice(36, 68)),
|
||||
ts: utils.readU32(p, 68),
|
||||
bits: utils.readU32(p, 72),
|
||||
nonce: utils.readU32(p, 76),
|
||||
height: utils.readU32(p, 80),
|
||||
chainwork: new bn(p.slice(84, 116), 'le')
|
||||
});
|
||||
};
|
||||
|
||||
ChainBlock.prototype.getMedianTimeAsync = function getMedianTime(callback) {
|
||||
var self = this;
|
||||
var median = [];
|
||||
var timeSpan = constants.block.medianTimespan;
|
||||
var i = 0;
|
||||
|
||||
(function next(err, entry) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!entry || i >= timeSpan) {
|
||||
median = median.sort();
|
||||
return callback(null, median[median.length / 2 | 0]);
|
||||
}
|
||||
|
||||
median[i] = entry.ts;
|
||||
i++;
|
||||
|
||||
entry.getPrevious(next);
|
||||
})(null, this);
|
||||
};
|
||||
|
||||
ChainBlock.prototype.isOutdatedAsync = function isOutdated(version, callback) {
|
||||
return this.isSuperMajority(version, network.block.majorityRejectOutdated, callback);
|
||||
};
|
||||
|
||||
ChainBlock.prototype.isUpgradedAsync = function isUpgraded(version, callback) {
|
||||
return this.isSuperMajority(version, network.block.majorityEnforceUpgrade, callback);
|
||||
};
|
||||
|
||||
ChainBlock.prototype.isSuperMajorityAsync = function isSuperMajority(version, required, callback) {
|
||||
var self = this;
|
||||
var found = 0;
|
||||
var majorityWindow = network.block.majorityWindow;
|
||||
var i = 0;
|
||||
|
||||
(function next(err, entry) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!entry || i >= majorityWindow || found >= required)
|
||||
return callback(null, found >= required);
|
||||
|
||||
if (entry.version >= version)
|
||||
found++;
|
||||
|
||||
i++;
|
||||
|
||||
entry.getPrevious(next);
|
||||
})(null, this);
|
||||
};
|
||||
|
||||
ChainBlock.prototype.ensureAncestors = function ensureAncestors(callback) {
|
||||
var majorityWindow = network.block.majorityWindow;
|
||||
var medianTimespan = constants.block.medianTimespan;
|
||||
@ -161,7 +59,7 @@ ChainBlock.prototype.ensureAncestors = function ensureAncestors(callback) {
|
||||
var max = Math.max(majorityWindow, medianTimespan);
|
||||
if ((this.height + 1) % powDiffInterval === 0 || allowMinDiff)
|
||||
max = Math.max(max, powDiffInterval);
|
||||
assert(this.previous.length === 0);
|
||||
assert(this.ancestors.length === 0);
|
||||
return this.alloc(max, callback);
|
||||
};
|
||||
|
||||
@ -169,16 +67,16 @@ ChainBlock.prototype.alloc = function alloc(max, callback) {
|
||||
var self = this;
|
||||
var i;
|
||||
|
||||
return this.getAncestors(max, function(err, previous) {
|
||||
return this.getAncestors(max, function(err, ancestors) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
assert(previous);
|
||||
assert(ancestors);
|
||||
|
||||
self.previous.length = 0;
|
||||
self.ancestors.length = 0;
|
||||
|
||||
for (i = 0; i < previous.length; i++)
|
||||
self.previous.push(previous[i]);
|
||||
for (i = 0; i < ancestors.length; i++)
|
||||
self.ancestors.push(ancestors[i]);
|
||||
|
||||
return callback();
|
||||
});
|
||||
@ -187,26 +85,26 @@ ChainBlock.prototype.alloc = function alloc(max, callback) {
|
||||
ChainBlock.prototype.getAncestors = function getAncestors(max, callback) {
|
||||
var self = this;
|
||||
var entry = this;
|
||||
var previous = this.previous.slice();
|
||||
var ancestors = this.ancestors.slice();
|
||||
|
||||
if (max === 0)
|
||||
return callback(null, []);
|
||||
|
||||
if (previous.length)
|
||||
entry = previous.pop();
|
||||
if (ancestors.length)
|
||||
entry = ancestors.pop();
|
||||
|
||||
assert(utils.isFinite(max));
|
||||
|
||||
// Try to do this iteratively and synchronously
|
||||
// so we don't have to wait on nextTicks.
|
||||
for (;;) {
|
||||
previous.push(entry);
|
||||
ancestors.push(entry);
|
||||
|
||||
if (previous.length >= max)
|
||||
return callback(null, previous);
|
||||
if (ancestors.length >= max)
|
||||
return callback(null, ancestors);
|
||||
|
||||
if (!this.chain.db.hasCache(entry.prevBlock)) {
|
||||
previous.pop();
|
||||
ancestors.pop();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -218,19 +116,19 @@ ChainBlock.prototype.getAncestors = function getAncestors(max, callback) {
|
||||
return callback(err);
|
||||
|
||||
if (!entry)
|
||||
return callback(null, previous);
|
||||
return callback(null, ancestors);
|
||||
|
||||
previous.push(entry);
|
||||
ancestors.push(entry);
|
||||
|
||||
if (previous.length >= max)
|
||||
return callback(null, previous);
|
||||
if (ancestors.length >= max)
|
||||
return callback(null, ancestors);
|
||||
|
||||
entry.getPrevious(next);
|
||||
})(null, entry);
|
||||
};
|
||||
|
||||
ChainBlock.prototype.free = function free() {
|
||||
this.previous.length = 0;
|
||||
this.ancestors.length = 0;
|
||||
};
|
||||
|
||||
ChainBlock.prototype.isMainChain = function isMainChain(callback) {
|
||||
@ -264,14 +162,14 @@ ChainBlock.prototype.getAncestorByHeight = function getAncestorByHeight(height,
|
||||
|
||||
ChainBlock.prototype.getAncestor = function getAncestor(index, callback) {
|
||||
assert(index >= 0);
|
||||
return this.getAncestors(index + 1, function(err, previous) {
|
||||
return this.getAncestors(index + 1, function(err, ancestors) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (previous.length !== index + 1)
|
||||
if (ancestors.length !== index + 1)
|
||||
return callback();
|
||||
|
||||
return callback(null, previous[previous.length - 1]);
|
||||
return callback(null, ancestors[ancestors.length - 1]);
|
||||
});
|
||||
};
|
||||
|
||||
@ -292,16 +190,16 @@ ChainBlock.prototype.getNext = function getNext(callback) {
|
||||
});
|
||||
};
|
||||
|
||||
ChainBlock.prototype.getMedianTime = function getMedianTime(previous) {
|
||||
ChainBlock.prototype.getMedianTime = function getMedianTime(ancestors) {
|
||||
var entry = this;
|
||||
var median = [];
|
||||
var timeSpan = constants.block.medianTimespan;
|
||||
var i;
|
||||
|
||||
if (!previous)
|
||||
previous = this.previous;
|
||||
if (!ancestors)
|
||||
ancestors = this.ancestors;
|
||||
|
||||
for (i = 0; i < timeSpan && entry; i++, entry = previous[i])
|
||||
for (i = 0; i < timeSpan && entry; i++, entry = ancestors[i])
|
||||
median.push(entry.ts);
|
||||
|
||||
median = median.sort();
|
||||
@ -309,27 +207,27 @@ ChainBlock.prototype.getMedianTime = function getMedianTime(previous) {
|
||||
return median[median.length / 2 | 0];
|
||||
};
|
||||
|
||||
ChainBlock.prototype.isOutdated = function isOutdated(version, previous) {
|
||||
return this.isSuperMajority(version, network.block.majorityRejectOutdated, previous);
|
||||
ChainBlock.prototype.isOutdated = function isOutdated(version, ancestors) {
|
||||
return this.isSuperMajority(version, network.block.majorityRejectOutdated, ancestors);
|
||||
};
|
||||
|
||||
ChainBlock.prototype.isUpgraded = function isUpgraded(version, previous) {
|
||||
return this.isSuperMajority(version, network.block.majorityEnforceUpgrade, previous);
|
||||
ChainBlock.prototype.isUpgraded = function isUpgraded(version, ancestors) {
|
||||
return this.isSuperMajority(version, network.block.majorityEnforceUpgrade, ancestors);
|
||||
};
|
||||
|
||||
ChainBlock.prototype.isSuperMajority = function isSuperMajority(version, required, previous) {
|
||||
ChainBlock.prototype.isSuperMajority = function isSuperMajority(version, required, ancestors) {
|
||||
var entry = this;
|
||||
var found = 0;
|
||||
var majorityWindow = network.block.majorityWindow;
|
||||
var i;
|
||||
|
||||
if (!previous)
|
||||
previous = this.previous;
|
||||
if (!ancestors)
|
||||
ancestors = this.ancestors;
|
||||
|
||||
for (i = 0; i < majorityWindow && found < required && entry; i++) {
|
||||
if (entry.version >= version)
|
||||
found++;
|
||||
entry = previous[i + 1];
|
||||
entry = ancestors[i + 1];
|
||||
}
|
||||
|
||||
return found >= required;
|
||||
@ -338,24 +236,69 @@ ChainBlock.prototype.isSuperMajority = function isSuperMajority(version, require
|
||||
ChainBlock.prototype.getMedianTimeAsync = function getMedianTimeAsync(callback) {
|
||||
var self = this;
|
||||
|
||||
return this.getAncestors(constants.block.medianTimespan, function(err, previous) {
|
||||
return this.getAncestors(constants.block.medianTimespan, function(err, ancestors) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return callback(null, self.getMedianTime(previous));
|
||||
return callback(null, self.getMedianTime(ancestors));
|
||||
});
|
||||
};
|
||||
|
||||
ChainBlock.prototype.toRaw = function toRaw() {
|
||||
var res = new Buffer(116);
|
||||
|
||||
utils.write32(res, this.version, 0);
|
||||
utils.copy(new Buffer(this.prevBlock, 'hex'), res, 4);
|
||||
utils.copy(new Buffer(this.merkleRoot, 'hex'), res, 36);
|
||||
utils.writeU32(res, this.ts, 68);
|
||||
utils.writeU32(res, this.bits, 72);
|
||||
utils.writeU32(res, this.nonce, 76);
|
||||
utils.writeU32(res, this.height, 80);
|
||||
utils.copy(new Buffer(this.chainwork.toArray('le', 32)), res, 84);
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
ChainBlock.fromRaw = function fromRaw(chain, p) {
|
||||
return new ChainBlock(chain, {
|
||||
hash: utils.toHex(utils.dsha256(p.slice(0, 80))),
|
||||
version: utils.read32(p, 0),
|
||||
prevBlock: utils.toHex(p.slice(4, 36)),
|
||||
merkleRoot: utils.toHex(p.slice(36, 68)),
|
||||
ts: utils.readU32(p, 68),
|
||||
bits: utils.readU32(p, 72),
|
||||
nonce: utils.readU32(p, 76),
|
||||
height: utils.readU32(p, 80),
|
||||
chainwork: new bn(p.slice(84, 116), 'le')
|
||||
});
|
||||
};
|
||||
|
||||
ChainBlock.prototype.toJSON = function toJSON() {
|
||||
return {
|
||||
version: this.version,
|
||||
hash: utils.revHex(this.hash),
|
||||
prevBlock: utils.revHex(this.prevBlock),
|
||||
merkleRoot: utils.revHex(this.merkleRoot),
|
||||
ts: this.ts,
|
||||
bits: this.bits,
|
||||
nonce: this.nonce,
|
||||
height: this.height,
|
||||
chainwork: this.chainwork.toString('hex')
|
||||
};
|
||||
};
|
||||
|
||||
ChainBlock.fromJSON = function fromJSON(chain, json) {
|
||||
json.hash = utils.revHex(json.hash);
|
||||
json.prevBlock = utils.revHex(json.prevBlock);
|
||||
json.merkleRoot = utils.revHex(json.merkleRoot);
|
||||
json.chainwork = new bn(json.chainwork, 'hex');
|
||||
return new ChainBlock(chain, json);
|
||||
};
|
||||
|
||||
ChainBlock.prototype.inspect = function inspect() {
|
||||
var copy = new ChainBlock(this.chain, this, null);
|
||||
copy.__proto__ = null;
|
||||
copy.hash = utils.revHex(copy.hash);
|
||||
copy.prevBlock = utils.revHex(copy.prevBlock);
|
||||
copy.merkleRoot = utils.revHex(copy.merkleRoot);
|
||||
copy.chainwork = copy.chainwork.toString(10);
|
||||
delete copy.chain;
|
||||
copy.previous = this.previous.length;
|
||||
return copy;
|
||||
var json = this.toJSON();
|
||||
json.ancestors = this.ancestors.length;
|
||||
return json;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -96,7 +96,7 @@ ChainDB.prototype._init = function _init() {
|
||||
ChainDB.prototype.load = function load(callback) {
|
||||
var self = this;
|
||||
|
||||
var genesis = bcoin.chainblock.fromJSON(this.chain, {
|
||||
var genesis = new bcoin.chainblock(this.chain, {
|
||||
hash: network.genesis.hash,
|
||||
version: network.genesis.version,
|
||||
prevBlock: network.genesis.prevBlock,
|
||||
@ -104,8 +104,9 @@ ChainDB.prototype.load = function load(callback) {
|
||||
ts: network.genesis.ts,
|
||||
bits: network.genesis.bits,
|
||||
nonce: network.genesis.nonce,
|
||||
height: 0
|
||||
});
|
||||
height: 0,
|
||||
chainwork: null
|
||||
}, null);
|
||||
|
||||
this.loading = true;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user