block timestamp - "Error: Number can only safely store up to 53 bits" #1905
Description
Hi, this issue is related to 1,2. And because it is a problem related to 3rd parties implementation of the blockchain, must be the responsibility of them to manage the particular implementation of the precision related to the timestamp.
As the documentation defines, the timestamp must be interpreted as unix time, but currently, an error breaks the execution of the application (if the timestamp value is bigger than expected) throwing an error.
It is expected that the block timestamp data could change over time --given the limitations of unix time spec-- but the behavior of the web3 must not break because of it.
Finally, the problem is related to a timestamp value bigger than a 32bit representation value. So, the right solution must be managing the timestamp as BN (in little endian) and then convert it to the first 32bit representable values by the developer.
This means that a decimal number with more than 10 digits must be truncated to be interpreted as 32bit length.
My solution at release @beta.35 file web3-core-helpers/src/formatters.js 235
< block.timestamp = utils.hexToNumber(block.timestamp);
> block.timestamp = outputBigNumberFormatter(block.timestamp);
at relase @beta.36 file web3-core-helpers/src/formatters.js:185
< block.timestamp = utils.toDecimal(block.timestamp);
> block.timestamp = utils.toBigNumber(block.timestamp);
a substring(0,10) operation is not recomended here to avoid problems with big-endian implementations
Example:
Phisical block: {"difficulty":"0x20000","extraData":"0x","gasLimit":"0xdee8afcd","gasUsed":"0xc705","hash":"0x71ef9a9e5e3575b9861e81da7ebd0fe465879602f6aff27964d9de6bd62e8bdd","logsBloom":"0x00000000000000000000000000000000000000080000000000000000000000000000000008000000000000000000000000000000000000000000400000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000010000000080000000000000000000000000000000000000000000000000021000000000002000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000","miner":"0x0000000000000000000000000000000000000000","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","number":"0x5","parentHash":"0xcc0cd85704ccee6615b5d4a182c18d98080685acee0eb6aeb2816b5c14ebb26e","receiptsRoot":"0x90889007d6b3836f3bbdaa22ed5cae062ccfc6c5758fc92e9e042b715f10cc26","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x2ae","stateRoot":"0xdf0a5715a8e861f689d3262b84fd02a95bbe76c536501cc34b519a3d051813a6","timestamp":"0x154f146681969c9e","totalDifficulty":"0xa0000","transactions":["0x406cdd51e197c04cc31b9bf0548d61f411375b7c63791f155d297e14402ed0bc"],"transactionsRoot":"0x513fe6d019912f97352635b19bb0144d035752c320a41e17680382237289c878","uncles":[]}
Help Logs:
timestamp (orig): 0x154f146681969c9e
BigNumber: 1535468428449979550 timestamp: 1535468428 (equal to BigNumber.substring(0,10))
timestamp date: 2018-08-28T15:00:28.000Z
jstimestamp: 1535468428449
At the application level: Using a wrapper to override the buggy function.
wrapperFile.js
// Bug Fix on web3 code version @1.0.0.beta.35
// Override Dependencies
var _ = require('underscore');
var utils = require('web3-utils');
/**
* Same as web3-utils formatters, copied & pasted.
* @param {String} number
*/
var outputBigNumberFormatter = function (number) {
return utils.toBN(number).toString(10);
};
/**
* @override
* Formats the output of a block to its proper values
*
* @method outputBlockFormatter
* @param {Object} block
* @returns {Object}
*/
function outputBlockFormatterOverride(block){
console.log("WARN: Override of internal web3 function.");
// transform to number
block.gasLimit = utils.hexToNumber(block.gasLimit);
block.gasUsed = utils.hexToNumber(block.gasUsed);
block.size = utils.hexToNumber(block.size);
// don't do a substring(0,10) here, parse the timestamp outside this function.
block.timestamp = outputBigNumberFormatter(block.timestamp);
if (block.number !== null)
block.number = utils.hexToNumber(block.number);
if(block.difficulty)
block.difficulty = outputBigNumberFormatter(block.difficulty);
if(block.totalDifficulty)
block.totalDifficulty = outputBigNumberFormatter(block.totalDifficulty);
if (_.isArray(block.transactions)) {
block.transactions.forEach(function(item){
if(!_.isString(item))
return outputTransactionFormatter(item);
});
}
if (block.miner)
block.miner = utils.toChecksumAddress(block.miner);
return block;
}
// trying to force override and cache of helpers
var helpers = require('web3-core-helpers');
helpers.formatters.outputBlockFormatter=outputBlockFormatterOverride;
const web3Client =require( 'web3');