Repository navigation
Conversation
|
⛔ Snyk checks have failed. 23 issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
This fixes a truncation bug that results in an invalid serialization of
empty EIP712.
For example:
```json
{
"method": "eth_signTypedData_v4",
"request": {
"types": {
"EIP712Domain": [
{
"name": "version",
"type": "string"
}
],
"Empty": []
},
"primaryType": "Empty",
"domain": {
"version": "0"
},
"message": {}
}
}
```
When calculating the type-hash for the stuct-hash, it will incorrectly
use `Empty)` instead of `Empty()`
runtime.setDefaults was unconditionally assigning cfg.Random =
&common.Hash{}, which silently overwrote any caller-provided Random
value. This made it impossible to simulate a specific PREVRANDAO and
also forced post-merge rules whenever London was active, regardless of
the intended environment.
This change only initializes cfg.Random when it is nil, matching how
other fields in Config are defaulted. Existing callers that did not set
Random keep the same behavior (a non-nil zero hash still enables
post-merge semantics), while callers that explicitly set Random now get
their value respected.
Fixes #34108 The UDPv5 test harness (`newUDPV5Test`) uses the default `PingInterval` of 3 seconds. When tests like `TestUDPv5_findnodeHandling` insert nodes into the routing table via `fillTable`, the table's revalidation loop may schedule PING packets for those nodes. Under the race detector or on slow CI runners, the test runs long enough for revalidation to fire, causing background pings to be written to the test pipe. The `close()` method then finds these as unmatched packets and fails. The fix sets `PingInterval` to a very large value in the test harness so revalidation never fires during tests. Verified locally: 100 iterations with `-race -count=100` pass reliably, where previously the test would fail within ~50 iterations.
… (#34043) This fixes the remaining Hive discv5/FindnodeResults failures in the cmd/devp2p/internal/v5test fixture. The issue was in the simulator-side bystander behavior, not in production discovery logic. The existing fixture could get bystanders inserted into the remote table, but under current geth behavior they were not stable enough to remain valid FINDNODE results. In particular, the fixture still had a few protocol/behavior mismatches: - incomplete WHOAREYOU recovery - replies not consistently following the UDP envelope source - incorrect endpoint echoing in PONG - fixture-originated PING using the wrong ENR sequence - bystanders answering background FINDNODE with empty NODES That last point was important because current lookup accounting can treat repeatedly unhelpful FINDNODE interactions as failures. As a result, a bystander could become live via PING/PONG and still later be dropped from the table before the final FindnodeResults assertion. This change updates the fixture so that bystanders behave more like stable discv5 peers: - perform one explicit initial handshake, then switch to passive response handling - resend the exact challenged packet when handling WHOAREYOU - reply to the actual UDP packet source and mirror that source in PONG.ToIP / PONG.ToPort - use the bystander’s own ENR sequence in fixture-originated PING - prefill each bystander with the bystander ENR set and answer FINDNODE from that set The result is that the fixture now forms a small self-consistent lookup environment instead of a set of peers that are live but systematically poor lookup participants.
This is meant to be run daily, in order to verify the FreeBSD build wasn't broken like last time.
Adds config to add Prague prune point for the hoodi testnet.
Optimizes the transient storage. Turns it from a map of maps into a single map keyed by <account,slot>.
This PR simplifies the implementation of EIP-7610 by eliminating the
need to check storage emptiness during contract deployment.
EIP-7610 specifies that contract creation must be rejected if the
destination account has a non-zero nonce, non-empty runtime code, or
**non-empty storage**.
After EIP-161, all newly deployed contracts are initialized with a nonce
of one. As a result, such accounts are no longer eligible as deployment
targets unless they are explicitly cleared.
However, prior to EIP-161, contracts were initialized with a nonce of
zero. This made it possible to end up with accounts that have:
- zero nonce
- empty runtime code
- non-empty storage (created during constructor execution)
- non-zero balance
These edge-case accounts complicate the storage emptiness check.
In practice, contract addresses are derived using one of the following
formulas:
- `Keccak256(rlp({sender, nonce}))[12:]`
- `Keccak256([]byte{0xff}, sender, salt[:], initHash)[12:]`
As such, an existing address is not selected as a deployment target
unless a collision occurs, which is extremely unlikely.
---
Previously, verifying storage emptiness relied on GetStorageRoot.
However, with the transition to the block-based access list (BAL),
the storage root is no longer available, as computing it would require
reconstructing the full storage trie from all mutations of preceding
transactions.
To address this, this PR introduces a simplified approach: it hardcodes
the set of known accounts that have zero nonce, empty runtime code,
but non-empty storage and non-zero balance. During contract deployment,
if the destination address belongs to this set, the deployment is
rejected.
This check is applied retroactively back to genesis. Since no address
collision events have occurred in Ethereum’s history, this change does
not
alter existing behavior. Instead, it serves as a safeguard for future
state
transitions.
… `testing_buildBlockV1` (#34722) This is a copy of #34721 but against `master` (rather than `bal-devnet-3`), as requested by @jwasinger, since the slotnum logic now exists on `master` as well.
…y (#34723) StateDB.Commit first commits all storage changes into the storage trie, then updates the account metadata with the new storage root into the account trie. Within StateDB.Commit, the new storage trie root has already been computed and applied as the storage root. This PR explicitly skips the redundant storage trie root assignment for readability.
Auto-enable logic for `StatelessSelfValidation` was reading CLI flag directly via `ctx.Bool()`, bypassing the merged `cfg.EnableWitnessStats` value. Now uses `cfg.EnableWitnessStats` so config file settings trigger the same auto-enable behavior as CLI flags.
Changes the log handler to check for vmodule level overrides even for messages above the current level. This enables the user to selectively hide messages from certain packages, among other things. Also fixes a bug where handler instances created by WithAttr would not follow the level setting anymore. The WithAttrs method is calledd by slog.Logger.With, which we also use in go-ethereum to create context specific loggers with pre-filled attributes. Under the previous implementation of WithAttrs, if the application created a long-lived logger (for example, for a specific peer), then that logger would not be affected by later level changes done on the top-level logger, leading to potentially missed events. Closes: #30717 --------- Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de> Co-authored-by: Felix Lange <fjl@twurst.com>
`trace.noreturndata` is documented as "enable return data output" but the flag name/value imply it disables return data. This is confusing for users and likely inverted wording. Update the Usage string to reflect the actual behavior (disable return data output).
…34700) This Pr implements some prerequisite changes for #34004 : split the `CachingDB` into a `MerkleDB` and a `UBTDB`, so that very different behaviors don't clash as much. The transition isn't handled by this PR, but after talking to Gary we agreed that `UBTDB` should receive another `triedb`, which will only be loaded if the `Ended` flag is set to false in the conversion contract. If this is too hard to achieve, it makes sense to load it regardless, and then loading can be prevented at a later stage by adding a `UBTTransitionFinalizationTime` in `ChainConfig`. --------- Co-authored-by: Gary Rong <garyrong0905@gmail.com>
Adds a 'code' exporter to 'geth db export' that iterates over all contract bytecode entries (CodePrefix + code_hash -> bytecode). Usage: geth --datadir <dir> db export code code.rlp This enables exporting contract bytecode.
…tlptracehttp from 1.34.0 to 1.43.0 (#3637) Co-authored-by: allformless <213398294+allformless@users.noreply.github.com>
merge: develop to master for v1.7.3
…entity (#34733) `timedExec` compares errors by direct interface inequality (haveErr != err). If execFunc returns newly constructed errors with the same message each run, this will panic even though behavior is equivalent.
… amplification (#34754) ## Problem `BinaryTrie.Commit` unconditionally walked every resolved in-memory node and flushed it into the `NodeSet`, producing one Pebble write per resolved internal + stem node on every block — even when the node's on-disk blob was bitwise identical to the previous commit. On a warm 400M-state workload this meant tens of thousands of redundant 65-byte writes per block, compounding Pebble compaction pressure on every commit. The existing `mustRecompute` flag tracks *hash* staleness, not *disk-blob* staleness: after `Hash()` completes, `mustRecompute` is cleared even though the fresh blob has not been persisted. It is therefore insufficient for a skip-flush optimization. ## Fix Mirror the MPT committer pattern (`trie/committer.go:51-56`) by adding a `dirty` flag on `InternalNode` and `StemNode` with the semantics *the on-disk blob is stale*. The flag is: - set to `true` wherever the node is created or structurally modified (the same call sites that already set `mustRecompute = true`); - set to `false` only after the node has been passed to the `flushfn` inside `CollectNodes`; - left `false` on nodes produced by `DeserializeNodeWithHash`, matching the *loaded from disk, already persisted* semantics. `CollectNodes` short-circuits on `!dirty` subtrees. The propagation invariant (an ancestor of any dirty node is itself dirty) is already maintained by the existing `InsertValuesAtStem` / `Insert` paths, which now mirror every `mustRecompute = true` setter with a `dirty = true` setter. ## Benchmark New `BenchmarkCollectNodes_SparseWrite` measures commit cost when only one leaf changes between blocks — the common case for state updates. 10,000-stem trie, one-leaf modification + Commit per iteration, Apple M4 Pro: | | before | after | delta | |---|---|---|---| | time / op | 12,653,000 ns | 7,336 ns | **~1,725×** | | bytes / op | 107,224,740 B | 37,774 B | **~2,839×** | | allocs / op | 80,953 | 134 | **~604×** | End-to-end impact on a real workload depends on the resolved-footprint-to-dirty-path ratio; the new `TestBinaryTrieCommitIncremental` provides a structural regression guard (asserts that a Commit following a single-leaf modification flushes a root-to-leaf path, not the whole tree). --- Found all of this stuff while bloating my #34706 DB to make some benchmarks. And saw we were spending A LOT OF TIME on hashing. Hope this helps the perf a bit. Will rebase the flat-state PR on top of this once merged.
…e Amsterdam BlockAccessListHash (EIP-7928) and SlotNumber (EIP-7843) are trailing rlp:"optional" header fields that are covered by the block hash but not by the Parlia seal preimage (EncodeSigHeader stops after RequestsHash). Parlia's header verification never validated them, so before Amsterdam an unprivileged peer could append a crafted BlockAccessListHash to any validator-signed block: RLP-valid, seal preimage and signature unchanged, but a different block hash. Every node accepted the mutated block as validly sealed, letting a peer with no stake or key grind the block hash of an honest validator's block (e.g. to bias BLOCKHASH-based consumers or win a same-height lower-hash fork-choice tie). Validate these fields in VerifyUnsealedHeader, which is on the peer-import path (VerifyHeader -> verifyHeader -> VerifyUnsealedHeader, before verifySeal) as well as the bid pre-seal path, mirroring the existing RequestsHash/ParentBeaconRoot handling: require them absent before Amsterdam and present from Amsterdam on. This closes the live pre-Amsterdam malleability; from Amsterdam the fields are legitimately present and their content is bound by state validation and the slot rules. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* miner: persist BidBlock revokes across restarts * miner: journal BidBlock revokes under datadir instead of chaindata * miner: version the BidBlock revoke journal and pin its keys
* internal/ethapi: introduce gRPC endpoint for mev send bidblock request * internal/ethapi: expose MEV protobuf definitions * internal/ethapi: preserve MEV error details over gRPC * eth, miner: configure MEV gRPC by port
…e at Jenner verifyDoubleSignEvidence charges a flat DoubleSignEvidenceVerifyGas regardless of input size, while Run computes SealHash over both RLP-decoded headers whose Extra fields are not size-bounded, so the metered cost does not track the hashing work. Add a Jenner-gated variant (verifyDoubleSignEvidenceJenner) pricing per input byte (DoubleSignEvidenceVerifyPerByteGas = 16), mirroring 0x67's cometBFTLightBlockValidatePasteur. Verification logic inherited unchanged; pre-Jenner tables (including Pasteur) keep the flat-gas contract. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Expose Miner.Config.DelayLeftOver via mev_params so builders can compute BidMustBefore per validator instead of hardcoding 15ms.
…r-nil consensus/parlia: validate BlockAccessListHash and SlotNumber in header verification
core/vm: price the 0x68 double-sign-evidence precompile per input byte at Pasteur
* params: add the Jenner fork and the CAS20 governance constant
Jenner is the fork BEP-702 ships in. IsOnJenner marks the single block that
crosses into it, and it counts block 1 as that block on a chain whose genesis is
already Jenner-active — such a chain has no false-to-true transition to find, and
the fork's state changes have to be applied somewhere or the feature can never be
bootstrapped.
CAS20GovHubAddress duplicates GovHub's fixed system address, which
core/systemcontracts cannot supply because it imports core/vm and so cannot be
imported back. It is the one address a governance proposal can reach the
activation registry through, and it is the same on every network — which is why
the switch can be a constant rather than configuration.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm: add the stateful-precompile host and the CAS20 token family
Two layers, in one commit because they do not compile apart: the host's AddLog
meters through a charge helper the family defines.
**The host.** A StatefulPrecompiledContract receives a PrecompileContext
carrying the StateDB, the caller, the call-form guards and dynamic gas
accounting, so a precompile can read and write consensus state. RequiredGas
reports nothing, because a stateful cost depends on state not yet read — whether
a slot is cold, whether a write creates or rewrites — so metering happens inside
the handler as the work is performed. Existing precompiles and
RunPrecompiledContract are untouched.
Gas accounting is frame-scoped and sticky. A refused charge marks the frame and
every later charge on it refuses too, so one failure ends the call rather than
letting the rest of a handler run on an exhausted budget; the exit turns that
mark into ErrOutOfGas whatever the handler returned. Charges mirror the
interpreter's own cost functions — EIP-2929 warm/cold, EIP-2200 net metering with
EIP-3529 refunds, the EIP-2200 reentrancy sentry, LOG and KECCAK256 prices — so
nothing a CAS20 call does is cheaper than the same work through bytecode.
**The family.** A factory at a fixed address derives a token's address from
(variant, creator, salt) and plants a one-byte 0xEF sentinel there; the token
holds no executable code, is routed by its address prefix, and keeps its state
under that address in ERC-7201 namespaces. Two variants — Asset, with the
ERC-8056 scaled multiplier and disclosure announcements, and Stablecoin — share
the shared ERC-20 surface, role-based access control, a pause mask, EIP-2612
permit, and transfer policies resolved through a singleton PolicyRegistry. An
ActivationRegistry holds the per-feature switch that gates creation and policy
writes, and never reaches a token that already exists.
Every state write is metered before it happens and refused in a read-only frame
by the metering layer itself, so a handler that forgot its own guard cannot write
during a STATICCALL. Malformed calldata and unknown selectors revert with empty
returndata rather than a selector echo, keeping one client's internal strings out
of consensus.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/systemcontracts: plant the CAS20 registry sentinels at the fork
The two singleton registries hold storage and no code, so EIP-161 would clear
them and their storage with them. They are precompiles rather than upgradeable
contracts, so the sentinels are planted here instead of through an Upgrade
config, and nothing else is written: no feature is opened and there is no admin
to seed, the activation admin being governance's to appoint afterwards.
The sentinels are also what make that appointment possible. GovHub refuses a
proposal target carrying no code and reports the refusal in an event while
leaving the proposal itself successful, so a registry without one could never
receive its first parameter change and the failure would read as a success.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm: answer as an equivalent Solidity contract does
Nine places where the precompiles answered differently from the contract they
stand in for. None was reachable from a test the suite had, because the checks
that would have caught them compared our own artifacts against each other.
Argument decoding. A malformed narrow argument is a decode failure, and
Solidity's external decoder reverts with empty returndata for every one of them:
an integer outside an enum's range, a bool that is neither 0 nor 1, a uint8 or
address carrying padding a caller could not have produced, a bytes4 with nonzero
trailing bytes. Measured against solc 0.8.16 and 0.8.19, which agree. Panic(0x21)
comes from an internal uint-to-enum cast and never from argument handling, so
seven sites raising it were reporting a failure Solidity does not report there;
supportsInterface answered false for an encoding it should have refused. The six
Panic(0x11) sites are arithmetic overflow and stay.
PolicyRegistry. The registry's absence error carries no id — the caller named the
policy — and the parameterized form belongs to a token reporting an id it could
not find; two composite paths used the token's. createCompositePolicy checked the
type before the zero-admin guard, where the two simple constructors check the
admin first; all three now agree, and the order is observable through which error
a caller receives. Child validation ran one interleaved pass per child, so a set
naming both an ineligible child and a missing one reported whichever came first;
it now runs existence over the whole set before eligibility over the whole set,
and a set holding both reports the absence. A sentinel was accepted as a child,
though it stores no membership for a composite to consult. And an INTERSECT over
no children answered false, alone among the four types in not taking its own
empty-set semantics: an AND over nothing is vacuously true, which makes a
never-created INTERSECT as permissive as a never-created BLOCKLIST already was.
Binding checks existence, so no token can reference either.
Storage. A string length word in the long form encodes 32 bytes or more; a
shorter one is as non-canonical as an oversized one and now reads as empty. The
word has two readers, and the second feeds setStringAt's release loop, so leaving
it out would have released chunks for a string the reader reports as absent.
Every change is witnessed: reverting any one of them fails a test.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm: open the token space at 0xCA52
The reserved prefix is two bytes, but the eight zero bytes that follow it are
part of the layout, so the first five hex digits of every token address are the
marker plus a zero the padding supplies for free. Spending the second byte on
0x52 makes those digits spell the standard's name; 0x50 spelled it without its
number.
Nothing structural moves. The factory keeps 0xCA5F, the registries keep 0x7020,
and the reserved-space audit was made against the whole 0xCA5 namespace rather
than the token prefix alone, so it covers this choice without being redone.
The one vector that names the prefix in full is the padding case, which has to
carry a valid marker to reach the check it is named for. It does, and deleting
the padding check still fails it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm: drop comments the identifier already makes
A doc comment that restates its own name costs a reader the time to find that
out. Eleven of them go; what stays is the half a name cannot carry.
Deleted outright where the signature was the whole story: eventTopic, revCAS20,
revCAS20Bytes, the policy precompile type, the core storage root. Trimmed to the
part that is not derivable elsewhere: the delegate-call error keeps why it is
refused rather than what it is, cas20ErrorSel keeps that it registers as well as
computes, and two exported accessors keep their one line and lose the examples of
who calls them.
Left alone: anything naming a consensus rule, a check order, or a distinction the
identifier does not draw — that a policy view is metered where the same type has
an unmetered constructor, which two of the four policy types count as composite,
that an empty metadata value clears rather than writes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm: plant the registry sentinels only at the fork
Remove the lazy ensureSentinel path that every registry write ran. On a
conforming chain it was unreachable: the fork transition seeds both
registries before any transaction, and it could not rescue the case it
existed for, since GovHub tests extcodesize before forwarding a
parameter change and would have refused the registry before the write
was ever attempted. What it did cost was a code-hash read per write.
With the admin appointed through governance rather than taken from
configuration, the fork hook is the only path that can plant the byte,
and it now stands alone. The sentinel tests that only exercised the lazy path go
with it; the seeded case gains a negative control showing a bare
account with the same storage is reaped by EIP-161 clearing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm: decode announce and batchMint arguments before the state checks
Solidity's dispatcher decodes a function's arguments before any
modifier runs, so calldata that does not decode is reported as such
whoever sent it and whatever the token's state. announce and batchMint
checked the pause, the role and the reentrancy flag first, answering a
business error for a payload that never named a valid call.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm: keep only the comments a name cannot carry
Delete a comment when the identifier or the body already says it, or
when a test pins the behaviour; keep, compressed, the why a name cannot
express and no test guards: check order, storage layout, deliberate
dead code, the gas and sentinel invariants. Test files lose the step
comments that restated their own assertion messages.
Dead code met on the way goes too: the unused cas20PendingMulBits, an
activate() call in a test whose result was discarded, updateMembers'
second identical bool check, and finalizeUpdateAdmin's zero-caller
clause already implied by the non-zero pending admin. readU64 now
delegates to u64FromWord instead of repeating its loop.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm: bound getStringAt's allocation by paid reads; log a foreign registry code
getStringAt allocated the stored length before any tail read was
charged, so a call forwarding too little gas could still trigger a
large allocation before running out. The buffer now grows only behind
reads that were paid for.
seedCAS20Sentinel finding code on a registry address can only mean an
address collision, so say so in the log instead of returning silently.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* params: write IsOnJenner the way IsOnPasteur is written
Drop the arm that treated block 1 as the fork boundary on a chain born
Jenner-active. CAS20MarkerCode is exported so such a chain carries the
registry sentinels in its genesis allocation, as the other system
accounts do; the boundary predicate then needs no special case and
reads like the other IsOn* helpers. Also restore UBTTime to its place
in the aligned field block.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm: answer newUIMultiplier with the current multiplier when nothing is scheduled
It returned the raw pending lane, which is zero for a new token, after an
instant update and after a cancellation. ERC-8056 answers with
the effective multiplier whenever no schedule is live.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm, internal/ethapi: add cas20_getTokenInfo
A wallet reading one CAS20 token today issues a dozen eth_calls against
the same address, and reconstructing a consistent view of the scheduled
multiplier from multiplier, newUIMultiplier and effectiveAt across
separate calls is racy across blocks. cas20_getTokenInfo(address, block)
answers the whole configuration from one state, variant-tagged, with the
effective multiplier already folded and a pending schedule reported only
while it is live; cas20_getTokenInfoBatch does the same over up to twenty
addresses, answering null for one that holds no token.
The facade reads through the unmetered storage accessors and is bounded
against state the precompile could not have written: a string longer than
256 KiB is refused rather than walked. The namespace is not in the default
module list.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* internal/ethapi: serve the CAS20 token info from the eth namespace
eth_getCAS20TokenInfo and eth_getCAS20TokenInfoBatch, beside the other
BSC additions to eth_, so no extra module has to be enabled.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm: decode before the static-frame guard in every token method
pause, batchMint and announce refused a static frame before decoding
their arguments, while every other token method decodes first, so the
same malformed calldata under STATICCALL reported StaticCallNotAllowed
from three methods and an empty revert from the rest. The order is
observable and therefore consensus; every token method now shares one
prefix. The factory and the registries keep their guard before decoding.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm: refuse a code write in a static frame at the metering layer
chargeStorageWrite and AddLog already mark the frame write-protected, so a
handler missing its own guard fails closed; chargeCodeWrite did not, and
the factory's SetCode was covered only by the entry-point guard. Now every
mutation the family performs is refused at the point of mutation as well.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm: name the standard, not another implementation, in comments
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm: charge each internal dispatch what the reference contract pays
The bytes[] decoder accepts entries whose offsets alias one another, so an
announce bundle or an initCalls array of size O(N+M) could name N×M
dispatches, and a constant getter reads no state, so each one ran for
nothing: 12.5M dispatches fit in a 15M-gas transaction and took 746 ms.
Every entry now pays a warm CALL plus the copy of its own bytes before it
runs, which is what the reference contract pays to route it through a call
of its own. Aliasing stays accepted; it is no longer free.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/systemcontracts: pin the CAS20 GovHub constant to GovHubContract
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm: make the dispatch-charge test run out of gas inside the loop
The negative case's budget could not pay for the announcement itself, so it
never reached the loop it claimed to test. It now pays for the announcement
and exactly 200 dispatches, then for a hundred fewer.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/tracing, core/vm, eth/tracers: announce native storage access to tracers
The prestate and access-list tracers discover storage through the SLOAD and
SSTORE opcodes, and a CAS20 operation executes none: a traced transfer
showed no token storage, diffMode missed the balance change, and
eth_createAccessList returned an empty list. A new OnStorageRead hook fires
for every slot a stateful precompile reads or is about to write; the two
tracers consume it and see the same slots bytecode would have shown them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm, internal/ethapi: let a code override reach a CAS20 address
StateOverride.Apply removed an overridden address from the static precompile
map, but a CAS20 address is routed by prefix, so the call still reached
native code and reverted against the replaced marker. An override on such
an address now leaves a DisabledPrecompile marker in the map, which dispatch
reads as "ordinary account"; on-chain routing is untouched.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/tracing, eth/tracers, internal/ethapi: finish the native-access tracing
Three gaps in the previous two commits. An account read had no hook, so a
token appeared in a prestate only once a slot was touched, and createCAS20's
new account was captured after its sentinel was written: the prestate showed
the code as pre-existing and the diff missed its creation. OnAccountRead now
fires before every native account read, from the existence check and the
factory's occupancy check alike. The mux tracer did not forward the new
hooks, so a prestate tracer requested beside a call tracer lost every CAS20
slot again. And eth_createAccessList applied overrides against a nil
precompile map, which a CAS20 code override then wrote to; it now builds the
set, applies the overrides to it and hands it to the EVM it simulates with.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm: let a memo transfer declare the format its payload follows
A memo is a 32-byte hash, and a hash says nothing about how the payload
behind it is encoded: an indexer or a receiving institution cannot tell
which message format a transfer claims to follow, or parse the payload it
receives out of band, without a side channel.
transferWithMemoFormat(to, amount, memo, formatId)
transferFromWithMemoFormat(from, to, amount, memo, formatId)
run the ordinary memo transfer of their own entry point — the transferFrom
form is transferFrom whoever calls it, so a holder moving its own balance
spends its self-approval as through transferFromWithMemo — and emit
MemoFormatDeclared(declarer, memo, formatId) right after Memo, so an indexer
ties the declaration to its transfer by log position. The formatId is one
bytes32 naming a format definition maintained off chain: composing several
standards is the definition's business, not the chain's. The chain records
the declaration and nothing more — it never sees the payload, so it never
verifies the claim, and it keeps no registry of formats. A zero formatId is
refused; the plain memo methods are how a transfer declares nothing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* core/vm: consolidate cas20 abi helpers
* core/tracing, core/vm, eth/tracers: clarify native access hook contracts
* core/vm: simplify gas accounting and compare native access costs
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…BEP-714) (#3822) * consensus/parlia, core/systemcontracts: implement BEP-714 client changes for Jenner
…er, drop dead StateOverride copy (#3826) * core/vm: emit CAS20Created before the admin grant and initCalls CAS20Created is the token's identity record. Emit it as soon as that identity is written, ahead of the initial RoleGranted and whatever the initCalls log, so a creation transaction's logs read in the order the state was built. The event test pins the order. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * core/vm: run the bootstrap window as the factory initCalls are calls the factory makes into the new token, so the token should see the factory as msg.sender, as it would for any contract the factory called. Running them as the creator let the factory act in the creator's name: approve, transfer, burn and the renounce methods inside the window operated on the creator's balances and roles, a power no ordinary caller of the token has. The initial admin's RoleGranted names the factory as sender for the same reason. No test relied on the old caller; the event test now pins the new one. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * internal/ethapi: drop the unused StateOverride copy internal/ethapi/override owns OverrideAccount, StateOverride and Apply, and every RPC path uses that package. The copy left in api.go was reachable only from a test that the override package already carries, and it lacked the DisabledPrecompile handling the live Apply gained, so a future caller pointed at it would silently lose CAS20 override routing. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
#3825) * eth/protocols/eth: fix deadlock when re-requesting partial receipts (#35537) When an eth/70 receipts response arrives with LastBlockIncomplete set, requestPartialReceipts re-requested the remainder while holding receiptBufferLock across the dispatch. That dispatch blocks until the dispatcher loop accepts the request. If the loop is concurrently cancelling a request for that peer, its cleanup takes the same receiptBufferLock. The dispatcher then waits for the lock the re-request holds while the re-request waits on a channel only the dispatcher reads. The fix releases the lock before sending and routes the follow-up through the dispatcher as a new resend request. --------- Co-authored-by: Gary Rong <garyrong0905@gmail.com> (cherry picked from commit c57bbe4) * eth/protocols/eth, eth/downloader: reject empty partial receipt responses (#35593) eth/70 can complete a receipts request over multiple round trips. Current implementation has two issues in requester side. 1. A peer could keep a request loop alive with incomplete responses that deliver no receipt. An incomplete response must now add at least one receipt. A trailing empty list after other blocks is still accepted. We already have a grace period and peer-dropping logic covering this, but an additional guard is nice to have. 2. Response.Time is recorded across all rounds, making the peer's roundtrip estimate incorrect. The dispatcher now counts the rounds made under a request id, and the downloader divides the delivered items and elapsed time to one round trip. (cherry picked from commit 596096a) * eth/protocols/eth: add regression tests for partial receipt cancellation and continuation --------- Co-authored-by: 0xSHKWON <kwonsanghyeon3245@naver.com> Co-authored-by: Gary Rong <garyrong0905@gmail.com> Co-authored-by: Bosul Mun <bosul.mun@ethereum.org>
…3847) * params: set bsc testnet jenner hardfork to 2026-10-29 02:30:00 AM UTC * chore: bump 1.8.1 for bsc testnet jenner hf
all: merge develop to master
params, version: prepare v1.8.2 for Mainnet Jenner hardfork
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.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )