Skip to content

Commit 7c3c192

Browse files
committed
Lock the state transition during conversion (#384)
* heavy handed approach: lock the state transition during conversion * also lock transition state loading/unloading * reduce logs verbosity * add conversion test to workflow (#386) * add conversion test to workflow * mandatory -f switch fix in rm * forgot & at the end of the geth command * remove incorrect kill * add debug traces * add an overlay stride * fix typo
1 parent 1fcd5ce commit 7c3c192

File tree

4 files changed

+105
-2
lines changed

4 files changed

+105
-2
lines changed

.github/workflows/conversion.yml

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
name: Overlay conversion
2+
3+
on:
4+
push:
5+
branches: [ master, transition-post-genesis, store-transition-state-in-db ]
6+
pull_request:
7+
branches: [ master, kaustinen-with-shapella, transition-post-genesis, store-transition-state-in-db, lock-overlay-transition ]
8+
workflow_dispatch:
9+
10+
jobs:
11+
build:
12+
runs-on: self-hosted
13+
steps:
14+
- uses: actions/checkout@v2
15+
- name: Set up Go
16+
uses: actions/setup-go@v2
17+
with:
18+
go-version: 1.21.1
19+
20+
- name: Cleanup from previous runs
21+
run: |
22+
rm -f log.txt
23+
rm -rf .shadowfork
24+
rm -f genesis.json
25+
26+
- name: Download genesis file
27+
run: wget https://gist.githubusercontent.com/gballet/0b02a025428aa0e7b67941864d54716c/raw/bfb4e158bca5217b356a19b2ec55c4a45a7b2bad/genesis.json
28+
29+
- name: Init data
30+
run: go run ./cmd/geth --dev --cache.preimages init genesis.json
31+
32+
- name: Run geth in devmode
33+
run: go run ./cmd/geth --dev --dev.period=5 --cache.preimages --http --datadir=.shadowfork --override.overlay-stride=10 --override.prague=$(($(date +%s) + 45)) > log.txt &
34+
35+
- name: Wait for the transition to start
36+
run: |
37+
start_time=$(date +%s)
38+
while true; do
39+
sleep 5
40+
current_time=$(date +%s)
41+
elapsed_time=$((current_time - start_time))
42+
43+
# 2 minute timeout
44+
if [ $elapsed_time -ge 120 ]; then
45+
kill -9 $(pgrep -f geth)
46+
exit 1
47+
fi
48+
49+
# Check for signs that the conversion has started
50+
if grep -q "Processing verkle conversion starting at" log.txt; then
51+
break
52+
fi
53+
done
54+
55+
- name: Wait for the transition to end
56+
run: |
57+
start_time=$(date +%s)
58+
while true; do
59+
sleep 5
60+
current_time=$(date +%s)
61+
elapsed_time=$((current_time - start_time))
62+
63+
# 10 minute timeout
64+
if [ $elapsed_time -ge 300 ]; then
65+
cat log.txt
66+
kill -9 $(pgrep -f geth)
67+
exit 1
68+
fi
69+
70+
# Check for signs that the conversion has started
71+
if egrep -q "at block.*performing transition\? false" log.txt; then
72+
kill -9 $(pgrep -f geth)
73+
break
74+
fi
75+
done

core/overlay/conversion.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ func (kvm *keyValueMigrator) migrateCollectedKeyValues(tree *trie.VerkleTrie) er
221221
// OverlayVerkleTransition contains the overlay conversion logic
222222
func OverlayVerkleTransition(statedb *state.StateDB, root common.Hash, maxMovedCount uint64) error {
223223
migrdb := statedb.Database()
224+
migrdb.LockCurrentTransitionState()
225+
defer migrdb.UnLockCurrentTransitionState()
224226

225227
// verkle transition: if the conversion process is in progress, move
226228
// N values from the MPT into the verkle tree.
@@ -402,7 +404,9 @@ func OverlayVerkleTransition(statedb *state.StateDB, root common.Hash, maxMovedC
402404
if crypto.Keccak256Hash(addr[:]) != accIt.Hash() {
403405
return fmt.Errorf("preimage file does not match account hash: %s != %s", crypto.Keccak256Hash(addr[:]), accIt.Hash())
404406
}
405-
fmt.Printf("Converting account address hash=%x addr=%x", accIt.Hash(), addr)
407+
if count%100 == 0 {
408+
fmt.Printf("Converting account address hash=%x addr=%x\n", accIt.Hash(), addr)
409+
}
406410
preimageSeek += int64(len(addr))
407411
migrdb.SetCurrentAccountAddress(addr)
408412
} else {

core/state/database.go

+18-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"errors"
2323
"fmt"
2424
"runtime/debug"
25+
"sync"
2526

2627
"github.com/ethereum/go-ethereum/common"
2728
"github.com/ethereum/go-ethereum/common/lru"
@@ -105,6 +106,10 @@ type Database interface {
105106
SaveTransitionState(common.Hash)
106107

107108
LoadTransitionState(common.Hash)
109+
110+
LockCurrentTransitionState()
111+
112+
UnLockCurrentTransitionState()
108113
}
109114

110115
// Trie is a Ethereum Merkle Patricia trie.
@@ -311,11 +316,11 @@ type cachingDB struct {
311316
LastMerkleRoot common.Hash // root hash of the read-only base tree
312317
CurrentTransitionState *TransitionState
313318
TransitionStatePerRoot lru.BasicLRU[common.Hash, *TransitionState]
319+
transitionStateLock sync.Mutex
314320

315321
addrToPoint *utils.PointCache
316322

317323
baseRoot common.Hash // hash of the read-only base tree
318-
319324
}
320325

321326
func (db *cachingDB) openMPTTrie(root common.Hash) (Trie, error) {
@@ -548,6 +553,8 @@ func (db *cachingDB) SetLastMerkleRoot(merkleRoot common.Hash) {
548553
}
549554

550555
func (db *cachingDB) SaveTransitionState(root common.Hash) {
556+
db.transitionStateLock.Lock()
557+
defer db.transitionStateLock.Unlock()
551558
if db.CurrentTransitionState != nil {
552559
var buf bytes.Buffer
553560
enc := gob.NewEncoder(&buf)
@@ -570,6 +577,8 @@ func (db *cachingDB) SaveTransitionState(root common.Hash) {
570577
}
571578

572579
func (db *cachingDB) LoadTransitionState(root common.Hash) {
580+
db.transitionStateLock.Lock()
581+
defer db.transitionStateLock.Unlock()
573582
// Try to get the transition state from the cache and
574583
// the DB if it's not there.
575584
ts, ok := db.TransitionStatePerRoot.Get(root)
@@ -614,3 +623,11 @@ func (db *cachingDB) LoadTransitionState(root common.Hash) {
614623
fmt.Println("loaded transition state", "storage processed", db.CurrentTransitionState.StorageProcessed, "addr", db.CurrentTransitionState.CurrentAccountAddress, "slot hash", db.CurrentTransitionState.CurrentSlotHash, "root", root, "ended", db.CurrentTransitionState.ended, "started", db.CurrentTransitionState.started)
615624
debug.PrintStack()
616625
}
626+
627+
func (db *cachingDB) LockCurrentTransitionState() {
628+
db.transitionStateLock.Lock()
629+
}
630+
631+
func (db *cachingDB) UnLockCurrentTransitionState() {
632+
db.transitionStateLock.Unlock()
633+
}

light/trie.go

+7
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,13 @@ func (db *odrDatabase) LoadTransitionState(common.Hash) {
177177
panic("not implemented") // TODO: Implement
178178
}
179179

180+
func (db *odrDatabase) LockCurrentTransitionState() {
181+
panic("not implemented") // TODO: Implement
182+
}
183+
func (db *odrDatabase) UnLockCurrentTransitionState() {
184+
panic("not implemented") // TODO: Implement
185+
}
186+
180187
type odrTrie struct {
181188
db *odrDatabase
182189
id *TrieID

0 commit comments

Comments
 (0)