execution, rlp: switch total difficulty and chainID to uint256.Int#21119
Merged
Conversation
The on-wire total difficulty fits in 256 bits, so store it as a uint256.Int directly. Decoding no longer round-trips through *big.Int, and the encoder uses rlp.Uint256Len / rlp.EncodeUint256. Call sites that hold a *big.Int convert at the packet boundary via uint256.FromBig (broadcastNewBlock, publisher) — outer pipeline signatures are left unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Moves the conversion from *big.Int to uint256.Int up to where the TD is computed (parent TD + header difficulty in checkPrefetchedBlock), so BroadcastNewBlock and the BlockPropagator type both take uint256.Int directly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
publishTask.td, Publisher.PublishNewBlock and the polygon p2pService interface (plus mock) now use uint256.Int. The *big.Int -> uint256.Int conversion moves up to polygon/sync near the GetTd call, matching the shape of the BlockPropagator change in body_algos. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ReadTd and ReadTdByHash now return *uint256.Int; WriteTd takes uint256.Int by value. Total difficulty fits in 256 bits and the on-disk RLP bytes are unchanged (uint256.Int encodes to the same canonical big-endian bytes as big.Int). Direct rawdb callers were updated to use uint256 arithmetic where they already had access to uint256 inputs (header.Difficulty, checkPrefetchedBlock, reset_stages.go, exec_module.go inserter). Where the surrounding API still hands around *big.Int (chain reader GetTd methods, ShouldReorg, NewHeaderInserter, ethstats), the conversion sits at the rawdb boundary via ToBig() / MustFromBig(). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Migrate total-difficulty types to *uint256.Int across internal call surfaces: - rules.ChainHeaderReader.GetTd and all implementations (stagedsync, exec, consensuschain, polygon, FakeChainReader, test mocks). - ethash.ShouldReorg (callers convert *big.Int -> uint256.Int at the boundary). - headerdownload.HeaderInserter (localTd, FeedHeaderFunc, FeedHeaderPoW, GetLocalTd) and the InsertHeader returnTd accumulator. - execmodule.ExecutionModule.GetTD interface + impl, ExecModule.getTD, ChainReaderWriterEth1.GetTd. - polygon ExecutionClient.GetTd and the executionClient impl. - engineapi engine_server.go newPayload TD var (uses CmpBig against the *big.Int TerminalTotalDifficulty in chain.Config). - ethstats.assembleBlockStats. chain.Config.TerminalTotalDifficulty stays *big.Int to preserve the existing genesis/chain-spec JSON wire shape; comparisons use uint256.Int.CmpBig at the boundary. Tracing BlockEvent.TD remains *big.Int (external API parity); converted in protocol/block_exec.go and stagedsync/exec3.go. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
parentTd / currentHeadTd / importedTipTd were left as *big.Int with round-trip conversions to uint256.Int at the ShouldReorg and WriteTd call sites. Since rawdb.ReadTd returns *uint256.Int and ShouldReorg / WriteTd now take uint256.Int directly, those conversions are pointless - compute the sums natively against header.Difficulty (already uint256.Int). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
uint256.Int.Add silently wraps on overflow (unlike big.Int.Add). Use AddOverflow on every TD accumulation introduced by the uint256 migration: - headerdownload.FeedHeaderPoW (parentTd + header.Difficulty) - execmodule.InsertBlocks (parentTd + header.Difficulty) - rawdbreset header range (running TD over snapshot headers) - bodydownload.checkPrefetchedBlock (header.Difficulty + parent) - cmd/utils/app/import_cmd.go (importedTipTd + Difficulty, side-chain td + Difficulty) Functions with an error return propagate the overflow as an error; the body-propagator path (no error return) logs and skips propagating the block, matching its existing best-effort semantics. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
After the uint256 migration, no production struct uses *big.Int as an RLP-encoded field via the code generator, so the only callers of rlp.EncodeBigInt and rlp.BigIntLen are dead. Drop the helpers along with the rlpgen big.Int handler and the *big.Int fields in the rlpgen testing fixture (regenerated). Reflect-based encoding/decoding of *big.Int (writeBigInt*, decodeBigInt, Stream.BigInt, Stream.decodeBigInt) is kept, since the legacy ethereum/tests RLPTests include test vectors with values >= 2^256 that don't fit in uint256.Int and the SigHash struct fields used in transaction signing still rely on the reflect path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ig.Int RLP Total difficulty already migrated to uint256.Int; now do the same for transaction chainID. EIP-7702 caps chainID at < 2**256, and the stagnant EIP-2294 even proposes ~2**63 — so a uint256 ceiling is strictly above what the Ethereum protocol can use. Changes: - Transaction.SigningHash(chainID *uint256.Int) interface + 7 impls (LegacyTx, AccessListTx, DynamicFeeTransaction, BlobTx, SetCodeTransaction, BlobTxWrapper, AccountAbstractionTransaction). - The 5 *SigHash structs' ChainID fields are now *uint256.Int, so RLP-encoded sig hashes no longer depend on reflect-based *big.Int. - transaction_signing.go SignTx / SignNewTx / SenderWithContext pass &s.chainID (already uint256.Int) directly. - abi/bind/auth.go and txpool test convert at the boundary via uint256.MustFromBig. With chainID off *big.Int, the rlp package's reflect-based *big.Int support is no longer needed: - Remove EncodeBigInt / BigIntLen exported helpers (no callers). - Remove writeBigIntPtr / writeBigIntNoPtr / encBuffer.writeBigInt / EncoderBuffer.WriteBigInt and the reflect dispatch in makeWriter. - Remove decodeBigInt / decodeBigIntNoPtr / Stream.BigInt / Stream.decodeBigInt and the reflect dispatch in makeDecoder. - Remove ErrNegativeBigInt and the bigInt reflect type var. - Drop big.Int test cases / fixtures in rlp encode/decode tests. The legacy ethereum/tests RLPTests rlptest.json/bigint vector encodes 2**256 and exceeds the new uint256 ceiling; SkipLoad it in TestRLP with an EIP-7702 / EIP-2294 rationale comment. The other "mediumint" fixtures fit in uint256 and round-trip through translateJSON via uint256.FromBig. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR migrates total difficulty (TD) and transaction chain ID usage from *big.Int to *uint256.Int / uint256.Int across execution, P2P, and Polygon components, and removes the execution RLP package’s reflect-based big.Int encoding/decoding support that becomes unnecessary after the migration.
Changes:
- Switch TD plumbing (DB accessors, wire types, sync/execution APIs) to
uint256with explicit overflow handling viaAddOverflow. - Switch transaction signing APIs and RLP signing payload fields from
*big.Intchain IDs to*uint256.Int. - Remove
big.Intsupport fromexecution/rlpand regenerate/updaterlpgenfixtures and related tests.
Reviewed changes
Copilot reviewed 74 out of 75 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| txnprovider/txpool/pool_txn_parser_test.go | Update tx signing-hash test to pass *uint256.Int chain ID. |
| rpc/jsonrpc/graphql_api.go | Convert TD uint256 to big.Int for hexutil.Big JSON output. |
| polygon/sync/sync.go | Ensure TD is present before publishing; pass TD by value. |
| polygon/sync/p2p_service.go | Update Polygon sync P2P service interface to TD uint256.Int. |
| polygon/sync/p2p_service_mock.go | Update gomock for new TD uint256.Int signature. |
| polygon/sync/execution_client.go | Update execution client TD return type to *uint256.Int. |
| polygon/p2p/service.go | Update PublishNewBlock to accept TD uint256.Int. |
| polygon/bor/bor_test.go | Update bor tests for NewBlockPacket.TD as uint256.Int. |
| p2p/sentry/status_data_provider.go | Use TD *uint256.Int directly from rawdb and default missing TD to 0. |
| p2p/sentry/status_data_provider_test.go | Update test TD writes to uint256.Int. |
| p2p/sentry/sentry_multi_client/broadcast.go | Update broadcast new-block TD parameter to uint256.Int. |
| p2p/sentry/sentry_grpc_server_test.go | Use *uint256.Int TD directly for status data conversion. |
| p2p/protocols/eth/protocol.go | Change NewBlockPacket.TD to uint256.Int; update RLP encode/decode. |
| p2p/protocols/eth/handler.go | Convert TD *uint256.Int to *big.Int at geth-compat boundary for NodeInfo. |
| node/ethstats/ethstats.go | Accept TD as *uint256.Int and stringify for ethstats payload. |
| node/eth/backend.go | Convert stored TD *uint256.Int to *big.Int for existing callers. |
| execution/vm/runtime/runtime_test.go | Update fake chain reader TD signature to *uint256.Int. |
| execution/types/transaction.go | Change Transaction.SigningHash to accept *uint256.Int. |
| execution/types/transaction_test.go | Update signing-hash tests to uint256 chain ID. |
| execution/types/transaction_signing.go | Pass signer chain ID as *uint256.Int into SigningHash. |
| execution/types/set_code_tx.go | Switch set-code tx signing payload ChainID type to *uint256.Int. |
| execution/types/legacy_tx.go | Switch legacy tx signing payload ChainID type to *uint256.Int. |
| execution/types/dynamic_fee_tx.go | Switch 1559 tx signing payload ChainID type to *uint256.Int. |
| execution/types/block_test.go | Rename/update panic-prevention test to target EncodeUint256. |
| execution/types/blob_tx.go | Switch blob tx signing payload ChainID type to *uint256.Int. |
| execution/types/blob_tx_wrapper.go | Update wrapper SigningHash signature to *uint256.Int. |
| execution/types/access_list_tx.go | Switch 2930 tx signing payload ChainID type to *uint256.Int. |
| execution/types/aa_transaction.go | Update AA SigningHash signature and convert big chainID at call sites. |
| execution/tests/testutil/rlp_test_util.go | Update RLP JSON test translation/decoding to use uint256. |
| execution/tests/rlp_test.go | Skip legacy bigint vector that exceeds uint256 ceiling. |
| execution/tests/blockgen/chain_makers.go | Update fake chain reader TD signature to *uint256.Int. |
| execution/tests/blockchain_test.go | Convert TD reads to uint256, compare accordingly, and bridge to big.Int where needed. |
| execution/state/genesiswrite/genesis_write.go | Write genesis TD using uint256.Int value. |
| execution/stagedsync/rawdbreset/reset_stages.go | Accumulate TD as uint256.Int with overflow checks when filling DB from snapshots. |
| execution/stagedsync/headerdownload/header_data_struct.go | Update HeaderInserter local TD to *uint256.Int. |
| execution/stagedsync/headerdownload/header_algos.go | Update feed/insert TD plumbing to uint256 + overflow errors and CmpBig at TTD boundary. |
| execution/stagedsync/headerdownload/header_algo_test.go | Update header download tests for uint256 TD and comparisons. |
| execution/stagedsync/exec3.go | Convert *uint256.Int TD to *big.Int for tracing hook compatibility. |
| execution/stagedsync/chain_reader.go | Change ChainReader.GetTd return type to *uint256.Int. |
| execution/stagedsync/bodydownload/body_algos.go | Compute propagated TD as uint256.Int with overflow handling. |
| execution/stagedsync/bodydownload/block_propagator.go | Change block propagator TD parameter to uint256.Int. |
| execution/rlp/encode.go | Remove reflect-based big.Int encoding and exported helpers; keep uint256 encoding. |
| execution/rlp/encode_test.go | Remove big.Int encoding tests; add/keep uint256 tests and benchmark. |
| execution/rlp/encbuffer.go | Remove big.Int buffer-writing helpers; keep uint256 support. |
| execution/rlp/decode.go | Remove reflect-based big.Int decoding and Stream big-int APIs; keep uint256. |
| execution/rlp/decode_test.go | Remove big.Int decoding tests/fixtures; keep uint256 coverage. |
| execution/protocol/rules/rules.go | Update ChainHeaderReader.GetTd to return *uint256.Int. |
| execution/protocol/rules/merge/merge.go | Compare TD vs TTD via uint256.Int.CmpBig. |
| execution/protocol/rules/merge/merge_test.go | Update merge rule tests for uint256 TD reader signature. |
| execution/protocol/rules/ethash/forkchoice.go | Update forkchoice ShouldReorg to compare *uint256.Int TD values. |
| execution/protocol/rules/ethash/forkchoice_test.go | Update forkchoice tests to use uint256 TDs. |
| execution/protocol/block_exec.go | Convert *uint256.Int TD to *big.Int for tracer boundary. |
| execution/p2p/publisher.go | Publish NewBlock with TD as uint256.Int value. |
| execution/p2p/publisher_test.go | Update publisher tests for NewBlockPacket.TD as uint256.Int. |
| execution/p2p/message_sender_test.go | Update message sender tests for NewBlockPacket.TD as uint256.Int. |
| execution/execmodule/interface.go | Change ExecutionModule.GetTD return type to *uint256.Int. |
| execution/execmodule/inserters.go | Compute and store TD in overlay as uint256 with overflow checks. |
| execution/execmodule/getters.go | Update GetTD signature to return *uint256.Int. |
| execution/execmodule/execmoduletester/exec_module_tester.go | Update block propagator test hook signature for uint256.Int TD. |
| execution/execmodule/exec_module.go | Update internal getTD helper to return *uint256.Int. |
| execution/execmodule/chainreader/chain_reader.go | Update engine chain reader GetTd to return *uint256.Int. |
| execution/exec/chain_reader.go | Update execution chain reader GetTd to return *uint256.Int. |
| execution/engineapi/testing_api_test.go | Update stub GetTD signature to return *uint256.Int. |
| execution/engineapi/engine_server.go | Use CmpBig for TD vs TTD comparisons with *uint256.Int. |
| execution/engineapi/engine_server_getpayload_test.go | Update stub GetTD signature to return *uint256.Int. |
| execution/abi/bind/auth.go | Convert *big.Int chainID to *uint256.Int at signing boundary. |
| db/rawdb/accessors_chain.go | Store/read TD as uint256 (encoding unchanged); compare to TTD via CmpBig. |
| db/rawdb/accessors_chain_test.go | Update TD storage tests to use uint256. |
| db/consensuschain/consensus_chain_reader.go | Update consensus chain reader GetTd to return *uint256.Int. |
| cmd/utils/app/import_cmd.go | Sum side-chain TD with uint256 + overflow checks and persist via new rawdb API. |
| cmd/rlpgen/testing/testing_struct.go | Remove big.Int fields from rlpgen test fixture. |
| cmd/rlpgen/testing/gen_testingstruct_rlp.go | Regenerate fixture RLP code without big.Int paths. |
| cmd/rlpgen/testing/encdec_test.go | Remove big.Int random generation/comparisons from rlpgen tests. |
| cmd/rlpgen/matcher.go | Remove big.Int / *big.Int handler mapping from rlpgen. |
| cmd/rlpgen/handlers.go | Remove big.Int handlers from rlpgen generator. |
Files not reviewed (1)
- cmd/rlpgen/testing/gen_testingstruct_rlp.go: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Removed in the prior commit's simplification of ReadChainHeadWithTx (rawdb.ReadTd now returns *uint256.Int directly) but the helper was left behind. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The earlier hedge — keeping TerminalTotalDifficulty as *big.Int for JSON wire compatibility — was unnecessary. uint256.Int.UnmarshalJSON accepts both quoted decimal strings and unquoted decimal numbers, so every existing chainspec / DB-stored chain config still parses. The only output-side change is that re-marshaling a Config now emits the field as a quoted decimal string instead of an unquoted JSON number; Erigon round-trips its own writes fine, and external consumers that deal with TTD already need string/BigInt handling since 5.9e22+ does not fit in a JS Number. Side effects of the migration: - All 5 TTD comparisons drop CmpBig in favor of plain Cmp. - Transitioned(..., terminalTotalDifficulty *uint256.Int) and HeaderDownload.InsertHeader / InsertHeaders take *uint256.Int. - header_algos blocksToTTD estimation is now pure uint256 (no big.Int conversion of lastD or returnTd). - chainspec.IsChainPoS / hasChainPassedTerminalTD and readCurrentTotalDifficulty / currentTDProvider thread *uint256.Int. - TestChain/testforks initializers use uint256.NewInt(0). Verified manually that existing chainspec JSON (mainnet, gnosis, chiado, sepolia, bloatnet) all fit comfortably in uint256 and parse unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…pers
The earlier hedge — keeping LatestSignerForChainID and
NewKeyedTransactorWithChainID on *big.Int while the rest of the
signing stack moved to uint256 — was leftover lint. Both helpers
already converted *big.Int to uint256.Int internally, so callers
were paying for a pointless round-trip.
Migrate both helpers to *uint256.Int. Callers either:
- drop a redundant `.ToBig()` (where the local was already uint256),
- replace `big.NewInt(N)` literals with `uint256.NewInt(N)`,
- or wrap a *big.Int chain.Config.ChainID at the call site via
`uint256.MustFromBig(...)` (chain.Config.ChainID stays *big.Int
for now — separate scope, similar JSON wire shape concern).
Touches signer/test plumbing across cmd/rpcdaemontest, cmd/pics,
db/snapshotsync, execution/{engineapi,execmodule,state,tests,types,
abi/bind,verify}, rpc/{ethapi,jsonrpc}, polygon, txnprovider/{txpool,
shutter}, and a few other test helpers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The last *big.Int holdout in the TD/chainID migration. Existing
chainspec JSON parses fine (uint256.Int.UnmarshalJSON accepts both
unquoted decimal numbers and quoted strings); the WriteChainConfig DB
JSON round-trips since the read side accepts both. All known chainIDs
(mainnet=1, sepolia=11155111, gnosis=100, chiado=10200, hoodi=560048,
holesky=17000) are well within uint256.
Touches 54 files:
- chain.Config.ChainID and chain.Rules.ChainID typed *uint256.Int
- evmtypes.BlockContext.Rules uses uint256 directly; drops math/big
- All ChainID: big.NewInt(N) initializers in chain spec + tests
switched to uint256.NewInt(N)
- uint256.MustFromBig(cfg.ChainID) round-trips dropped throughout
(signer construction, transaction signing, RPC, txpool, etc.)
- aa_transaction.PaymasterFrame/ValidationFrame now take *uint256.Int
- GraphQLAPI.GetChainID returns *uint256.Int
- engineapitester.{Transactor, EngineApiTester.ChainId()} return
*uint256.Int; testhelpers.NewContractsDeployer takes *uint256.Int
- TransactionTest.Run(chainID *uint256.Int)
Boundary carve-outs kept as *big.Int (geth-compat / JSON-RPC):
- eth_simulation args.ChainID: (*hexutil.Big)(cfg.ChainID.ToBig())
- NewRPCBorTransaction emits (*hexutil.Big)(chainId.ToBig())
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 121 out of 122 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- cmd/rlpgen/testing/gen_testingstruct_rlp.go: Language not supported
Comments suppressed due to low confidence (1)
execution/abi/bind/auth.go:47
- After changing NewKeyedTransactorWithChainID to accept *uint256.Int, there are still call sites passing *big.Int (e.g., execution/abi/bind/bind_test.go uses big.NewInt(1337)), which will cause compile failures in tests. Update remaining callers/imports to use uint256.NewInt / uint256.MustFromBig at the boundary.
// NewKeyedTransactorWithChainID is a utility method to easily create a transaction signer
// from a single private key.
func NewKeyedTransactorWithChainID(key *ecdsa.PrivateKey, chainID *uint256.Int) (*TransactOpts, error) {
keyAddr := crypto.PubkeyToAddress(key.PublicKey)
if chainID == nil {
return nil, ErrNoChainID
}
signer := types.LatestSignerForChainID(chainID)
return &TransactOpts{
…ansaction
uint256.Int.Format is defined on *Int, not Int. Passing a dereferenced
value (*txnChainId) to %d boxes it into interface{}, fmt cannot take
its address, and the format reverts to the underlying [4]uint64 array
("[42 0 0 0]" instead of "42"). Pass the pointer (txnChainId)
directly so the Formatter method on *Int is invoked.
Caught by Copilot reviewer on the prior ChainID -> *uint256.Int
migration commit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Last big.Int TD field in the migration. No in-tree readers — only the two OnBlockStart construction sites in protocol/block_exec.go and stagedsync/exec3.go, both of which now pass chainReader.GetTd(...) directly without the .ToBig() / tdBig dance. Drops one allocation per traced block. Mechanical break for downstream tracers that implement OnBlockStart against this package; the fix is event.TD.ToBig() at the reader. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Leftover lint from the rawdb.ReadTd -> *uint256.Int migration: the testFork callback was still typed func(td1, td2 *big.Int), so the TD values had to be round-tripped via .ToBig() at the rawdb boundary to feed into the comparator. Migrate the comparator and the local tdPre/tdPost vars to *uint256.Int directly, and assign tdPre/tdPost straight from rawdb.ReadTd. No behavior change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Match the flag's declared type to its usage. The ChainID accessor was already migrated to ctx.Uint64(...) when chain.Config.ChainID became *uint256.Int; declaring the flag itself as cli.Uint64Flag closes the mismatch and (per Copilot review) avoids any subtle accessor-type quirk in urfave/cli. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two leftovers from the migration: - execution/types/transaction_test.go: TestEIP2930Signer's table-driven chainID was *big.Int with `uint256.MustFromBig(test.chainID)` at the SigningHash call. Re-type to *uint256.Int and drop the wrapper. - p2p/protocols/eth/handler.go: NodeInfo.Difficulty was *big.Int with td256.ToBig() at the assign site. Re-type to *uint256.Int — same JSON wire-shape concession as TerminalTotalDifficulty (UnmarshalJSON accepts both unquoted decimal and quoted strings). CallArgs.ChainID in rpc/ethapi/api.go intentionally stays *hexutil.Big: that file has 44 *hexutil.Big fields representing the hex-encoded JSON-RPC wire convention; introducing a hexutil.U256 to migrate ChainID alone would be asymmetric and is well out of scope for this PR. The conversion to uint256 happens internally at the boundary. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts: # execution/chain/chain_config.go
taratorio
approved these changes
May 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Migrate total difficulty and chain ID from
*big.Intto*uint256.Int(oruint256.Int) across the codebase, and drop the rlp package's reflect-basedbig.Intsupport that's no longer needed.Total difficulty
NewBlockPacket.TDandrawdb.ReadTd/ReadTdByHash/WriteTduseuint256.Int. Wire and DB bytes are unchanged —uint256.Intencodes to the same canonical big-endian RLP asbig.Int.chain.Config.TerminalTotalDifficulty *uint256.Int. Existing chainspec JSON parses without changes (uint256'sUnmarshalJSONaccepts both unquoted decimal numbers and quoted strings); the DB-stored config round-trips through Erigon. Re-marshaling emits a quoted decimal string instead of an unquoted JSON number; Erigon reads either.rules.ChainHeaderReader.GetTd,ethash.ShouldReorg,headerdownload.HeaderInserter(incl.FeedHeaderFunc/FeedHeaderPoW/GetLocalTd),execmodule.ExecutionModule.GetTD, polygonExecutionClient.GetTd,p2p.Publisher.PublishNewBlock+publishTask.td,sentry_multi_client.BroadcastNewBlock,bodydownload.BlockPropagator,ethstats.assembleBlockStats,rawdb.Transitioned,chainspec.IsChainPoS/currentTDProvider, the engineapinewPayloadTD var,tracing.BlockEvent.TD,eth.NodeInfo.Difficulty, and thetestForkcomparator inexecution/tests/blockchain_test.go.FeedHeaderPoW,InsertBlocks,rawdbresetsnapshot fill,checkPrefetchedBlock,import_cmd.goside-chain accumulator) usesAddOverflowand surfaces overflow as an error (or a logged skip on the propagator's best-effort path) —uint256.Int.Addsilently wraps, unlikebig.Int.Add.Transaction chainID
chain.Config.ChainID *uint256.Intandchain.Rules.ChainID *uint256.Int. Same JSON-shape concession as TerminalTotalDifficulty — existing chainspec JSON parses unchanged.Transaction.SigningHash(chainID *uint256.Int)interface + 7 implementations; the 5*SigHashstructs'ChainIDfields are*uint256.Int.LatestSignerForChainIDandNewKeyedTransactorWithChainIDtake*uint256.Intdirectly.evmtypes.BlockContext.Rulesbuildschain.Rulesin uint256 directly (dropsmath/big).cmd/evm/t8ntoolChainIDFlagswitched fromcli.Int64Flagtocli.Uint64Flagto match the type now consumed downstream.chain_id < 2**256; the stagnant EIP-2294 even proposes a ~2^63 chainID bound. uint256 strictly contains every chainID the protocol can use. Largest in-tree chainID is sepolia at 11,155,111.RLP big.Int support removed
With every production TD and chainID off
*big.Int, no type in this repo encodes/decodes*big.Intvia the rlp package anymore. Removed:rlp.EncodeBigInt,rlp.BigIntLen,rlp.ErrNegativeBigIntwriteBigIntPtr,writeBigIntNoPtr,decodeBigInt,decodeBigIntNoPtr, thebigIntreflect type var, and the dispatch entries inmakeWriter/makeDecoderStream.BigInt,Stream.decodeBigInt,encBuffer.writeBigInt,EncoderBuffer.WriteBigIntcmd/rlpgenbigIntHandle/bigIntPtrHandlecode paths and thebig.Int/*big.Intfields in the rlpgen testing fixture (regenerated)The legacy
ethereum/testsrlptest.json/bigintvector encodes 2^256 — above the uint256 ceiling — soTestRLPSkipLoads it with a comment citing EIP-7702 / EIP-2294. The othermediumint*vectors fit in uint256 and round-trip throughtranslateJSONviauint256.FromBig.JSON-RPC carve-outs (intentionally kept
*hexutil.Big)Hex-encoded JSON-RPC wire types remain
*hexutil.Big(which is*big.Intunder the hood) since the JSON-RPC convention is hex-encoded big numbers. Conversion to*uint256.Inthappens internally at the boundary:rpc/ethapi/api.go CallArgs.ChainID(and the 43 other*hexutil.Bigfields in the same struct family)eth_simulationargs.ChainIDNewRPCBorTransactionchainId field on the JSON responseIntroducing a
hexutil.U256shim to migrate these would be a separate refactor.Downstream impact
tracing.Hooks.OnBlockStart(event tracing.BlockEvent)against Erigon's tracing package see a compile error onevent.TDif they treat it as*big.Int; one-line fix isevent.TD.ToBig()at the read site.github.com/erigontech/erigon/execution/rlpthat call the removedrlp.EncodeBigInt/rlp.BigIntLen/Stream.BigInthelpers will break; switch to the uint256 equivalents or do the conversion at the boundary.admin_nodeInfoJSON output for thedifficultyfield shifts from an unquoted decimal number to a quoted decimal string (same shape asterminalTotalDifficulty). Most consumers treating it as a big number string already accept both.Test plan
make lint— 0 issuesmake erigon integration— clean buildgo test -short ./...— passes locallychain.ConfigJSON round-trip: existing unquoted-decimal genesis input parses; new quoted-string output re-parsesDiff size
124 files, +432 / −765 — more code removed than added.
🤖 Generated with Claude Code