Skip to content

Commit 892922e

Browse files
committed
refactor block replay verification
1 parent 0ed0573 commit 892922e

File tree

3 files changed

+220
-128
lines changed

3 files changed

+220
-128
lines changed

cmd/util/cmd/verify-evm-offchain-replay/verify.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ func Verify(log zerolog.Logger, from uint64, to uint64, chainID flow.ChainID, da
7777
storages.Results,
7878
executionDataStore,
7979
store,
80+
func(uint64) error { return nil },
8081
)
8182

8283
if err != nil {

fvm/evm/offchain/utils/replay.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package utils
2+
3+
import (
4+
"github.com/rs/zerolog"
5+
6+
"github.com/onflow/flow-go/fvm/environment"
7+
"github.com/onflow/flow-go/fvm/evm/events"
8+
"github.com/onflow/flow-go/fvm/evm/offchain/blocks"
9+
evmStorage "github.com/onflow/flow-go/fvm/evm/offchain/storage"
10+
"github.com/onflow/flow-go/fvm/evm/offchain/sync"
11+
"github.com/onflow/flow-go/fvm/evm/testutils"
12+
"github.com/onflow/flow-go/model/flow"
13+
)
14+
15+
func ReplayEVMEventsToStore(
16+
log zerolog.Logger,
17+
store environment.ValueStore,
18+
chainID flow.ChainID,
19+
rootAddr flow.Address,
20+
evmBlockEvent *events.BlockEventPayload, // EVM block event
21+
evmTxEvents []events.TransactionEventPayload, // EVM transaction event
22+
) (
23+
map[flow.RegisterID]flow.RegisterValue, // EVM state transition updates
24+
map[flow.RegisterID]flow.RegisterValue, // block provider updates
25+
error,
26+
) {
27+
28+
bpStorage := evmStorage.NewEphemeralStorage(store)
29+
bp, err := blocks.NewBasicProvider(chainID, bpStorage, rootAddr)
30+
if err != nil {
31+
return nil, nil, err
32+
}
33+
34+
err = bp.OnBlockReceived(evmBlockEvent)
35+
if err != nil {
36+
return nil, nil, err
37+
}
38+
39+
sp := testutils.NewTestStorageProvider(store, evmBlockEvent.Height)
40+
cr := sync.NewReplayer(chainID, rootAddr, sp, bp, log, nil, true)
41+
res, results, err := cr.ReplayBlock(evmTxEvents, evmBlockEvent)
42+
if err != nil {
43+
return nil, nil, err
44+
}
45+
46+
// commit all register changes from the EVM state transition
47+
for k, v := range res.StorageRegisterUpdates() {
48+
err = store.SetValue([]byte(k.Owner), []byte(k.Key), v)
49+
if err != nil {
50+
return nil, nil, err
51+
}
52+
}
53+
54+
blockProposal := blocks.ReconstructProposal(evmBlockEvent, results)
55+
56+
err = bp.OnBlockExecuted(evmBlockEvent.Height, res, blockProposal)
57+
if err != nil {
58+
return nil, nil, err
59+
}
60+
61+
// commit all register changes from non-EVM state transition, such
62+
// as block hash list changes
63+
for k, v := range bpStorage.StorageRegisterUpdates() {
64+
// verify the block hash list changes are included in the trie update
65+
66+
err = store.SetValue([]byte(k.Owner), []byte(k.Key), v)
67+
if err != nil {
68+
return nil, nil, err
69+
}
70+
}
71+
72+
return res.StorageRegisterUpdates(), bpStorage.StorageRegisterUpdates(), nil
73+
}
74+
75+
type EVMEventsAccumulator struct {
76+
pendingEVMTxEvents []events.TransactionEventPayload
77+
}
78+
79+
func NewEVMEventsAccumulator() *EVMEventsAccumulator {
80+
return &EVMEventsAccumulator{
81+
pendingEVMTxEvents: make([]events.TransactionEventPayload, 0),
82+
}
83+
}
84+
85+
func (a *EVMEventsAccumulator) HasBlockEvent(
86+
evmBlockEvent *events.BlockEventPayload,
87+
evmTxEvents []events.TransactionEventPayload) (
88+
*events.BlockEventPayload,
89+
[]events.TransactionEventPayload,
90+
bool, // true if there is an EVM block event
91+
) {
92+
a.pendingEVMTxEvents = append(a.pendingEVMTxEvents, evmTxEvents...)
93+
94+
// if there is no EVM block event, we will accumulate the pending txs
95+
if evmBlockEvent == nil {
96+
return evmBlockEvent, a.pendingEVMTxEvents, false
97+
}
98+
99+
// if there is an EVM block event, we return the EVM block and the accumulated tx events
100+
return evmBlockEvent, a.pendingEVMTxEvents, true
101+
}

0 commit comments

Comments
 (0)