This repository has been archived by the owner on Apr 4, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 563
Support stateful precompiled contract #1116
Labels
Comments
type StatefulPrecompiled interface {
PrecompiledContract
Commit(ctx sdk.Context) error
}
type ExtStateDB interface {
StateDB
AppendJournalEntry(entry journalEntry)
}
type StateDB struct {
precompiles map[Address]StatefulPrecompiled
}
func (db *StateDB) Commit(ctx sdk.Context) error {
for _, contract := range db.precompiles {
if err := contract.Commit(ctx); err != nil {
return err
}
}
}
db := NewStateDB()
db.precompiles := {
addr: NewExampleContract(ctx, db),
}
evm := NewEVM(db, db.precompiles)
evm.Call(...) type ExampleContract struct {
db StateDB
state ExampleState
}
func NewExampleContract(ctx sdk.Context, db StateDB) *ExampleContract {
return &ExampleContract {
db: db,
state: loadState(ctx),
}
}
func (p *ExampleContract) RequiredGas(input []byte) uint64 {
// TODO
}
func (p *ExampleContract) Run(input []byte) ([]byte, error) {
p.db.append(revertEntry{
p: p,
saved: p.state,
})
// modify p.state in memory
}
func (p *ExampleContract) Commit(ctx sdk.Context) error {
// write p.state into cosmos-sdk storage.
}
// implements journalEntry interface
type revertEntry struct {
p *ExampleContract
saved ExampleState
}
func (r revertEntry) revert(*StateDB) {
r.p.state = r.saved
}
func (r revertEntry) dirtied() *common.Address {
// TODO
} |
An example bank transfer precompiled contract: type BankTransferContract struct {
bankKeeper BankKeeper
cachedCtx sdk.Context
writeCache CacheWriter
stateDB ExtStateDB
}
func NewBankTransferContract(ctx sdk.Context, bankKeeper BankKeeer, stateDB StateDB) *BankTransferContract {
cachedCtx, writeCache := ctx.CacheContext()
return &BankTransferContract{
bankKeeper, cachedCtx, writeCache, stateDB,
}
}
func (bc *BankTransferContract) Run(input []byte) error {
from, to, amount := decodeInput(input);
if err := bc.bankKeeper.Transfer(bc.cachedCtx, from, to, amount); err != nil {
return err
}
bc.stateDB.AppendJournalEntry(revertBankEntry{
bc.bankKeeper, bc.cachedCtx, from, to, amount,
})
}
func (bc *BankContract) Commit(ctx sdk.Context) error {
bc.writeCache()
}
type revertBankEntry struct {
bankKeeper BankKeeper
ctx sdk.Context
from, to, amount
}
func (r revertBankEntry) revert(*StateDB) {
if err := r.bankKeeper.Transfer(r.ctx, to, from, amount); err != nil {
// invariant, should not fail.
}
}
func (r revertBankEntry) dirtied() *common.Address {
return nil
} |
11 tasks
should look into making special stripped out go-ethereum fork specifically for ethermint. (Think SubnetEVM) |
(Maybe that's even the place to start) |
yihuang
added a commit
to yihuang/ethermint
that referenced
this issue
Jul 6, 2022
This issue is stale because it has been open 45 days with no activity. Remove |
unstale |
This issue is stale because it has been open 45 days with no activity. Remove |
This was referenced Feb 1, 2023
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Proposal: Support stateful precompiled contract
Current behavior:
EVM support registering precompiled smart contract, but we can't simply modify the state in it, pitfalls of doing that, basically it doesn't play well with the statedb's snapshot and revert.
Desired behavior: Make stateful precompiled smart contract possible.
Use case:
Precompiled smart contract is a powerful tool for many use cases.
Allow precompile to extend statedb in memory logic somehow.
The text was updated successfully, but these errors were encountered: