Skip to content

Commit 0e65d31

Browse files
authored
Extend devnet test coverage (#19334)
This extends TestExecutionSpecBlockchainDevnet and has a technical fix which was preventing the paris tests from running caused by a deadlick from runing the parallel executor on domains in parallel tests. The hang is due to code in shared domains, so likley causes hangs in parallel runs with a serial executor. I have not investigated why multiple tests are run whith the same domain, becuase this does not cause logical errors, but conceivaly could do.
1 parent 84d91b8 commit 0e65d31

File tree

5 files changed

+88
-24
lines changed

5 files changed

+88
-24
lines changed

db/kv/kv_interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,7 @@ type TemporalMemBatch interface {
487487
ClearRam()
488488
IndexAdd(table InvertedIdx, key []byte, txNum uint64) (err error)
489489
IteratePrefix(domain Domain, prefix []byte, roTx Tx, it func(k []byte, v []byte, step Step) (cont bool, err error)) error
490+
HasPrefix(domain Domain, prefix []byte, roTx Tx) ([]byte, []byte, bool, error)
490491
SizeEstimate() uint64
491492
Flush(ctx context.Context, tx RwTx) error
492493
Close()

db/state/execctx/domain_shared.go

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -337,22 +337,7 @@ func (sd *SharedDomains) SetTrace(b, capture bool) []string {
337337
}
338338

339339
func (sd *SharedDomains) HasPrefix(domain kv.Domain, prefix []byte, roTx kv.Tx) ([]byte, []byte, bool, error) {
340-
var firstKey, firstVal []byte
341-
var hasPrefix bool
342-
err := sd.IteratePrefix(domain, prefix, roTx, func(k []byte, v []byte, step kv.Step) (bool, error) {
343-
// we need to do this to ensure the value has not been unwound
344-
if lv, _, ok := sd.mem.GetLatest(domain, k); ok {
345-
v = lv
346-
}
347-
if len(v) > 0 {
348-
firstKey = common.Copy(k)
349-
firstVal = common.Copy(v)
350-
hasPrefix = true
351-
return false, nil // do not continue, end on first occurrence
352-
}
353-
return true, nil
354-
})
355-
return firstKey, firstVal, hasPrefix, err
340+
return sd.mem.HasPrefix(domain, prefix, roTx)
356341
}
357342

358343
func (sd *SharedDomains) IteratePrefix(domain kv.Domain, prefix []byte, roTx kv.Tx, it func(k []byte, v []byte, step kv.Step) (cont bool, err error)) error {

db/state/temporal_mem_batch.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,13 @@ func (sd *TemporalMemBatch) putLatest(domain kv.Domain, key string, val []byte,
175175
func (sd *TemporalMemBatch) GetLatest(domain kv.Domain, key []byte) (v []byte, step kv.Step, ok bool) {
176176
sd.latestStateLock.RLock()
177177
defer sd.latestStateLock.RUnlock()
178+
return sd.getLatest(domain, key)
179+
}
178180

181+
// getLatest is the lock-free implementation of GetLatest.
182+
// The caller must already hold latestStateLock (either RLock or Lock),
183+
// e.g. from within an IteratePrefix callback.
184+
func (sd *TemporalMemBatch) getLatest(domain kv.Domain, key []byte) (v []byte, step kv.Step, ok bool) {
179185
var unwoundLatest = func(domain kv.Domain, key string) (v []byte, step kv.Step, ok bool) {
180186
if sd.unwindChangeset != nil {
181187
if values := sd.unwindChangeset[domain]; values != nil {
@@ -294,6 +300,24 @@ func (sd *TemporalMemBatch) IteratePrefix(domain kv.Domain, prefix []byte, roTx
294300
return AggTx(roTx).d[domain].debugIteratePrefixLatest(prefix, ramIter, it, roTx)
295301
}
296302

303+
func (sd *TemporalMemBatch) HasPrefix(domain kv.Domain, prefix []byte, roTx kv.Tx) ([]byte, []byte, bool, error) {
304+
var firstKey, firstVal []byte
305+
var hasPrefix bool
306+
err := sd.IteratePrefix(domain, prefix, roTx, func(k []byte, v []byte, step kv.Step) (bool, error) {
307+
if lv, _, ok := sd.getLatest(domain, k); ok {
308+
v = lv
309+
}
310+
if len(v) > 0 {
311+
firstKey = common.Copy(k)
312+
firstVal = common.Copy(v)
313+
hasPrefix = true
314+
return false, nil // do not continue, end on first occurrence
315+
}
316+
return true, nil
317+
})
318+
return firstKey, firstVal, hasPrefix, err
319+
}
320+
297321
func (sd *TemporalMemBatch) SetChangesetAccumulator(acc *changeset.StateChangeSet) {
298322
sd.currentChangesAccumulator = acc
299323
for idx := range sd.domainWriters {

execution/state/journal.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ func (ch selfdestructChange) revert(s *IntraBlockState) error {
237237
if ch.wasCommited {
238238
if trace {
239239
if v, ok := s.versionedWrites[ch.account][AccountKey{Path: SelfDestructPath}]; ok {
240-
fmt.Printf("%s WRT Revert %x: %d -> %d\n", tracePrefix, ch.account, v.Val, &ch.prev)
240+
fmt.Printf("%s WRT Revert %x: %v -> %v\n", tracePrefix, ch.account, v.Val, &ch.prev)
241241
}
242242
if v, ok := s.versionedWrites[ch.account][AccountKey{Path: BalancePath}]; ok {
243243
val := v.Val.(uint256.Int)
@@ -248,12 +248,16 @@ func (ch selfdestructChange) revert(s *IntraBlockState) error {
248248
s.versionedWrites.Delete(ch.account, AccountKey{Path: SelfDestructPath})
249249
} else {
250250
if v, ok := s.versionedWrites[ch.account][AccountKey{Path: SelfDestructPath}]; ok {
251-
fmt.Printf("%s WRT Revert %x: %d -> %d\n", tracePrefix, ch.account, v.Val, &ch.prev)
251+
if trace {
252+
fmt.Printf("%s WRT Revert %x: %v -> %v\n", tracePrefix, ch.account, v.Val, &ch.prev)
253+
}
252254
v.Val = ch.prev
253255
}
254256
if v, ok := s.versionedWrites[ch.account][AccountKey{Path: BalancePath}]; ok {
255257
val := v.Val.(uint256.Int)
256-
fmt.Printf("%s WRT Revert %x: %d -> %d\n", tracePrefix, ch.account, &val, &ch.prevbalance)
258+
if trace {
259+
fmt.Printf("%s WRT Revert %x: %d -> %d\n", tracePrefix, ch.account, &val, &ch.prevbalance)
260+
}
257261
v.Val = ch.prevbalance
258262
}
259263
}

execution/tests/block_test.go

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525
"testing"
2626

2727
"github.com/erigontech/erigon/common/log/v3"
28-
"github.com/erigontech/erigon/common/race"
2928
"github.com/erigontech/erigon/execution/tests/testutil"
3029
)
3130

@@ -104,9 +103,9 @@ func TestExecutionSpecBlockchainDevnet(t *testing.T) {
104103
if testing.Short() {
105104
t.Skip()
106105
}
107-
if race.Enabled {
108-
// TODO fix -race issues with parallel exec
109-
// t.Skip("skipping from race tests until parallel exec flow is race free")
106+
if runtime.GOOS == "windows" {
107+
// TODO(yperbasis, mh0lt)
108+
t.Skip("fix me on windows please")
110109
}
111110

112111
t.Parallel()
@@ -116,7 +115,58 @@ func TestExecutionSpecBlockchainDevnet(t *testing.T) {
116115
bt := new(testMatcher)
117116
// to run only tests for 1 eip do:
118117
//bt.whitelist(`.*amsterdam/eip8024_dupn_swapn_exchange.*`)
119-
bt.whitelist(`.*amsterdam.*`) // TODO run tests for older forks too once we fix amsterdam eips, for now focus only on amsterdam eips
118+
119+
// byzantium — BAL mismatch
120+
bt.skipLoad(`^byzantium/eip214_staticcall/test_staticcall_call_to_precompile.json`)
121+
bt.skipLoad(`^byzantium/eip214_staticcall/test_staticcall_call_to_precompile_from_contract_init.json`)
122+
bt.skipLoad(`^byzantium/eip214_staticcall/test_staticcall_nested_call_to_precompile.json`)
123+
bt.skipLoad(`^byzantium/eip214_staticcall/test_staticcall_reentrant_call_to_precompile.json`)
124+
125+
// cancun — BAL mismatch
126+
bt.skipLoad(`^cancun/create/test_create_oog_from_eoa_refunds.json`)
127+
bt.skipLoad(`^cancun/eip4844_blobs/test_correct_decreasing_blob_gas_costs.json`)
128+
bt.skipLoad(`^cancun/eip4844_blobs/test_correct_increasing_blob_gas_costs.json`)
129+
bt.skipLoad(`^cancun/eip6780_selfdestruct/test_dynamic_create2_selfdestruct_collision_multi_tx.json`)
130+
bt.skipLoad(`^cancun/eip6780_selfdestruct/test_dynamic_create2_selfdestruct_collision_two_different_transactions.json`)
131+
bt.skipLoad(`^cancun/eip6780_selfdestruct/test_self_destructing_initcode.json`)
132+
bt.skipLoad(`^cancun/eip6780_selfdestruct/test_selfdestruct_created_in_same_tx_with_revert.json`)
133+
bt.skipLoad(`^cancun/eip6780_selfdestruct/test_selfdestruct_not_created_in_same_tx_with_revert.json`)
134+
135+
// frontier — BAL mismatch
136+
bt.skipLoad(`^frontier/identity_precompile/test_call_identity_precompile.json`)
137+
bt.skipLoad(`^frontier/scenarios/test_scenarios.json`)
138+
139+
// osaka — BAL mismatch
140+
bt.skipLoad(`^osaka/eip7918_blob_reserve_price/test_reserve_price_boundary.json`)
141+
142+
// paris — BAL mismatch
143+
bt.skipLoad(`^paris/security/test_tx_selfdestruct_balance_bug.json`)
144+
145+
// prague — invalid state root hash
146+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_call_pointer_to_created_from_create_after_oog_call_again.json`)
147+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_call_to_precompile_in_pointer_context.json`)
148+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_delegated_eoa_can_send_creating_tx.json`)
149+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_delegation_clearing.json`)
150+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_delegation_clearing_and_set.json`)
151+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_delegation_clearing_tx_to.json`)
152+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_delegation_replacement_call_previous_contract.json`)
153+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_pointer_contract_pointer_loop.json`)
154+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_pointer_normal.json`)
155+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_pointer_resets_an_empty_code_account_with_storage.json`)
156+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_pointer_reverts.json`)
157+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_pointer_to_pointer.json`)
158+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_pointer_to_precompile.json`)
159+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_pointer_to_static.json`)
160+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_pointer_to_static_reentry.json`)
161+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_reset_code.json`)
162+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_self_sponsored_set_code.json`)
163+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_set_code_to_sstore.json`)
164+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_set_code_to_sstore_then_sload.json`)
165+
bt.skipLoad(`^prague/eip7702_set_code_tx/test_static_to_pointer.json`)
166+
167+
// static — tested in state test format by TestState
168+
bt.skipLoad(`^static/state_tests/`)
169+
120170
bt.walk(t, dir, func(t *testing.T, name string, test *testutil.BlockTest) {
121171
// import pre accounts & construct test genesis block & state root
122172
test.ExperimentalBAL = true // TODO eventually remove this from BlockTest and run normally

0 commit comments

Comments
 (0)