o2-client
Version:
Light Client for O2 Blockchain
93 lines (70 loc) • 3.14 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.verifyBlock = verifyBlock;
var _primitive = require('../types/primitive');
var primitive = _interopRequireWildcard(_primitive);
var _message = require('../types/message');
var _hexadecimal = require('../types/hexadecimal');
var _generic = require('../types/generic');
var _convert = require('../types/convert');
var _crypto = require('../crypto');
var _helpers = require('../helpers');
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
var Block = (0, _generic.newType)({
fields: [{ name: 'proposer_id', type: primitive.Uint16 }, { name: 'height', type: primitive.Uint64 }, { name: 'tx_count', type: primitive.Uint32 }, { name: 'prev_hash', type: _hexadecimal.Hash }, { name: 'tx_hash', type: _hexadecimal.Hash }, { name: 'state_hash', type: _hexadecimal.Hash }]
});
var SystemTime = (0, _generic.newType)({
fields: [{ name: 'secs', type: primitive.Uint64 }, { name: 'nanos', type: primitive.Uint32 }]
});
/**
* Validate block and each precommit in block
* @param {Object} data
* @param {Array} validators
* @return {boolean}
*/
function verifyBlock(data, validators) {
var blockHash = void 0;
try {
blockHash = (0, _crypto.hash)(data.block, Block);
} catch (error) {
return false;
}
for (var i = 0; i < data.precommits.length; i++) {
var precommit = data.precommits[i];
var buffer = (0, _convert.hexadecimalToUint8Array)(precommit.message);
if (precommit.payload.height !== data.block.height) {
// height of block is not match
return false;
}
if (precommit.payload.block_hash !== blockHash) {
// hash of block is not match
return false;
}
var publicKey = validators[precommit.payload.validator];
if ((0, _convert.uint8ArrayToHexadecimal)(buffer.slice(0, _hexadecimal.PUBLIC_KEY_LENGTH)) !== publicKey) {
// public key is not match
return false;
}
var Precommit = (0, _message.newPrecommit)({
author: publicKey,
fields: [{ name: 'validator', type: primitive.Uint16 }, { name: 'height', type: primitive.Uint64 }, { name: 'round', type: primitive.Uint32 }, { name: 'propose_hash', type: _hexadecimal.Hash }, { name: 'block_hash', type: _hexadecimal.Hash }, { name: 'time', type: SystemTime }]
});
var precommitBody = buffer.slice(0, buffer.length - _message.SIGNATURE_LENGTH);
if (!(0, _helpers.compareUint8Arrays)(Precommit.serialize(precommit.payload), precommitBody)) {
// payload is not match
return false;
}
var signature = (0, _convert.uint8ArrayToHexadecimal)(buffer.slice(buffer.length - _message.SIGNATURE_LENGTH, buffer.length));
try {
if (!(0, _crypto.verifySignature)(signature, publicKey, precommitBody)) {
// signature is not match
return false;
}
} catch (error) {
return false;
}
}
return true;
}