UNPKG

noob-ethereum

Version:
148 lines (147 loc) 6.51 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; 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 rlp = __importStar(require("./rlp")); const keccak_1 = __importDefault(require("keccak")); const conversion_1 = require("../utils/conversion"); /* ---------------------------- Internal Methods ---------------------------------- */ 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 = (0, conversion_1.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); } /* -------------------------------------------------------------------------------- */ /* ******************************************************************************** */ /* --------------------------- Methods to Expose ---------------------------------- */ /** * Serialise a transaction via RLP-encoding scheme * @param {RawTransaction} tx - transaction object (can be legacy, 2930, 1559 type transaction bodies) * @returns {Buffer} - RLP-encoded transaction */ 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 Buffer.from(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 = Buffer.from(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 = Buffer.from(rlp.encode(byteTuple)); const type = Buffer.from('02', 'hex'); return Buffer.concat([type, encodedPayload]); } } } exports.serialiseTransaction = serialiseTransaction; /** * Serialise an array of transaction objects via RLP-encoding scheme * @param {RawTransactions} arr - array of transaction objects * @returns {Buffer[]} - array of RLP-encoded transactions */ function serialiseTransactions(arr) { return arr.map((tx) => serialiseTransaction(tx)); } exports.serialiseTransactions = serialiseTransactions; /** * Calculate transaction hash generated by a transaction object * @param {Raw Transaction} tx - transaction object (can be legacy, 2930, 1559 type transaction bodies) * @returns {string} - transaction hash computed */ function calculateTransactionHash(tx) { const serialised = serialiseTransaction(tx); return (0, conversion_1.hexify)((0, keccak_1.default)('keccak256').update(serialised).digest('hex')); } exports.calculateTransactionHash = calculateTransactionHash; /** * Calculate transaction hashes generated from an array of transactions provided * @param {RawTransactions} arr - array of transaction objects * @returns {string[]} - array of transaction hashes computed */ 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;