diff --git a/Dockerfile.local b/Dockerfile.local index 8798cd37477..88dccc079d4 100644 --- a/Dockerfile.local +++ b/Dockerfile.local @@ -3,6 +3,12 @@ FROM docker.io/library/golang:1.20-alpine3.17 AS builder RUN apk --no-cache add build-base linux-headers git bash ca-certificates libstdc++ +# install rust env +RUN apk add --no-cache curl build-base +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y +ENV PATH="/root/.cargo/bin:${PATH}" +RUN rustup install nightly + WORKDIR /app ADD go.mod go.mod ADD go.sum go.sum @@ -10,6 +16,10 @@ ADD go.sum go.sum RUN go mod download ADD . . +WORKDIR /app/smt/pkg/hash/poseidon_goldilocks +RUN cargo +nightly build --release && cp ./target/release/libposeidon_goldilocks.* . && cargo clean +WORKDIR /app + RUN --mount=type=cache,target=/root/.cache \ --mount=type=cache,target=/tmp/go-build \ --mount=type=cache,target=/go/pkg/mod \ diff --git a/smt/pkg/blockinfo/block_info.go b/smt/pkg/blockinfo/block_info.go index 612df1504b3..9c13846caaa 100644 --- a/smt/pkg/blockinfo/block_info.go +++ b/smt/pkg/blockinfo/block_info.go @@ -4,14 +4,15 @@ import ( "context" "encoding/hex" "math/big" + "runtime" + "sync" ethTypes "github.com/ledgerwatch/erigon/core/types" + "github.com/gateway-fm/cdk-erigon-lib/common" "github.com/ledgerwatch/erigon/smt/pkg/smt" "github.com/ledgerwatch/erigon/smt/pkg/utils" zktx "github.com/ledgerwatch/erigon/zk/tx" - - "github.com/gateway-fm/cdk-erigon-lib/common" "github.com/ledgerwatch/log/v3" ) @@ -50,34 +51,39 @@ func BuildBlockInfoTree( "l1BlockHash", l1BlockHash.String(), ) var logIndex int64 = 0 - for i, txInfo := range *transactionInfos { - receipt := txInfo.Receipt - t := txInfo.Tx + jobs := make(chan TxParserJob, len(*transactionInfos)) + results := make(chan interface{}, len(*transactionInfos)) + var wg sync.WaitGroup - l2TxHash, err := zktx.ComputeL2TxHash( - t.GetChainID().ToBig(), - t.GetValue(), - t.GetPrice(), - t.GetNonce(), - t.GetGas(), - t.GetTo(), - txInfo.Signer, - t.GetData(), - ) - if err != nil { - return nil, err + for workerId := 1; workerId <= runtime.NumCPU(); workerId++ { + wg.Add(1) + go txParserWorker(infoTree, blockNumber, jobs, results, &wg) + } + + for i, txInfo := range *transactionInfos { + jobs <- TxParserJob{ + txIdx: i, + txInfo: txInfo, + logIndex: logIndex, } - log.Trace("info-tree-tx", "block", blockNumber, "idx", i, "hash", l2TxHash.String()) + logIndex += int64(len(txInfo.Receipt.Logs)) + } + close(jobs) + + wg.Wait() + close(results) - genKeys, genVals, err := infoTree.GenerateBlockTxKeysVals(&l2TxHash, i, receipt, logIndex, receipt.CumulativeGasUsed, txInfo.EffectiveGasPrice) - if err != nil { - return nil, err - } - keys = append(keys, genKeys...) - vals = append(vals, genVals...) + for data := range results { + switch data.(type) { + case ParsedKeyVals: + txKeysVals := data.(ParsedKeyVals) + keys = append(keys, txKeysVals.keys...) + vals = append(vals, txKeysVals.vals...) - logIndex += int64(len(receipt.Logs)) + default: + log.Error("not supported data type") + } } key, val, err := generateBlockGasUsed(blockGasUsed) @@ -358,3 +364,49 @@ func (b *BlockInfoTree) GenerateBlockTxKeysVals( return keys, vals, nil } + +type TxParserJob struct { + txIdx int + txInfo ExecutedTxInfo + logIndex int64 +} + +type ParsedKeyVals struct { + keys []*utils.NodeKey + vals []*utils.NodeValue8 +} + +func txParserWorker(infoTree *BlockInfoTree, blockNumber uint64, jobs <-chan TxParserJob, results chan<- interface{}, wg *sync.WaitGroup) { + defer wg.Done() + + for job := range jobs { + receipt := job.txInfo.Receipt + t := job.txInfo.Tx + + l2TxHash, err := zktx.ComputeL2TxHash( + t.GetChainID().ToBig(), + t.GetValue(), + t.GetPrice(), + t.GetNonce(), + t.GetGas(), + t.GetTo(), + job.txInfo.Signer, + t.GetData(), + ) + if err != nil { + log.Error("Fail to ComputeL2TxHash", "TxHash", t.Hash(), "error", err) + } + + log.Trace("info-tree-tx", "block", blockNumber, "idx", job.txIdx, "hash", l2TxHash.String()) + + genKeys, genVals, err := infoTree.GenerateBlockTxKeysVals(&l2TxHash, job.txIdx, receipt, job.logIndex, receipt.CumulativeGasUsed, job.txInfo.EffectiveGasPrice) + if err != nil { + log.Error("Fail to GenerateBlockTxKeysVals", "TxHash", t.Hash(), "error", err) + } + + results <- ParsedKeyVals{ + keys: genKeys, + vals: genVals, + } + } +} diff --git a/smt/pkg/hash/poseidon_godilocks_hash.go b/smt/pkg/hash/poseidon_godilocks_hash.go new file mode 100644 index 00000000000..bd7a76a15a8 --- /dev/null +++ b/smt/pkg/hash/poseidon_godilocks_hash.go @@ -0,0 +1,48 @@ +package hash + +/* +#cgo LDFLAGS: -L./poseidon_goldilocks -lposeidon_goldilocks +#include "./poseidon_goldilocks/poseidon_goldilocks.h" +*/ +import "C" +import ( + "unsafe" +) + +func cBufferToGoSlice(cBuffer *C.Buffer) [4]uint64 { + if cBuffer == nil || cBuffer.len == 0 { + return [4]uint64{} + } + + rst := unsafe.Slice((*uint64)(cBuffer.data), cBuffer.len) + + var result [4]uint64 + copy(result[:], rst) + + return result +} + +func goSliceToCBuffer(in []uint64) C.Buffer { + if len(in) == 0 { + return C.Buffer{} + } + + return C.Buffer{ + data: (*C.uint64_t)(unsafe.Pointer(&in[0])), + len: C.size_t(len(in)), + } +} + +func Hash(in [8]uint64, capacity [4]uint64) ([4]uint64, error) { + input := make([]uint64, 0, len(in)+len(capacity)) + input = append(input, in[:]...) + input = append(input, capacity[:]...) + + cInput := goSliceToCBuffer(input[:]) + cHashRst := C.rustPoseidongoldHash(cInput) + rst := cBufferToGoSlice(&cHashRst) + + C.free_buf(cHashRst) + + return rst, nil +} diff --git a/smt/pkg/hash/poseidon_godilocks_hash_test.go b/smt/pkg/hash/poseidon_godilocks_hash_test.go new file mode 100644 index 00000000000..11afa81fe62 --- /dev/null +++ b/smt/pkg/hash/poseidon_godilocks_hash_test.go @@ -0,0 +1,93 @@ +package hash + +import ( + "github.com/stretchr/testify/assert" + "math/rand" + "testing" + "time" +) + +func TestPoseidonHashFunc(t *testing.T) { + tests := []struct { + input [8]uint64 + capacity [4]uint64 + result [4]uint64 + }{ + { + input: [8]uint64{5577006791947779410, 8674665223082153551, 15352856648520921629, 13260572831089785859, 3916589616287113937, 6334824724549167320, 9828766684487745566, 10667007354186551956}, + capacity: [4]uint64{0, 0, 0, 0}, + result: [4]uint64{7986352640330579808, 16698976638447200418, 14099060853601989680, 1806029100513259151}, + }, + { + input: [8]uint64{894385949183117216, 11998794077335055257, 4751997750760398084, 7504504064263669287, 11199607447739267382, 3510942875414458836, 12156940908066221323, 4324745483838182873}, + capacity: [4]uint64{0, 0, 0, 0}, + result: [4]uint64{4912038160490892692, 4103686885524875147, 10541378107520313959, 17279065624757782690}, + }, + { + input: [8]uint64{11833901312327420776, 11926759511765359899, 6263450610539110790, 11239168150708129139, 1874068156324778273, 3328451335138149956, 14486903973548550719, 7955079406183515637}, + capacity: [4]uint64{0, 0, 0, 0}, + result: [4]uint64{7890399244011379224, 3893786354640587971, 13560196409483468805, 2948784903943663078}, + }, + { + input: [8]uint64{11926873763676642186, 2740103009342231109, 6941261091797652072, 1905388747193831650, 17204678798284737396, 15649472107743074779, 4831389563158288344, 261049867304784443}, + capacity: [4]uint64{0, 0, 0, 0}, + result: [4]uint64{14700294369684741534, 14895735373969203815, 16434826207003907392, 17867437290801947189}, + }, + { + input: [8]uint64{10683692646452562431, 5600924393587988459, 18218388313430417611, 9956202364908137547, 5486140987150761883, 9768663798983814715, 6382800227808658932, 2781055864473387780}, + capacity: [4]uint64{0, 0, 0, 0}, + result: [4]uint64{17625602373883346164, 18149609703473926001, 2824810185344003270, 9975387089464755098}, + }, + { + input: [8]uint64{10821471013040158923, 4990765271833742716, 14242321332569825828, 11792151447964398879, 13126262220165910460, 14117161486975057715, 2338498362660772719, 2601737961087659062}, + capacity: [4]uint64{0, 0, 0, 0}, + result: [4]uint64{2691796281516679790, 14584425213549820217, 14318483276994184927, 17940735015359233298}, + }, + { + input: [8]uint64{7273596521315663110, 3337066551442961397, 17344948852394588913, 11963748953446345529, 8249030965139585917, 898860202204764712, 9010467728050264449, 9908585559158765387}, + capacity: [4]uint64{0, 0, 0, 0}, + result: [4]uint64{8150678766998536923, 14721645535435562842, 2012097115710913290, 6143064933387483688}, + }, + { + input: [8]uint64{11273630029763932141, 15505210698284655633, 2227583514184312746, 12096659438561119542, 8603989663476771718, 6842348953158377901, 7388428680384065704, 6735196588112087610}, + capacity: [4]uint64{0, 0, 0, 0}, + result: [4]uint64{9286804905202849659, 7450030268744143082, 2587697138684996149, 603260420412321806}, + }, + } + + for _, test := range tests { + rst, err := Hash(test.input, test.capacity) + assert.Nil(t, err, "fail to calculate poseidon hash") + + if rst != test.result { + t.Errorf("parse doesn't match, expected: %v, got: %v", test.result, rst) + } + } +} + +func RandCalPoseidonHashFunc() { + rand.Seed(time.Now().UnixNano()) + + input := [8]uint64{rand.Uint64(), rand.Uint64(), rand.Uint64(), rand.Uint64(), rand.Uint64(), rand.Uint64(), rand.Uint64(), rand.Uint64()} + capacity := [4]uint64{rand.Uint64(), rand.Uint64(), rand.Uint64(), rand.Uint64()} + Hash(input, capacity) +} + +func BenchmarkRandCalculateHash_rust(b *testing.B) { + for i := 0; i < b.N; i++ { + RandCalPoseidonHashFunc() + } +} + +func CalPoseidonHashFunc() { + input := [8]uint64{5577006791947779410, 8674665223082153551, 15352856648520921629, 13260572831089785859, 3916589616287113937, 6334824724549167320, 9828766684487745566, 10667007354186551956} + capacity := [4]uint64{0, 0, 0, 0} + + Hash(input, capacity) +} + +func BenchmarkCalculateHash_rust(b *testing.B) { + for i := 0; i < b.N; i++ { + CalPoseidonHashFunc() + } +} diff --git a/smt/pkg/hash/poseidon_goldilocks/.gitignore b/smt/pkg/hash/poseidon_goldilocks/.gitignore new file mode 100644 index 00000000000..c41cc9e35e3 --- /dev/null +++ b/smt/pkg/hash/poseidon_goldilocks/.gitignore @@ -0,0 +1 @@ +/target \ No newline at end of file diff --git a/smt/pkg/hash/poseidon_goldilocks/Cargo.lock b/smt/pkg/hash/poseidon_goldilocks/Cargo.lock new file mode 100644 index 00000000000..8682fe03e0c --- /dev/null +++ b/smt/pkg/hash/poseidon_goldilocks/Cargo.lock @@ -0,0 +1,629 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "const-random", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "fixed-hash" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "rayon", + "serde", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "jemalloc-sys" +version = "0.5.4+5.3.0-patched" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac6c1946e1cea1788cbfde01c993b52a10e2da07f4bac608228d1bed20bfebf2" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "jemallocator" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0de374a9f8e63150e6f5e8a60cc14c668226d7a347d8aee1a45766e3c4dd3bc" +dependencies = [ + "jemalloc-sys", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "keccak-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce2bd4c29270e724d3eaadf7bdc8700af4221fc0ed771b855eadcd1b98d52851" +dependencies = [ + "primitive-types", + "tiny-keccak", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", + "rand", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "plonky2" +version = "0.2.2" +source = "git+https://github.com/louisliu2048/plonky2?branch=xiong/hermez-poseidon#11242f9e7c00fb169941e9e30c9e0352238cf686" +dependencies = [ + "ahash", + "anyhow", + "getrandom", + "hashbrown", + "itertools", + "keccak-hash", + "log", + "num", + "plonky2_field", + "plonky2_maybe_rayon", + "plonky2_util", + "rand", + "rand_chacha", + "serde", + "static_assertions", + "unroll", + "web-time", +] + +[[package]] +name = "plonky2_field" +version = "0.2.2" +source = "git+https://github.com/louisliu2048/plonky2?branch=xiong/hermez-poseidon#11242f9e7c00fb169941e9e30c9e0352238cf686" +dependencies = [ + "anyhow", + "itertools", + "num", + "plonky2_util", + "rand", + "serde", + "static_assertions", + "unroll", +] + +[[package]] +name = "plonky2_maybe_rayon" +version = "0.2.0" +source = "git+https://github.com/louisliu2048/plonky2?branch=xiong/hermez-poseidon#11242f9e7c00fb169941e9e30c9e0352238cf686" +dependencies = [ + "rayon", +] + +[[package]] +name = "plonky2_util" +version = "0.2.0" +source = "git+https://github.com/louisliu2048/plonky2?branch=xiong/hermez-poseidon#11242f9e7c00fb169941e9e30c9e0352238cf686" + +[[package]] +name = "poseidon_goldilocks" +version = "0.1.0" +dependencies = [ + "jemallocator", + "libc", + "plonky2", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "primitive-types" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" +dependencies = [ + "fixed-hash", + "uint", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "serde" +version = "1.0.208" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.208" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unroll" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ad948c1cb799b1a70f836077721a92a35ac177d4daddf4c20a633786d4cf618" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.75", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] \ No newline at end of file diff --git a/smt/pkg/hash/poseidon_goldilocks/Cargo.toml b/smt/pkg/hash/poseidon_goldilocks/Cargo.toml new file mode 100644 index 00000000000..ceead77adc0 --- /dev/null +++ b/smt/pkg/hash/poseidon_goldilocks/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "poseidon_goldilocks" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["staticlib"] + +[dependencies] +plonky2 = { git = "https://github.com/louisliu2048/plonky2", branch = "xiong/hermez-poseidon" } +jemallocator = "0.5.0" +libc = "0.2" \ No newline at end of file diff --git a/smt/pkg/hash/poseidon_goldilocks/cbindgen.toml b/smt/pkg/hash/poseidon_goldilocks/cbindgen.toml new file mode 100644 index 00000000000..f5682f0236e --- /dev/null +++ b/smt/pkg/hash/poseidon_goldilocks/cbindgen.toml @@ -0,0 +1,3 @@ +include_guard = "POSEIDON_GOLDILOCKS_H" +autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */" +language = "C" \ No newline at end of file diff --git a/smt/pkg/hash/poseidon_goldilocks/libposeidon_goldilocks.a b/smt/pkg/hash/poseidon_goldilocks/libposeidon_goldilocks.a new file mode 100644 index 00000000000..a84b39eb46e Binary files /dev/null and b/smt/pkg/hash/poseidon_goldilocks/libposeidon_goldilocks.a differ diff --git a/smt/pkg/hash/poseidon_goldilocks/poseidon_goldilocks.h b/smt/pkg/hash/poseidon_goldilocks/poseidon_goldilocks.h new file mode 100644 index 00000000000..b6d8f3aeb30 --- /dev/null +++ b/smt/pkg/hash/poseidon_goldilocks/poseidon_goldilocks.h @@ -0,0 +1,20 @@ +#ifndef POSEIDON_GOLDILOCKS_H +#define POSEIDON_GOLDILOCKS_H + +/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */ + +#include +#include +#include +#include + +typedef struct Buffer { + uint64_t *data; + uintptr_t len; +} Buffer; + +struct Buffer rustPoseidongoldHash(struct Buffer input_ptr); + +void free_buf(struct Buffer buf); + +#endif /* POSEIDON_GOLDILOCKS_H */ \ No newline at end of file diff --git a/smt/pkg/hash/poseidon_goldilocks/src/lib.rs b/smt/pkg/hash/poseidon_goldilocks/src/lib.rs new file mode 100644 index 00000000000..2d3bea65630 --- /dev/null +++ b/smt/pkg/hash/poseidon_goldilocks/src/lib.rs @@ -0,0 +1,50 @@ +use plonky2::field::goldilocks_field::GoldilocksField; +use plonky2::hash::poseidon::{PoseidonHash}; +use plonky2::hash::hash_types::HashOut; +use plonky2::field::types::{Field, PrimeField64}; +use plonky2::plonk::config::{GenericHashOut, Hasher}; +use jemallocator::Jemalloc; + +#[global_allocator] +static GLOBAL: Jemalloc = Jemalloc; + +#[repr(C)] +pub struct Buffer { + data: *mut u64, + len: usize, +} + +#[no_mangle] +pub extern fn rustPoseidongoldHash(input_ptr: Buffer) -> Buffer { + let input = unsafe { + std::slice::from_raw_parts_mut(input_ptr.data, input_ptr.len) + }; + + let inputs:Vec= input.into_iter() + .map(|x| {GoldilocksField::from_canonical_u64(*x)}) + .collect(); + + // Calculate the Poseidon hash using Plonky2 + let hash_output: HashOut = PoseidonHash::hash_result_scalar(&inputs); + + let transformed_hash_vec: Vec = hash_output.to_vec().into_iter() + .map(|x| GoldilocksField::to_canonical_u64(&x)) + .collect(); + + let mut buf = transformed_hash_vec.into_boxed_slice(); + let data = buf.as_mut_ptr(); + let len = buf.len(); + + std::mem::forget(buf); + + Buffer { data, len } +} + +#[no_mangle] +pub extern fn free_buf(buf: Buffer) { + if !buf.data.is_null() { + unsafe { + let _ = Box::from_raw(std::slice::from_raw_parts_mut(buf.data, buf.len)); + } + } +} \ No newline at end of file diff --git a/smt/pkg/smt/smt_batch.go b/smt/pkg/smt/smt_batch.go index eb924c03a68..413f1446b1a 100644 --- a/smt/pkg/smt/smt_batch.go +++ b/smt/pkg/smt/smt_batch.go @@ -1,6 +1,7 @@ package smt import ( + "container/list" "context" "fmt" "sync" @@ -8,6 +9,7 @@ import ( "github.com/dgravesa/go-parallel/parallel" "github.com/ledgerwatch/erigon/smt/pkg/utils" "github.com/ledgerwatch/erigon/zk" + "github.com/ledgerwatch/log/v3" ) func (s *SMT) InsertBatch(ctx context.Context, logPrefix string, nodeKeys []*utils.NodeKey, nodeValues []*utils.NodeValue8, nodeValuesHashes []*[4]uint64, rootNodeHash *utils.NodeKey) (*SMTResponse, error) { @@ -168,7 +170,7 @@ func (s *SMT) InsertBatch(ctx context.Context, logPrefix string, nodeKeys []*uti if smtBatchNodeRoot == nil { rootNodeHash = &utils.NodeKey{0, 0, 0, 0} } else { - if err := calculateAndSaveHashesDfs(s, smtBatchNodeRoot, make([]int, 256), 0); err != nil { + if err := calculateAndSaveHashes(s, smtBatchNodeRoot, make([]int, 256), 0); err != nil { return nil, fmt.Errorf("calculating and saving hashes dfs: %w", err) } rootNodeHash = (*utils.NodeKey)(smtBatchNodeRoot.hash) @@ -602,3 +604,187 @@ func getNodeKeyMapValue[T int | *utils.NodeKey](nodeKeyMap map[uint64]map[uint64 value, found := mapLevel2[nodeKey[3]] return value, found } + +type SmtNodeJob struct { + smtBatchNode *smtBatchNode + path []int + level int +} + +type SaveNodeHash struct { + in [8]uint64 + capacity [4]uint64 + h utils.NodeKey +} + +type SaveHashKey struct { + key utils.NodeKey + value utils.NodeKey +} + +func calculateAndSaveHashes(s *SMT, smtBatchNode *smtBatchNode, path []int, level int) error { + //return calculateAndSaveHashesDfs(s, smtBatchNode, path, level) + + queue := list.New() + var mu sync.Mutex + + findAsyncAbleNodeJobDfs(smtBatchNode, path, level, queue) + + results := make(chan interface{}, 200) + var wg sync.WaitGroup + for i := 1; i <= 100; i++ { + wg.Add(1) + go asyncSmtNodeHash(queue, &mu, results, &wg) + } + + go func() { + wg.Wait() + close(results) + }() + + for data := range results { + switch data.(type) { + case SaveNodeHash: + hashInfo := data.(SaveNodeHash) + err := s.hashSave(hashInfo.in, hashInfo.capacity, hashInfo.h) + if err != nil { + log.Error("fail to save node hash: ", err) + } + case SaveHashKey: + hashKey := data.(SaveHashKey) + err := s.Db.InsertHashKey(hashKey.key, hashKey.value) + if err != nil { + log.Error("fail to save hash key pair: ", err) + } + default: + log.Error("not supported data type") + } + } + + return nil +} + +func findAsyncAbleNodeJobDfs(smtBatchNode *smtBatchNode, path []int, level int, jobQueue *list.List) { + if smtBatchNode == nil { + return + } + + if smtBatchNode.leftNode != nil { + leftPath := make([]int, len(path)) + copy(leftPath, path) + leftPath[level] = 0 + findAsyncAbleNodeJobDfs(smtBatchNode.leftNode, leftPath, level+1, jobQueue) + } + + if smtBatchNode.rightNode != nil { + rightPath := make([]int, len(path)) + copy(rightPath, path) + rightPath[level] = 1 + findAsyncAbleNodeJobDfs(smtBatchNode.rightNode, rightPath, level+1, jobQueue) + } + + if smtBatchNode.isLeaf() || smtBatchNode.leftNode == nil && smtBatchNode.rightNode == nil { + jobQueue.PushBack(&SmtNodeJob{ + smtBatchNode: smtBatchNode, + path: path, + level: level, + }) + } + + return +} + +func asyncSmtNodeHash(jobQueue *list.List, mu *sync.Mutex, results chan<- interface{}, wg *sync.WaitGroup) { + defer wg.Done() + + var newTask *SmtNodeJob + for { + mu.Lock() + + newTask = nil + if jobQueue.Len() > 0 { + front := jobQueue.Front() + nodeJob := front.Value.(*SmtNodeJob) + jobQueue.Remove(front) + mu.Unlock() + + if nodeJob.smtBatchNode.hash != nil { + continue + } + + if nodeJob.smtBatchNode.isLeaf() { + in := utils.ConcatArrays4(*nodeJob.smtBatchNode.nodeLeftHashOrRemainingKey, *nodeJob.smtBatchNode.nodeRightHashOrValueHash) + hashObj, err := utils.Hash(in, utils.LeafCapacity) + if err != nil { + log.Error("Fail to calculate leaf node hash", "err", err) + } + nodeJob.smtBatchNode.hash = &hashObj + + results <- SaveNodeHash{ + in: in, + capacity: utils.LeafCapacity, + h: hashObj, + } + + nodeKey := utils.JoinKey(nodeJob.path[:nodeJob.level], *nodeJob.smtBatchNode.nodeLeftHashOrRemainingKey) + results <- SaveHashKey{ + key: hashObj, + value: *nodeKey, + } + } else { + var totalHash utils.NodeValue8 + if nodeJob.smtBatchNode.leftNode != nil { + if nodeJob.smtBatchNode.leftNode.hash == nil { + newTask = nodeJob + + continue + } + totalHash.SetHalfValue(*nodeJob.smtBatchNode.leftNode.hash, 0) + } else { + totalHash.SetHalfValue(*nodeJob.smtBatchNode.nodeLeftHashOrRemainingKey, 0) + } + + if nodeJob.smtBatchNode.rightNode != nil { + if nodeJob.smtBatchNode.rightNode.hash == nil { + newTask = nodeJob + + continue + } + totalHash.SetHalfValue(*nodeJob.smtBatchNode.rightNode.hash, 1) + } else { + totalHash.SetHalfValue(*nodeJob.smtBatchNode.nodeRightHashOrValueHash, 1) + } + + hashObj, err := utils.Hash(totalHash.ToUintArray(), utils.BranchCapacity) + if err != nil { + log.Error("Fail to calculate internal node hash", "err", err) + } + nodeJob.smtBatchNode.hash = &hashObj + + results <- SaveNodeHash{ + in: totalHash.ToUintArray(), + capacity: utils.BranchCapacity, + h: hashObj, + } + } + + // add parent node to task list + if nodeJob.level > 0 { + newTask = &SmtNodeJob{ + smtBatchNode: nodeJob.smtBatchNode.parentNode, + path: nodeJob.path, // internal node do not need path to cal hash + level: nodeJob.level - 1, + } + } + } else { + mu.Unlock() + break + } + + if newTask != nil { + mu.Lock() + jobQueue.PushBack(newTask) + mu.Unlock() + } + } +} diff --git a/smt/pkg/smt/smt_batch_test.go b/smt/pkg/smt/smt_batch_test.go index 59b4b7ad59c..61019224a5f 100644 --- a/smt/pkg/smt/smt_batch_test.go +++ b/smt/pkg/smt/smt_batch_test.go @@ -185,7 +185,7 @@ func TestBatchSimpleInsert2(t *testing.T) { smtBatch := smt.NewSMT(nil, false) batchInsert(smtBatch, keys, vals) - smtBatchNoSave := smt.NewSMT(nil, false) + smtBatchNoSave := smt.NewSMT(nil, true) batchInsert(smtBatchNoSave, keys, vals) smtIncrementalRootHash, _ := smtIncremental.Db.GetLastRoot() diff --git a/smt/pkg/utils/util_test.go b/smt/pkg/utils/util_test.go index 8b155152a0a..432946fa7cf 100644 --- a/smt/pkg/utils/util_test.go +++ b/smt/pkg/utils/util_test.go @@ -3,10 +3,15 @@ package utils import ( "fmt" "math/big" + "math/rand" "reflect" "strconv" "strings" "testing" + "time" + + poseidon "github.com/gateway-fm/vectorized-poseidon-gold/src/vectorizedposeidongold" + "github.com/stretchr/testify/assert" ) const forkId7BlockGasLimit = 18446744073709551615 @@ -777,3 +782,88 @@ func TestNodeKeyFromPath(t *testing.T) { } } } + +func TestPoseidonHashFunc(t *testing.T) { + tests := []struct { + input [8]uint64 + capacity [4]uint64 + result [4]uint64 + }{ + { + input: [8]uint64{5577006791947779410, 8674665223082153551, 15352856648520921629, 13260572831089785859, 3916589616287113937, 6334824724549167320, 9828766684487745566, 10667007354186551956}, + capacity: [4]uint64{0, 0, 0, 0}, + result: [4]uint64{7986352640330579808, 16698976638447200418, 14099060853601989680, 1806029100513259151}, + }, + { + input: [8]uint64{894385949183117216, 11998794077335055257, 4751997750760398084, 7504504064263669287, 11199607447739267382, 3510942875414458836, 12156940908066221323, 4324745483838182873}, + capacity: [4]uint64{0, 0, 0, 0}, + result: [4]uint64{4912038160490892692, 4103686885524875147, 10541378107520313959, 17279065624757782690}, + }, + { + input: [8]uint64{11833901312327420776, 11926759511765359899, 6263450610539110790, 11239168150708129139, 1874068156324778273, 3328451335138149956, 14486903973548550719, 7955079406183515637}, + capacity: [4]uint64{0, 0, 0, 0}, + result: [4]uint64{7890399244011379224, 3893786354640587971, 13560196409483468805, 2948784903943663078}, + }, + { + input: [8]uint64{11926873763676642186, 2740103009342231109, 6941261091797652072, 1905388747193831650, 17204678798284737396, 15649472107743074779, 4831389563158288344, 261049867304784443}, + capacity: [4]uint64{0, 0, 0, 0}, + result: [4]uint64{14700294369684741534, 14895735373969203815, 16434826207003907392, 17867437290801947189}, + }, + { + input: [8]uint64{10683692646452562431, 5600924393587988459, 18218388313430417611, 9956202364908137547, 5486140987150761883, 9768663798983814715, 6382800227808658932, 2781055864473387780}, + capacity: [4]uint64{0, 0, 0, 0}, + result: [4]uint64{17625602373883346164, 18149609703473926001, 2824810185344003270, 9975387089464755098}, + }, + { + input: [8]uint64{10821471013040158923, 4990765271833742716, 14242321332569825828, 11792151447964398879, 13126262220165910460, 14117161486975057715, 2338498362660772719, 2601737961087659062}, + capacity: [4]uint64{0, 0, 0, 0}, + result: [4]uint64{2691796281516679790, 14584425213549820217, 14318483276994184927, 17940735015359233298}, + }, + { + input: [8]uint64{7273596521315663110, 3337066551442961397, 17344948852394588913, 11963748953446345529, 8249030965139585917, 898860202204764712, 9010467728050264449, 9908585559158765387}, + capacity: [4]uint64{0, 0, 0, 0}, + result: [4]uint64{8150678766998536923, 14721645535435562842, 2012097115710913290, 6143064933387483688}, + }, + { + input: [8]uint64{11273630029763932141, 15505210698284655633, 2227583514184312746, 12096659438561119542, 8603989663476771718, 6842348953158377901, 7388428680384065704, 6735196588112087610}, + capacity: [4]uint64{0, 0, 0, 0}, + result: [4]uint64{9286804905202849659, 7450030268744143082, 2587697138684996149, 603260420412321806}, + }, + } + + for _, test := range tests { + rst, err := poseidon.Hash(test.input, test.capacity) + assert.Nil(t, err, "fail to calculate poseidon hash") + + if rst != test.result { + t.Errorf("parse doesn't match, expected: %v, got: %v", test.result, rst) + } + } +} + +func RandCalPoseidonHashFunc() { + rand.Seed(time.Now().UnixNano()) + + input := [8]uint64{rand.Uint64(), rand.Uint64(), rand.Uint64(), rand.Uint64(), rand.Uint64(), rand.Uint64(), rand.Uint64(), rand.Uint64()} + capacity := [4]uint64{rand.Uint64(), rand.Uint64(), rand.Uint64(), rand.Uint64()} + poseidon.Hash(input, capacity) +} + +func BenchmarkRandCalculateHash_CPP(b *testing.B) { + for i := 0; i < b.N; i++ { + RandCalPoseidonHashFunc() + } +} + +func CalPoseidonHashFunc() { + input := [8]uint64{5577006791947779410, 8674665223082153551, 15352856648520921629, 13260572831089785859, 3916589616287113937, 6334824724549167320, 9828766684487745566, 10667007354186551956} + capacity := [4]uint64{0, 0, 0, 0} + + poseidon.Hash(input, capacity) +} + +func BenchmarkCalculateHash_CPP(b *testing.B) { + for i := 0; i < b.N; i++ { + CalPoseidonHashFunc() + } +} diff --git a/smt/pkg/utils/utils.go b/smt/pkg/utils/utils.go index 1410cddc74f..c6f50c1ef2c 100644 --- a/smt/pkg/utils/utils.go +++ b/smt/pkg/utils/utils.go @@ -13,6 +13,7 @@ import ( "github.com/gateway-fm/cdk-erigon-lib/common" "github.com/gateway-fm/cdk-erigon-lib/common/length" poseidon "github.com/gateway-fm/vectorized-poseidon-gold/src/vectorizedposeidongold" + "github.com/ledgerwatch/erigon/smt/pkg/hash" ) const ( @@ -48,10 +49,11 @@ var ( LeafCapacity = [4]uint64{1, 0, 0, 0} BranchCapacity = [4]uint64{0, 0, 0, 0} hashFunc = poseidon.Hash + rHashFunc = hash.Hash ) func Hash(in [8]uint64, capacity [4]uint64) ([4]uint64, error) { - return hashFunc(in, capacity) + return rHashFunc(in, capacity) } func (nk *NodeKey) IsZero() bool { diff --git a/zk/stages/stage_sequence_execute_blocks.go b/zk/stages/stage_sequence_execute_blocks.go index 060c753a26d..fce1479bde0 100644 --- a/zk/stages/stage_sequence_execute_blocks.go +++ b/zk/stages/stage_sequence_execute_blocks.go @@ -136,6 +136,7 @@ func finaliseBlock( } txInfos := []blockinfo.ExecutedTxInfo{} + txHash2SenderCache := make(map[common.Hash]common.Address) builtBlockElements := batchState.blockState.builtBlockElements for i, tx := range builtBlockElements.transactions { var from common.Address @@ -157,6 +158,8 @@ func finaliseBlock( Receipt: localReceipt, Signer: &from, }) + + txHash2SenderCache[tx.Hash()] = sender } if err := postBlockStateHandling(*batchContext.cfg, ibs, batchContext.sdb.hermezDb, newHeader, ger, l1BlockHash, parentBlock.Root(), txInfos); err != nil { @@ -232,7 +235,7 @@ func finaliseBlock( } // now process the senders to avoid a stage by itself - if err := addSenders(*batchContext.cfg, newNum, finalTransactions, batchContext.sdb.tx, finalHeader); err != nil { + if err := addSenders(*batchContext.cfg, newNum, finalTransactions, batchContext.sdb.tx, finalHeader, txHash2SenderCache); err != nil { return nil, err } @@ -303,14 +306,21 @@ func addSenders( finalTransactions types.Transactions, tx kv.RwTx, finalHeader *types.Header, + txHash2SenderCache map[common.Hash]common.Address, ) error { signer := types.MakeSigner(cfg.chainConfig, newNum.Uint64()) cryptoContext := secp256k1.ContextForThread(1) senders := make([]common.Address, 0, len(finalTransactions)) + var from common.Address for _, transaction := range finalTransactions { - from, err := signer.SenderWithContext(cryptoContext, transaction) - if err != nil { - return err + if val, ok := txHash2SenderCache[transaction.Hash()]; ok { + from = val + } else { + val, err := signer.SenderWithContext(cryptoContext, transaction) + if err != nil { + return err + } + from = val } senders = append(senders, from) }