UNPKG

noob-ethereum

Version:
128 lines (127 loc) 5.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.calculateBlockTransactionHashes = exports.calculateTransactionHashes = exports.calculateTransactionHash = exports.serialiseTransactions = exports.serialiseTransaction = void 0; const ethereumjs_util_1 = require("ethereumjs-util"); const trie_1 = require("@ethereumjs/trie"); const ethers_1 = require("ethers"); const keccak_1 = __importDefault(require("keccak")); const conversion_1 = require("../../lib/utils/conversion"); function convertToByteArray(field) { const isNested = Array.isArray(field); const emptyArr = Array.isArray(field) && field.length === 0; if (emptyArr) return []; if (!isNested) { if (field === '0x0') { return Uint8Array.from([]); } else { return toByteArr(field); } } else { return convertToByteArray(field); } } function toByteArr(field) { const arr = []; const suffix = field.slice(2); const byteLength = Math.ceil(suffix.length / 2); const padded = ethers_1.utils.hexZeroPad(field, byteLength).slice(2); for (let i = 0; i < padded.length; i += 2) { arr.push(parseInt(padded.slice(i, i + 2), 16)); } return new Uint8Array(arr); } function serialiseTransaction(tx) { const toByteTuple = (tuple) => { return tuple.map((field) => convertToByteArray(field)); }; switch (tx.type) { /* Legacy transaction */ case '0x0': default: { const { nonce, gasPrice, gas, to, value, input, v, r, s } = tx; const tuple = [nonce, gasPrice, gas, to, value, input, v, r, s]; const byteTuple = toByteTuple(tuple); return ethereumjs_util_1.rlp.encode(byteTuple); } /* EIP-2930 transaction */ case '0x1': { const { chainId, nonce, gasPrice, gas, to, value, input, accessList, v, r, s } = tx; const tuple = [chainId, nonce, gasPrice, gas, to, value, input, accessList, v, r, s]; const byteTuple = toByteTuple(tuple); const encodedPayload = ethereumjs_util_1.rlp.encode(byteTuple); const type = Buffer.from('01', 'hex'); return Buffer.concat([type, encodedPayload]); } /* EIP-1559 transaction */ case '0x2': { const { chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gas, to, value, input, accessList, v, r, s } = tx; const tuple = [chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gas, to, value, input, accessList, v, r, s]; const byteTuple = toByteTuple(tuple); const encodedPayload = ethereumjs_util_1.rlp.encode(byteTuple); const type = Buffer.from('02', 'hex'); return Buffer.concat([type, encodedPayload]); } } } exports.serialiseTransaction = serialiseTransaction; function serialiseTransactions(arr) { return arr.map((tx) => serialiseTransaction(tx)); } exports.serialiseTransactions = serialiseTransactions; function calculateTransactionHash(tx) { const serialised = serialiseTransaction(tx); return '0x' + (0, keccak_1.default)('keccak256').update(serialised).digest('hex'); } exports.calculateTransactionHash = calculateTransactionHash; function calculateTransactionHashes(arr) { const hashes = []; if (typeof arr[0] !== 'string') { arr.forEach((t) => hashes.push(calculateTransactionHash(t))); } return hashes; } exports.calculateTransactionHashes = calculateTransactionHashes; /** * Given a raw block (with full transaction objects), return the calculated transaction hashes * @param {IRawBlock} block - raw block including full transaction records * @returns {string[]} - an array of transaction hash strings */ function calculateBlockTransactionHashes(block) { if (block.transactions[0] === 'string') { console.error(`Block supplied does not consist of an array of transaction objects corresponding to the 'transactions' key (possibly a condensed block with only transaction hashes)`); return []; } return calculateTransactionHashes(block.transactions); } exports.calculateBlockTransactionHashes = calculateBlockTransactionHashes; const _15122054_json_1 = __importDefault(require("../../seeder/blocks/1559/15122054.json")); const trie = new trie_1.Trie(); const testBlock = _15122054_json_1.default; const serialisedTxs = serialiseTransactions(testBlock.transactions); async function insertTransactions(arr) { for (let i = 0; i < arr.length; i++) { await trie.put(ethereumjs_util_1.rlp.encode(i), arr[i]); } const expected = testBlock.transactionsRoot; const calculated = '0x' + trie.root.toString('hex'); console.log(expected, calculated, expected === calculated); } insertTransactions(serialisedTxs).then(() => { const expected = testBlock.transactionsRoot; const calculated = (0, conversion_1.hexify)(trie.root); console.log(expected, calculated, expected === calculated); trie.get(ethereumjs_util_1.rlp.encode(0)).then((x) => { console.log(x); const data = ethereumjs_util_1.rlp.decode(x); console.log(data); // convert tuple fields from buffer to hex strings let hexed = data.map((elem) => (0, conversion_1.hexify)(elem)); console.log(hexed); }); });