tendermint
Version:
A light client which talks to your Tendermint node over RPC
104 lines (89 loc) • 3.19 kB
JavaScript
;
var createHash = require('create-hash');
var _require = require('./types.js'),
UVarInt = _require.UVarInt,
VarInt = _require.VarInt,
VarString = _require.VarString,
VarBuffer = _require.VarBuffer,
VarHexBuffer = _require.VarHexBuffer,
Time = _require.Time,
BlockID = _require.BlockID,
ValidatorHashInput = _require.ValidatorHashInput,
Version = _require.Version;
var sha256 = hashFunc('sha256');
var tmhash = sha256;
function getBlockHash(header) {
var encodedFields = [Version.encode(header.version), VarString.encode(header.chain_id), UVarInt.encode(header.height), Time.encode(header.time), BlockID.encode(header.last_block_id), omitEmpty(VarHexBuffer.encode(header.last_commit_hash)), omitEmpty(VarHexBuffer.encode(header.data_hash)), VarHexBuffer.encode(header.validators_hash), VarHexBuffer.encode(header.next_validators_hash), VarHexBuffer.encode(header.consensus_hash), omitEmpty(VarHexBuffer.encode(header.app_hash)), omitEmpty(VarHexBuffer.encode(header.last_results_hash)), omitEmpty(VarHexBuffer.encode(header.evidence_hash)), VarHexBuffer.encode(header.proposer_address)];
return treeHash(encodedFields).toString('hex').toUpperCase();
}
function getValidatorSetHash(validators) {
var bytes = validators.map(ValidatorHashInput.encode);
return treeHash(bytes).toString('hex').toUpperCase();
}
function omitEmpty(bytes) {
if (bytes.length === 1 && bytes[0] === 0) {
return Buffer.alloc(0);
}
return bytes;
}
function treeHash(hashes) {
if (hashes.length === 0) {
return null;
}
if (hashes.length === 1) {
// leaf hash
return tmhash(Buffer.concat([Buffer.from([0]), hashes[0]]));
}
var splitPoint = getSplitPoint(hashes.length);
var left = treeHash(hashes.slice(0, splitPoint));
var right = treeHash(hashes.slice(splitPoint));
// inner hash
return tmhash(Buffer.concat([Buffer.from([1]), left, right]));
}
function getSplitPoint(n) {
if (n < 1) {
throw Error('Trying to split tree with length < 1');
}
var mid = 2 ** Math.floor(Math.log2(n));
if (mid === n) {
mid /= 2;
}
return mid;
}
function hashFunc(algorithm) {
return function () {
var hash = createHash(algorithm);
for (var _len = arguments.length, chunks = Array(_len), _key = 0; _key < _len; _key++) {
chunks[_key] = arguments[_key];
}
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = chunks[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var data = _step.value;
hash.update(data);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return hash.digest();
};
}
module.exports = {
getBlockHash: getBlockHash,
getValidatorSetHash: getValidatorSetHash,
sha256: sha256,
tmhash: tmhash
};