Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use transient store for EVM deferred info #1690

Merged
merged 2 commits into from
Jun 28, 2024

Conversation

codchen
Copy link
Collaborator

@codchen codchen commented May 20, 2024

Describe your changes and provide context

Previously, we were using an adhoc sync.Map to keep track of deferred information that needs to be persisted from each transaction's individual processing to EndBlock (for purposes like surplus settlement, fee aggregation, etc.), where the map is key'ed on transaction index. The assumption of such usage is that the deferred info will be consistent across nodes by the end of the block because each TX index's entry will be overwritten by the final run of that transaction, under the context of OCC.

However this assumption is not correct, because a later incarnation of a transaction does not immediately (or ever) terminates its previous incarnation's goroutine (because there is no way to do so in Golang), so it is possible that a former incarnation may finish (and write to deferred info map) later than the final incarnation, potentially causing the state to be inconsistent with other nodes (where the final incarnation does write the last).

This PR changes the store of such deferred info to a transient store that's governed by the multiversion store. Specifically we choose transient store instead of memstore because we don't need any of these deferred info to be carried over to the next block. Using a memstore means we'd need to delete every entry one-by-one at the start of each block, which can add a lot to latency, whereas with a transient store it will simply be replaced with a new store instance for every block. In doing so for deferred info, we also changed the store for ante surplus from memstore to transient store for the same reason.

Note that this change in theory would not affect app state (and thus not app hash breaking, because all relevant states are in-memory)

Testing performed to validate your change

unit test

x/evm/keeper/deferred.go Fixed Show fixed Hide fixed
am.keeper.SetTxHashesOnHeight(ctx, ctx.BlockHeight(), utils.Filter(utils.Map(evmTxDeferredInfoList, func(i keeper.EvmTxDeferredInfo) common.Hash { return i.TxHash }), func(h common.Hash) bool { return h.Cmp(ethtypes.EmptyTxsHash) != 0 }))
am.keeper.SetBlockBloom(ctx, ctx.BlockHeight(), utils.Map(evmTxDeferredInfoList, func(i keeper.EvmTxDeferredInfo) ethtypes.Bloom { return i.TxBloom }))
am.keeper.DeleteAllAnteSurplus(ctx)
am.keeper.SetTxHashesOnHeight(ctx, ctx.BlockHeight(), utils.Filter(utils.Map(evmTxDeferredInfoList, func(i *types.DeferredInfo) common.Hash { return common.BytesToHash(i.TxHash) }), func(h common.Hash) bool { return h.Cmp(ethtypes.EmptyTxsHash) != 0 }))

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

path flow from Begin/EndBlock to a panic call
am.keeper.SetBlockBloom(ctx, ctx.BlockHeight(), utils.Map(evmTxDeferredInfoList, func(i keeper.EvmTxDeferredInfo) ethtypes.Bloom { return i.TxBloom }))
am.keeper.DeleteAllAnteSurplus(ctx)
am.keeper.SetTxHashesOnHeight(ctx, ctx.BlockHeight(), utils.Filter(utils.Map(evmTxDeferredInfoList, func(i *types.DeferredInfo) common.Hash { return common.BytesToHash(i.TxHash) }), func(h common.Hash) bool { return h.Cmp(ethtypes.EmptyTxsHash) != 0 }))
am.keeper.SetBlockBloom(ctx, ctx.BlockHeight(), utils.Map(evmTxDeferredInfoList, func(i *types.DeferredInfo) ethtypes.Bloom { return ethtypes.BytesToBloom(i.TxBloom) }))

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

path flow from Begin/EndBlock to a panic call
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this safe?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the panic seems to be a sanity check in BytesToBloom which I think should be okay? (all bloom bytes are produced by geth code)

if err := info.Unmarshal(val); err != nil {
// unable to unmarshal deferred info is serious, because it could cause
// balance surplus to be mishandled and thus affect total supply
panic(err)

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods Warning

Possible panics in BeginBock- or EndBlock-related consensus methods could cause a chain halt
@codchen codchen force-pushed the use-transient-store-for-evm-deferred branch from da6304b to 4ec6c09 Compare May 20, 2024 14:21
@codecov-commenter
Copy link

codecov-commenter commented May 20, 2024

Codecov Report

Attention: Patch coverage is 66.66667% with 27 lines in your changes missing coverage. Please review.

Project coverage is 60.76%. Comparing base (d25456d) to head (9902e71).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1690      +/-   ##
==========================================
- Coverage   60.81%   60.76%   -0.06%     
==========================================
  Files         373      373              
  Lines       27116    27129      +13     
==========================================
- Hits        16491    16485       -6     
- Misses       9518     9530      +12     
- Partials     1107     1114       +7     
Files Coverage Δ
app/ante.go 53.57% <ø> (-0.55%) ⬇️
x/evm/keeper/keeper.go 48.55% <100.00%> (-1.18%) ⬇️
x/evm/keeper/msg_server.go 76.72% <ø> (+0.55%) ⬆️
x/evm/module.go 55.55% <100.00%> (-0.33%) ⬇️
x/evm/types/keys.go 23.25% <ø> (ø)
x/evm/keeper/ante.go 27.77% <50.00%> (+2.77%) ⬆️
app/app.go 66.02% <57.14%> (-0.21%) ⬇️
x/evm/types/message_evm_transaction.go 37.03% <0.00%> (-7.41%) ⬇️
x/evm/keeper/deferred.go 75.00% <75.00%> (ø)

... and 3 files with indirect coverage changes

@codchen codchen force-pushed the use-transient-store-for-evm-deferred branch from 4ec6c09 to 2b8bcb7 Compare May 20, 2024 14:59
@codchen codchen force-pushed the use-transient-store-for-evm-deferred branch from 2b8bcb7 to 888db56 Compare June 27, 2024 02:36
@codchen codchen force-pushed the use-transient-store-for-evm-deferred branch from 888db56 to 9902e71 Compare June 28, 2024 01:25
@codchen codchen merged commit c3d0eee into main Jun 28, 2024
49 checks passed
@codchen codchen deleted the use-transient-store-for-evm-deferred branch June 28, 2024 02:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants