-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add package
w3vm
for simulating EVM message execution (#58)
* added multiEVMLogger * added `defaultChainConfig` * added `Receipt` * switching to `go-ethereum` head * added `VM` API * added `Fetcher` interface * added `Option`'s * added `nilToZero` util * moved and added zero values * state: added `RPCFetcher` * state: added `noopKeyValueStore` * state: added `noopNodeIterator` and fixed `noopBatch` * state: added `DB` * state: renamed `account2` -> `account` * added `defaultBlockContext` * internal/mod: init * state: added `Account` marshalling test * state: added `forkState` * state: added `NewTestingRPCFetcher` * added `TestVMApply_Integration` * added `VM` implementation * w3types: using `types.EmptyCodeHash` * upgraded `go-ethereum` * filter nil-EVMLoggers in multiEVMLogger * refactored db + drop all db storage logic * moved `w3.RandA()` to `w3vm.RandA()` * state: drop unused noop structs * added testdata * added `.gitattributes` * try change selector * move * fixed name * changed selector * added `VM.Apply` tests * added WETH storage slot utils * added `VM` tests * added `VM` Benchmark * not always revert to zero, but take a snapshot in the before the call/apply instead * disable BaseFee for calls * fixing storage overwriting * adding support for `WithFork` * dependency upgrade * added more integration test blocks * ignore nil-Option's * fixed repetitive state read * state: fixed forkState change detection * reverted dependency update * updated comment * upgraded to Go1.21 * dependency update * dropped `Returner` interface for `CallFuncFactory` struct * upgraded ´go-ethereum` * return fetch error in vm state access methods * refactored `VM` * fixed `WithNoBaseFee` option * doc update * added support for pending block number * state: changed API visibility * merged package `w3vm/state` and `w3vm` * return `ErrRevert` for revert errors * improved doc * updated `defaultBlockContext()` * exposed `Slot` and `Slot2` * added `WETHBalanceSlot` example * doc update * fixed fetcher setup in `New` * doc update --------- Co-authored-by: lmittmann <lmittmann@users.noreply.github.com>
- Loading branch information
Showing
62 changed files
with
101,889 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
testdata/ linguist-generated=true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package mod | ||
|
||
import ( | ||
"os/exec" | ||
"strings" | ||
) | ||
|
||
// Root contains the absolute path of the module root. Its value is empty if | ||
// used outside of a module. | ||
var Root string | ||
|
||
func init() { | ||
stdout, _ := exec.Command("go", "env", "GOMOD").Output() | ||
|
||
var ok bool | ||
Root, ok = strings.CutSuffix(strings.TrimSpace(string(stdout)), "/go.mod") | ||
if !ok { | ||
Root = "" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package mod_test | ||
|
||
import ( | ||
"strings" | ||
"testing" | ||
|
||
"github.com/lmittmann/w3/internal/mod" | ||
) | ||
|
||
func TestModRoot(t *testing.T) { | ||
if !strings.HasSuffix(mod.Root, "w3") { | ||
t.Fatalf("Unexpected module root: %q", mod.Root) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package w3vm | ||
|
||
import ( | ||
"errors" | ||
"math/big" | ||
|
||
"github.com/ethereum/go-ethereum/common" | ||
gethState "github.com/ethereum/go-ethereum/core/state" | ||
"github.com/ethereum/go-ethereum/core/types" | ||
"github.com/ethereum/go-ethereum/ethdb" | ||
"github.com/ethereum/go-ethereum/trie" | ||
"github.com/ethereum/go-ethereum/trie/trienode" | ||
"github.com/lmittmann/w3/internal/crypto" | ||
) | ||
|
||
var errNotFound = errors.New("not found") | ||
|
||
// db implements the [state.Database] and [state.Trie] interfaces. | ||
type db struct { | ||
fetcher Fetcher | ||
} | ||
|
||
func newDB(fetcher Fetcher) *db { | ||
return &db{ | ||
fetcher: fetcher, | ||
} | ||
} | ||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// state.Database methods ////////////////////////////////////////////////////////////////////////// | ||
//////////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
func (db *db) OpenTrie(root common.Hash) (gethState.Trie, error) { return db, nil } | ||
|
||
func (db *db) OpenStorageTrie(stateRoot common.Hash, addr common.Address, root common.Hash) (gethState.Trie, error) { | ||
return db, nil | ||
} | ||
|
||
func (*db) CopyTrie(gethState.Trie) gethState.Trie { panic("not implemented") } | ||
|
||
func (db *db) ContractCode(addr common.Address, codeHash common.Hash) ([]byte, error) { | ||
if db.fetcher == nil { | ||
return []byte{}, nil | ||
} | ||
|
||
code, err := db.fetcher.Code(addr) | ||
if err != nil { | ||
return nil, errNotFound | ||
} | ||
return code, nil | ||
} | ||
|
||
func (db *db) ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error) { | ||
code, err := db.ContractCode(addr, codeHash) | ||
if err != nil { | ||
return 0, err | ||
} | ||
return len(code), nil | ||
} | ||
|
||
func (*db) DiskDB() ethdb.KeyValueStore { panic("not implemented") } | ||
|
||
func (*db) TrieDB() *trie.Database { panic("not implemented") } | ||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// state.Trie methods ////////////////////////////////////////////////////////////////////////////// | ||
//////////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
func (*db) GetKey([]byte) []byte { panic("not implemented") } | ||
|
||
func (db *db) GetStorage(addr common.Address, key []byte) ([]byte, error) { | ||
if db.fetcher == nil { | ||
return []byte{}, nil | ||
} | ||
|
||
storageKey := common.BytesToHash(key) | ||
storageVal, err := db.fetcher.StorageAt(addr, storageKey) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return storageVal.Bytes(), nil | ||
} | ||
|
||
func (db *db) GetAccount(addr common.Address) (*types.StateAccount, error) { | ||
if db.fetcher == nil { | ||
return &types.StateAccount{ | ||
Balance: new(big.Int), | ||
CodeHash: types.EmptyCodeHash[:], | ||
}, nil | ||
} | ||
|
||
nonce, err := db.fetcher.Nonce(addr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
balance, err := db.fetcher.Balance(addr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
code, err := db.fetcher.Code(addr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var codeHash []byte | ||
if len(code) == 0 { | ||
codeHash = types.EmptyCodeHash[:] | ||
} else { | ||
codeHash = crypto.Keccak256(code) | ||
} | ||
|
||
return &types.StateAccount{ | ||
Nonce: nonce, | ||
Balance: balance, | ||
CodeHash: codeHash, | ||
}, nil | ||
} | ||
|
||
func (*db) UpdateStorage(addr common.Address, key, value []byte) error { panic("not implemented") } | ||
|
||
func (*db) UpdateAccount(addr common.Address, acc *types.StateAccount) error { | ||
panic("not implemented") | ||
} | ||
|
||
func (*db) UpdateContractCode(addr common.Address, codeHash common.Hash, code []byte) error { | ||
panic("not implemented") | ||
} | ||
|
||
func (*db) DeleteStorage(addr common.Address, key []byte) error { panic("not implemented") } | ||
|
||
func (*db) DeleteAccount(addr common.Address) error { panic("not implemented") } | ||
|
||
func (*db) Hash() common.Hash { panic("not implemented") } | ||
|
||
func (*db) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error) { | ||
panic("not implemented") | ||
} | ||
|
||
func (*db) NodeIterator(startKey []byte) (trie.NodeIterator, error) { panic("not implemented") } | ||
|
||
func (*db) Prove(key []byte, proofDb ethdb.KeyValueWriter) error { panic("not implemented") } |
Oops, something went wrong.