feat: upgrade zktrie to v0.6.0 (#403)

* 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 <peter@scroll.io>
This commit is contained in:
Ho 2023-08-02 10:54:41 +08:00 committed by GitHub
parent 7b75f163b0
commit 11b35cd014
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 64 additions and 29 deletions

View file

@ -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. // DeveloperGenesisBlock returns the 'geth --dev' genesis block.
func DeveloperGenesisBlock(period uint64, gasLimit uint64, faucet common.Address) *Genesis { func DeveloperGenesisBlock(period uint64, gasLimit uint64, faucet common.Address) *Genesis {
// Override the default period to the user requested one // Override the default period to the user requested one

View file

@ -173,7 +173,8 @@ func TestGenesisHashes(t *testing.T) {
// {DefaultRopstenGenesisBlock(), params.RopstenGenesisHash}, // {DefaultRopstenGenesisBlock(), params.RopstenGenesisHash},
// {DefaultRinkebyGenesisBlock(), params.RinkebyGenesisHash}, // {DefaultRinkebyGenesisBlock(), params.RinkebyGenesisHash},
// {DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash}, // {DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash},
{DefaultScrollAlphaGenesisBlock(), params.ScrollAlphaGenesisHash}, // {DefaultScrollAlphaGenesisBlock(), params.ScrollAlphaGenesisHash},
{DefaultScrollSepoliaGenesisBlock(), params.ScrollSepoliaGenesisHash},
} { } {
// Test via MustCommit // Test via MustCommit
if have := c.genesis.MustCommit(rawdb.NewMemoryDatabase()).Hash(); have != c.want { if have := c.genesis.MustCommit(rawdb.NewMemoryDatabase()).Hash(); have != c.want {

View file

@ -9,6 +9,8 @@ import (
"github.com/iden3/go-iden3-crypto/ff" "github.com/iden3/go-iden3-crypto/ff"
"github.com/iden3/go-iden3-crypto/utils" "github.com/iden3/go-iden3-crypto/utils"
"github.com/scroll-tech/go-ethereum/log"
) )
const NROUNDSF = 8 //nolint:golint 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 // Hash computes the Poseidon hash for the given fixed-size inputs, with specified domain field
func HashFixed(inpBI []*big.Int) (*big.Int, error) { func HashFixedWithDomain(inpBI []*big.Int, domain *big.Int) (*big.Int, error) {
t := len(inpBI) + 1 t := len(inpBI) + 1
if len(inpBI) == 0 || len(inpBI) > len(NROUNDSP) { 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 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[:]) inp := utils.BigIntArrayToElementArray(inpBI[:])
state := make([]*ff.Element, t) state := make([]*ff.Element, t)
state[0] = zero() state[0] = ff.NewElement().SetBigInt(domain)
copy(state[1:], inp[:]) copy(state[1:], inp[:])
state = permute(state, t) state = permute(state, t)
@ -175,3 +177,9 @@ func HashFixed(inpBI []*big.Int) (*big.Int, error) {
rE.ToBigIntRegular(r) rE.ToBigIntRegular(r)
return r, nil 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))
}

View file

@ -92,6 +92,14 @@ func TestPoseidonHashFixed(t *testing.T) {
assert.Equal(t, assert.Equal(t,
"9989051620750914585850546081941653841776809718687451684622678807385399211877", "9989051620750914585850546081941653841776809718687451684622678807385399211877",
h.String()) 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) { func TestErrorInputs(t *testing.T) {

2
go.mod
View file

@ -48,7 +48,7 @@ require (
github.com/prometheus/tsdb v0.7.1 github.com/prometheus/tsdb v0.7.1
github.com/rjeczalik/notify v0.9.1 github.com/rjeczalik/notify v0.9.1
github.com/rs/cors v1.7.0 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/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4
github.com/stretchr/testify v1.8.2 github.com/stretchr/testify v1.8.2

4
go.sum
View file

@ -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 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= 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/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.6.0 h1:xLrMAO31Yo2BiPg1jtYKzcjpEFnXy8acbB7iIsyshPs=
github.com/scroll-tech/zktrie v0.5.3/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk= 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.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
github.com/segmentio/kafka-go v0.2.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= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=

View file

@ -29,12 +29,13 @@ import (
// Genesis hashes to enforce below configs on. // Genesis hashes to enforce below configs on.
var ( var (
MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3") MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
RopstenGenesisHash = common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d") RopstenGenesisHash = common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d")
SepoliaGenesisHash = common.HexToHash("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9") SepoliaGenesisHash = common.HexToHash("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9")
RinkebyGenesisHash = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177") RinkebyGenesisHash = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")
GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a") GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a")
ScrollAlphaGenesisHash = common.HexToHash("0xa4fc62b9b0643e345bdcebe457b3ae898bef59c7203c3db269200055e037afda") ScrollAlphaGenesisHash = common.HexToHash("0xa4fc62b9b0643e345bdcebe457b3ae898bef59c7203c3db269200055e037afda")
ScrollSepoliaGenesisHash = common.HexToHash("0x8deefb75edbf59fbff1cd9ffd6ebcd42dced646a1487ef369e0a64ccfc8b1fa2")
) )
// TrustedCheckpoints associates each known checkpoint with the genesis hash of // TrustedCheckpoints associates each known checkpoint with the genesis hash of

View file

@ -24,7 +24,7 @@ import (
const ( const (
VersionMajor = 4 // Major version component of the current release VersionMajor = 4 // Major version component of the current release
VersionMinor = 3 // Minor 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 VersionMeta = "sepolia" // Version metadata to append to the version string
) )

View file

@ -38,7 +38,7 @@ type ZkTrie struct {
} }
func init() { func init() {
zkt.InitHashScheme(poseidon.HashFixed) zkt.InitHashScheme(poseidon.HashFixedWithDomain)
} }
func sanityCheckByte32Key(b []byte) { func sanityCheckByte32Key(b []byte) {
@ -180,7 +180,7 @@ func (t *ZkTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter)
return err return err
} }
if n.Type == zktrie.NodeTypeLeaf { if n.Type == zktrie.NodeTypeLeaf_New {
preImage := t.GetKey(n.NodeKey.Bytes()) preImage := t.GetKey(n.NodeKey.Bytes())
if len(preImage) > 0 { if len(preImage) > 0 {
n.KeyPreimage = &zkt.Byte32{} n.KeyPreimage = &zkt.Byte32{}

View file

@ -200,7 +200,7 @@ func randomZktrie(t *testing.T, n int) (*ZkTrie, map[string]*kv) {
func TestProofWithDeletion(t *testing.T) { func TestProofWithDeletion(t *testing.T) {
tr, _ := NewZkTrie(common.Hash{}, NewZktrieDatabase((memorydb.New()))) tr, _ := NewZkTrie(common.Hash{}, NewZktrieDatabase((memorydb.New())))
mt := &zkTrieImplTestWrapper{tr.Tree()} mt := &zkTrieImplTestWrapper{tr.Tree()}
key1 := bytes.Repeat([]byte("k"), 32) key1 := bytes.Repeat([]byte("l"), 32)
key2 := bytes.Repeat([]byte("m"), 32) key2 := bytes.Repeat([]byte("m"), 32)
err := mt.UpdateWord( err := mt.UpdateWord(
zkt.NewByte32FromBytesPaddingZero(key1), zkt.NewByte32FromBytesPaddingZero(key1),
@ -229,7 +229,7 @@ func TestProofWithDeletion(t *testing.T) {
err = proofTracer.Prove(s_key2.Bytes(), 0, proof) err = proofTracer.Prove(s_key2.Bytes(), 0, proof)
assert.NoError(t, err) assert.NoError(t, err)
// assert.Equal(t, len(sibling1), len(delTracer.GetProofs())) //assert.Equal(t, len(sibling1), len(delTracer.GetProofs()))
siblings, err := proofTracer.GetDeletionProofs() siblings, err := proofTracer.GetDeletionProofs()
assert.NoError(t, err) assert.NoError(t, err)

View file

@ -55,7 +55,7 @@ func resumeProofs(proof []hexutil.Bytes, db *memorydb.Database) *zktrie.Node {
//notice: must consistent with trie/merkletree.go //notice: must consistent with trie/merkletree.go
bt := hash[:] bt := hash[:]
db.Put(bt, buf) 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 return n
} }
} }
@ -107,9 +107,9 @@ func decodeProofForMPTPath(proof proofList, path *SMTPath) {
keyCounter.Mul(keyCounter, big.NewInt(2)) keyCounter.Mul(keyCounter, big.NewInt(2))
} }
switch n.Type { switch n.Type {
case zktrie.NodeTypeParent: case zktrie.NodeTypeBranch_0, zktrie.NodeTypeBranch_1, zktrie.NodeTypeBranch_2, zktrie.NodeTypeBranch_3:
lastNode = n lastNode = n
case zktrie.NodeTypeLeaf: case zktrie.NodeTypeLeaf_New:
vhash, _ := n.ValueHash() vhash, _ := n.ValueHash()
path.Leaf = &SMTPathNode{ path.Leaf = &SMTPathNode{
//here we just return the inner represent of hash (little endian, reversed byte order to common hash) //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 return
case zktrie.NodeTypeEmpty: case zktrie.NodeTypeEmpty_New:
return return
default: default:
panic(fmt.Errorf("unknown node type %d", n.Type)) 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 { for addrs, proof := range storage.Proofs {
if n := resumeProofs(proof, underlayerDb); n != nil { if n := resumeProofs(proof, underlayerDb); n != nil {
addr := common.HexToAddress(addrs) addr := common.HexToAddress(addrs)
if n.Type == zktrie.NodeTypeEmpty { if n.Type == zktrie.NodeTypeEmpty_New {
accounts[addr] = nil accounts[addr] = nil
} else if acc, err := types.UnmarshalStateAccount(n.Data()); err == nil { } else if acc, err := types.UnmarshalStateAccount(n.Data()); err == nil {
if bytes.Equal(n.NodeKey[:], addressToKey(addr)[:]) { 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 { } else if data != nil {
arr, flag := data.MarshalFields() 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)) //log.Info("sanity check acc before", "addr", addr.String(), "key", leaf.Sibling.Text(16), "hash", h.Text(16))
if err != nil { if err != nil {

View file

@ -2,6 +2,7 @@ package trie
import ( import (
"bytes" "bytes"
"fmt"
zktrie "github.com/scroll-tech/zktrie/trie" zktrie "github.com/scroll-tech/zktrie/trie"
zkt "github.com/scroll-tech/zktrie/types" zkt "github.com/scroll-tech/zktrie/types"
@ -98,7 +99,7 @@ func (t *ProofTracer) GetDeletionProofs() ([][]byte, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if sibling.Type != zktrie.NodeTypeEmpty { if sibling.Type != zktrie.NodeTypeEmpty_New {
retMap[*siblingHash] = sibling.Value() retMap[*siblingHash] = sibling.Value()
} }
} }
@ -125,7 +126,7 @@ func (t *ProofTracer) MarkDeletion(key []byte) {
// sanity check // sanity check
leafNode := path[len(path)-1] 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") 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 return err
} }
if n.Type == zktrie.NodeTypeLeaf { switch n.Type {
case zktrie.NodeTypeLeaf_New:
preImage := t.GetKey(n.NodeKey.Bytes()) preImage := t.GetKey(n.NodeKey.Bytes())
if len(preImage) > 0 { if len(preImage) > 0 {
n.KeyPreimage = &zkt.Byte32{} n.KeyPreimage = &zkt.Byte32{}
copy(n.KeyPreimage[:], preImage) 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) 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 // empty node is considered as "unhit" but it should be also being added
// into a temporary slot for possibly being marked as deletion later // into a temporary slot for possibly being marked as deletion later
mptPath = append(mptPath, n) mptPath = append(mptPath, n)
t.emptyTermPaths[string(key)] = mptPath t.emptyTermPaths[string(key)] = mptPath
default:
panic(fmt.Errorf("unexpected node type %d", n.Type))
} }
return proofDb.Put(nodeHash[:], n.Value()) return proofDb.Put(nodeHash[:], n.Value())