From d6fe349f4170adc78d0a865ad147d2b7adeeacca Mon Sep 17 00:00:00 2001 From: rianhughes Date: Tue, 3 Oct 2023 16:56:36 +0300 Subject: [PATCH] typo --- utils/keccak.go | 173 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 utils/keccak.go diff --git a/utils/keccak.go b/utils/keccak.go new file mode 100644 index 00000000..3065b99e --- /dev/null +++ b/utils/keccak.go @@ -0,0 +1,173 @@ +package utils + +import ( + "bytes" + "encoding/hex" + "fmt" + "hash" + "math/big" + "strings" + + "github.com/NethermindEth/juno/core/felt" + "golang.org/x/crypto/sha3" +) + +// KeccakState wraps sha3.state. In addition to the usual hash methods, it also supports +// Read to get a variable amount of data from the hash state. Read is faster than Sum +// because it doesn't copy the internal state, but also modifies the internal state. +type KeccakState interface { + hash.Hash + Read([]byte) (int, error) +} + +// Convert utf8 string to big int +func UTF8StrToBig(str string) *big.Int { + hexStr := hex.EncodeToString([]byte(str)) + b, _ := new(big.Int).SetString(hexStr, 16) + + return b +} + +// convert decimal string to big int +func StrToBig(str string) *big.Int { + b, _ := new(big.Int).SetString(str, 10) + + return b +} + +// convert hex string to Starknet 'short string' +func HexToShortStr(hexStr string) string { + numStr := strings.Replace(hexStr, "0x", "", -1) + hb, _ := new(big.Int).SetString(numStr, 16) + + return string(hb.Bytes()) +} + +// trim "0x" prefix(if exists) and converts hexidecimal string to big int +func HexToBN(hexString string) *big.Int { + numStr := strings.Replace(hexString, "0x", "", -1) + + n, _ := new(big.Int).SetString(numStr, 16) + return n +} + +// trim "0x" prefix(if exists) and converts hexidecimal string to byte slice +func HexToBytes(hexString string) ([]byte, error) { + numStr := strings.Replace(hexString, "0x", "", -1) + if (len(numStr) % 2) != 0 { + numStr = fmt.Sprintf("%s%s", "0", numStr) + } + + return hex.DecodeString(numStr) +} + +func BytesToBig(bytes []byte) *big.Int { + return new(big.Int).SetBytes(bytes) +} + +// convert big int to hexidecimal string +func BigToHex(in *big.Int) string { + return fmt.Sprintf("0x%x", in) +} + +// todo(): this is used by the signer. Should it return a felt? +func GetSelectorFromName(funcName string) *big.Int { + kec := Keccak256([]byte(funcName)) + + maskedKec := MaskBits(250, 8, kec) + + return new(big.Int).SetBytes(maskedKec) +} + +func GetSelectorFromNameFelt(funcName string) *felt.Felt { + kec := Keccak256([]byte(funcName)) + + maskedKec := MaskBits(250, 8, kec) + + return new(felt.Felt).SetBytes(maskedKec) +} + +// Keccak256 calculates and returns the Keccak256 hash of the input data. +// (ref: https://github.com/ethereum/go-ethereum/blob/master/crypto/crypto.go) +func Keccak256(data ...[]byte) []byte { + b := make([]byte, 32) + d := NewKeccakState() + for _, b := range data { + d.Write(b) + } + d.Read(b) + return b +} + +// NewKeccakState creates a new KeccakState +// (ref: https://github.com/ethereum/go-ethereum/blob/master/crypto/crypto.go) +func NewKeccakState() KeccakState { + return sha3.NewLegacyKeccak256().(KeccakState) +} + +// mask excess bits +func MaskBits(mask, wordSize int, slice []byte) (ret []byte) { + excess := len(slice)*wordSize - mask + for _, by := range slice { + if excess > 0 { + if excess > wordSize { + excess = excess - wordSize + continue + } + by <<= excess + by >>= excess + excess = 0 + } + ret = append(ret, by) + } + return ret +} + +// compute the keccack fact given the program hash and outputs +func ComputeFact(programHash *big.Int, programOutputs []*big.Int) *big.Int { + var progOutBuf []byte + for _, programOutput := range programOutputs { + inBuf := FmtKecBytes(programOutput, 32) + progOutBuf = append(progOutBuf[:], inBuf...) + } + + kecBuf := FmtKecBytes(programHash, 32) + kecBuf = append(kecBuf[:], Keccak256(progOutBuf)...) + + return new(big.Int).SetBytes(Keccak256(kecBuf)) +} + +// split a fact into two felts +func SplitFactStr(fact string) (fact_low, fact_high string) { + factBN := HexToBN(fact) + factBytes := factBN.Bytes() + lpadfactBytes := bytes.Repeat([]byte{0x00}, 32-len(factBytes)) + factBytes = append(lpadfactBytes, factBytes...) + low := BytesToBig(factBytes[16:]) + high := BytesToBig(factBytes[:16]) + return BigToHex(low), BigToHex(high) +} + +// format the bytes in Keccak hash +func FmtKecBytes(in *big.Int, rolen int) (buf []byte) { + buf = append(buf, in.Bytes()...) + + // pad with zeros if too short + if len(buf) < rolen { + padded := make([]byte, rolen) + copy(padded[rolen-len(buf):], buf) + + return padded + } + + return buf +} + +// used in string conversions when interfacing with the APIs +func SNValToBN(str string) *big.Int { + if strings.Contains(str, "0x") { + return HexToBN(str) + } else { + return StrToBig(str) + } +}