github.com/cryptotooltop/go-ethereum@v0.0.0-20231103184714-151d1922f3e5/crypto/poseidon/codehash.go (about) 1 package poseidon 2 3 import ( 4 "math/big" 5 6 "github.com/scroll-tech/go-ethereum/common" 7 ) 8 9 const defaultPoseidonChunk = 3 10 const nBytesToFieldElement = 31 11 12 func CodeHash(code []byte) (h common.Hash) { 13 nBytes := int64(len(code)) 14 15 // step 1: pad code with 0x0 (STOP) so that len(code) % nBytesToFieldElement == 0 16 // step 2: for every nBytesToFieldElement bytes, convert to Fr, so that we get a Fr array 17 var length = (len(code) + nBytesToFieldElement - 1) / nBytesToFieldElement 18 19 Frs := make([]*big.Int, length) 20 ii := 0 21 22 for ii < length-1 { 23 Frs[ii] = big.NewInt(0) 24 Frs[ii].SetBytes(code[ii*nBytesToFieldElement : (ii+1)*nBytesToFieldElement]) 25 ii++ 26 } 27 28 if length > 0 { 29 Frs[ii] = big.NewInt(0) 30 bytes := make([]byte, nBytesToFieldElement) 31 copy(bytes, code[ii*nBytesToFieldElement:]) 32 Frs[ii].SetBytes(bytes) 33 } 34 35 // step 3: apply the array onto a sponge process with the current poseidon scheme 36 // (3 Frs permutation and 1 Fr for output, so the throughout is 2 Frs) 37 // step 4: convert final root Fr to u256 (big-endian representation) 38 hash, err := HashWithCap(Frs, defaultPoseidonChunk, nBytes) 39 if err != nil { 40 return common.Hash{} 41 } 42 return common.BigToHash(hash) 43 }