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

zktrie part2: add zktrie; allow switch trie type by config; #113

Merged
merged 25 commits into from
Jun 27, 2022
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f6c03c0
induce zktrie
noel2004 May 29, 2022
7676e9f
refactoring zktrie
noel2004 Jun 8, 2022
f17d42f
fix crash issue in logger
noel2004 Jun 8, 2022
942bfe4
renaming JSON field
noel2004 Jun 8, 2022
9b7c672
unify hash scheme
noel2004 Jun 8, 2022
c958ea1
goimport and mod lint
noel2004 Jun 8, 2022
2f9f3b2
backward compatible with go 1.17
noel2004 Jun 8, 2022
0b6200f
lints
noel2004 Jun 8, 2022
86d287d
add option on genesis file
noel2004 Jun 9, 2022
50ce37a
corrections according to the reviews
noel2004 Jun 16, 2022
d16cf7d
trivial fixes: ValueKey entry, key in prove nodes
noel2004 Jun 17, 2022
5725fa9
fixing for the proof fix ...
noel2004 Jun 17, 2022
9e0f9ec
avoiding panic before loading stateDb in genesis setup
noel2004 Jun 22, 2022
d129b78
Merge remote-tracking branch 'main/zkrollup' into l2witness/zktrie
noel2004 Jun 22, 2022
09ca2a1
Merge remote-tracking branch 'main/zkrollup' into l2witness/zktrie
noel2004 Jun 23, 2022
9293637
Merge branch 'zkrollup' into l2witness/zktrie
0xmountaintop Jun 23, 2022
ae3d7e1
revert ExtraData.StateList json annotation for compatibility
0xmountaintop Jun 23, 2022
091a0a2
fix goimports lint
0xmountaintop Jun 23, 2022
2492b27
fix goimports lint
0xmountaintop Jun 23, 2022
80f4832
better encoding for leaf node
noel2004 Jun 24, 2022
3188709
fix proof's printing issue, add handling on coinbase
noel2004 Jun 24, 2022
77fe488
update genesis, and rule out snapshot in zktrie mode
noel2004 Jun 24, 2022
9f7900d
update readme and lint
noel2004 Jun 24, 2022
9920040
fix an issue
noel2004 Jun 25, 2022
d6156cc
Merge branch 'zkrollup' into l2witness/zktrie
0xmountaintop Jun 27, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/geth/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func TestCustomGenesis(t *testing.T) {
runGeth(t, "--datadir", datadir, "init", json).WaitExit()

// Query the custom genesis block
geth := runGeth(t, "--networkid", "1337", "--syncmode=full", "--cache", "16",
geth := runGeth(t, "--networkid", "1337", "--syncmode=full", "--snapshot=false", "--cache", "16",
"--datadir", datadir, "--maxpeers", "0", "--port", "0",
"--nodiscover", "--nat", "none", "--ipcdisable",
"--exec", tt.query, "console")
Expand Down
6 changes: 6 additions & 0 deletions common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,12 @@ func IsHexAddress(s string) bool {
// Bytes gets the string representation of the underlying address.
func (a Address) Bytes() []byte { return a[:] }

func (a Address) Bytes32() []byte {
ret := make([]byte, 32)
copy(ret, a.Bytes())
return ret
}

// Hash converts an address to a hash by left-padding it with zeros.
func (a Address) Hash() Hash { return BytesToHash(a[:]) }

Expand Down
1 change: 1 addition & 0 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
Cache: cacheConfig.TrieCleanLimit,
Journal: cacheConfig.TrieCleanJournal,
Preimages: cacheConfig.Preimages,
Zktrie: chainConfig.Zktrie,
}),
quit: make(chan struct{}),
chainmu: syncx.NewClosableMutex(),
Expand Down
22 changes: 19 additions & 3 deletions core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,18 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override
// We have the genesis block in database(perhaps in ancient database)
// but the corresponding state is missing.
header := rawdb.ReadHeader(db, stored, 0)
if _, err := state.New(header.Root, state.NewDatabaseWithConfig(db, nil), nil); err != nil {

var trieCfg *trie.Config

if genesis == nil {
storedcfg := rawdb.ReadChainConfig(db, stored)
noel2004 marked this conversation as resolved.
Show resolved Hide resolved
if storedcfg == nil {
panic("this should never be reached: if genesis is nil, the config is already present or 'geth init' is being called which created it (in the code above, which means genesis != nil)")
}
trieCfg = &trie.Config{Zktrie: storedcfg.Zktrie}
}

if _, err := state.New(header.Root, state.NewDatabaseWithConfig(db, trieCfg), nil); err != nil {
if genesis == nil {
genesis = DefaultGenesisBlock()
}
Expand Down Expand Up @@ -261,7 +272,11 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
if db == nil {
db = rawdb.NewMemoryDatabase()
}
statedb, err := state.New(common.Hash{}, state.NewDatabase(db), nil)
var trieCfg *trie.Config
if g.Config != nil {
trieCfg = &trie.Config{Zktrie: g.Config.Zktrie}
}
statedb, err := state.New(common.Hash{}, state.NewDatabaseWithConfig(db, trieCfg), nil)
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -441,7 +456,8 @@ func DeveloperGenesisBlock(period uint64, gasLimit uint64, faucet common.Address
common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b
faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))},
// LSH 250 due to finite field limitation
faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 250), big.NewInt(9))},
},
}
}
Expand Down
18 changes: 18 additions & 0 deletions core/state/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ func NewDatabase(db ethdb.Database) Database {
func NewDatabaseWithConfig(db ethdb.Database, config *trie.Config) Database {
csc, _ := lru.New(codeSizeCacheSize)
return &cachingDB{
zktrie: config != nil && config.Zktrie,
db: trie.NewDatabaseWithConfig(db, config),
codeSizeCache: csc,
codeCache: fastcache.New(codeCacheSize),
Expand All @@ -130,10 +131,18 @@ type cachingDB struct {
db *trie.Database
codeSizeCache *lru.Cache
codeCache *fastcache.Cache
zktrie bool
}

// OpenTrie opens the main account trie at a specific root hash.
func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
if db.zktrie {
tr, err := trie.NewZkTrie(root, trie.NewZktrieDatabaseFromTriedb(db.db))
if err != nil {
return nil, err
}
return tr, nil
}
tr, err := trie.NewSecure(root, db.db)
if err != nil {
return nil, err
Expand All @@ -143,6 +152,13 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {

// OpenStorageTrie opens the storage trie of an account.
func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) {
if db.zktrie {
tr, err := trie.NewZkTrie(root, trie.NewZktrieDatabaseFromTriedb(db.db))
if err != nil {
return nil, err
}
return tr, nil
}
tr, err := trie.NewSecure(root, db.db)
if err != nil {
return nil, err
Expand All @@ -155,6 +171,8 @@ func (db *cachingDB) CopyTrie(t Trie) Trie {
switch t := t.(type) {
case *trie.SecureTrie:
return t.Copy()
case *trie.ZkTrie:
return t.Copy()
default:
panic(fmt.Errorf("unknown trie type %T", t))
}
Expand Down
3 changes: 3 additions & 0 deletions core/state/snapshot/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ type Tree struct {
// a background thread.
func New(diskdb ethdb.KeyValueStore, triedb *trie.Database, cache int, root common.Hash, async bool, rebuild bool, recovery bool) (*Tree, error) {
// Create a new, empty snapshot tree
if triedb.Zktrie {
panic("zktrie does not support snapshot yet")
}
snap := &Tree{
diskdb: diskdb,
triedb: triedb,
Expand Down
28 changes: 18 additions & 10 deletions core/state/state_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func newObject(db *StateDB, address common.Address, data types.StateAccount) *st
data.CodeHash = emptyCodeHash
}
if data.Root == (common.Hash{}) {
data.Root = emptyRoot
data.Root = db.db.TrieDB().EmptyRoot()
}
return &stateObject{
db: db,
Expand Down Expand Up @@ -151,7 +151,7 @@ func (s *stateObject) getTrie(db Database) Trie {
if s.trie == nil {
// Try fetching from prefetcher first
// We don't prefetch empty tries
if s.data.Root != emptyRoot && s.db.prefetcher != nil {
if s.data.Root != s.db.db.TrieDB().EmptyRoot() && s.db.prefetcher != nil {
// When the miner is creating the pending state, there is no
// prefetcher
s.trie = s.db.prefetcher.trie(s.data.Root)
Expand Down Expand Up @@ -245,12 +245,16 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has
}
}
var value common.Hash
if len(enc) > 0 {
_, content, _, err := rlp.Split(enc)
if err != nil {
s.setError(err)
if db.TrieDB().Zktrie {
value = common.BytesToHash(enc)
} else {
if len(enc) > 0 {
_, content, _, err := rlp.Split(enc)
if err != nil {
s.setError(err)
}
value.SetBytes(content)
}
value.SetBytes(content)
}
s.originStorage[key] = value
return value
Expand Down Expand Up @@ -309,7 +313,7 @@ func (s *stateObject) finalise(prefetch bool) {
slotsToPrefetch = append(slotsToPrefetch, common.CopyBytes(key[:])) // Copy needed for closure
}
}
if s.db.prefetcher != nil && prefetch && len(slotsToPrefetch) > 0 && s.data.Root != emptyRoot {
if s.db.prefetcher != nil && prefetch && len(slotsToPrefetch) > 0 && s.data.Root != s.db.db.TrieDB().EmptyRoot() {
s.db.prefetcher.prefetch(s.data.Root, slotsToPrefetch)
}
if len(s.dirtyStorage) > 0 {
Expand Down Expand Up @@ -348,8 +352,12 @@ func (s *stateObject) updateTrie(db Database) Trie {
s.setError(tr.TryDelete(key[:]))
s.db.StorageDeleted += 1
} else {
// Encoding []byte cannot fail, ok to ignore the error.
v, _ = rlp.EncodeToBytes(common.TrimLeftZeroes(value[:]))
if db.TrieDB().Zktrie {
v = common.CopyBytes(value[:])
} else {
// Encoding []byte cannot fail, ok to ignore the error.
v, _ = rlp.EncodeToBytes(common.TrimLeftZeroes(value[:]))
}
s.setError(tr.TryUpdate(key[:], v))
s.db.StorageUpdated += 1
}
Expand Down
42 changes: 32 additions & 10 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ type revision struct {
journalIndex int
}

var (
// emptyRoot is the known root hash of an empty trie.
emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
)

type proofList [][]byte

func (n *proofList) Put(key []byte, value []byte) error {
Expand Down Expand Up @@ -187,6 +182,10 @@ func (s *StateDB) Error() error {
return s.dbErr
}

func (s *StateDB) IsZktrie() bool {
return s.db.TrieDB().Zktrie
}

func (s *StateDB) AddLog(log *types.Log) {
s.journal.append(addLogChange{txhash: s.thash})

Expand Down Expand Up @@ -315,11 +314,19 @@ func (s *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash {

// GetProof returns the Merkle proof for a given account.
func (s *StateDB) GetProof(addr common.Address) ([][]byte, error) {
if s.IsZktrie() {
var proof proofList
err := s.trie.Prove(addr.Bytes32(), 0, &proof)
return proof, err
}
return s.GetProofByHash(crypto.Keccak256Hash(addr.Bytes()))
}

// GetProofByHash returns the Merkle proof for a given account.
func (s *StateDB) GetProofByHash(addrHash common.Hash) ([][]byte, error) {
if s.IsZktrie() {
panic("unimplemented")
}
var proof proofList
err := s.trie.Prove(addrHash[:], 0, &proof)
return proof, err
Expand All @@ -339,6 +346,7 @@ func (s *StateDB) GetRootHash() common.Hash {

// StorageTrieProof is not in Db interface and used explictily for reading proof in storage trie (not the dirty value)
func (s *StateDB) GetStorageTrieProof(a common.Address, key common.Hash) ([][]byte, error) {

// try the trie in stateObject first, else we would create one
stateObject := s.getStateObject(a)
if stateObject == nil {
Expand All @@ -356,7 +364,11 @@ func (s *StateDB) GetStorageTrieProof(a common.Address, key common.Hash) ([][]by
}

var proof proofList
err = trie.Prove(crypto.Keccak256(key.Bytes()), 0, &proof)
if s.IsZktrie() {
err = trie.Prove(key.Bytes(), 0, &proof)
} else {
err = trie.Prove(crypto.Keccak256(key.Bytes()), 0, &proof)
}
return proof, err
}

Expand All @@ -367,7 +379,12 @@ func (s *StateDB) GetStorageProof(a common.Address, key common.Hash) ([][]byte,
if trie == nil {
return proof, errors.New("storage trie for requested address does not exist")
}
err := trie.Prove(crypto.Keccak256(key.Bytes()), 0, &proof)
var err error
if s.IsZktrie() {
err = trie.Prove(key.Bytes(), 0, &proof)
} else {
err = trie.Prove(crypto.Keccak256(key.Bytes()), 0, &proof)
}
return proof, err
}

Expand Down Expand Up @@ -564,7 +581,7 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
data.CodeHash = emptyCodeHash
}
if data.Root == (common.Hash{}) {
data.Root = emptyRoot
data.Root = s.db.TrieDB().EmptyRoot()
}
}
}
Expand All @@ -582,7 +599,12 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
return nil
}
data = new(types.StateAccount)
if err := rlp.DecodeBytes(enc, data); err != nil {
if s.IsZktrie() {
data, err = types.UnmarshalStateAccount(enc)
} else {
err = rlp.DecodeBytes(enc, data)
}
if err != nil {
log.Error("Failed to decode state object", "addr", addr, "err", err)
return nil
}
Expand Down Expand Up @@ -977,7 +999,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
if err := rlp.DecodeBytes(leaf, &account); err != nil {
return nil
}
if account.Root != emptyRoot {
if account.Root != s.db.TrieDB().EmptyRoot() {
s.db.TrieDB().Reference(account.Root, parent)
}
return nil
Expand Down
2 changes: 1 addition & 1 deletion core/types/l2trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ type ExtraData struct {
// callee contract address's account (value updated, before called)]
// STATICCALL: [stack.nth_last(1) (i.e. callee) address’s account,
// callee contract address's account (before called)]
StateList []*AccountWrapper `json:"proofList,omitempty"`
StateList []*AccountWrapper `json:"stateList,omitempty"`
}

type AccountWrapper struct {
Expand Down
Loading