-
Notifications
You must be signed in to change notification settings - Fork 566
Problem: contract call which does lots of message calls is slow to execute #729
Conversation
03e0e97
to
f680d4a
Compare
Codecov Report
@@ Coverage Diff @@
## main #729 +/- ##
==========================================
- Coverage 57.79% 56.74% -1.05%
==========================================
Files 74 78 +4
Lines 6205 6238 +33
==========================================
- Hits 3586 3540 -46
- Misses 2408 2499 +91
+ Partials 211 199 -12
|
@yihuang could I kindly ask if we've considered that things might be much faster using smt inside of cosmos-sdk instead of cosmos/iavl? |
Does that mean we need to reimplement state-sync too? |
@odeke-em SMT is orthogonal to it AFAIK: one of the core issues here is e.g. nested cache contexts (cosmos/cosmos-sdk#10310) #710 (comment) |
99f643c
to
69d4309
Compare
the importer test runs faster now:
vs on main:
|
Review GuideAbstractThe problem:
The basic idea is to adopt the design in go-ethereum:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for the review guide! I think moving out statedb makes sense. At least removing the need for the WithContext
calls makes it a bit less error-prone.
I left a few comments, but it's mostly random parts I came across and they were probably there before:
For the upgrade migrations, it seems some of the storage keys aren't used anymore -- should that be cleaned up in migrations?
In any case, at least from the importer test, this looks like a big win. It'd need a bit more testing (especially on the web3 RPC API) and pairs of eyes to look at this PR. But overall, it looks promising (GPL v3 re-licensing is a side-issue and there are already some code portions from go-ethereum before in the current codebase, e.g.: https://github.com/tharsis/ethermint/blob/main/x/evm/types/tx_args.go#L19 so Ethermint should be re-licensed anyway)
660903c
to
521369b
Compare
I think the removed keys are all transient storage, so no migration is needed. |
521369b
to
b07b2cc
Compare
c68fa89
to
42fb5e0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First pass
ef58960
to
b9168a5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Second pass
} | ||
|
||
if err := evmkeeper.CheckSenderBalance(ctx, avd.bankKeeper, from, txData, evmDenom); err != nil { | ||
if err := evmkeeper.CheckSenderBalance(sdk.NewIntFromBigInt(acct.Balance), txData); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check if acct.Balance
is not nil
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sdk.NewIntFromBigInt
treat nil as an empty int, so looks ok?
x/evm/keeper/grpc_query.go
Outdated
CodeHash: k.GetCodeHash(addr).Hex(), | ||
Nonce: k.GetNonce(addr), | ||
Balance: acct.Balance.String(), | ||
CodeHash: hexutil.Encode(acct.CodeHash), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use common
library instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
x/evm/statedb/access_list.go
Outdated
// operations. | ||
func (al *accessList) DeleteSlot(address common.Address, slot common.Hash) { | ||
idx, addrOk := al.addresses[address] | ||
// There are two ways this can fail |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two ways this can fail
... which ones? can you add a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually, I'm not sure, it's blindly copied from go-ethereum, by reading the code, it seems impossible to fail here, probably the comment is out of date here. let me remove it.
fce1c53
to
d229bb4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
third pass, would be great to add tests for journal
x/evm/statedb/state_object.go
Outdated
// DB error. | ||
// State objects are used by the consensus core and VM which are | ||
// unable to deal with database-level errors. Any error that occurs | ||
// during a database read is memoized here and will eventually be returned | ||
// by StateDB.Commit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no dbErr
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed, since our account keeper API doesn't return database errors, so the field is useless here.
x/evm/statedb/statedb_test.go
Outdated
return nil | ||
} | ||
|
||
func TestAccounts(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
create a suite for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
x/evm/statedb/statedb_test.go
Outdated
{ | ||
"success,empty account", | ||
func(t *testing.T, db *statedb.StateDB) { | ||
require.Equal(t, true, db.Empty(addr2)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use suite.Require()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
x/evm/statedb/statedb_test.go
Outdated
|
||
var _ statedb.Keeper = &MockKeeper{} | ||
|
||
type MockKeeper struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move to mock_test.go
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
x/evm/statedb/statedb_test.go
Outdated
require.Equal(t, big.NewInt(1), db.GetBalance(addr2)) | ||
}, | ||
}, | ||
// TODO access list, ForEachStorage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
address this TODO or create issue for follow up
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
linked the #876 here.
d229bb4
to
ed0daa2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Final rounds of comments. Mostly adding more code and godoc comments.
Can you also add a state machine breaking change changelog?
Also can you open a PR to update the spec with the new design?
976e39a
to
3c26f7f
Compare
unit tests unit tests keeper implementation extract TxConfig remove unused code
Co-authored-by: Federico Kunze Küllmer <[email protected]>
3c26f7f
to
646537b
Compare
ff0d692
to
a129af2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK! 💯 @yihuang can you add the relevant changelog entries?
for the unit tests and coding style of statedb package, I suggest postponing that to another PR (#876), because:
done
|
This reverts commit ade8431.
This reverts commit ade8431.
Description
Closes: #710
As profiled in the issue page, the bottleneck is the slowness of deep context stack, there's no easy way around it other than refactor the
StateDB
to use journal logs like what go-ethereum does, thus this big code refactoring.What this PR does
x/evm/statedb
which implementsvm.StateDB
interface with the support of several keeper methods, the keeper interface is captured instatedb.Keeper
.StateDB
implementation keep all the dirty states in memory, at the end of tx execution, commit all the dirty changes to keeper at oncex/evm/statedb/{journal.go, access_list.go, state_object.go}
are directly adapted from go-ethereum itself.Benchmark result
BenchmarkMessageCall (improved 310X)
Before
After
BenchmarkEmitLogs (improved 2.5X)
Before
After
For contributor use:
docs/
) or specification (x/<module>/spec/
)godoc
comments.Unreleased
section inCHANGELOG.md
Files changed
in the Github PR explorerFor admin use:
WIP
,R4R
,docs
, etc)