From 11b35cd0140f93bc09d3a2f9d3a0718afb40293c Mon Sep 17 00:00:00 2001 From: Ho Date: Wed, 2 Aug 2023 10:54:41 +0800 Subject: [PATCH] feat: upgrade zktrie to v0.6.0 (#403) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add domain-spec poseidon hash * add warning message for deprecated method * update goimports * update zktrie to v0.6 * fixes for upgrade * resume deletion proof * update alpha genesis since new hash sch eme * dump zktrie to 0.6 * induce genesis block for scroll sepolia network * Update version.go --------- Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com> Co-authored-by: Péter Garamvölgyi --- core/genesis.go | 12 ++++++++++++ core/genesis_test.go | 3 ++- crypto/poseidon/poseidon.go | 14 +++++++++++--- crypto/poseidon/poseidon_test.go | 8 ++++++++ go.mod | 2 +- go.sum | 4 ++-- params/config.go | 13 +++++++------ params/version.go | 2 +- trie/zk_trie.go | 4 ++-- trie/zk_trie_proof_test.go | 4 ++-- trie/zkproof/writer.go | 12 ++++++------ trie/zktrie_deletionproof.go | 15 ++++++++++----- 12 files changed, 64 insertions(+), 29 deletions(-) diff --git a/core/genesis.go b/core/genesis.go index eff72d83a54a..96d11c72dc2c 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -448,6 +448,18 @@ func DefaultScrollAlphaGenesisBlock() *Genesis { } } +// DefaultScrollSepoliaGenesisBlock returns the Scroll Sepolia network genesis block. +func DefaultScrollSepoliaGenesisBlock() *Genesis { + return &Genesis{ + Config: params.ScrollAlphaChainConfig, + Timestamp: 0x63f67207, + ExtraData: hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000000000b7C0c58702D0781C0e2eB3aaE301E4c340073448Ec9c139eFCBBe6323DA406fffBF4Db02a60A9720589c71deC4302fE718bE62350c174922782Cc6600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + GasLimit: 8000000, + Difficulty: big.NewInt(1), + Alloc: decodePrealloc(scrollAlphaAllocData), + } +} + // DeveloperGenesisBlock returns the 'geth --dev' genesis block. func DeveloperGenesisBlock(period uint64, gasLimit uint64, faucet common.Address) *Genesis { // Override the default period to the user requested one diff --git a/core/genesis_test.go b/core/genesis_test.go index e107cabaf58f..453a6b945a42 100644 --- a/core/genesis_test.go +++ b/core/genesis_test.go @@ -173,7 +173,8 @@ func TestGenesisHashes(t *testing.T) { // {DefaultRopstenGenesisBlock(), params.RopstenGenesisHash}, // {DefaultRinkebyGenesisBlock(), params.RinkebyGenesisHash}, // {DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash}, - {DefaultScrollAlphaGenesisBlock(), params.ScrollAlphaGenesisHash}, + // {DefaultScrollAlphaGenesisBlock(), params.ScrollAlphaGenesisHash}, + {DefaultScrollSepoliaGenesisBlock(), params.ScrollSepoliaGenesisHash}, } { // Test via MustCommit if have := c.genesis.MustCommit(rawdb.NewMemoryDatabase()).Hash(); have != c.want { diff --git a/crypto/poseidon/poseidon.go b/crypto/poseidon/poseidon.go index 0175563f4f9e..0902f6631d3a 100644 --- a/crypto/poseidon/poseidon.go +++ b/crypto/poseidon/poseidon.go @@ -9,6 +9,8 @@ import ( "github.com/iden3/go-iden3-crypto/ff" "github.com/iden3/go-iden3-crypto/utils" + + "github.com/scroll-tech/go-ethereum/log" ) const NROUNDSF = 8 //nolint:golint @@ -153,8 +155,8 @@ func HashWithCap(inpBI []*big.Int, width int, nBytes int64) (*big.Int, error) { } -// Hash computes the Poseidon hash for the given fixed-size inputs, select specs automatically from the size, no capacity flag is applied -func HashFixed(inpBI []*big.Int) (*big.Int, error) { +// Hash computes the Poseidon hash for the given fixed-size inputs, with specified domain field +func HashFixedWithDomain(inpBI []*big.Int, domain *big.Int) (*big.Int, error) { t := len(inpBI) + 1 if len(inpBI) == 0 || len(inpBI) > len(NROUNDSP) { return nil, fmt.Errorf("invalid inputs length %d, max %d", len(inpBI), len(NROUNDSP)) //nolint:gomnd,lll @@ -165,7 +167,7 @@ func HashFixed(inpBI []*big.Int) (*big.Int, error) { inp := utils.BigIntArrayToElementArray(inpBI[:]) state := make([]*ff.Element, t) - state[0] = zero() + state[0] = ff.NewElement().SetBigInt(domain) copy(state[1:], inp[:]) state = permute(state, t) @@ -175,3 +177,9 @@ func HashFixed(inpBI []*big.Int) (*big.Int, error) { rE.ToBigIntRegular(r) return r, nil } + +// Deprecated HashFixed entry, with domain field is 0 +func HashFixed(inpBI []*big.Int) (*big.Int, error) { + log.Warn("called a deprecated method for poseidon fixed hash", "inputs", inpBI) + return HashFixedWithDomain(inpBI, big.NewInt(0)) +} diff --git a/crypto/poseidon/poseidon_test.go b/crypto/poseidon/poseidon_test.go index 27cb341bdc33..5037c3da2d5d 100644 --- a/crypto/poseidon/poseidon_test.go +++ b/crypto/poseidon/poseidon_test.go @@ -92,6 +92,14 @@ func TestPoseidonHashFixed(t *testing.T) { assert.Equal(t, "9989051620750914585850546081941653841776809718687451684622678807385399211877", h.String()) + + h, err = HashFixedWithDomain([]*big.Int{b1, b2}, big.NewInt(256)) + assert.Nil(t, err) + assert.Equal(t, + "2362370911616048355006851495576377379220050231129891536935411970097789775493", + h.String()) + h_ref, _ := HashFixed([]*big.Int{b1, b2}) + assert.NotEqual(t, h_ref, h) } func TestErrorInputs(t *testing.T) { diff --git a/go.mod b/go.mod index 29f173216fa8..4ecc115856d6 100644 --- a/go.mod +++ b/go.mod @@ -48,7 +48,7 @@ require ( github.com/prometheus/tsdb v0.7.1 github.com/rjeczalik/notify v0.9.1 github.com/rs/cors v1.7.0 - github.com/scroll-tech/zktrie v0.5.3 + github.com/scroll-tech/zktrie v0.6.0 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 github.com/stretchr/testify v1.8.2 diff --git a/go.sum b/go.sum index bc40f08d60a0..e85236131d70 100644 --- a/go.sum +++ b/go.sum @@ -375,8 +375,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/scroll-tech/zktrie v0.5.3 h1:jjzQchGU6XPL5s1C5bwwivSadefSRuYASE9OL7UKAdE= -github.com/scroll-tech/zktrie v0.5.3/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk= +github.com/scroll-tech/zktrie v0.6.0 h1:xLrMAO31Yo2BiPg1jtYKzcjpEFnXy8acbB7iIsyshPs= +github.com/scroll-tech/zktrie v0.6.0/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk= github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= diff --git a/params/config.go b/params/config.go index c0522c54f28a..a9cc3fbb98b7 100644 --- a/params/config.go +++ b/params/config.go @@ -29,12 +29,13 @@ import ( // Genesis hashes to enforce below configs on. var ( - MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3") - RopstenGenesisHash = common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d") - SepoliaGenesisHash = common.HexToHash("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9") - RinkebyGenesisHash = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177") - GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a") - ScrollAlphaGenesisHash = common.HexToHash("0xa4fc62b9b0643e345bdcebe457b3ae898bef59c7203c3db269200055e037afda") + MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3") + RopstenGenesisHash = common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d") + SepoliaGenesisHash = common.HexToHash("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9") + RinkebyGenesisHash = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177") + GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a") + ScrollAlphaGenesisHash = common.HexToHash("0xa4fc62b9b0643e345bdcebe457b3ae898bef59c7203c3db269200055e037afda") + ScrollSepoliaGenesisHash = common.HexToHash("0x8deefb75edbf59fbff1cd9ffd6ebcd42dced646a1487ef369e0a64ccfc8b1fa2") ) // TrustedCheckpoints associates each known checkpoint with the genesis hash of diff --git a/params/version.go b/params/version.go index e5cc4f104dd9..6568b582dc21 100644 --- a/params/version.go +++ b/params/version.go @@ -24,7 +24,7 @@ import ( const ( VersionMajor = 4 // Major version component of the current release VersionMinor = 3 // Minor version component of the current release - VersionPatch = 3 // Patch version component of the current release + VersionPatch = 4 // Patch version component of the current release VersionMeta = "sepolia" // Version metadata to append to the version string ) diff --git a/trie/zk_trie.go b/trie/zk_trie.go index 627d3ee582ed..4cb116e64459 100644 --- a/trie/zk_trie.go +++ b/trie/zk_trie.go @@ -38,7 +38,7 @@ type ZkTrie struct { } func init() { - zkt.InitHashScheme(poseidon.HashFixed) + zkt.InitHashScheme(poseidon.HashFixedWithDomain) } func sanityCheckByte32Key(b []byte) { @@ -180,7 +180,7 @@ func (t *ZkTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter) return err } - if n.Type == zktrie.NodeTypeLeaf { + if n.Type == zktrie.NodeTypeLeaf_New { preImage := t.GetKey(n.NodeKey.Bytes()) if len(preImage) > 0 { n.KeyPreimage = &zkt.Byte32{} diff --git a/trie/zk_trie_proof_test.go b/trie/zk_trie_proof_test.go index 9246a7a992e0..308f6ccfe75b 100644 --- a/trie/zk_trie_proof_test.go +++ b/trie/zk_trie_proof_test.go @@ -200,7 +200,7 @@ func randomZktrie(t *testing.T, n int) (*ZkTrie, map[string]*kv) { func TestProofWithDeletion(t *testing.T) { tr, _ := NewZkTrie(common.Hash{}, NewZktrieDatabase((memorydb.New()))) mt := &zkTrieImplTestWrapper{tr.Tree()} - key1 := bytes.Repeat([]byte("k"), 32) + key1 := bytes.Repeat([]byte("l"), 32) key2 := bytes.Repeat([]byte("m"), 32) err := mt.UpdateWord( zkt.NewByte32FromBytesPaddingZero(key1), @@ -229,7 +229,7 @@ func TestProofWithDeletion(t *testing.T) { err = proofTracer.Prove(s_key2.Bytes(), 0, proof) assert.NoError(t, err) - // assert.Equal(t, len(sibling1), len(delTracer.GetProofs())) + //assert.Equal(t, len(sibling1), len(delTracer.GetProofs())) siblings, err := proofTracer.GetDeletionProofs() assert.NoError(t, err) diff --git a/trie/zkproof/writer.go b/trie/zkproof/writer.go index 06e5c944f9b9..003533a7742c 100644 --- a/trie/zkproof/writer.go +++ b/trie/zkproof/writer.go @@ -55,7 +55,7 @@ func resumeProofs(proof []hexutil.Bytes, db *memorydb.Database) *zktrie.Node { //notice: must consistent with trie/merkletree.go bt := hash[:] db.Put(bt, buf) - if n.Type == zktrie.NodeTypeLeaf || n.Type == zktrie.NodeTypeEmpty { + if n.Type == zktrie.NodeTypeLeaf_New || n.Type == zktrie.NodeTypeEmpty_New { return n } } @@ -107,9 +107,9 @@ func decodeProofForMPTPath(proof proofList, path *SMTPath) { keyCounter.Mul(keyCounter, big.NewInt(2)) } switch n.Type { - case zktrie.NodeTypeParent: + case zktrie.NodeTypeBranch_0, zktrie.NodeTypeBranch_1, zktrie.NodeTypeBranch_2, zktrie.NodeTypeBranch_3: lastNode = n - case zktrie.NodeTypeLeaf: + case zktrie.NodeTypeLeaf_New: vhash, _ := n.ValueHash() path.Leaf = &SMTPathNode{ //here we just return the inner represent of hash (little endian, reversed byte order to common hash) @@ -127,7 +127,7 @@ func decodeProofForMPTPath(proof proofList, path *SMTPath) { } return - case zktrie.NodeTypeEmpty: + case zktrie.NodeTypeEmpty_New: return default: panic(fmt.Errorf("unknown node type %d", n.Type)) @@ -160,7 +160,7 @@ func NewZkTrieProofWriter(storage *types.StorageTrace) (*zktrieProofWriter, erro for addrs, proof := range storage.Proofs { if n := resumeProofs(proof, underlayerDb); n != nil { addr := common.HexToAddress(addrs) - if n.Type == zktrie.NodeTypeEmpty { + if n.Type == zktrie.NodeTypeEmpty_New { accounts[addr] = nil } else if acc, err := types.UnmarshalStateAccount(n.Data()); err == nil { if bytes.Equal(n.NodeKey[:], addressToKey(addr)[:]) { @@ -328,7 +328,7 @@ func verifyAccount(addr common.Address, data *types.StateAccount, leaf *SMTPathN } } else if data != nil { arr, flag := data.MarshalFields() - h, err := zkt.PreHandlingElems(flag, arr) + h, err := zkt.HandlingElemsAndByte32(flag, arr) //log.Info("sanity check acc before", "addr", addr.String(), "key", leaf.Sibling.Text(16), "hash", h.Text(16)) if err != nil { diff --git a/trie/zktrie_deletionproof.go b/trie/zktrie_deletionproof.go index e350e5063b8d..02d32933c6d0 100644 --- a/trie/zktrie_deletionproof.go +++ b/trie/zktrie_deletionproof.go @@ -2,6 +2,7 @@ package trie import ( "bytes" + "fmt" zktrie "github.com/scroll-tech/zktrie/trie" zkt "github.com/scroll-tech/zktrie/types" @@ -98,7 +99,7 @@ func (t *ProofTracer) GetDeletionProofs() ([][]byte, error) { if err != nil { return nil, err } - if sibling.Type != zktrie.NodeTypeEmpty { + if sibling.Type != zktrie.NodeTypeEmpty_New { retMap[*siblingHash] = sibling.Value() } } @@ -125,7 +126,7 @@ func (t *ProofTracer) MarkDeletion(key []byte) { // sanity check leafNode := path[len(path)-1] - if leafNode.Type != zktrie.NodeTypeLeaf { + if leafNode.Type != zktrie.NodeTypeLeaf_New { panic("all path recorded in proofTrace should be ended with leafNode") } @@ -145,19 +146,23 @@ func (t *ProofTracer) Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWr return err } - if n.Type == zktrie.NodeTypeLeaf { + switch n.Type { + case zktrie.NodeTypeLeaf_New: preImage := t.GetKey(n.NodeKey.Bytes()) if len(preImage) > 0 { n.KeyPreimage = &zkt.Byte32{} copy(n.KeyPreimage[:], preImage) } - } else if n.Type == zktrie.NodeTypeParent { + case zktrie.NodeTypeBranch_0, zktrie.NodeTypeBranch_1, + zktrie.NodeTypeBranch_2, zktrie.NodeTypeBranch_3: mptPath = append(mptPath, n) - } else if n.Type == zktrie.NodeTypeEmpty { + case zktrie.NodeTypeEmpty_New: // empty node is considered as "unhit" but it should be also being added // into a temporary slot for possibly being marked as deletion later mptPath = append(mptPath, n) t.emptyTermPaths[string(key)] = mptPath + default: + panic(fmt.Errorf("unexpected node type %d", n.Type)) } return proofDb.Put(nodeHash[:], n.Value())