From 36fb89530bec2d28e2f02b02dbcf2a5caada36d9 Mon Sep 17 00:00:00 2001 From: harkamal Date: Fri, 13 Jan 2023 17:53:19 +0530 Subject: [PATCH 1/6] util: Change withdrawal amount representation for Wei to Gwei --- .../client/test/rpc/engine/withdrawals.spec.ts | 5 +++-- packages/util/src/withdrawal.ts | 14 +++++++++++--- packages/vm/src/buildBlock.ts | 6 ++++-- packages/vm/src/runBlock.ts | 14 ++++++++++++-- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/packages/client/test/rpc/engine/withdrawals.spec.ts b/packages/client/test/rpc/engine/withdrawals.spec.ts index dff4fd208c..65887068b2 100644 --- a/packages/client/test/rpc/engine/withdrawals.spec.ts +++ b/packages/client/test/rpc/engine/withdrawals.spec.ts @@ -1,5 +1,5 @@ import { Block } from '@ethereumjs/block' -import { Withdrawal, bigIntToHex, intToHex } from '@ethereumjs/util' +import { GWEI_TO_WEI, Withdrawal, bigIntToHex, intToHex } from '@ethereumjs/util' import * as tape from 'tape' import { INVALID_PARAMS } from '../../../lib/rpc/error-code' @@ -74,7 +74,8 @@ const withdrawalsGethVector = withdrawalsVector.map((testVec) => ({ index: intToHex(testVec.Index), validatorIndex: intToHex(testVec.Validator), address: testVec.Recipient, - amount: bigIntToHex(BigInt(testVec.Amount)), + // withdrawal amount is now represent in gwei to match CL representation + amount: bigIntToHex(BigInt(testVec.Amount) / GWEI_TO_WEI), })) const validForkChoiceState = { diff --git a/packages/util/src/withdrawal.ts b/packages/util/src/withdrawal.ts index 6ad5a301cc..7da01f658b 100644 --- a/packages/util/src/withdrawal.ts +++ b/packages/util/src/withdrawal.ts @@ -4,8 +4,11 @@ import { TypeOutput, toType } from './types' import type { AddressLike, BigIntLike } from './types' +/** Easy conversion from Gwei to wei */ +export const GWEI_TO_WEI = BigInt(1000000000) /** - * Flexible input data type for EIP-4895 withdrawal data + * Flexible input data type for EIP-4895 withdrawal data with amount in Gwei to + * match CL representation and for eventual ssz withdrawalsRoot */ export type WithdrawalData = { index: BigIntLike @@ -15,13 +18,14 @@ export type WithdrawalData = { } /** - * JSON RPC interface for EIP-4895 withdrawal data + * JSON RPC interface for EIP-4895 withdrawal data with amount in Gwei to + * match CL representation and for eventual ssz withdrawalsRoot */ export interface JsonRpcWithdrawal { index: string // QUANTITY - bigint 8 bytes validatorIndex: string // QUANTITY - bigint 8 bytes address: string // DATA, 20 Bytes address to withdraw to - amount: string // QUANTITY - bigint amount in wei 32 bytes + amount: string // QUANTITY - bigint amount in Gwei 8 bytes } export type WithdrawalBuffer = [Buffer, Buffer, Buffer, Buffer] @@ -33,11 +37,15 @@ export class Withdrawal { /** * This constructor assigns and validates the values. * Use the static factory methods to assist in creating a Withdrawal object from varying data types. + * Its amount is in Gwei to match CL representation and for eventual ssz withdrawalsRoot */ constructor( public readonly index: bigint, public readonly validatorIndex: bigint, public readonly address: Address, + /** + * withdrawal amount in Gwei to match the CL repesentation and eventually ssz withdrawalsRoot + * */ public readonly amount: bigint ) {} diff --git a/packages/vm/src/buildBlock.ts b/packages/vm/src/buildBlock.ts index 5637a5207b..b7679c57eb 100644 --- a/packages/vm/src/buildBlock.ts +++ b/packages/vm/src/buildBlock.ts @@ -2,7 +2,7 @@ import { Block } from '@ethereumjs/block' import { ConsensusType } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { Trie } from '@ethereumjs/trie' -import { Address, TypeOutput, Withdrawal, toBuffer, toType } from '@ethereumjs/util' +import { Address, GWEI_TO_WEI, TypeOutput, Withdrawal, toBuffer, toType } from '@ethereumjs/util' import { Bloom } from './bloom' import { calculateMinerReward, encodeReceipt, rewardAccount } from './runBlock' @@ -129,7 +129,9 @@ export class BlockBuilder { // although this should never happen as no withdrawals with 0 // amount should ever land up here. if (amount === 0n) continue - await rewardAccount(this.vm.eei, address, amount) + // Withdrawal amount is represented in Gwei so needs to be + // converted to wei + await rewardAccount(this.vm.eei, address, amount * GWEI_TO_WEI) } } diff --git a/packages/vm/src/runBlock.ts b/packages/vm/src/runBlock.ts index 05fb20d6bb..197a8364fb 100644 --- a/packages/vm/src/runBlock.ts +++ b/packages/vm/src/runBlock.ts @@ -2,7 +2,15 @@ import { Block } from '@ethereumjs/block' import { ConsensusType, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { Trie } from '@ethereumjs/trie' -import { Account, Address, bigIntToBuffer, bufArrToArr, intToBuffer, short } from '@ethereumjs/util' +import { + Account, + Address, + GWEI_TO_WEI, + bigIntToBuffer, + bufArrToArr, + intToBuffer, + short, +} from '@ethereumjs/util' import { debug as createDebugLogger } from 'debug' import { Bloom } from './bloom' @@ -328,7 +336,9 @@ async function assignWithdrawals(this: VM, block: Block): Promise { const { address, amount } = withdrawal // skip touching account if no amount update if (amount === BigInt(0)) continue - await rewardAccount(state, address, amount) + // Withdrawal amount is represented in Gwei so needs to be + // converted to wei + await rewardAccount(state, address, amount * GWEI_TO_WEI) } } From d0bd1915f36434803f0c2dc24726dae669eb79ac Mon Sep 17 00:00:00 2001 From: harkamal Date: Fri, 13 Jan 2023 17:58:21 +0530 Subject: [PATCH 2/6] cleanup --- packages/util/src/withdrawal.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/util/src/withdrawal.ts b/packages/util/src/withdrawal.ts index 7da01f658b..ff77e609e6 100644 --- a/packages/util/src/withdrawal.ts +++ b/packages/util/src/withdrawal.ts @@ -45,7 +45,7 @@ export class Withdrawal { public readonly address: Address, /** * withdrawal amount in Gwei to match the CL repesentation and eventually ssz withdrawalsRoot - * */ + */ public readonly amount: bigint ) {} From 5000cb1a08da7359a5ae8e0194512b2b3cda0c17 Mon Sep 17 00:00:00 2001 From: harkamal Date: Fri, 13 Jan 2023 18:54:41 +0530 Subject: [PATCH 3/6] fix test --- packages/client/test/rpc/engine/withdrawals.spec.ts | 8 +++----- packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts | 8 ++++---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/client/test/rpc/engine/withdrawals.spec.ts b/packages/client/test/rpc/engine/withdrawals.spec.ts index 65887068b2..07ba1cb274 100644 --- a/packages/client/test/rpc/engine/withdrawals.spec.ts +++ b/packages/client/test/rpc/engine/withdrawals.spec.ts @@ -1,5 +1,5 @@ import { Block } from '@ethereumjs/block' -import { GWEI_TO_WEI, Withdrawal, bigIntToHex, intToHex } from '@ethereumjs/util' +import { Withdrawal, bigIntToHex, intToHex } from '@ethereumjs/util' import * as tape from 'tape' import { INVALID_PARAMS } from '../../../lib/rpc/error-code' @@ -74,8 +74,7 @@ const withdrawalsGethVector = withdrawalsVector.map((testVec) => ({ index: intToHex(testVec.Index), validatorIndex: intToHex(testVec.Validator), address: testVec.Recipient, - // withdrawal amount is now represent in gwei to match CL representation - amount: bigIntToHex(BigInt(testVec.Amount) / GWEI_TO_WEI), + amount: bigIntToHex(BigInt(testVec.Amount)), })) const validForkChoiceState = { @@ -142,10 +141,9 @@ for (const { name, withdrawals, withdrawalsRoot, gethBlockRlp } of testCases) { if (gethBlockRlp !== undefined) { // check if stateroot matches - const gethBlock = Block.fromRLPSerializedBlock(Buffer.from(gethBlockRlp, 'hex'), { common }) t.equal( payload!.stateRoot, - `0x${gethBlock.header.stateRoot.toString('hex')}`, + '0x23eadd91fca55c0e14034e4d63b2b3ed43f2e807b6bf4d276b784ac245e7fa3f', 'stateRoot should match' ) } diff --git a/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts b/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts index 7a007722ea..a4163d45fb 100644 --- a/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts +++ b/packages/vm/test/api/EIPs/eip-4895-withdrawals.spec.ts @@ -3,7 +3,7 @@ import { Blockchain, parseGethGenesisState } from '@ethereumjs/blockchain' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { decode } from '@ethereumjs/rlp' import { FeeMarketEIP1559Transaction } from '@ethereumjs/tx' -import { Address, KECCAK256_RLP, Withdrawal, zeros } from '@ethereumjs/util' +import { Address, GWEI_TO_WEI, KECCAK256_RLP, Withdrawal, zeros } from '@ethereumjs/util' import * as tape from 'tape' import genesisJSON = require('../../../../client/test/testdata/geth-genesis/withdrawals.json') @@ -106,7 +106,7 @@ tape('EIP4895 tests', (t) => { const address = new Address(Buffer.from(addresses[i], 'hex')) const amount = amounts[i] const balance = (await vm.stateManager.getAccount(address)).balance - st.equals(BigInt(amount), balance, 'balance ok') + st.equals(BigInt(amount) * GWEI_TO_WEI, balance, 'balance ok') } st.ok(zeros(32).equals(result!), 'withdrawals happen after transactions') @@ -173,7 +173,7 @@ tape('EIP4895 tests', (t) => { postState = (await vm.eei.getStateRoot()).toString('hex') st.equal( postState, - '7f7510a0cb6203f456e34ec3e2ce30d6c5590ded42c10a9cf3f24784119c5afb', + '23eadd91fca55c0e14034e4d63b2b3ed43f2e807b6bf4d276b784ac245e7fa3f', 'post state should match' ) st.end() @@ -220,7 +220,7 @@ tape('EIP4895 tests', (t) => { st.equal( block.header.stateRoot.toString('hex'), - '7f7510a0cb6203f456e34ec3e2ce30d6c5590ded42c10a9cf3f24784119c5afb', + '23eadd91fca55c0e14034e4d63b2b3ed43f2e807b6bf4d276b784ac245e7fa3f', 'correct state root should be generated' ) From 50c8816fdf5d39a52035063a4287648c9e6909ab Mon Sep 17 00:00:00 2001 From: harkamal Date: Fri, 13 Jan 2023 21:50:02 +0530 Subject: [PATCH 4/6] fix test --- packages/client/test/rpc/engine/withdrawals.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/test/rpc/engine/withdrawals.spec.ts b/packages/client/test/rpc/engine/withdrawals.spec.ts index 07ba1cb274..85497e113e 100644 --- a/packages/client/test/rpc/engine/withdrawals.spec.ts +++ b/packages/client/test/rpc/engine/withdrawals.spec.ts @@ -107,7 +107,7 @@ for (const { name, withdrawals, withdrawalsRoot, gethBlockRlp } of testCases) { await Block.genWithdrawalsTrieRoot(withdrawals.map(Withdrawal.fromWithdrawalData)) ).toString('hex') t.equal(withdrawalsRoot, computedWithdrawalsRoot, 'withdrawalsRoot compuation should match') - const { server, common } = await setupChain(genesisJSON, 'post-merge', { engine: true }) + const { server } = await setupChain(genesisJSON, 'post-merge', { engine: true }) let req = params('engine_forkchoiceUpdatedV2', [validForkChoiceState, validPayloadAttributes]) let expectRes = checkError( From 9aa359e29619aad703e4359eedca92ce898550dc Mon Sep 17 00:00:00 2001 From: harkamal Date: Tue, 17 Jan 2023 13:29:11 +0530 Subject: [PATCH 5/6] move unit to separate file --- packages/util/src/index.ts | 5 +++++ packages/util/src/withdrawal.ts | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/util/src/index.ts b/packages/util/src/index.ts index 7fba7a6eb1..d2737fe8d0 100644 --- a/packages/util/src/index.ts +++ b/packages/util/src/index.ts @@ -3,6 +3,11 @@ */ export * from './constants' +/** + * Units helpers + */ +export * from './units' + /** * Account class and helper functions */ diff --git a/packages/util/src/withdrawal.ts b/packages/util/src/withdrawal.ts index ff77e609e6..8e9d8d51e6 100644 --- a/packages/util/src/withdrawal.ts +++ b/packages/util/src/withdrawal.ts @@ -4,8 +4,6 @@ import { TypeOutput, toType } from './types' import type { AddressLike, BigIntLike } from './types' -/** Easy conversion from Gwei to wei */ -export const GWEI_TO_WEI = BigInt(1000000000) /** * Flexible input data type for EIP-4895 withdrawal data with amount in Gwei to * match CL representation and for eventual ssz withdrawalsRoot From 8a20fa2c7ec5d63133577a70101f1fc69ded3e90 Mon Sep 17 00:00:00 2001 From: harkamal Date: Tue, 17 Jan 2023 13:30:39 +0530 Subject: [PATCH 6/6] add missing file --- packages/util/src/units.ts | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 packages/util/src/units.ts diff --git a/packages/util/src/units.ts b/packages/util/src/units.ts new file mode 100644 index 0000000000..4ed6f1a6c8 --- /dev/null +++ b/packages/util/src/units.ts @@ -0,0 +1,2 @@ +/** Easy conversion from Gwei to wei */ +export const GWEI_TO_WEI = BigInt(1000000000)