From 526b17cdea98ca9330740c1bdfa7a7e5b87a4e07 Mon Sep 17 00:00:00 2001 From: Petar Ivanov <29689712+dartdart26@users.noreply.github.com> Date: Wed, 8 May 2024 16:49:27 +0300 Subject: [PATCH] feat: remove protected storage/memory This is the first phase of a process of using an ACL contract instead of protected storage and memory in the fhEVM. Instead of protected storage contracts, we now store all ciphertexts in a single contract at address 94. We no longer use protected memory for cross-contract calls. fhEVM is NOT secure after this commit. Adding ACL checks will make it secure again in a future commit. --- fhevm/ciphertext_storage.go | 155 +++++ fhevm/contracts_test.go | 922 +++++++++++++----------------- fhevm/evm.go | 33 +- fhevm/fhelib.go | 44 +- fhevm/instructions.go | 182 +----- fhevm/instructions_test.go | 529 ----------------- fhevm/interface.go | 7 +- fhevm/operators_arithmetic.go | 108 ++-- fhevm/operators_arithmetic_gas.go | 60 +- fhevm/operators_bit.go | 189 +++--- fhevm/operators_bit_gas.go | 42 +- fhevm/operators_comparison.go | 240 ++++---- fhevm/operators_comparison_gas.go | 67 +-- fhevm/operators_crypto.go | 42 +- fhevm/operators_crypto_gas.go | 13 +- fhevm/operators_rand.go | 4 +- fhevm/otel.go | 5 +- fhevm/params.go | 8 +- tfhe-rs | 2 +- 19 files changed, 976 insertions(+), 1676 deletions(-) create mode 100644 fhevm/ciphertext_storage.go delete mode 100644 fhevm/instructions_test.go diff --git a/fhevm/ciphertext_storage.go b/fhevm/ciphertext_storage.go new file mode 100644 index 0000000..d9d1f3d --- /dev/null +++ b/fhevm/ciphertext_storage.go @@ -0,0 +1,155 @@ +package fhevm + +import ( + "encoding/hex" + + "github.com/ethereum/go-ethereum/common" + "github.com/holiman/uint256" + "github.com/zama-ai/fhevm-go/fhevm/tfhe" +) + +var ciphertextStorage = common.BytesToAddress([]byte{94}) + +func newInt(buf []byte) *uint256.Int { + i := uint256.NewInt(0) + return i.SetBytes(buf) +} + +func minUint64(a, b uint64) uint64 { + if a < b { + return a + } + return b +} + +// Ciphertext metadata is stored in a single 32-byte slot. +// Currently, we only utilize 9 bytes from the slot. +type ciphertextMetadata struct { + length uint64 + fheUintType tfhe.FheUintType +} + +func (m ciphertextMetadata) serialize() [32]byte { + u := uint256.NewInt(0) + u[0] = m.length + u[1] = uint64(m.fheUintType) + return u.Bytes32() +} + +func (m *ciphertextMetadata) deserialize(buf [32]byte) *ciphertextMetadata { + u := uint256.NewInt(0) + u.SetBytes(buf[:]) + m.length = u[0] + m.fheUintType = tfhe.FheUintType(u[1]) + return m +} + +func newCiphertextMetadata(buf [32]byte) *ciphertextMetadata { + m := ciphertextMetadata{} + return m.deserialize(buf) +} + +func isCiphertextPersisted(env EVMEnvironment, handle common.Hash) bool { + metadataInt := newInt(env.GetState(ciphertextStorage, handle).Bytes()) + return !metadataInt.IsZero() +} + +// Returns the ciphertext metadata for the given handle or nil if it doesn't point to a ciphertext. +func loadCiphertextMetadata(env EVMEnvironment, handle common.Hash) *ciphertextMetadata { + metadataInt := newInt(env.GetState(ciphertextStorage, handle).Bytes()) + if metadataInt.IsZero() { + return nil + } + return newCiphertextMetadata(metadataInt.Bytes32()) +} + +// Returns the ciphertext for the given `handle“ and the gas needed to laod the ciphertext. +// Returned gas would be zero if already loaded to memory. +// If `handle` doesn't point to a ciphertext or an error occurs, (nil, 0) is returned. +func loadCiphertext(env EVMEnvironment, handle common.Hash) (ct *tfhe.TfheCiphertext, gas uint64) { + logger := env.GetLogger() + ct, loaded := env.FhevmData().loadedCiphertexts[handle] + if loaded { + return ct, 0 + } + + metadataInt := newInt(env.GetState(ciphertextStorage, handle).Bytes()) + if metadataInt.IsZero() { + return nil, 0 + } + metadata := newCiphertextMetadata(metadataInt.Bytes32()) + ctBytes := make([]byte, 0) + left := metadata.length + idx := newInt(handle.Bytes()) + idx.AddUint64(idx, 1) + for left > 0 { + bytes := env.GetState(ciphertextStorage, idx.Bytes32()) + toAppend := minUint64(uint64(len(bytes)), left) + left -= toAppend + ctBytes = append(ctBytes, bytes[0:toAppend]...) + idx.AddUint64(idx, 1) + } + ct = new(tfhe.TfheCiphertext) + err := ct.Deserialize(ctBytes, metadata.fheUintType) + if err != nil { + logger.Error("failed to deserialize ciphertext from storage", "err", err) + return nil, 0 + } + env.FhevmData().loadedCiphertexts[handle] = ct + return ct, env.FhevmParams().GasCosts.FheStorageSloadGas[ct.Type()] +} + +func insertCiphertextToMemory(env EVMEnvironment, ct *tfhe.TfheCiphertext) { + env.FhevmData().loadedCiphertexts[ct.GetHash()] = ct +} + +// Persist the given ciphertext. +func persistCiphertext(env EVMEnvironment, ct *tfhe.TfheCiphertext) { + logger := env.GetLogger() + if isCiphertextPersisted(env, ct.GetHash()) { + // Assuming a handle is a hash of the ciphertext, if metadata is already existing in storage it means the ciphertext is too. + logger.Info("ciphertext already persisted to storage", "handle", ct.GetHash().Hex()) + return + } + + metadata := ciphertextMetadata{} + metadata.length = uint64(tfhe.ExpandedFheCiphertextSize[ct.FheUintType]) + metadata.fheUintType = ct.FheUintType + + // Persist the metadata in storage. + env.SetState(ciphertextStorage, ct.GetHash(), metadata.serialize()) + + ciphertextSlot := newInt(ct.GetHash().Bytes()) + ciphertextSlot.AddUint64(ciphertextSlot, 1) + if env.IsCommitting() { + logger.Info("persisting new ciphertext", + "handle", hex.EncodeToString(ct.GetHash().Bytes()), + "type", metadata.fheUintType, + "len", metadata.length, + "ciphertextSlot", hex.EncodeToString(ciphertextSlot.Bytes())) + } + ctPart32 := make([]byte, 32) + partIdx := 0 + ctBytes := ct.Serialize() + for i, b := range ctBytes { + if i%32 == 0 && i != 0 { + env.SetState(ciphertextStorage, ciphertextSlot.Bytes32(), common.BytesToHash(ctPart32)) + ciphertextSlot.AddUint64(ciphertextSlot, 1) + ctPart32 = make([]byte, 32) + partIdx = 0 + } + ctPart32[partIdx] = b + partIdx++ + } + if len(ctPart32) != 0 { + env.SetState(ciphertextStorage, ciphertextSlot.Bytes32(), common.BytesToHash(ctPart32)) + } +} + +func GetCiphertextFromMemory(env EVMEnvironment, handle common.Hash) *tfhe.TfheCiphertext { + ct, found := env.FhevmData().loadedCiphertexts[handle] + if found { + return ct + } + return nil +} diff --git a/fhevm/contracts_test.go b/fhevm/contracts_test.go index 60f5f39..2118ec2 100644 --- a/fhevm/contracts_test.go +++ b/fhevm/contracts_test.go @@ -2,6 +2,7 @@ package fhevm import ( "bytes" + "context" "encoding/binary" "encoding/hex" "errors" @@ -12,12 +13,100 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/holiman/uint256" "github.com/zama-ai/fhevm-go/fhevm/tfhe" ) +type MockEVMEnvironment struct { + fhevmData *FhevmData + depth int + stateDb *state.StateDB + commit bool + ethCall bool + readOnly bool + fhevmParams FhevmParams +} + +func (*MockEVMEnvironment) OtelContext() context.Context { + // can also return nil and disable Otel + return context.TODO() +} + +func (environment *MockEVMEnvironment) GetState(addr common.Address, hash common.Hash) common.Hash { + return environment.stateDb.GetState(addr, hash) +} + +func (environment *MockEVMEnvironment) SetState(addr common.Address, key common.Hash, value common.Hash) { + environment.stateDb.SetState(addr, key, value) +} + +func (environment *MockEVMEnvironment) GetNonce(common.Address) uint64 { + return 0 +} + +func (environment *MockEVMEnvironment) AddBalance(addr common.Address, amount *big.Int) { + environment.stateDb.AddBalance(addr, amount) +} + +func (environment *MockEVMEnvironment) GetBalance(addr common.Address) *big.Int { + return environment.stateDb.GetBalance(addr) +} + +func (environment *MockEVMEnvironment) Suicide(addr common.Address) bool { + return environment.stateDb.Suicide(addr) +} + +func (environment *MockEVMEnvironment) GetDepth() int { + return environment.depth +} + +func (environment *MockEVMEnvironment) GetLogger() Logger { + return NewDefaultLogger() +} + +func (environment *MockEVMEnvironment) IsCommitting() bool { + return environment.commit +} + +func (environment *MockEVMEnvironment) IsEthCall() bool { + return environment.ethCall +} + +func (environment *MockEVMEnvironment) IsReadOnly() bool { + return environment.readOnly +} + +func (environment *MockEVMEnvironment) CreateContract(caller common.Address, code []byte, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) { + return make([]byte, 0), common.Address{}, 0, nil +} + +func (environment *MockEVMEnvironment) CreateContract2(caller common.Address, code []byte, codeHash common.Hash, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) { + return make([]byte, 0), common.Address{}, 0, nil +} + +func (environment *MockEVMEnvironment) FhevmData() *FhevmData { + return environment.fhevmData +} + +func (environment *MockEVMEnvironment) FhevmParams() *FhevmParams { + return &environment.fhevmParams +} + +func (environment *MockEVMEnvironment) EVMEnvironment() EVMEnvironment { + return environment +} + +func newTestEVMEnvironment() *MockEVMEnvironment { + fhevmData := NewFhevmData() + db := rawdb.NewMemoryDatabase() + state, _ := state.New(common.Hash{}, state.NewDatabase(db), nil) + return &MockEVMEnvironment{fhevmData: &fhevmData, stateDb: state, commit: true, fhevmParams: DefaultFhevmParams()} +} + // generate keys if not present func setup() { if !tfhe.AllGlobalKeysPresent() { @@ -90,7 +179,7 @@ func decryptRunWithoutKms(environment EVMEnvironment, caller common.Address, add logger.Error(msg, "input", hex.EncodeToString(input), "len", len(input)) return nil, errors.New(msg) } - ct := getVerifiedCiphertext(environment, common.BytesToHash(input)) + ct, _ := loadCiphertext(environment, common.BytesToHash(input)) if ct == nil { msg := "decrypt unverified handle" logger.Error(msg, "input", hex.EncodeToString(input)) @@ -103,7 +192,7 @@ func decryptRunWithoutKms(environment EVMEnvironment, caller common.Address, add return bytes.Repeat([]byte{0xFF}, 32), nil } - plaintext, err := ct.ciphertext.Decrypt() + plaintext, err := ct.Decrypt() if err != nil { logger.Error("decrypt failed", "err", err) return nil, err @@ -157,6 +246,18 @@ func prepareInputForVerifyCiphertext(input []byte) []byte { return append(append(padding, size...), input...) } +func loadCiphertextInTestMemory(environment EVMEnvironment, value uint64, depth int, t tfhe.FheUintType) *tfhe.TfheCiphertext { + // Simulate as if the ciphertext is compact and comes externally. + ser := tfhe.EncryptAndSerializeCompact(uint64(value), t) + ct := new(tfhe.TfheCiphertext) + err := ct.DeserializeCompact(ser, t) + if err != nil { + panic(err) + } + insertCiphertextToMemory(environment, ct) + return ct +} + func VerifyCiphertext(t *testing.T, fheUintType tfhe.FheUintType) { var value uint64 switch fheUintType { @@ -191,7 +292,7 @@ func VerifyCiphertext(t *testing.T, fheUintType tfhe.FheUintType) { if common.BytesToHash(out) != ct.GetHash() { t.Fatalf("output hash in verifyCipertext is incorrect") } - res := getVerifiedCiphertextFromEVM(environment, ct.GetHash()) + res, _ := loadCiphertext(environment, ct.GetHash()) if res == nil { t.Fatalf("verifyCiphertext must have verified given ciphertext") } @@ -222,7 +323,7 @@ func VerifyCiphertextBadType(t *testing.T, actualType tfhe.FheUintType, metadata if err == nil { t.Fatalf("verifyCiphertext must have failed on type mismatch") } - if len(environment.FhevmData().verifiedCiphertexts) != 0 { + if len(environment.FhevmData().loadedCiphertexts) != 0 { t.Fatalf("verifyCiphertext mustn't have verified given ciphertext") } } @@ -258,7 +359,7 @@ func TrivialEncrypt(t *testing.T, fheUintType tfhe.FheUintType) { if common.BytesToHash(out) != ct.GetHash() { t.Fatalf("output hash in verifyCipertext is incorrect") } - res := getVerifiedCiphertextFromEVM(environment, ct.GetHash()) + res, _ := loadCiphertext(environment, ct.GetHash()) if res == nil { t.Fatalf("verifyCiphertext must have verified given ciphertext") } @@ -291,23 +392,23 @@ func FheLibAdd(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) out, err := FheLibRun(environment, addr, addr, input, readOnly) if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -339,23 +440,23 @@ func FheLibSub(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) out, err := FheLibRun(environment, addr, addr, input, readOnly) if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -387,23 +488,23 @@ func FheLibMul(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) out, err := FheLibRun(environment, addr, addr, input, readOnly) if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -434,12 +535,12 @@ func FheLibLe(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } // lhs <= rhs @@ -448,11 +549,11 @@ func FheLibLe(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != 0 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), err) } @@ -466,11 +567,11 @@ func FheLibLe(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ = loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err = res.ciphertext.Decrypt() + decrypted, err = res.Decrypt() if err != nil || decrypted.Uint64() != 1 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1) } @@ -503,12 +604,12 @@ func FheLibLt(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } // lhs < rhs @@ -517,11 +618,11 @@ func FheLibLt(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != 0 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0) } @@ -535,11 +636,11 @@ func FheLibLt(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ = loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err = res.ciphertext.Decrypt() + decrypted, err = res.Decrypt() if err != nil || decrypted.Uint64() != 1 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1) } @@ -571,12 +672,12 @@ func FheLibEq(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } // lhs == rhs input1 := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) @@ -584,11 +685,11 @@ func FheLibEq(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != 0 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0) } @@ -619,12 +720,12 @@ func FheLibGe(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } // lhs >= rhs input1 := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) @@ -632,11 +733,11 @@ func FheLibGe(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != 1 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1) } @@ -649,11 +750,11 @@ func FheLibGe(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ = loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err = res.ciphertext.Decrypt() + decrypted, err = res.Decrypt() if err != nil || decrypted.Uint64() != 0 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0) } @@ -686,12 +787,12 @@ func FheLibGt(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } // lhs > rhs input1 := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) @@ -699,11 +800,11 @@ func FheLibGt(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != 1 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1) } @@ -717,11 +818,11 @@ func FheLibGt(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ = loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err = res.ciphertext.Decrypt() + decrypted, err = res.Decrypt() if err != nil || decrypted.Uint64() != 0 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0) } @@ -754,23 +855,23 @@ func FheLibShl(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) out, err := FheLibRun(environment, addr, addr, input, readOnly) if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -802,23 +903,23 @@ func FheLibShr(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) out, err := FheLibRun(environment, addr, addr, input, readOnly) if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -850,23 +951,23 @@ func FheLibRotl(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) out, err := FheLibRun(environment, addr, addr, input, readOnly) if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -898,23 +999,23 @@ func FheLibRotr(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) out, err := FheLibRun(environment, addr, addr, input, readOnly) if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -945,12 +1046,12 @@ func FheLibNe(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } // lhs == rhs input1 := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) @@ -958,11 +1059,11 @@ func FheLibNe(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != 1 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1) } @@ -994,12 +1095,12 @@ func FheLibMin(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) @@ -1007,11 +1108,11 @@ func FheLibMin(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != rhs { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), rhs) } @@ -1024,11 +1125,11 @@ func FheLibMin(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ = loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err = res.ciphertext.Decrypt() + decrypted, err = res.Decrypt() if err != nil || decrypted.Uint64() != rhs { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), rhs) } @@ -1061,12 +1162,12 @@ func FheLibMax(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) @@ -1074,11 +1175,11 @@ func FheLibMax(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != lhs { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), lhs) } @@ -1091,11 +1192,11 @@ func FheLibMax(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ = loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err = res.ciphertext.Decrypt() + decrypted, err = res.Decrypt() if err != nil || decrypted.Uint64() != lhs { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), lhs) } @@ -1128,18 +1229,18 @@ func FheLibNeg(t *testing.T, fheUintType tfhe.FheUintType) { environment.depth = depth addr := common.Address{} readOnly := false - ptHash := verifyCiphertextInTestMemory(environment, pt, depth, fheUintType).GetHash() + ptHash := loadCiphertextInTestMemory(environment, pt, depth, fheUintType).GetHash() input := toLibPrecompileInputNoScalar(signature, ptHash) out, err := FheLibRun(environment, addr, addr, input, readOnly) if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -1174,18 +1275,18 @@ func FheLibNot(t *testing.T, fheUintType tfhe.FheUintType) { environment.depth = depth addr := common.Address{} readOnly := false - ptHash := verifyCiphertextInTestMemory(environment, pt, depth, fheUintType).GetHash() + ptHash := loadCiphertextInTestMemory(environment, pt, depth, fheUintType).GetHash() input := toLibPrecompileInputNoScalar(signature, ptHash) out, err := FheLibRun(environment, addr, addr, input, readOnly) if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -1218,12 +1319,12 @@ func FheLibDiv(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) out, err := FheLibRun(environment, addr, addr, input, readOnly) @@ -1231,11 +1332,11 @@ func FheLibDiv(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -1272,12 +1373,12 @@ func FheLibRem(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) out, err := FheLibRun(environment, addr, addr, input, readOnly) @@ -1285,11 +1386,11 @@ func FheLibRem(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -1329,12 +1430,12 @@ func FheLibBitAnd(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) out, err := FheLibRun(environment, addr, addr, input, readOnly) @@ -1346,11 +1447,11 @@ func FheLibBitAnd(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -1386,12 +1487,12 @@ func FheLibBitOr(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) out, err := FheLibRun(environment, addr, addr, input, readOnly) @@ -1403,11 +1504,11 @@ func FheLibBitOr(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -1443,12 +1544,12 @@ func FheLibBitXor(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toLibPrecompileInput(signature, scalar, lhsHash, rhsHash) out, err := FheLibRun(environment, addr, addr, input, readOnly) @@ -1460,11 +1561,11 @@ func FheLibBitXor(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -1489,12 +1590,12 @@ func FheLibRand(t *testing.T, fheUintType tfhe.FheUintType) { } else if len(out) != 32 { t.Fatalf("fheRand expected output len of 32, got %v", len(out)) } - if len(environment.FhevmData().verifiedCiphertexts) != 1 { + if len(environment.FhevmData().loadedCiphertexts) != 1 { t.Fatalf("fheRand expected 1 verified ciphertext") } hash := common.BytesToHash(out) - decrypted, err := environment.FhevmData().verifiedCiphertexts[hash].ciphertext.Decrypt() + decrypted, err := environment.FhevmData().loadedCiphertexts[hash].Decrypt() if err != nil { t.Fatalf(err.Error()) } @@ -1545,12 +1646,12 @@ func FheLibRandBounded(t *testing.T, fheUintType tfhe.FheUintType, upperBound64 } else if len(out) != 32 { t.Fatalf("fheRandBounded expected output len of 32, got %v", len(out)) } - if len(environment.FhevmData().verifiedCiphertexts) != 1 { + if len(environment.FhevmData().loadedCiphertexts) != 1 { t.Fatalf("fheRand expected 1 verified ciphertext") } hash := common.BytesToHash(out) - decrypted, err := environment.FhevmData().verifiedCiphertexts[hash].ciphertext.Decrypt() + decrypted, err := environment.FhevmData().loadedCiphertexts[hash].Decrypt() if err != nil { t.Fatalf(err.Error()) } @@ -1587,20 +1688,20 @@ func FheLibIfThenElse(t *testing.T, fheUintType tfhe.FheUintType, condition uint environment.depth = depth addr := common.Address{} readOnly := false - firstHash := verifyCiphertextInTestMemory(environment, condition, depth, tfhe.FheBool).GetHash() - secondHash := verifyCiphertextInTestMemory(environment, second, depth, fheUintType).GetHash() - thirdHash := verifyCiphertextInTestMemory(environment, third, depth, fheUintType).GetHash() + firstHash := loadCiphertextInTestMemory(environment, condition, depth, tfhe.FheBool).GetHash() + secondHash := loadCiphertextInTestMemory(environment, second, depth, fheUintType).GetHash() + thirdHash := loadCiphertextInTestMemory(environment, third, depth, fheUintType).GetHash() input := toLibPrecompileInputNoScalar(signature, firstHash, secondHash, thirdHash) out, err := FheLibRun(environment, addr, addr, input, readOnly) if err != nil { t.Fatalf("VALUE %v", len(input)) // t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || condition == 1 && decrypted.Uint64() != second || condition == 0 && decrypted.Uint64() != third { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1) } @@ -1641,7 +1742,7 @@ func LibTrivialEncrypt(t *testing.T, fheUintType tfhe.FheUintType) { if common.BytesToHash(out) != ct.GetHash() { t.Fatalf("output hash in verifyCipertext is incorrect") } - res := getVerifiedCiphertextFromEVM(environment, ct.GetHash()) + res, _ := loadCiphertext(environment, ct.GetHash()) if res == nil { t.Fatalf("verifyCiphertext must have verified given ciphertext") } @@ -1670,7 +1771,7 @@ func LibDecrypt(t *testing.T, fheUintType tfhe.FheUintType) { addr := common.Address{} readOnly := false input := make([]byte, 0) - hash := verifyCiphertextInTestMemory(environment, value, depth, fheUintType).GetHash() + hash := loadCiphertextInTestMemory(environment, value, depth, fheUintType).GetHash() input = append(input, signatureBytes...) input = append(input, hash.Bytes()...) out, err := FheLibRun(environment, addr, addr, input, readOnly) @@ -1722,7 +1823,7 @@ func TestLibVerifyCiphertextInvalidType(t *testing.T) { // environment.ethCall = true // toEncrypt := 7 // fheUintType := tfhe.FheUint8 -// encCiphertext := verifyCiphertextInTestMemory(environment, uint64(toEncrypt), depth, fheUintType).getHash() +// encCiphertext := loadCiphertextInTestMemory(environment, uint64(toEncrypt), depth, fheUintType).getHash() // addr := common.Address{} // readOnly := false // input := make([]byte, 0) @@ -1746,7 +1847,7 @@ func TestLibCast(t *testing.T) { environment.ethCall = true toEncrypt := 7 fheUintType := tfhe.FheUint8 - encCiphertext := verifyCiphertextInTestMemory(environment, uint64(toEncrypt), depth, fheUintType).GetHash() + encCiphertext := loadCiphertextInTestMemory(environment, uint64(toEncrypt), depth, fheUintType).GetHash() addr := common.Address{} readOnly := false input := make([]byte, 0) @@ -1784,23 +1885,23 @@ func FheAdd(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toPrecompileInput(scalar, lhsHash, rhsHash) out, err := fheAddRun(environment, addr, addr, input, readOnly, nil) if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -1831,23 +1932,23 @@ func FheSub(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toPrecompileInput(scalar, lhsHash, rhsHash) out, err := fheSubRun(environment, addr, addr, input, readOnly, nil) if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -1878,23 +1979,23 @@ func FheMul(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toPrecompileInput(scalar, lhsHash, rhsHash) out, err := fheMulRun(environment, addr, addr, input, readOnly, nil) if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -1925,12 +2026,12 @@ func FheDiv(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toPrecompileInput(scalar, lhsHash, rhsHash) out, err := fheDivRun(environment, addr, addr, input, readOnly, nil) @@ -1938,11 +2039,11 @@ func FheDiv(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -1978,12 +2079,12 @@ func FheRem(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toPrecompileInput(scalar, lhsHash, rhsHash) out, err := fheRemRun(environment, addr, addr, input, readOnly, nil) @@ -1991,11 +2092,11 @@ func FheRem(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -2034,12 +2135,12 @@ func FheBitAnd(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toPrecompileInput(scalar, lhsHash, rhsHash) out, err := fheBitAndRun(environment, addr, addr, input, readOnly, nil) @@ -2051,11 +2152,11 @@ func FheBitAnd(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -2087,12 +2188,12 @@ func FheBitOr(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toPrecompileInput(scalar, lhsHash, rhsHash) out, err := fheBitOrRun(environment, addr, addr, input, readOnly, nil) @@ -2104,11 +2205,11 @@ func FheBitOr(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -2140,12 +2241,12 @@ func FheBitXor(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toPrecompileInput(scalar, lhsHash, rhsHash) out, err := fheBitXorRun(environment, addr, addr, input, readOnly, nil) @@ -2157,11 +2258,11 @@ func FheBitXor(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -2193,23 +2294,23 @@ func FheShl(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toPrecompileInput(scalar, lhsHash, rhsHash) out, err := fheShlRun(environment, addr, addr, input, readOnly, nil) if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -2240,23 +2341,23 @@ func FheShr(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toPrecompileInput(scalar, lhsHash, rhsHash) out, err := fheShrRun(environment, addr, addr, input, readOnly, nil) if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -2286,12 +2387,12 @@ func FheEq(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } // lhs == rhs input1 := toPrecompileInput(scalar, lhsHash, rhsHash) @@ -2299,11 +2400,11 @@ func FheEq(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != 0 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0) } @@ -2333,12 +2434,12 @@ func FheNe(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } // lhs == rhs input1 := toPrecompileInput(scalar, lhsHash, rhsHash) @@ -2346,11 +2447,11 @@ func FheNe(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != 1 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1) } @@ -2380,12 +2481,12 @@ func FheGe(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } // lhs >= rhs input1 := toPrecompileInput(scalar, lhsHash, rhsHash) @@ -2393,11 +2494,11 @@ func FheGe(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != 1 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1) } @@ -2410,11 +2511,11 @@ func FheGe(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ = loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err = res.ciphertext.Decrypt() + decrypted, err = res.Decrypt() if err != nil || decrypted.Uint64() != 0 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0) } @@ -2446,12 +2547,12 @@ func FheGt(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } // lhs > rhs input1 := toPrecompileInput(scalar, lhsHash, rhsHash) @@ -2459,11 +2560,11 @@ func FheGt(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != 1 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1) } @@ -2477,11 +2578,11 @@ func FheGt(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ = loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err = res.ciphertext.Decrypt() + decrypted, err = res.Decrypt() if err != nil || decrypted.Uint64() != 0 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0) } @@ -2512,12 +2613,12 @@ func FheLe(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } // lhs <= rhs @@ -2526,11 +2627,11 @@ func FheLe(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != 0 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), err) } @@ -2544,11 +2645,11 @@ func FheLe(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ = loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err = res.ciphertext.Decrypt() + decrypted, err = res.Decrypt() if err != nil || decrypted.Uint64() != 1 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1) } @@ -2580,12 +2681,12 @@ func FheLt(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } // lhs < rhs @@ -2594,11 +2695,11 @@ func FheLt(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != 0 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0) } @@ -2612,11 +2713,11 @@ func FheLt(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ = loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err = res.ciphertext.Decrypt() + decrypted, err = res.Decrypt() if err != nil || decrypted.Uint64() != 1 { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 1) } @@ -2648,12 +2749,12 @@ func FheMin(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toPrecompileInput(scalar, lhsHash, rhsHash) @@ -2661,11 +2762,11 @@ func FheMin(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != rhs { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), rhs) } @@ -2678,11 +2779,11 @@ func FheMin(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ = loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err = res.ciphertext.Decrypt() + decrypted, err = res.Decrypt() if err != nil || decrypted.Uint64() != rhs { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), rhs) } @@ -2714,12 +2815,12 @@ func FheMax(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() var rhsHash common.Hash if scalar { rhsHash = common.BytesToHash(big.NewInt(int64(rhs)).Bytes()) } else { - rhsHash = verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + rhsHash = loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() } input := toPrecompileInput(scalar, lhsHash, rhsHash) @@ -2727,11 +2828,11 @@ func FheMax(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != lhs { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), lhs) } @@ -2744,11 +2845,11 @@ func FheMax(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res = getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ = loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err = res.ciphertext.Decrypt() + decrypted, err = res.Decrypt() if err != nil || decrypted.Uint64() != lhs { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), lhs) } @@ -2780,7 +2881,7 @@ func FheNeg(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - ptHash := verifyCiphertextInTestMemory(environment, pt, depth, fheUintType).GetHash() + ptHash := loadCiphertextInTestMemory(environment, pt, depth, fheUintType).GetHash() input := make([]byte, 0) input = append(input, ptHash.Bytes()...) @@ -2788,11 +2889,11 @@ func FheNeg(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -2823,7 +2924,7 @@ func FheNot(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { environment.depth = depth addr := common.Address{} readOnly := false - ptHash := verifyCiphertextInTestMemory(environment, pt, depth, fheUintType).GetHash() + ptHash := loadCiphertextInTestMemory(environment, pt, depth, fheUintType).GetHash() input := make([]byte, 0) input = append(input, ptHash.Bytes()...) @@ -2831,11 +2932,11 @@ func FheNot(t *testing.T, fheUintType tfhe.FheUintType, scalar bool) { if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || decrypted.Uint64() != expected { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), expected) } @@ -2865,20 +2966,20 @@ func FheIfThenElse(t *testing.T, fheUintType tfhe.FheUintType, condition uint64) environment.depth = depth addr := common.Address{} readOnly := false - conditionHash := verifyCiphertextInTestMemory(environment, condition, depth, tfhe.FheBool).GetHash() - lhsHash := verifyCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() - rhsHash := verifyCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() + conditionHash := loadCiphertextInTestMemory(environment, condition, depth, tfhe.FheBool).GetHash() + lhsHash := loadCiphertextInTestMemory(environment, lhs, depth, fheUintType).GetHash() + rhsHash := loadCiphertextInTestMemory(environment, rhs, depth, fheUintType).GetHash() input1 := toPrecompileInputNoScalar(false, conditionHash, lhsHash, rhsHash) out, err := fheIfThenElseRun(environment, addr, addr, input1, readOnly, nil) if err != nil { t.Fatalf(err.Error()) } - res := getVerifiedCiphertextFromEVM(environment, common.BytesToHash(out)) + res, _ := loadCiphertext(environment, common.BytesToHash(out)) if res == nil { - t.Fatalf("output ciphertext is not found in verifiedCiphertexts") + t.Fatalf("output ciphertext is not found in loadedCiphertexts") } - decrypted, err := res.ciphertext.Decrypt() + decrypted, err := res.Decrypt() if err != nil || condition == 1 && decrypted.Uint64() != lhs || condition == 0 && decrypted.Uint64() != rhs { t.Fatalf("invalid decrypted result, decrypted %v != expected %v", decrypted.Uint64(), 0) } @@ -2905,7 +3006,7 @@ func Decrypt(t *testing.T, fheUintType tfhe.FheUintType) { environment.depth = depth addr := common.Address{} readOnly := false - hash := verifyCiphertextInTestMemory(environment, value, depth, fheUintType).GetHash() + hash := loadCiphertextInTestMemory(environment, value, depth, fheUintType).GetHash() out, err := decryptRunWithoutKms(environment, addr, addr, hash.Bytes(), readOnly) if err != nil { t.Fatalf(err.Error()) @@ -2931,12 +3032,12 @@ func FheRand(t *testing.T, fheUintType tfhe.FheUintType) { } else if len(out) != 32 { t.Fatalf("fheRand expected output len of 32, got %v", len(out)) } - if len(environment.FhevmData().verifiedCiphertexts) != 1 { + if len(environment.FhevmData().loadedCiphertexts) != 1 { t.Fatalf("fheRand expected 1 verified ciphertext") } hash := common.BytesToHash(out) - _, err = environment.FhevmData().verifiedCiphertexts[hash].ciphertext.Decrypt() + _, err = environment.FhevmData().loadedCiphertexts[hash].Decrypt() if err != nil { t.Fatalf(err.Error()) } @@ -3531,7 +3632,7 @@ func TestCastInvalidType(t *testing.T) { addr := common.Address{} readOnly := false invalidType := tfhe.FheUintType(255) - hash := verifyCiphertextInTestMemory(environment, 1, depth, tfhe.FheUint8).GetHash() + hash := loadCiphertextInTestMemory(environment, 1, depth, tfhe.FheUint8).GetHash() input := make([]byte, 0) input = append(input, hash.Bytes()...) input = append(input, byte(invalidType)) @@ -3642,7 +3743,7 @@ func TestVerifyCiphertextBadCiphertext(t *testing.T) { if err == nil { t.Fatalf("verifyCiphertext must fail on bad ciphertext input") } - if len(environment.FhevmData().verifiedCiphertexts) != 0 { + if len(environment.FhevmData().loadedCiphertexts) != 0 { t.Fatalf("verifyCiphertext mustn't have verified given ciphertext") } } @@ -4581,66 +4682,18 @@ func TestUnknownCiphertextHandle(t *testing.T) { depth := 1 environment := newTestEVMEnvironment() environment.depth = depth - hash := verifyCiphertextInTestMemory(environment, 2, depth, tfhe.FheUint8).GetHash() + hash := loadCiphertextInTestMemory(environment, 2, depth, tfhe.FheUint8).GetHash() - ct := getVerifiedCiphertext(environment, hash) + ct, _ := loadCiphertext(environment, hash) if ct == nil { - t.Fatalf("expected that ciphertext is verified") + t.Fatalf("expected that ciphertext is loaded") } // change the hash hash[0]++ - ct = getVerifiedCiphertext(environment, hash) - if ct != nil { - t.Fatalf("expected that ciphertext is not verified") - } -} - -func TestCiphertextNotVerifiedWithoutReturn(t *testing.T) { - environment := newTestEVMEnvironment() - environment.depth = 1 - verifiedDepth := 2 - hash := verifyCiphertextInTestMemory(environment, 1, verifiedDepth, tfhe.FheUint8).GetHash() - - ct := getVerifiedCiphertext(environment, hash) - if ct != nil { - t.Fatalf("expected that ciphertext is not verified") - } -} - -func TestCiphertextNotAutomaticallyDelegated(t *testing.T) { - environment := newTestEVMEnvironment() - environment.depth = 3 - verifiedDepth := 2 - hash := verifyCiphertextInTestMemory(environment, 1, verifiedDepth, tfhe.FheUint8).GetHash() - - ct := getVerifiedCiphertext(environment, hash) - if ct != nil { - t.Fatalf("expected that ciphertext is not verified at depth (%d)", environment.depth) - } -} - -func TestCiphertextVerificationConditions(t *testing.T) { - environment := newTestEVMEnvironment() - verifiedDepth := 2 - hash := verifyCiphertextInTestMemory(environment, 1, verifiedDepth, tfhe.FheUint8).GetHash() - - environment.depth = verifiedDepth - ctPtr := getVerifiedCiphertext(environment, hash) - if ctPtr == nil { - t.Fatalf("expected that ciphertext is verified at verifiedDepth (%d)", verifiedDepth) - } - - environment.depth = verifiedDepth + 1 - ct := getVerifiedCiphertext(environment, hash) - if ct != nil { - t.Fatalf("expected that ciphertext is not verified at verifiedDepth + 1 (%d)", verifiedDepth+1) - } - - environment.depth = verifiedDepth - 1 - ct = getVerifiedCiphertext(environment, hash) + ct, _ = loadCiphertext(environment, hash) if ct != nil { - t.Fatalf("expected that ciphertext is not verified at verifiedDepth - 1 (%d)", verifiedDepth-1) + t.Fatalf("expected that ciphertext is not loaded") } } @@ -4654,7 +4707,7 @@ func TestFheRandInvalidInput(t *testing.T) { if err == nil { t.Fatalf("fheRand expected failure on invalid type") } - if len(environment.FhevmData().verifiedCiphertexts) != 0 { + if len(environment.FhevmData().loadedCiphertexts) != 0 { t.Fatalf("fheRand expected 0 verified ciphertexts on invalid input") } } @@ -4669,7 +4722,7 @@ func TestFheRandInvalidType(t *testing.T) { if err == nil { t.Fatalf("fheRand expected failure on invalid type") } - if len(environment.FhevmData().verifiedCiphertexts) != 0 { + if len(environment.FhevmData().loadedCiphertexts) != 0 { t.Fatalf("fheRand expected 0 verified ciphertexts on invalid type") } } @@ -4688,7 +4741,7 @@ func TestFheRandBoundedInvalidType(t *testing.T) { if err == nil { t.Fatalf("fheRandBounded expected failure on invalid type") } - if len(environment.FhevmData().verifiedCiphertexts) != 0 { + if len(environment.FhevmData().loadedCiphertexts) != 0 { t.Fatalf("fheRandBounded expected 0 verified ciphertexts on invalid type") } } @@ -4707,7 +4760,7 @@ func FheRandBoundedInvalidBound(t *testing.T, fheUintType tfhe.FheUintType, boun if err == nil { t.Fatalf("fheRandBounded expected failure on invalid bound") } - if len(environment.FhevmData().verifiedCiphertexts) != 0 { + if len(environment.FhevmData().loadedCiphertexts) != 0 { t.Fatalf("fheRandBounded expected 0 verified ciphertexts on invalid bound") } } @@ -4763,7 +4816,7 @@ func TestFheRandEthCall(t *testing.T) { if err == nil { t.Fatalf("fheRand expected failure on EthCall") } - if len(environment.FhevmData().verifiedCiphertexts) != 0 { + if len(environment.FhevmData().loadedCiphertexts) != 0 { t.Fatalf("fheRand expected 0 verified ciphertexts on EthCall") } } @@ -4783,20 +4836,11 @@ func TestFheRandBoundedEthCall(t *testing.T) { if err == nil { t.Fatalf("fheRandBounded expected failure on EthCall") } - if len(environment.FhevmData().verifiedCiphertexts) != 0 { + if len(environment.FhevmData().loadedCiphertexts) != 0 { t.Fatalf("fheRandBounded expected 0 verified ciphertexts on EthCall") } } -func interpreterRunWithStopContract(environment *MockEVMEnvironment, interpreter *vm.EVMInterpreter, contract *vm.Contract, input []byte, readOnly bool) (ret []byte, err error) { - ret, _ = interpreter.Run(contract, input, readOnly) - // the following functions are meant to be ran from within interpreter.run so we increment depth to emulate that - environment.depth++ - RemoveVerifiedCipherextsAtCurrentDepth(environment) - environment.depth-- - return ret, err -} - func newInterpreterFromEnvironment(environment *MockEVMEnvironment) *vm.EVMInterpreter { cfg := vm.Config{} evm := &vm.EVM{Config: cfg} @@ -4806,7 +4850,6 @@ func newInterpreterFromEnvironment(environment *MockEVMEnvironment) *vm.EVMInter evm.StateDB = environment.stateDb interpreter := vm.NewEVMInterpreter(evm) return interpreter - } func newStopOpcodeContract() *vm.Contract { @@ -4826,7 +4869,7 @@ func TestDecryptInTransactionDisabled(t *testing.T) { environment.fhevmParams.DisableDecryptionsInTransaction = true addr := common.Address{} readOnly := false - hash := verifyCiphertextInTestMemory(environment, 1, depth, tfhe.FheUint8).GetHash() + hash := loadCiphertextInTestMemory(environment, 1, depth, tfhe.FheUint8).GetHash() // Call decrypt and expect it to fail due to disabling of decryptions during commit _, err := decryptRunWithoutKms(environment, addr, addr, hash.Bytes(), readOnly) if err == nil { @@ -4853,198 +4896,7 @@ func TestFheLibGetCiphertextInvalidInputSize(t *testing.T) { } } -func TestFheLibGetCiphertextNonEthCall(t *testing.T) { - environment := newTestEVMEnvironment() - pc := uint64(0) - depth := 1 - environment.depth = depth - plaintext := uint64(2) - ct := verifyCiphertextInTestMemory(environment, plaintext, depth, tfhe.FheUint32) - ctHash := ct.GetHash() - scope := newTestScopeConext() - loc := uint256.NewInt(10) - value := uint256FromBig(ctHash.Big()) - - // Setup and call SSTORE - it requires a location and a value to set there. - scope.pushToStack(value) - scope.pushToStack(loc) - _, err := OpSstore(&pc, environment, scope) - if err != nil { - t.Fatalf(err.Error()) - } - - // Call getCiphertext. - addr := common.Address{} - environment.ethCall = false - readOnly := true - input := make([]byte, 0) - zeroPadding := make([]byte, 12) - signature := crypto.Keccak256([]byte("getCiphertext(address,uint256)"))[0:4] - input = append(input, signature...) - input = append(input, zeroPadding...) - input = append(input, testContractAddress{}.Address().Bytes()...) - input = append(input, ctHash.Bytes()...) - _, err = FheLibRun(environment, addr, addr, input, readOnly) - if err == nil { - t.Fatalf("getCiphertext expected failure non-EthCall") - } -} - -func TestFheLibGetCiphertextNonExistentHandle(t *testing.T) { - environment := newTestEVMEnvironment() - pc := uint64(0) - depth := 1 - environment.depth = depth - plaintext := uint64(2) - ct := verifyCiphertextInTestMemory(environment, plaintext, depth, tfhe.FheUint32) - ctHash := ct.GetHash() - scope := newTestScopeConext() - loc := uint256.NewInt(10) - value := uint256FromBig(ctHash.Big()) - - // Setup and call SSTORE - it requires a location and a value to set there. - scope.pushToStack(value) - scope.pushToStack(loc) - _, err := OpSstore(&pc, environment, scope) - if err != nil { - t.Fatalf(err.Error()) - } - - // Change ctHash to something that doesn't exist - ctHash[0]++ - - // Call getCiphertext. - addr := common.Address{} - environment.ethCall = true - readOnly := true - input := make([]byte, 0) - zeroPadding := make([]byte, 12) - signature := crypto.Keccak256([]byte("getCiphertext(address,uint256)"))[0:4] - input = append(input, signature...) - input = append(input, zeroPadding...) - input = append(input, testContractAddress{}.Address().Bytes()...) - input = append(input, ctHash.Bytes()...) - out, err := FheLibRun(environment, addr, addr, input, readOnly) - if err != nil { - t.Fatalf(err.Error()) - } - if len(out) != 0 { - t.Fatalf("getCiphertext expected empty output on non-existent handle") - } -} - -func TestFheLibGetCiphertextWrongContractAddress(t *testing.T) { - environment := newTestEVMEnvironment() - pc := uint64(0) - depth := 1 - environment.depth = depth - plaintext := uint64(2) - ct := verifyCiphertextInTestMemory(environment, plaintext, depth, tfhe.FheUint32) - ctHash := ct.GetHash() - scope := newTestScopeConext() - loc := uint256.NewInt(10) - value := uint256FromBig(ctHash.Big()) - - // Setup and call SSTORE - it requires a location and a value to set there. - scope.pushToStack(value) - scope.pushToStack(loc) - _, err := OpSstore(&pc, environment, scope) - if err != nil { - t.Fatalf(err.Error()) - } - - // Call getCiphertext. - addr := common.Address{} - environment.ethCall = true - readOnly := true - contractAddress := testContractAddress{}.Address() - // Change address to another one that doesn't contain the handle. - contractAddress[0]++ - input := make([]byte, 0) - zeroPadding := make([]byte, 12) - signature := crypto.Keccak256([]byte("getCiphertext(address,uint256)"))[0:4] - input = append(input, signature...) - input = append(input, zeroPadding...) - input = append(input, contractAddress.Bytes()...) - input = append(input, ctHash.Bytes()...) - out, err := FheLibRun(environment, addr, addr, input, readOnly) - if err != nil { - t.Fatalf(err.Error()) - } - if len(out) != 0 { - t.Fatalf("getCiphertext expected empty output on wrong contract address") - } -} - -func FheLibGetCiphertext(t *testing.T, fheUintType tfhe.FheUintType) { - environment := newTestEVMEnvironment() - pc := uint64(0) - depth := 1 - environment.depth = depth - plaintext := uint64(2) - ct := verifyCiphertextInTestMemory(environment, plaintext, depth, fheUintType) - ctHash := ct.GetHash() - scope := newTestScopeConext() - loc := uint256.NewInt(10) - value := uint256FromBig(ctHash.Big()) - - // Setup and call SSTORE - it requires a location and a value to set there. - scope.pushToStack(value) - scope.pushToStack(loc) - _, err := OpSstore(&pc, environment, scope) - if err != nil { - t.Fatalf(err.Error()) - } - - // Call getCiphertext. - addr := common.Address{} - environment.ethCall = true - readOnly := true - input := make([]byte, 0) - zeroPadding := make([]byte, 12) - signature := crypto.Keccak256([]byte("getCiphertext(address,uint256)"))[0:4] - input = append(input, signature...) - input = append(input, zeroPadding...) - input = append(input, testContractAddress{}.Address().Bytes()...) - input = append(input, ctHash.Bytes()...) - out, err := FheLibRun(environment, addr, addr, input, readOnly) - if err != nil { - t.Fatalf(err.Error()) - } - size, _ := tfhe.GetExpandedFheCiphertextSize(fheUintType) - if size != uint(len(out)) { - t.Fatalf("getCiphertext returned ciphertext size of %d, expected %d", len(out), size) - } - - outCt := new(tfhe.TfheCiphertext) - err = outCt.Deserialize(out, fheUintType) - if err != nil { - t.Fatalf(err.Error()) - } - decrypted, err := outCt.Decrypt() - if err != nil { - t.Fatalf(err.Error()) - } - if decrypted.Uint64() != plaintext { - t.Fatalf("getCiphertext returned ciphertext value of %d, expected %d", decrypted.Uint64(), plaintext) - } -} - -func TestFheLibGetCiphertext8(t *testing.T) { - FheLibGetCiphertext(t, tfhe.FheUint8) -} - -func TestFheLibGetCiphertext16(t *testing.T) { - FheLibGetCiphertext(t, tfhe.FheUint16) -} - -func TestFheLibGetCiphertext32(t *testing.T) { - FheLibGetCiphertext(t, tfhe.FheUint32) -} - -func TestFheLibGetCiphertext64(t *testing.T) { - FheLibGetCiphertext(t, tfhe.FheUint64) -} +// TODO GetCiphertext func TestFheArrayEq4(t *testing.T) { FheArrayEq(t, tfhe.FheUint4) @@ -5264,4 +5116,4 @@ func TesFheArrayEqNoRhsGas32(t *testing.T) { func TestFheArrayEqNoRhsGas64(t *testing.T) { FheArrayEqNoRhsGas(t, tfhe.FheUint64) -} +} \ No newline at end of file diff --git a/fhevm/evm.go b/fhevm/evm.go index d998c78..b5cd0e3 100644 --- a/fhevm/evm.go +++ b/fhevm/evm.go @@ -53,43 +53,14 @@ func (l *DefaultLogger) Error(msg string, keyvals ...interface{}) { l.slogger.Error(msg, keyvals...) } -func getVerifiedCiphertext(environment EVMEnvironment, ciphertextHash common.Hash) *verifiedCiphertext { - return getVerifiedCiphertextFromEVM(environment, ciphertextHash) -} - -func importCiphertextToEVMAtDepth(environment EVMEnvironment, ct *tfhe.TfheCiphertext, depth int) *verifiedCiphertext { - existing, ok := environment.FhevmData().verifiedCiphertexts[ct.GetHash()] - if ok { - existing.verifiedDepths.add(depth) - return existing - } else { - verifiedDepths := newDepthSet() - verifiedDepths.add(depth) - new := &verifiedCiphertext{ - verifiedDepths, - ct, - } - environment.FhevmData().verifiedCiphertexts[ct.GetHash()] = new - return new - } -} - -func importCiphertextToEVM(environment EVMEnvironment, ct *tfhe.TfheCiphertext) *verifiedCiphertext { - return importCiphertextToEVMAtDepth(environment, ct, environment.GetDepth()) -} - -func importCiphertext(environment EVMEnvironment, ct *tfhe.TfheCiphertext) *verifiedCiphertext { - return importCiphertextToEVM(environment, ct) -} - -func importRandomCiphertext(environment EVMEnvironment, t tfhe.FheUintType) []byte { +func insertRandomCiphertext(environment EVMEnvironment, t tfhe.FheUintType) []byte { nextCtHash := &environment.FhevmData().nextCiphertextHashOnGasEst ctHashBytes := crypto.Keccak256(nextCtHash.Bytes()) handle := common.BytesToHash(ctHashBytes) ct := new(tfhe.TfheCiphertext) ct.FheUintType = t ct.Hash = &handle - importCiphertext(environment, ct) + insertCiphertextToMemory(environment, ct) temp := nextCtHash.Clone() nextCtHash.Add(temp, uint256.NewInt(1)) return ct.GetHash().Bytes() diff --git a/fhevm/fhelib.go b/fhevm/fhelib.go index b3e955e..a885ee6 100644 --- a/fhevm/fhelib.go +++ b/fhevm/fhelib.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/holiman/uint256" + "github.com/zama-ai/fhevm-go/fhevm/tfhe" "go.opentelemetry.io/otel/trace" ) @@ -293,19 +294,22 @@ func toEVMBytes(input []byte) []byte { return ret } -func get2VerifiedOperands(environment EVMEnvironment, input []byte) (lhs *verifiedCiphertext, rhs *verifiedCiphertext, err error) { +func load2Ciphertexts(environment EVMEnvironment, input []byte) (lhs *tfhe.TfheCiphertext, rhs *tfhe.TfheCiphertext, loadGas uint64, err error) { if len(input) != 65 { - return nil, nil, errors.New("input needs to contain two 256-bit sized values and 1 8-bit value") + return nil, nil, 0, errors.New("input needs to contain two 256-bit sized values and 1 8-bit value") } - lhs = getVerifiedCiphertext(environment, common.BytesToHash(input[0:32])) + loadGasLhs := uint64(0) + loadGasRhs := uint64(0) + lhs, loadGasLhs = loadCiphertext(environment, common.BytesToHash(input[0:32])) if lhs == nil { - return nil, nil, errors.New("unverified ciphertext handle") + return nil, nil, 0, errors.New("unverified ciphertext handle") } - rhs = getVerifiedCiphertext(environment, common.BytesToHash(input[32:64])) + rhs, loadGasRhs = loadCiphertext(environment, common.BytesToHash(input[32:64])) if rhs == nil { - return nil, nil, errors.New("unverified ciphertext handle") + return nil, nil, 0, errors.New("unverified ciphertext handle") } err = nil + loadGas = loadGasLhs + loadGasRhs return } @@ -317,33 +321,37 @@ func isScalarOp(input []byte) (bool, error) { return isScalar, nil } -func get3VerifiedOperands(environment EVMEnvironment, input []byte) (first *verifiedCiphertext, second *verifiedCiphertext, third *verifiedCiphertext, err error) { +func load3Ciphertexts(environment EVMEnvironment, input []byte) (first *tfhe.TfheCiphertext, second *tfhe.TfheCiphertext, third *tfhe.TfheCiphertext, loadGas uint64, err error) { if len(input) != 96 { - return nil, nil, nil, errors.New("input needs to contain three 256-bit sized values") + return nil, nil, nil, 0, errors.New("input needs to contain three 256-bit sized values") } - first = getVerifiedCiphertext(environment, common.BytesToHash(input[0:32])) + loadGasFirst := uint64(0) + loadGasSecond := uint64(0) + loadGasThird := uint64(0) + first, loadGasFirst = loadCiphertext(environment, common.BytesToHash(input[0:32])) if first == nil { - return nil, nil, nil, errors.New("unverified ciphertext handle") + return nil, nil, nil, 0, errors.New("unverified ciphertext handle") } - second = getVerifiedCiphertext(environment, common.BytesToHash(input[32:64])) + second, loadGasSecond = loadCiphertext(environment, common.BytesToHash(input[32:64])) if second == nil { - return nil, nil, nil, errors.New("unverified ciphertext handle") + return nil, nil, nil, 0, errors.New("unverified ciphertext handle") } - third = getVerifiedCiphertext(environment, common.BytesToHash(input[64:96])) + third, loadGasThird = loadCiphertext(environment, common.BytesToHash(input[64:96])) if third == nil { - return nil, nil, nil, errors.New("unverified ciphertext handle") + return nil, nil, nil, 0, errors.New("unverified ciphertext handle") } err = nil + loadGas = loadGasFirst + loadGasSecond + loadGasThird return } -func getScalarOperands(environment EVMEnvironment, input []byte) (lhs *verifiedCiphertext, rhs *big.Int, err error) { +func getScalarOperands(environment EVMEnvironment, input []byte) (lhs *tfhe.TfheCiphertext, rhs *big.Int, loadGas uint64, err error) { if len(input) != 65 { - return nil, nil, errors.New("input needs to contain two 256-bit sized values and 1 8-bit value") + return nil, nil, 0, errors.New("input needs to contain two 256-bit sized values and 1 8-bit value") } - lhs = getVerifiedCiphertext(environment, common.BytesToHash(input[0:32])) + lhs, loadGas = loadCiphertext(environment, common.BytesToHash(input[0:32])) if lhs == nil { - return nil, nil, errors.New("unverified ciphertext handle") + return nil, nil, 0, errors.New("failed to load ciphertext") } rhs = &big.Int{} rhs.SetBytes(input[32:64]) diff --git a/fhevm/instructions.go b/fhevm/instructions.go index 9cb2ed3..2296f9e 100644 --- a/fhevm/instructions.go +++ b/fhevm/instructions.go @@ -1,95 +1,10 @@ package fhevm import ( - "errors" - "math/big" - "strings" - "github.com/ethereum/go-ethereum/common" - crypto "github.com/ethereum/go-ethereum/crypto" - "github.com/holiman/uint256" - fhevm_crypto "github.com/zama-ai/fhevm-go/fhevm/crypto" - "github.com/zama-ai/fhevm-go/fhevm/tfhe" "go.opentelemetry.io/otel" ) -var zero = common.BytesToHash(uint256.NewInt(0).Bytes()) - -func newInt(buf []byte) *uint256.Int { - i := uint256.NewInt(0) - return i.SetBytes(buf) -} - -func contains(haystack []byte, needle []byte) bool { - return strings.Contains(string(haystack), string(needle)) -} - -func isVerifiedAtCurrentDepth(environment EVMEnvironment, ct *verifiedCiphertext) bool { - return ct.verifiedDepths.has(environment.GetDepth()) -} - -// Returns a pointer to the ciphertext if the given hash points to a verified ciphertext. -// Else, it returns nil. -func getVerifiedCiphertextFromEVM(environment EVMEnvironment, ciphertextHash common.Hash) *verifiedCiphertext { - ct, ok := environment.FhevmData().verifiedCiphertexts[ciphertextHash] - if ok && isVerifiedAtCurrentDepth(environment, ct) { - return ct - } - return nil -} - -// Returns the type of the verified ciphertext for `ciphertextHash` or nil if it doesn't exist or not verified at current depth. -func GetTypeOfVerifiedCiphertext(env EVMEnvironment, ciphertextHash common.Hash) *tfhe.FheUintType { - ct := getVerifiedCiphertextFromEVM(env, ciphertextHash) - if ct == nil { - return nil - } - t := ct.ciphertext.Type() - return &t -} - -func verifyIfCiphertextHandle(handle common.Hash, env EVMEnvironment, contractAddress common.Address) error { - ct, ok := env.FhevmData().verifiedCiphertexts[handle] - if ok { - // If already existing in memory, skip storage and import the same ciphertext at the current depth. - // - // Also works for gas estimation - we don't persist anything to protected storage during gas estimation. - // However, ciphertexts remain in memory for the duration of the call, allowing for this lookup to find it. - // Note that even if a ciphertext has an empty verification depth set, it still remains in memory. - importCiphertextToEVM(env, ct.ciphertext) - return nil - } - - ciphertext := getCiphertextFromProtectedStoage(env, contractAddress, handle) - if ciphertext != nil { - ct := new(tfhe.TfheCiphertext) - err := ct.Deserialize(ciphertext.bytes, ciphertext.metadata.fheUintType) - if err != nil { - msg := "opSload failed to deserialize a ciphertext" - env.GetLogger().Error(msg, "err", err) - return errors.New(msg) - } - importCiphertextToEVM(env, ct) - } - return nil -} - -// This function is a modified copy from https://github.com/ethereum/go-ethereum -func OpSload(pc *uint64, env EVMEnvironment, scope ScopeContext) ([]byte, error) { - if otelCtx := env.OtelContext(); otelCtx != nil { - _, span := otel.Tracer("fhevm").Start(otelCtx, "OpSload") - defer span.End() - } - loc := scope.GetStack().Peek() - hash := common.Hash(loc.Bytes32()) - val := env.GetState(scope.GetContract().Address(), hash) - if err := verifyIfCiphertextHandle(val, env, scope.GetContract().Address()); err != nil { - return nil, err - } - loc.SetBytes(val.Bytes()) - return nil, nil -} - func OpSstore(pc *uint64, env EVMEnvironment, scope ScopeContext) ([]byte, error) { // This function is a modified copy from https://github.com/ethereum/go-ethereum if otelCtx := env.OtelContext(); otelCtx != nil { @@ -100,104 +15,17 @@ func OpSstore(pc *uint64, env EVMEnvironment, scope ScopeContext) ([]byte, error return nil, ErrWriteProtection } loc := scope.GetStack().Pop() - locHash := common.BytesToHash(loc.Bytes()) newVal := scope.GetStack().Pop() newValHash := common.BytesToHash(newVal.Bytes()) oldValHash := env.GetState(scope.GetContract().Address(), common.Hash(loc.Bytes32())) - // If the value is the same or if we are not going to commit, don't do anything to protected storage. + // If the value is the same or if we are not going to commit, don't do anything to ciphertext storage. if newValHash != oldValHash && env.IsCommitting() { - protectedStorage := fhevm_crypto.CreateProtectedStorageContractAddress(scope.GetContract().Address()) - - // Define flag location as keccak256(keccak256(loc)) in protected storage. Used to mark the location as containing a handle. - // Note: We apply the hash function twice to make sure a flag location in protected storage cannot clash with a ciphertext - // metadata location that is keccak256(keccak256(ciphertext)). Since a location is 32 bytes, it cannot clash with a well-formed - // ciphertext. Therefore, there needs to be a hash collistion for a clash to happen. If hash is applied only once, there could - // be a collision, since malicous users could store at loc = keccak256(ciphertext), making the flag clash with metadata. - flagHandleLocation := crypto.Keccak256Hash(crypto.Keccak256Hash(locHash[:]).Bytes()) - - // Since the old value is no longer stored in actual contract storage, run garbage collection on protected storage. - garbageCollectProtectedStorage(flagHandleLocation, oldValHash, protectedStorage, env) - - // If a verified ciphertext, persist to protected storage. - persistIfVerifiedCiphertext(flagHandleLocation, newValHash, protectedStorage, env) + ct := GetCiphertextFromMemory(env, newValHash) + if ct != nil { + persistCiphertext(env, ct) + } } // Set the SSTORE's value in the actual contract. env.SetState(scope.GetContract().Address(), loc.Bytes32(), newValHash) return nil, nil } - -// If there are ciphertext handles in the arguments to a call, delegate them to the callee. -// Return a map from ciphertext hash -> depthSet before delegation. -func DelegateCiphertextHandlesInArgs(env EVMEnvironment, args []byte) (verified map[common.Hash]*depthSet) { - verified = make(map[common.Hash]*depthSet) - for key, verifiedCiphertext := range env.FhevmData().verifiedCiphertexts { - if contains(args, key.Bytes()) && isVerifiedAtCurrentDepth(env, verifiedCiphertext) { - if env.IsCommitting() { - env.GetLogger().Info("delegateCiphertextHandlesInArgs", - "handle", verifiedCiphertext.ciphertext.GetHash().Hex(), - "fromDepth", env.GetDepth(), - "toDepth", env.GetDepth()+1) - } - verified[key] = verifiedCiphertext.verifiedDepths.clone() - verifiedCiphertext.verifiedDepths.add(env.GetDepth() + 1) - } - } - return -} - -func RestoreVerifiedDepths(env EVMEnvironment, verified map[common.Hash]*depthSet) { - for k, v := range verified { - env.FhevmData().verifiedCiphertexts[k].verifiedDepths = v - } -} - -func delegateCiphertextHandlesToCaller(env EVMEnvironment, ret []byte) { - for key, verifiedCiphertext := range env.FhevmData().verifiedCiphertexts { - if contains(ret, key.Bytes()) && isVerifiedAtCurrentDepth(env, verifiedCiphertext) { - if env.IsCommitting() { - env.GetLogger().Info("opReturn making ciphertext available to caller", - "handle", verifiedCiphertext.ciphertext.GetHash().Hex(), - "fromDepth", env.GetDepth(), - "toDepth", env.GetDepth()-1) - } - // If a handle is returned, automatically make it available to the caller. - verifiedCiphertext.verifiedDepths.add(env.GetDepth() - 1) - } - } -} - -func RemoveVerifiedCipherextsAtCurrentDepth(env EVMEnvironment) { - for _, verifiedCiphertext := range env.FhevmData().verifiedCiphertexts { - if env.IsCommitting() { - env.GetLogger().Info("Run removing ciphertext from depth", - "handle", verifiedCiphertext.ciphertext.GetHash().Hex(), - "depth", env.GetDepth()) - } - // Delete the current EVM depth from the set of verified depths. - verifiedCiphertext.verifiedDepths.del(env.GetDepth()) - } -} - -func OpReturn(pc *uint64, env EVMEnvironment, scope ScopeContext) []byte { - // This function is a modified copy from https://github.com/ethereum/go-ethereum - if otelCtx := env.OtelContext(); otelCtx != nil { - _, span := otel.Tracer("fhevm").Start(otelCtx, "OpReturn") - defer span.End() - } - offset, size := scope.GetStack().Pop(), scope.GetStack().Pop() - ret := scope.GetMemory().GetPtr(int64(offset.Uint64()), int64(size.Uint64())) - delegateCiphertextHandlesToCaller(env, ret) - return ret -} - -func OpSelfdestruct(pc *uint64, env EVMEnvironment, scope ScopeContext) (beneficiary uint256.Int, balance *big.Int) { - // This function is a modified copy from https://github.com/ethereum/go-ethereum - beneficiary = scope.GetStack().Pop() - protectedStorage := fhevm_crypto.CreateProtectedStorageContractAddress(scope.GetContract().Address()) - balance = env.GetBalance(scope.GetContract().Address()) - balance.Add(balance, env.GetBalance(protectedStorage)) - env.AddBalance(beneficiary.Bytes20(), balance) - env.Suicide(scope.GetContract().Address()) - env.Suicide(protectedStorage) - return -} diff --git a/fhevm/instructions_test.go b/fhevm/instructions_test.go deleted file mode 100644 index b85f6d7..0000000 --- a/fhevm/instructions_test.go +++ /dev/null @@ -1,529 +0,0 @@ -package fhevm - -import ( - "bytes" - "context" - "math/big" - "sync" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/holiman/uint256" - fhevm_crypto "github.com/zama-ai/fhevm-go/fhevm/crypto" - "github.com/zama-ai/fhevm-go/fhevm/tfhe" -) - -func init() { - // register errors from geth so that tests recognize them - RegisterErrors( - vm.ErrOutOfGas, - vm.ErrCodeStoreOutOfGas, - vm.ErrDepth, - vm.ErrInsufficientBalance, - vm.ErrContractAddressCollision, - vm.ErrExecutionReverted, - vm.ErrMaxInitCodeSizeExceeded, - vm.ErrMaxCodeSizeExceeded, - vm.ErrInvalidJump, - vm.ErrWriteProtection, - vm.ErrReturnDataOutOfBounds, - vm.ErrGasUintOverflow, - vm.ErrInvalidCode, - vm.ErrNonceUintOverflow, - nil, - nil, - nil, - ) -} - -func verifyCiphertextInTestMemory(environment EVMEnvironment, value uint64, depth int, t tfhe.FheUintType) *tfhe.TfheCiphertext { - // Simulate as if the ciphertext is compact and comes externally. - ser := tfhe.EncryptAndSerializeCompact(uint64(value), t) - ct := new(tfhe.TfheCiphertext) - err := ct.DeserializeCompact(ser, t) - if err != nil { - panic(err) - } - return verifyTfheCiphertextInTestMemory(environment, ct, depth) -} - -func verifyTfheCiphertextInTestMemory(environment EVMEnvironment, ct *tfhe.TfheCiphertext, depth int) *tfhe.TfheCiphertext { - verifiedCiphertext := importCiphertextToEVMAtDepth(environment, ct, depth) - return verifiedCiphertext.ciphertext -} - -// Implementation of some geth data structures used for testing - -var stackPool = sync.Pool{ - New: func() interface{} { - return &TestStack{data: make([]uint256.Int, 0, 16)} - }, -} - -type TestStack struct { - data []uint256.Int -} - -func newstack() *TestStack { - return stackPool.Get().(*TestStack) -} - -// Data returns the underlying uint256.Int array. -func (st *TestStack) Data() []uint256.Int { - return st.data -} - -func (st *TestStack) push(d *uint256.Int) { - // NOTE push limit (1024) is checked in baseCheck - st.data = append(st.data, *d) -} - -func (st *TestStack) pop() (ret uint256.Int) { - ret = st.data[len(st.data)-1] - st.data = st.data[:len(st.data)-1] - return -} - -func (st *TestStack) len() int { - return len(st.data) -} - -func (st *TestStack) peek() *uint256.Int { - return &st.data[st.len()-1] -} - -// Back returns the n'th item in stack -func (st *TestStack) Back(n int) *uint256.Int { - return &st.data[st.len()-n-1] -} - -func (st *TestStack) Peek() *uint256.Int { return st.peek() } - -func (st *TestStack) Pop() uint256.Int { return st.pop() } - -type TestScopeContext struct { - Memory *vm.Memory - Stack *TestStack - Contract *vm.Contract -} - -type TestScopeContextInterface interface { - ScopeContext - pushToStack(*uint256.Int) -} - -func (scope *TestScopeContext) GetContract() Contract { return scope.Contract } -func (scope *TestScopeContext) GetMemory() Memory { return scope.Memory } -func (scope *TestScopeContext) GetStack() Stack { return scope.Stack } -func (scope *TestScopeContext) pushToStack(v *uint256.Int) { scope.Stack.push(v) } - -type testContractAddress struct{} - -func (c testContractAddress) Address() common.Address { - return common.Address{} -} - -type testCallerAddress struct{} - -func (c testCallerAddress) Address() common.Address { - addr := common.Address{} - addr[0]++ - return addr -} - -func newTestScopeConext() TestScopeContextInterface { - c := new(TestScopeContext) - c.Memory = vm.NewMemory() - c.Memory.Resize(uint64(tfhe.ExpandedFheCiphertextSize[tfhe.FheUint8]) * 3) - c.Stack = newstack() - c.Contract = vm.NewContract(testCallerAddress{}, testContractAddress{}, big.NewInt(10), 100000) - return c -} - -func uint256FromBig(b *big.Int) *uint256.Int { - value, overflow := uint256.FromBig(b) - if overflow { - panic("overflow") - } - return value -} - -type MockEVMEnvironment struct { - fhevmData *FhevmData - depth int - stateDb *state.StateDB - commit bool - ethCall bool - readOnly bool - fhevmParams FhevmParams -} - -func (*MockEVMEnvironment) OtelContext() context.Context { - // can also return nil and disable Otel - return context.TODO() -} - -func (environment *MockEVMEnvironment) GetState(addr common.Address, hash common.Hash) common.Hash { - return environment.stateDb.GetState(addr, hash) -} - -func (environment *MockEVMEnvironment) SetState(addr common.Address, key common.Hash, value common.Hash) { - environment.stateDb.SetState(addr, key, value) -} - -func (environment *MockEVMEnvironment) GetNonce(common.Address) uint64 { - return 0 -} - -func (environment *MockEVMEnvironment) AddBalance(addr common.Address, amount *big.Int) { - environment.stateDb.AddBalance(addr, amount) -} - -func (environment *MockEVMEnvironment) GetBalance(addr common.Address) *big.Int { - return environment.stateDb.GetBalance(addr) -} - -func (environment *MockEVMEnvironment) Suicide(addr common.Address) bool { - return environment.stateDb.Suicide(addr) -} - -func (environment *MockEVMEnvironment) GetDepth() int { - return environment.depth -} - -func (environment *MockEVMEnvironment) GetLogger() Logger { - return NewDefaultLogger() -} - -func (environment *MockEVMEnvironment) IsCommitting() bool { - return environment.commit -} - -func (environment *MockEVMEnvironment) IsEthCall() bool { - return environment.ethCall -} - -func (environment *MockEVMEnvironment) IsReadOnly() bool { - return environment.readOnly -} - -func (environment *MockEVMEnvironment) CreateContract(caller common.Address, code []byte, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) { - return make([]byte, 0), common.Address{}, 0, nil -} - -func (environment *MockEVMEnvironment) CreateContract2(caller common.Address, code []byte, codeHash common.Hash, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) { - return make([]byte, 0), common.Address{}, 0, nil -} - -func (environment *MockEVMEnvironment) FhevmData() *FhevmData { - return environment.fhevmData -} - -func (environment *MockEVMEnvironment) FhevmParams() *FhevmParams { - return &environment.fhevmParams -} - -func (environment *MockEVMEnvironment) EVMEnvironment() EVMEnvironment { - return environment -} - -func newTestEVMEnvironment() *MockEVMEnvironment { - fhevmData := NewFhevmData() - db := rawdb.NewMemoryDatabase() - state, _ := state.New(common.Hash{}, state.NewDatabase(db), nil) - return &MockEVMEnvironment{fhevmData: &fhevmData, stateDb: state, commit: true, fhevmParams: DefaultFhevmParams()} -} - -func TestProtectedStorageSstoreSload(t *testing.T) { - environment := newTestEVMEnvironment() - pc := uint64(0) - depth := 1 - environment.depth = depth - ct := verifyCiphertextInTestMemory(environment, 2, depth, tfhe.FheUint32) - ctHash := ct.GetHash() - scope := newTestScopeConext() - loc := uint256.NewInt(10) - value := uint256FromBig(ctHash.Big()) - - // Setup and call SSTORE - it requires a location and a value to set there. - scope.pushToStack(value) - scope.pushToStack(loc) - _, err := OpSstore(&pc, environment, scope) - if err != nil { - t.Fatalf(err.Error()) - } - - // Clear the verified ciphertexts. - environment.FhevmData().verifiedCiphertexts = make(map[common.Hash]*verifiedCiphertext) - - // Setup and call SLOAD - it requires a location to load. - scope.pushToStack(loc) - _, err = OpSload(&pc, environment, scope) - if err != nil { - t.Fatalf(err.Error()) - } - - // Expect the ciphertext is verified after SLOAD. - ctAfterSload := getVerifiedCiphertextFromEVM(environment, ctHash) - if ctAfterSload == nil { - t.Fatalf("expected ciphertext is verified after sload") - } - if !bytes.Equal(ct.Serialize(), ctAfterSload.ciphertext.Serialize()) { - t.Fatalf("expected ciphertext after sload is the same as original") - } -} - -func TestProtectedStorageGarbageCollectionNoFlaggedLocation(t *testing.T) { - environment := newTestEVMEnvironment() - pc := uint64(0) - depth := 1 - environment.depth = depth - ctHash := verifyCiphertextInTestMemory(environment, 2, depth, tfhe.FheUint8).GetHash() - scope := newTestScopeConext() - loc := uint256.NewInt(10) - locHash := common.BytesToHash(loc.Bytes()) - value := uint256FromBig(ctHash.Big()) - protectedStorage := fhevm_crypto.CreateProtectedStorageContractAddress(scope.GetContract().Address()) - - // Persist the ciphertext in protected storage. - scope.pushToStack(value) - scope.pushToStack(loc) - _, err := OpSstore(&pc, environment, scope) - if err != nil { - t.Fatalf(err.Error()) - } - - // Set location flag to zero, such that garbage collection doesn't happen. - flagHandleLocation := crypto.Keccak256Hash(crypto.Keccak256Hash(locHash.Bytes()).Bytes()) - environment.SetState(protectedStorage, flagHandleLocation, zero) - - // Overwrite the ciphertext handle with 0. - scope.pushToStack(uint256.NewInt(0)) - scope.pushToStack(loc) - _, err = OpSstore(&pc, environment, scope) - if err != nil { - t.Fatalf(err.Error()) - } - - // Verify that garbage collection hasn't happened. - metadata := ciphertextMetadata{} - metadataKey := crypto.Keccak256Hash(ctHash.Bytes()) - metadata.deserialize(environment.GetState(protectedStorage, metadataKey)) - slot := uint256FromBig(metadataKey.Big()) - slot = slot.AddUint64(slot, 1) - foundNonZero := false - for i := uint64(0); i < metadata.length; i++ { - res := environment.GetState(protectedStorage, common.BytesToHash(slot.Bytes())) - if !bytes.Equal(res.Bytes(), zero.Bytes()) { - foundNonZero = true - break - } - slot = slot.AddUint64(slot, i) - } - if !foundNonZero { - t.Fatalf("garbage collection must not have happened") - } -} - -func TestProtectedStorageGarbageCollection(t *testing.T) { - environment := newTestEVMEnvironment() - pc := uint64(0) - depth := 1 - environment.depth = depth - ctHash := verifyCiphertextInTestMemory(environment, 2, depth, tfhe.FheUint8).GetHash() - scope := newTestScopeConext() - loc := uint256.NewInt(10) - locHash := common.BytesToHash(loc.Bytes()) - value := uint256FromBig(ctHash.Big()) - - // Persist the ciphertext in protected storage. - scope.pushToStack(value) - scope.pushToStack(loc) - _, err := OpSstore(&pc, environment, scope) - if err != nil { - t.Fatalf(err.Error()) - } - - // Make sure ciphertext is persisted to protected storage. - protectedStorage := fhevm_crypto.CreateProtectedStorageContractAddress(scope.GetContract().Address()) - metadata := ciphertextMetadata{} - metadataKey := crypto.Keccak256Hash(ctHash.Bytes()) - metadata.deserialize(environment.GetState(protectedStorage, metadataKey)) - if metadata.refCount != 1 { - t.Fatalf("metadata.refcount of ciphertext is not 1") - } - if metadata.length != uint64(tfhe.ExpandedFheCiphertextSize[tfhe.FheUint8]) { - t.Fatalf("metadata.length (%v) != ciphertext len (%v)", metadata.length, uint64(tfhe.ExpandedFheCiphertextSize[tfhe.FheUint8])) - } - ciphertextLocationsToCheck := (metadata.length + 32 - 1) / 32 - startOfCiphertext := newInt(metadataKey.Bytes()) - startOfCiphertext.AddUint64(startOfCiphertext, 1) - ctIdx := startOfCiphertext - foundNonZero := false - for i := uint64(0); i < ciphertextLocationsToCheck; i++ { - c := environment.GetState(protectedStorage, common.BytesToHash(ctIdx.Bytes())) - u := uint256FromBig(c.Big()) - if !u.IsZero() { - foundNonZero = true - break - } - ctIdx.AddUint64(startOfCiphertext, 1) - } - if !foundNonZero { - t.Fatalf("ciphertext is not persisted to protected storage") - } - - // Check if the handle location is flagged in protected storage. - flagHandleLocation := crypto.Keccak256Hash(crypto.Keccak256Hash(locHash.Bytes()).Bytes()) - foundFlag := environment.GetState(protectedStorage, flagHandleLocation) - if !bytes.Equal(foundFlag.Bytes(), flag.Bytes()) { - t.Fatalf("location flag not persisted to protected storage") - } - - // Overwrite the ciphertext handle with 0. - scope.pushToStack(uint256.NewInt(0)) - scope.pushToStack(loc) - _, err = OpSstore(&pc, environment, scope) - if err != nil { - t.Fatalf(err.Error()) - } - - // Make sure the metadata and the ciphertext are garbage collected from protected storage. - protectedStorageIdx := newInt(metadataKey.Bytes()) - foundNonZero = false - for i := uint64(0); i < ciphertextLocationsToCheck; i++ { - c := environment.GetState(protectedStorage, common.BytesToHash(protectedStorageIdx.Bytes())) - u := uint256FromBig(c.Big()) - if !u.IsZero() { - foundNonZero = true - break - } - ctIdx.AddUint64(startOfCiphertext, 1) - } - if foundNonZero { - t.Fatalf("ciphertext is not garbage collected from protected storage") - } - - // Make sure the flag location is zero. - foundFlag = environment.GetState(protectedStorage, flagHandleLocation) - if !bytes.Equal(foundFlag.Bytes(), zero.Bytes()) { - t.Fatalf("location flag is not set to zero on garbage collection") - } -} - -func TestProtectedStorageSloadDoesNotVerifyNonHandle(t *testing.T) { - environment := newTestEVMEnvironment() - pc := uint64(0) - scope := newTestScopeConext() - loc := uint256.NewInt(10) - value := uint256.NewInt(42) - - scope.pushToStack(value) - scope.pushToStack(loc) - _, err := OpSstore(&pc, environment, scope) - if err != nil { - t.Fatalf(err.Error()) - } - - scope.pushToStack(loc) - _, err = OpSload(&pc, environment, scope) - if err != nil { - t.Fatalf(err.Error()) - } - - // Expect no verified ciphertexts. - if len(environment.FhevmData().verifiedCiphertexts) != 0 { - t.Fatalf("expected no verified ciphetexts") - } -} - -func TestOpReturnDelegation(t *testing.T) { - environment := newTestEVMEnvironment() - pc := uint64(0) - depth := 2 - scope := newTestScopeConext() - ct := verifyCiphertextInTestMemory(environment, 2, depth, tfhe.FheUint8) - ctHash := ct.GetHash() - - offset := uint256.NewInt(0) - length := uint256.NewInt(32) - scope.pushToStack(length) - scope.pushToStack(offset) - scope.GetMemory().Set(offset.Uint64(), length.Uint64(), ctHash[:]) - environment.depth = depth - OpReturn(&pc, environment, scope) - environment.depth-- - ctAfterOp := getVerifiedCiphertextFromEVM(environment, ctHash) - if ctAfterOp == nil { - t.Fatalf("expected ciphertext is still verified after the return op") - } - if !bytes.Equal(ct.Serialize(), ctAfterOp.ciphertext.Serialize()) { - t.Fatalf("expected ciphertext after the return op is the same as original") - } -} - -func TestOpReturnUnverifyIfNotReturned(t *testing.T) { - environment := newTestEVMEnvironment() - pc := uint64(0) - depth := 2 - scope := newTestScopeConext() - ctHash := verifyCiphertextInTestMemory(environment, 2, depth, tfhe.FheUint8).GetHash() - - offset := uint256.NewInt(0) - len := uint256.NewInt(32) - scope.pushToStack(len) - scope.pushToStack(offset) - // Set 0s as return. - scope.GetMemory().Set(offset.Uint64(), len.Uint64(), make([]byte, len.Uint64())) - environment.depth = depth - OpReturn(&pc, environment, scope) - environment.depth = depth - 1 - ct := getVerifiedCiphertextFromEVM(environment, ctHash) - if ct != nil { - t.Fatalf("expected ciphertext is not verified after the return op") - } -} - -func TestOpReturnDoesNotUnverifyIfNotVerified(t *testing.T) { - environment := newTestEVMEnvironment() - pc := uint64(0) - scope := newTestScopeConext() - ct := verifyCiphertextInTestMemory(environment, 2, 4, tfhe.FheUint8) - ctHash := ct.GetHash() - - // Return from depth 3 to depth 2. However, ct is not verified at 3 and, hence, cannot - // be passed from 3 to 2. However, we expect that ct remains verified at 4. - offset := uint256.NewInt(0) - len := uint256.NewInt(32) - scope.pushToStack(len) - scope.pushToStack(offset) - scope.GetMemory().Set(offset.Uint64(), len.Uint64(), ctHash[:]) - environment.depth = 3 - OpReturn(&pc, environment, scope) - environment.depth-- - - ctAt2 := getVerifiedCiphertextFromEVM(environment, ctHash) - if ctAt2 != nil { - t.Fatalf("expected ciphertext is not verified at 2") - } - environment.depth = 3 - ctAt3 := getVerifiedCiphertextFromEVM(environment, ctHash) - if ctAt3 != nil { - t.Fatalf("expected ciphertext is not verified at 3") - } - environment.depth = 4 - ctAt4 := getVerifiedCiphertextFromEVM(environment, ctHash) - if ctAt4 == nil { - t.Fatalf("expected ciphertext is still verified at 4") - } - if !bytes.Equal(ct.Serialize(), ctAt4.ciphertext.Serialize()) { - t.Fatalf("expected ciphertext after the return op is the same as original") - } - if ctAt4.verifiedDepths.count() != 1 || !ctAt4.verifiedDepths.has(environment.depth) { - t.Fatalf("expected ciphertext to be verified at depth 4") - } -} diff --git a/fhevm/interface.go b/fhevm/interface.go index 79c4ca6..160332e 100644 --- a/fhevm/interface.go +++ b/fhevm/interface.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/holiman/uint256" + "github.com/zama-ai/fhevm-go/fhevm/tfhe" ) type EVMEnvironment interface { @@ -43,14 +44,14 @@ type EVMEnvironment interface { } type FhevmData struct { - // A map from a ciphertext hash to itself and stack depth at which it is verified - verifiedCiphertexts map[common.Hash]*verifiedCiphertext + // A map from a ciphertext hash to the ciphertext itself. + loadedCiphertexts map[common.Hash]*tfhe.TfheCiphertext nextCiphertextHashOnGasEst uint256.Int } func NewFhevmData() FhevmData { return FhevmData{ - verifiedCiphertexts: make(map[common.Hash]*verifiedCiphertext), + loadedCiphertexts: make(map[common.Hash]*tfhe.TfheCiphertext), } } diff --git a/fhevm/operators_arithmetic.go b/fhevm/operators_arithmetic.go index d57de27..d4a01df 100644 --- a/fhevm/operators_arithmetic.go +++ b/fhevm/operators_arithmetic.go @@ -20,56 +20,56 @@ func fheAddRun(environment EVMEnvironment, caller common.Address, addr common.Ad } if !isScalar { - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheAdd inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheAdd failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheAdd operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.Add(rhs.ciphertext) + result, err := lhs.Add(rhs) if err != nil { logger.Error("fheAdd failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheAdd success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheAdd success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheAdd scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheAdd scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.ScalarAdd(rhs) + result, err := lhs.ScalarAdd(rhs) if err != nil { logger.Error("fheAdd failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheAdd scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheAdd scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } @@ -86,56 +86,56 @@ func fheSubRun(environment EVMEnvironment, caller common.Address, addr common.Ad } if !isScalar { - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheSub inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheSub failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheSub operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.Sub(rhs.ciphertext) + result, err := lhs.Sub(rhs) if err != nil { logger.Error("fheSub failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheSub success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheSub success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheSub scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheSub scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.ScalarSub(rhs) + result, err := lhs.ScalarSub(rhs) if err != nil { logger.Error("fheSub failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheSub scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheSub scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } @@ -152,56 +152,56 @@ func fheMulRun(environment EVMEnvironment, caller common.Address, addr common.Ad } if !isScalar { - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheMul inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheMul failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheMul operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.Mul(rhs.ciphertext) + result, err := lhs.Mul(rhs) if err != nil { logger.Error("fheMul failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheMul success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheMul success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheMul scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheMul scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.ScalarMul(rhs) + result, err := lhs.ScalarMul(rhs) if err != nil { logger.Error("fheMul failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheMul scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheMul scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } @@ -222,27 +222,27 @@ func fheDivRun(environment EVMEnvironment, caller common.Address, addr common.Ad logger.Error("fheDiv supports only scalar input operation, two ciphertexts received", "input", hex.EncodeToString(input)) return nil, err } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheDiv scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheDiv scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.ScalarDiv(rhs) + result, err := lhs.ScalarDiv(rhs) if err != nil { logger.Error("fheDiv failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheDiv scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheDiv scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } @@ -263,27 +263,27 @@ func fheRemRun(environment EVMEnvironment, caller common.Address, addr common.Ad logger.Error("fheRem supports only scalar input operation, two ciphertexts received", "input", hex.EncodeToString(input)) return nil, err } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheRem scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheRem scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.ScalarRem(rhs) + result, err := lhs.ScalarRem(rhs) if err != nil { logger.Error("fheRem failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheRem scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheRem scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } diff --git a/fhevm/operators_arithmetic_gas.go b/fhevm/operators_arithmetic_gas.go index 33916cc..4f0f8b4 100644 --- a/fhevm/operators_arithmetic_gas.go +++ b/fhevm/operators_arithmetic_gas.go @@ -1,6 +1,10 @@ package fhevm -import "encoding/hex" +import ( + "encoding/hex" + + "github.com/zama-ai/fhevm-go/fhevm/tfhe" +) func fheAddSubRequiredGas(environment EVMEnvironment, input []byte) uint64 { input = input[:minInt(65, len(input))] @@ -11,26 +15,27 @@ func fheAddSubRequiredGas(environment EVMEnvironment, input []byte) uint64 { logger.Error("fheAdd/Sub RequiredGas() can not detect if operator is meant to be scalar", "err", err, "input", hex.EncodeToString(input)) return 0 } - var lhs, rhs *verifiedCiphertext + loadGas := uint64(0) + var lhs, rhs *tfhe.TfheCiphertext if !isScalar { - lhs, rhs, err = get2VerifiedOperands(environment, input) + lhs, rhs, loadGas, err = load2Ciphertexts(environment, input) if err != nil { - logger.Error("fheAdd/Sub RequiredGas() ciphertext inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheAdd/Sub RequiredGas() ciphertext failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return 0 } - if lhs.fheUintType() != rhs.fheUintType() { - logger.Error("fheAdd/Sub RequiredGas() operand type mismatch", "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + if lhs.Type() != rhs.Type() { + logger.Error("fheAdd/Sub RequiredGas() operand type mismatch", "lhs", lhs.Type(), "rhs", rhs.Type()) return 0 } } else { - lhs, _, err = getScalarOperands(environment, input) + lhs, _, loadGas, err = getScalarOperands(environment, input) if err != nil { - logger.Error("fheAdd/Sub RequiredGas() scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheAdd/Sub RequiredGas() scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return 0 } } - return environment.FhevmParams().GasCosts.FheAddSub[lhs.fheUintType()] + return environment.FhevmParams().GasCosts.FheAddSub[lhs.Type()] + loadGas } func fheMulRequiredGas(environment EVMEnvironment, input []byte) uint64 { @@ -42,25 +47,26 @@ func fheMulRequiredGas(environment EVMEnvironment, input []byte) uint64 { logger.Error("fheMul RequiredGas() can not detect if operator is meant to be scalar", "err", err, "input", hex.EncodeToString(input)) return 0 } - var lhs, rhs *verifiedCiphertext + loadGas := uint64(0) + var lhs, rhs *tfhe.TfheCiphertext if !isScalar { - lhs, rhs, err = get2VerifiedOperands(environment, input) + lhs, rhs, loadGas, err = load2Ciphertexts(environment, input) if err != nil { - logger.Error("fheMul RequiredGas() ciphertext inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheMul RequiredGas() ciphertext failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return 0 } - if lhs.fheUintType() != rhs.fheUintType() { - logger.Error("fheMul RequiredGas() operand type mismatch", "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + if lhs.Type() != rhs.Type() { + logger.Error("fheMul RequiredGas() operand type mismatch", "lhs", lhs.Type(), "rhs", rhs.Type()) return 0 } - return environment.FhevmParams().GasCosts.FheMul[lhs.fheUintType()] + return environment.FhevmParams().GasCosts.FheMul[lhs.Type()] } else { - lhs, _, err = getScalarOperands(environment, input) + lhs, _, loadGas, err = getScalarOperands(environment, input) if err != nil { - logger.Error("fheMul RequiredGas() scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheMul RequiredGas() scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return 0 } - return environment.FhevmParams().GasCosts.FheScalarMul[lhs.fheUintType()] + return environment.FhevmParams().GasCosts.FheScalarMul[lhs.Type()] + loadGas } } @@ -73,17 +79,18 @@ func fheDivRequiredGas(environment EVMEnvironment, input []byte) uint64 { logger.Error("fheDiv RequiredGas() cannot detect if operator is meant to be scalar", "err", err, "input", hex.EncodeToString(input)) return 0 } - var lhs *verifiedCiphertext + loadGas := uint64(0) + var lhs *tfhe.TfheCiphertext if !isScalar { logger.Error("fheDiv RequiredGas() only scalar in division is supported, two ciphertexts received", "input", hex.EncodeToString(input)) return 0 } else { - lhs, _, err = getScalarOperands(environment, input) + lhs, _, loadGas, err = getScalarOperands(environment, input) if err != nil { - logger.Error("fheDiv RequiredGas() scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheDiv RequiredGas() scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return 0 } - return environment.FhevmParams().GasCosts.FheScalarDiv[lhs.fheUintType()] + return environment.FhevmParams().GasCosts.FheScalarDiv[lhs.Type()] + loadGas } } @@ -96,16 +103,17 @@ func fheRemRequiredGas(environment EVMEnvironment, input []byte) uint64 { logger.Error("fheRem RequiredGas() cannot detect if operator is meant to be scalar", "err", err, "input", hex.EncodeToString(input)) return 0 } - var lhs *verifiedCiphertext + var lhs *tfhe.TfheCiphertext + loadGas := uint64(0) if !isScalar { logger.Error("fheRem RequiredGas() only scalar in division is supported, two ciphertexts received", "input", hex.EncodeToString(input)) return 0 } else { - lhs, _, err = getScalarOperands(environment, input) + lhs, _, loadGas, err = getScalarOperands(environment, input) if err != nil { - logger.Error("fheRem RequiredGas() scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheRem RequiredGas() scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return 0 } - return environment.FhevmParams().GasCosts.FheScalarRem[lhs.fheUintType()] + return environment.FhevmParams().GasCosts.FheScalarRem[lhs.Type()] + loadGas } } diff --git a/fhevm/operators_bit.go b/fhevm/operators_bit.go index cd77065..a21cf09 100644 --- a/fhevm/operators_bit.go +++ b/fhevm/operators_bit.go @@ -20,56 +20,56 @@ func fheShlRun(environment EVMEnvironment, caller common.Address, addr common.Ad } if !isScalar { - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheShl inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheShl failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheShl operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.Shl(rhs.ciphertext) + result, err := lhs.Shl(rhs) if err != nil { logger.Error("fheShl failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheShl success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheShl success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheShl scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheShl scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.ScalarShl(rhs) + result, err := lhs.ScalarShl(rhs) if err != nil { logger.Error("fheShl failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheShl scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheShl scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } @@ -86,61 +86,60 @@ func fheShrRun(environment EVMEnvironment, caller common.Address, addr common.Ad } if !isScalar { - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheShr inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheShr failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheShr operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.Shr(rhs.ciphertext) + result, err := lhs.Shr(rhs) if err != nil { logger.Error("fheShr failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheShr success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheShr success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheShr scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheShr scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.ScalarShr(rhs) + result, err := lhs.ScalarShr(rhs) if err != nil { logger.Error("fheShr failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheShr scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheShr scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } - func fheRotlRun(environment EVMEnvironment, caller common.Address, addr common.Address, input []byte, readOnly bool, runSpan trace.Span) ([]byte, error) { input = input[:minInt(65, len(input))] @@ -153,56 +152,56 @@ func fheRotlRun(environment EVMEnvironment, caller common.Address, addr common.A } if !isScalar { - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheShl inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheShl failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheShl operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.Rotl(rhs.ciphertext) + result, err := lhs.Rotl(rhs) if err != nil { logger.Error("fheRotl failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheRotl success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheRotl success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheRotl scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheRotl scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.ScalarRotl(rhs) + result, err := lhs.ScalarRotl(rhs) if err != nil { logger.Error("fheRotl failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheRotl scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheRotl scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } @@ -219,56 +218,56 @@ func fheRotrRun(environment EVMEnvironment, caller common.Address, addr common.A } if !isScalar { - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheRotr inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheRotr failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheRotr operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.Rotr(rhs.ciphertext) + result, err := lhs.Rotr(rhs) if err != nil { logger.Error("fheRotr failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheRotr success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheRotr success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheRotr scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheRotr scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.ScalarRotr(rhs) + result, err := lhs.ScalarRotr(rhs) if err != nil { logger.Error("fheRotr failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheRotr scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheRotr scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } @@ -285,28 +284,28 @@ func fheNegRun(environment EVMEnvironment, caller common.Address, addr common.Ad } - ct := getVerifiedCiphertext(environment, common.BytesToHash(input[0:32])) + ct, _ := loadCiphertext(environment, common.BytesToHash(input[0:32])) if ct == nil { - msg := "fheNeg input not verified" + msg := "fheNeg failed to load input" logger.Error(msg, msg, "input", hex.EncodeToString(input)) return nil, errors.New(msg) } - otelDescribeOperandsFheTypes(runSpan, ct.fheUintType()) + otelDescribeOperandsFheTypes(runSpan, ct.Type()) // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, ct.fheUintType()), nil + return insertRandomCiphertext(environment, ct.Type()), nil } - result, err := ct.ciphertext.Neg() + result, err := ct.Neg() if err != nil { logger.Error("fheNeg failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheNeg success", "ct", ct.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheNeg success", "ct", ct.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } @@ -322,28 +321,28 @@ func fheNotRun(environment EVMEnvironment, caller common.Address, addr common.Ad } - ct := getVerifiedCiphertext(environment, common.BytesToHash(input[0:32])) + ct, _ := loadCiphertext(environment, common.BytesToHash(input[0:32])) if ct == nil { - msg := "fheNot input not verified" + msg := "fheNot failed to load input" logger.Error(msg, msg, "input", hex.EncodeToString(input)) return nil, errors.New(msg) } - otelDescribeOperandsFheTypes(runSpan, ct.fheUintType()) + otelDescribeOperandsFheTypes(runSpan, ct.Type()) // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, ct.fheUintType()), nil + return insertRandomCiphertext(environment, ct.Type()), nil } - result, err := ct.ciphertext.Not() + result, err := ct.Not() if err != nil { logger.Error("fheNot failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheNot success", "ct", ct.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheNot success", "ct", ct.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } @@ -364,33 +363,33 @@ func fheBitAndRun(environment EVMEnvironment, caller common.Address, addr common return nil, errors.New(msg) } - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheBitAnd inputs not verified", "err", err) + logger.Error("fheBitAnd failed to load inputs", "err", err) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheBitAnd operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.Bitand(rhs.ciphertext) + result, err := lhs.Bitand(rhs) if err != nil { logger.Error("fheBitAnd failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheBitAnd success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheBitAnd success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } @@ -411,33 +410,33 @@ func fheBitOrRun(environment EVMEnvironment, caller common.Address, addr common. return nil, errors.New(msg) } - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheBitOr inputs not verified", "err", err) + logger.Error("fheBitOr failed to load inputs", "err", err) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheBitOr operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.Bitor(rhs.ciphertext) + result, err := lhs.Bitor(rhs) if err != nil { logger.Error("fheBitOr failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheBitOr success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheBitOr success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } @@ -458,32 +457,32 @@ func fheBitXorRun(environment EVMEnvironment, caller common.Address, addr common return nil, errors.New(msg) } - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheBitXor inputs not verified", "err", err) + logger.Error("fheBitXor failed to load inputs", "err", err) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheBitXor operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.Bitxor(rhs.ciphertext) + result, err := lhs.Bitxor(rhs) if err != nil { logger.Error("fheBitXor failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheBitXor success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheBitXor success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } diff --git a/fhevm/operators_bit_gas.go b/fhevm/operators_bit_gas.go index 60e10a5..d0dbb6c 100644 --- a/fhevm/operators_bit_gas.go +++ b/fhevm/operators_bit_gas.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "github.com/ethereum/go-ethereum/common" + "github.com/zama-ai/fhevm-go/fhevm/tfhe" ) func fheShlRequiredGas(environment EVMEnvironment, input []byte) uint64 { @@ -15,25 +16,26 @@ func fheShlRequiredGas(environment EVMEnvironment, input []byte) uint64 { logger.Error("fheShift RequiredGas() can not detect if operator is meant to be scalar", "err", err, "input", hex.EncodeToString(input)) return 0 } - var lhs, rhs *verifiedCiphertext + var lhs, rhs *tfhe.TfheCiphertext + loadGas := uint64(0) if !isScalar { - lhs, rhs, err = get2VerifiedOperands(environment, input) + lhs, rhs, loadGas, err = load2Ciphertexts(environment, input) if err != nil { - logger.Error("fheShift RequiredGas() ciphertext inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheShift RequiredGas() ciphertext failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return 0 } - if lhs.fheUintType() != rhs.fheUintType() { - logger.Error("fheShift RequiredGas() operand type mismatch", "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + if lhs.Type() != rhs.Type() { + logger.Error("fheShift RequiredGas() operand type mismatch", "lhs", lhs.Type(), "rhs", rhs.Type()) return 0 } - return environment.FhevmParams().GasCosts.FheShift[lhs.fheUintType()] + return environment.FhevmParams().GasCosts.FheShift[lhs.Type()] } else { - lhs, _, err = getScalarOperands(environment, input) + lhs, _, loadGas, err = getScalarOperands(environment, input) if err != nil { - logger.Error("fheShift RequiredGas() scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheShift RequiredGas() scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return 0 } - return environment.FhevmParams().GasCosts.FheScalarShift[lhs.fheUintType()] + return environment.FhevmParams().GasCosts.FheScalarShift[lhs.Type()] + loadGas } } @@ -60,12 +62,12 @@ func fheNegRequiredGas(environment EVMEnvironment, input []byte) uint64 { logger.Error("fheNeg input needs to contain one 256-bit sized value", "input", hex.EncodeToString(input)) return 0 } - ct := getVerifiedCiphertext(environment, common.BytesToHash(input[0:32])) + ct, loadGas := loadCiphertext(environment, common.BytesToHash(input[0:32])) if ct == nil { - logger.Error("fheNeg input not verified", "input", hex.EncodeToString(input)) + logger.Error("fheNeg failed to load input", "input", hex.EncodeToString(input)) return 0 } - return environment.FhevmParams().GasCosts.FheNeg[ct.fheUintType()] + return environment.FhevmParams().GasCosts.FheNeg[ct.Type()] + loadGas } func fheNotRequiredGas(environment EVMEnvironment, input []byte) uint64 { @@ -76,12 +78,12 @@ func fheNotRequiredGas(environment EVMEnvironment, input []byte) uint64 { logger.Error("fheNot input needs to contain one 256-bit sized value", "input", hex.EncodeToString(input)) return 0 } - ct := getVerifiedCiphertext(environment, common.BytesToHash(input[0:32])) + ct, loadGas := loadCiphertext(environment, common.BytesToHash(input[0:32])) if ct == nil { - logger.Error("fheNot input not verified", "input", hex.EncodeToString(input)) + logger.Error("fheNot failed to load input", "input", hex.EncodeToString(input)) return 0 } - return environment.FhevmParams().GasCosts.FheNot[ct.fheUintType()] + return environment.FhevmParams().GasCosts.FheNot[ct.Type()] + loadGas } func fheBitAndRequiredGas(environment EVMEnvironment, input []byte) uint64 { @@ -101,16 +103,16 @@ func fheBitAndRequiredGas(environment EVMEnvironment, input []byte) uint64 { return 0 } - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, loadGas, err := load2Ciphertexts(environment, input) if err != nil { - logger.Error("Bitwise op RequiredGas() inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("Bitwise op RequiredGas() failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return 0 } - if lhs.fheUintType() != rhs.fheUintType() { - logger.Error("Bitwise op RequiredGas() operand type mismatch", "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + if lhs.Type() != rhs.Type() { + logger.Error("Bitwise op RequiredGas() operand type mismatch", "lhs", lhs.Type(), "rhs", rhs.Type()) return 0 } - return environment.FhevmParams().GasCosts.FheBitwiseOp[lhs.fheUintType()] + return environment.FhevmParams().GasCosts.FheBitwiseOp[lhs.Type()] + loadGas } func fheBitOrRequiredGas(environment EVMEnvironment, input []byte) uint64 { diff --git a/fhevm/operators_comparison.go b/fhevm/operators_comparison.go index 6c68faa..b1bd12a 100644 --- a/fhevm/operators_comparison.go +++ b/fhevm/operators_comparison.go @@ -25,56 +25,56 @@ func fheLeRun(environment EVMEnvironment, caller common.Address, addr common.Add } if !isScalar { - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheLe inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheLe failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheLe operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, tfhe.FheBool), nil + return insertRandomCiphertext(environment, tfhe.FheBool), nil } - result, err := lhs.ciphertext.Le(rhs.ciphertext) + result, err := lhs.Le(rhs) if err != nil { logger.Error("fheLe failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheLe success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheLe success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheLe scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheLe scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, tfhe.FheBool), nil + return insertRandomCiphertext(environment, tfhe.FheBool), nil } - result, err := lhs.ciphertext.ScalarLe(rhs) + result, err := lhs.ScalarLe(rhs) if err != nil { logger.Error("fheLe failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheLe scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheLe scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } @@ -91,56 +91,56 @@ func fheLtRun(environment EVMEnvironment, caller common.Address, addr common.Add } if !isScalar { - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheLt inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheLt failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheLt operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, tfhe.FheBool), nil + return insertRandomCiphertext(environment, tfhe.FheBool), nil } - result, err := lhs.ciphertext.Lt(rhs.ciphertext) + result, err := lhs.Lt(rhs) if err != nil { logger.Error("fheLt failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheLt success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheLt success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheLt scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheLt scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, tfhe.FheBool), nil + return insertRandomCiphertext(environment, tfhe.FheBool), nil } - result, err := lhs.ciphertext.ScalarLt(rhs) + result, err := lhs.ScalarLt(rhs) if err != nil { logger.Error("fheLt failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheLt scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheLt scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } @@ -157,56 +157,56 @@ func fheEqRun(environment EVMEnvironment, caller common.Address, addr common.Add } if !isScalar { - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheEq inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheEq dailed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheEq operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, tfhe.FheBool), nil + return insertRandomCiphertext(environment, tfhe.FheBool), nil } - result, err := lhs.ciphertext.Eq(rhs.ciphertext) + result, err := lhs.Eq(rhs) if err != nil { logger.Error("fheEq failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheEq success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheEq success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheEq scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheEq scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, tfhe.FheBool), nil + return insertRandomCiphertext(environment, tfhe.FheBool), nil } - result, err := lhs.ciphertext.ScalarEq(rhs) + result, err := lhs.ScalarEq(rhs) if err != nil { logger.Error("fheEq failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheEq scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheEq scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } @@ -223,56 +223,56 @@ func fheGeRun(environment EVMEnvironment, caller common.Address, addr common.Add } if !isScalar { - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheGe inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheGe failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheGe operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, tfhe.FheBool), nil + return insertRandomCiphertext(environment, tfhe.FheBool), nil } - result, err := lhs.ciphertext.Ge(rhs.ciphertext) + result, err := lhs.Ge(rhs) if err != nil { logger.Error("fheGe failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheGe success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheGe success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheGe scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheGe scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, tfhe.FheBool), nil + return insertRandomCiphertext(environment, tfhe.FheBool), nil } - result, err := lhs.ciphertext.ScalarGe(rhs) + result, err := lhs.ScalarGe(rhs) if err != nil { logger.Error("fheGe failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheGe scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheGe scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } @@ -289,56 +289,56 @@ func fheGtRun(environment EVMEnvironment, caller common.Address, addr common.Add } if !isScalar { - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheGt inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheGt failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheGt operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, tfhe.FheBool), nil + return insertRandomCiphertext(environment, tfhe.FheBool), nil } - result, err := lhs.ciphertext.Gt(rhs.ciphertext) + result, err := lhs.Gt(rhs) if err != nil { logger.Error("fheGt failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheGt success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheGt success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheGt scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheGt scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, tfhe.FheBool), nil + return insertRandomCiphertext(environment, tfhe.FheBool), nil } - result, err := lhs.ciphertext.ScalarGt(rhs) + result, err := lhs.ScalarGt(rhs) if err != nil { logger.Error("fheGt failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheGt scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheGt scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } @@ -355,56 +355,56 @@ func fheNeRun(environment EVMEnvironment, caller common.Address, addr common.Add } if !isScalar { - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheNe inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheNe failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheNe operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, tfhe.FheBool), nil + return insertRandomCiphertext(environment, tfhe.FheBool), nil } - result, err := lhs.ciphertext.Ne(rhs.ciphertext) + result, err := lhs.Ne(rhs) if err != nil { logger.Error("fheNe failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheNe success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheNe success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheNe scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheNe scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, tfhe.FheBool), nil + return insertRandomCiphertext(environment, tfhe.FheBool), nil } - result, err := lhs.ciphertext.ScalarNe(rhs) + result, err := lhs.ScalarNe(rhs) if err != nil { logger.Error("fheNe failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheNe scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheNe scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } @@ -421,56 +421,56 @@ func fheMinRun(environment EVMEnvironment, caller common.Address, addr common.Ad } if !isScalar { - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheMin inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheMin failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheMin operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.Min(rhs.ciphertext) + result, err := lhs.Min(rhs) if err != nil { logger.Error("fheMin failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheMin success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheMin success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheMin scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheMin scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.ScalarMin(rhs) + result, err := lhs.ScalarMin(rhs) if err != nil { logger.Error("fheMin failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheMin scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheMin scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } @@ -487,56 +487,56 @@ func fheMaxRun(environment EVMEnvironment, caller common.Address, addr common.Ad } if !isScalar { - lhs, rhs, err := get2VerifiedOperands(environment, input) + lhs, rhs, _, err := load2Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), encryptedOperand(*rhs)) if err != nil { - logger.Error("fheMax inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheMax failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } - if lhs.fheUintType() != rhs.fheUintType() { + if lhs.Type() != rhs.Type() { msg := "fheMax operand type mismatch" - logger.Error(msg, "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + logger.Error(msg, "lhs", lhs.Type(), "rhs", rhs.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.Max(rhs.ciphertext) + result, err := lhs.Max(rhs) if err != nil { logger.Error("fheMax failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheMax success", "lhs", lhs.hash().Hex(), "rhs", rhs.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheMax success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } else { - lhs, rhs, err := getScalarOperands(environment, input) + lhs, rhs, _, err := getScalarOperands(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*lhs), plainOperand(*rhs)) if err != nil { - logger.Error("fheMax scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheMax scalar failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, lhs.fheUintType()), nil + return insertRandomCiphertext(environment, lhs.Type()), nil } - result, err := lhs.ciphertext.ScalarMax(rhs) + result, err := lhs.ScalarMax(rhs) if err != nil { logger.Error("fheMax failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheMax scalar success", "lhs", lhs.hash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) + logger.Info("fheMax scalar success", "lhs", lhs.GetHash().Hex(), "rhs", rhs.Uint64(), "result", resultHash.Hex()) return resultHash[:], nil } } @@ -545,33 +545,33 @@ func fheIfThenElseRun(environment EVMEnvironment, caller common.Address, addr co input = input[:minInt(96, len(input))] logger := environment.GetLogger() - first, second, third, err := get3VerifiedOperands(environment, input) + first, second, third, _, err := load3Ciphertexts(environment, input) otelDescribeOperands(runSpan, encryptedOperand(*first), encryptedOperand(*second), encryptedOperand(*third)) if err != nil { - logger.Error("fheIfThenElse inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheIfThenElse failed to load inputs", "err", err, "input", hex.EncodeToString(input)) return nil, err } - if second.fheUintType() != third.fheUintType() { + if second.Type() != third.Type() { msg := "fheIfThenElse operand type mismatch" - logger.Error(msg, "second", second.fheUintType(), "third", third.fheUintType()) + logger.Error(msg, "second", second.Type(), "third", third.Type()) return nil, errors.New(msg) } // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, second.fheUintType()), nil + return insertRandomCiphertext(environment, second.Type()), nil } - result, err := first.ciphertext.IfThenElse(second.ciphertext, third.ciphertext) + result, err := first.IfThenElse(second, third) if err != nil { logger.Error("fheIfThenElse failed", "err", err) return nil, err } - importCiphertext(environment, result) + insertCiphertextToMemory(environment, result) resultHash := result.GetHash() - logger.Info("fheIfThenElse success", "first", first.hash().Hex(), "second", second.hash().Hex(), "third", third.hash().Hex(), "result", resultHash.Hex()) + logger.Info("fheIfThenElse success", "first", first.GetHash().Hex(), "second", second.GetHash().Hex(), "third", third.GetHash().Hex(), "result", resultHash.Hex()) return resultHash[:], nil } diff --git a/fhevm/operators_comparison_gas.go b/fhevm/operators_comparison_gas.go index 7417509..4207cc2 100644 --- a/fhevm/operators_comparison_gas.go +++ b/fhevm/operators_comparison_gas.go @@ -16,25 +16,26 @@ func fheLeRequiredGas(environment EVMEnvironment, input []byte) uint64 { logger.Error("comparison RequiredGas() can not detect if operator is meant to be scalar", "err", err, "input", hex.EncodeToString(input)) return 0 } - var lhs, rhs *verifiedCiphertext + var lhs, rhs *tfhe.TfheCiphertext + loadGas := uint64(0) if !isScalar { - lhs, rhs, err = get2VerifiedOperands(environment, input) + lhs, rhs, loadGas, err = load2Ciphertexts(environment, input) if err != nil { - logger.Error("comparison RequiredGas() ciphertext inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("comparison RequiredGas() failed to load input ciphertexts", "err", err, "input", hex.EncodeToString(input)) return 0 } - if lhs.fheUintType() != rhs.fheUintType() { - logger.Error("comparison RequiredGas() operand type mismatch", "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + if lhs.Type() != rhs.Type() { + logger.Error("comparison RequiredGas() operand type mismatch", "lhs", lhs.Type(), "rhs", rhs.Type()) return 0 } } else { - lhs, _, err = getScalarOperands(environment, input) + lhs, _, loadGas, err = getScalarOperands(environment, input) if err != nil { - logger.Error("comparison RequiredGas() scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("comparison RequiredGas() scalar failed to load input ciphertexts", "err", err, "input", hex.EncodeToString(input)) return 0 } } - return environment.FhevmParams().GasCosts.FheLe[lhs.fheUintType()] + return environment.FhevmParams().GasCosts.FheLe[lhs.Type()] + loadGas } func fheLtRequiredGas(environment EVMEnvironment, input []byte) uint64 { @@ -51,25 +52,26 @@ func fheEqRequiredGas(environment EVMEnvironment, input []byte) uint64 { logger.Error("comparison RequiredGas() can not detect if operator is meant to be scalar", "err", err, "input", hex.EncodeToString(input)) return 0 } - var lhs, rhs *verifiedCiphertext + var lhs, rhs *tfhe.TfheCiphertext + loadGas := uint64(0) if !isScalar { - lhs, rhs, err = get2VerifiedOperands(environment, input) + lhs, rhs, loadGas, err = load2Ciphertexts(environment, input) if err != nil { - logger.Error("comparison RequiredGas() ciphertext inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("comparison RequiredGas() failed to load input ciphertexts", "err", err, "input", hex.EncodeToString(input)) return 0 } - if lhs.fheUintType() != rhs.fheUintType() { - logger.Error("comparison RequiredGas() operand type mismatch", "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + if lhs.Type() != rhs.Type() { + logger.Error("comparison RequiredGas() operand type mismatch", "lhs", lhs.Type(), "rhs", rhs.Type()) return 0 } } else { - lhs, _, err = getScalarOperands(environment, input) + lhs, _, loadGas, err = getScalarOperands(environment, input) if err != nil { - logger.Error("comparison RequiredGas() scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("comparison RequiredGas() scalar failed to load input ciphertexts", "err", err, "input", hex.EncodeToString(input)) return 0 } } - return environment.FhevmParams().GasCosts.FheEq[lhs.fheUintType()] + return environment.FhevmParams().GasCosts.FheEq[lhs.Type()] + loadGas } func fheGeRequiredGas(environment EVMEnvironment, input []byte) uint64 { @@ -96,25 +98,26 @@ func fheMinRequiredGas(environment EVMEnvironment, input []byte) uint64 { logger.Error("fheMin/Max RequiredGas() can not detect if operator is meant to be scalar", "err", err, "input", hex.EncodeToString(input)) return 0 } - var lhs, rhs *verifiedCiphertext + var lhs, rhs *tfhe.TfheCiphertext + loadGas := uint64(0) if !isScalar { - lhs, rhs, err = get2VerifiedOperands(environment, input) + lhs, rhs, loadGas, err = load2Ciphertexts(environment, input) if err != nil { - logger.Error("fheMin/Max RequiredGas() ciphertext inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheMin/Max RequiredGas() failed to load input ciphertexts", "err", err, "input", hex.EncodeToString(input)) return 0 } - if lhs.fheUintType() != rhs.fheUintType() { - logger.Error("fheMin/Max RequiredGas() operand type mismatch", "lhs", lhs.fheUintType(), "rhs", rhs.fheUintType()) + if lhs.Type() != rhs.Type() { + logger.Error("fheMin/Max RequiredGas() operand type mismatch", "lhs", lhs.Type(), "rhs", rhs.Type()) return 0 } - return environment.FhevmParams().GasCosts.FheMinMax[lhs.fheUintType()] + return environment.FhevmParams().GasCosts.FheMinMax[lhs.Type()] } else { - lhs, _, err = getScalarOperands(environment, input) + lhs, _, loadGas, err = getScalarOperands(environment, input) if err != nil { - logger.Error("fheMin/Max RequiredGas() scalar inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("fheMin/Max RequiredGas() scalar failed to load input ciphertexts", "err", err, "input", hex.EncodeToString(input)) return 0 } - return environment.FhevmParams().GasCosts.FheScalarMinMax[lhs.fheUintType()] + return environment.FhevmParams().GasCosts.FheScalarMinMax[lhs.Type()] + loadGas } } @@ -127,20 +130,20 @@ func fheIfThenElseRequiredGas(environment EVMEnvironment, input []byte) uint64 { input = input[:minInt(96, len(input))] logger := environment.GetLogger() - first, second, third, err := get3VerifiedOperands(environment, input) + first, second, third, loadGas, err := load3Ciphertexts(environment, input) if err != nil { - logger.Error("IfThenElse op RequiredGas() inputs not verified", "err", err, "input", hex.EncodeToString(input)) + logger.Error("IfThenElse op RequiredGas()failed to load input ciphertexts", "err", err, "input", hex.EncodeToString(input)) return 0 } - if first.fheUintType() != tfhe.FheBool { - logger.Error("IfThenElse op RequiredGas() invalid type for condition", "first", first.fheUintType()) + if first.Type() != tfhe.FheBool { + logger.Error("IfThenElse op RequiredGas() invalid type for condition", "first", first.Type()) return 0 } - if second.fheUintType() != third.fheUintType() { - logger.Error("IfThenElse op RequiredGas() operand type mismatch", "second", second.fheUintType(), "third", third.fheUintType()) + if second.Type() != third.Type() { + logger.Error("IfThenElse op RequiredGas() operand type mismatch", "second", second.Type(), "third", third.Type()) return 0 } - return environment.FhevmParams().GasCosts.FheIfThenElse[second.fheUintType()] + return environment.FhevmParams().GasCosts.FheIfThenElse[second.Type()] + loadGas } func fheArrayEqRequiredGas(environment EVMEnvironment, input []byte) uint64 { diff --git a/fhevm/operators_crypto.go b/fhevm/operators_crypto.go index 6e1e41f..1119bbf 100644 --- a/fhevm/operators_crypto.go +++ b/fhevm/operators_crypto.go @@ -60,7 +60,7 @@ func verifyCiphertextRun(environment EVMEnvironment, caller common.Address, addr // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, ctType), nil + return insertRandomCiphertext(environment, ctType), nil } ct := new(tfhe.TfheCiphertext) @@ -73,7 +73,7 @@ func verifyCiphertextRun(environment EVMEnvironment, caller common.Address, addr return nil, err } ctHash := ct.GetHash() - importCiphertext(environment, ct) + insertCiphertextToMemory(environment, ct) if environment.IsCommitting() { logger.Info("verifyCiphertext success", "ctHash", ctHash.Hex(), @@ -97,12 +97,13 @@ func reencryptRun(environment EVMEnvironment, caller common.Address, addr common logger.Error(msg, "input", hex.EncodeToString(input), "len", len(input)) return nil, errors.New(msg) } - ct := getVerifiedCiphertext(environment, common.BytesToHash(input[0:32])) + handle := common.BytesToHash(input[0:32]) + ct, _ := loadCiphertext(environment, handle) if ct != nil { - otelDescribeOperandsFheTypes(runSpan, ct.fheUintType()) + otelDescribeOperandsFheTypes(runSpan, ct.Type()) var fheType kms.FheType - switch ct.fheUintType() { + switch ct.Type() { case tfhe.FheBool: fheType = kms.FheType_Bool case tfhe.FheUint4: @@ -129,7 +130,7 @@ func reencryptRun(environment EVMEnvironment, caller common.Address, addr common reencryptionRequest := &kms.ReencryptionRequest{ FheType: fheType, - Ciphertext: ct.serialization(), + Ciphertext: ct.Serialize(), Request: pubKey, // TODO: change according to the structure of `Request` Proof: proof, } @@ -162,7 +163,7 @@ func reencryptRun(environment EVMEnvironment, caller common.Address, addr common outputBytes = append(outputBytes, reencryptedValue...) return padArrayTo32Multiple(outputBytes), nil } - msg := "reencrypt unverified ciphertext handle" + msg := "reencrypt could not load ciphertext handle" logger.Error(msg, "input", hex.EncodeToString(input)) return nil, errors.New(msg) } @@ -182,13 +183,13 @@ func decryptRun(environment EVMEnvironment, caller common.Address, addr common.A logger.Error(msg, "input", hex.EncodeToString(input), "len", len(input)) return nil, errors.New(msg) } - ct := getVerifiedCiphertext(environment, common.BytesToHash(input)) + ct, _ := loadCiphertext(environment, common.BytesToHash(input)) if ct == nil { msg := "decrypt unverified handle" logger.Error(msg, "input", hex.EncodeToString(input)) return nil, errors.New(msg) } - otelDescribeOperandsFheTypes(runSpan, ct.fheUintType()) + otelDescribeOperandsFheTypes(runSpan, ct.Type()) // If we are doing gas estimation, skip decryption and make sure we return the maximum possible value. // We need that, because non-zero bytes cost more than zero bytes in some contexts (e.g. SSTORE or memory operations). @@ -196,7 +197,7 @@ func decryptRun(environment EVMEnvironment, caller common.Address, addr common.A return bytes.Repeat([]byte{0xFF}, 32), nil } - plaintext, err := decryptValue(environment, ct.ciphertext) + plaintext, err := decryptValue(environment, ct) if err != nil { logger.Error("decrypt failed", "err", err) return nil, err @@ -225,15 +226,16 @@ func getCiphertextRun(environment EVMEnvironment, caller common.Address, addr co return nil, errors.New(msg) } - contractAddress := common.BytesToAddress(input[:32]) + // TODO + // contractAddress := common.BytesToAddress(input[:32]) handle := common.BytesToHash(input[32:]) - ciphertext := getCiphertextFromProtectedStoage(environment, contractAddress, handle) + ciphertext, _ := loadCiphertext(environment, handle) if ciphertext == nil { return make([]byte, 0), nil } - otelDescribeOperandsFheTypes(runSpan, ciphertext.metadata.fheUintType) - return ciphertext.bytes, nil + otelDescribeOperandsFheTypes(runSpan, ciphertext.FheUintType) + return ciphertext.Serialize(), nil } func decryptValue(environment EVMEnvironment, ct *tfhe.TfheCiphertext) (*big.Int, error) { @@ -307,7 +309,7 @@ func castRun(environment EVMEnvironment, caller common.Address, addr common.Addr return nil, errors.New(msg) } - ct := getVerifiedCiphertext(environment, common.BytesToHash(input[0:32])) + ct, _ := loadCiphertext(environment, common.BytesToHash(input[0:32])) if ct == nil { logger.Error("cast input not verified") return nil, errors.New("unverified ciphertext handle") @@ -319,14 +321,14 @@ func castRun(environment EVMEnvironment, caller common.Address, addr common.Addr } castToType := tfhe.FheUintType(input[32]) - otelDescribeOperandsFheTypes(runSpan, ct.fheUintType(), castToType) + otelDescribeOperandsFheTypes(runSpan, ct.Type(), castToType) // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() && !environment.IsEthCall() { - return importRandomCiphertext(environment, castToType), nil + return insertRandomCiphertext(environment, castToType), nil } - res, err := ct.ciphertext.CastTo(castToType) + res, err := ct.CastTo(castToType) if err != nil { msg := "cast Run() error casting ciphertext to" logger.Error(msg, "type", castToType) @@ -335,7 +337,7 @@ func castRun(environment EVMEnvironment, caller common.Address, addr common.Addr resHash := res.GetHash() - importCiphertext(environment, res) + insertCiphertextToMemory(environment, res) if environment.IsCommitting() { logger.Info("cast success", "ctHash", resHash.Hex(), @@ -390,7 +392,7 @@ func trivialEncryptRun(environment EVMEnvironment, caller common.Address, addr c ct := new(tfhe.TfheCiphertext).TrivialEncrypt(valueToEncrypt, encryptToType) ctHash := ct.GetHash() - importCiphertext(environment, ct) + insertCiphertextToMemory(environment, ct) if environment.IsCommitting() { logger.Info("trivialEncrypt success", "ctHash", ctHash.Hex(), diff --git a/fhevm/operators_crypto_gas.go b/fhevm/operators_crypto_gas.go index 71bab04..da24bdf 100644 --- a/fhevm/operators_crypto_gas.go +++ b/fhevm/operators_crypto_gas.go @@ -26,12 +26,12 @@ func reencryptRequiredGas(environment EVMEnvironment, input []byte) uint64 { logger.Error("reencrypt RequiredGas() input len must be 64 bytes", "input", hex.EncodeToString(input), "len", len(input)) return 0 } - ct := getVerifiedCiphertext(environment, common.BytesToHash(input[0:32])) + ct, loadGas := loadCiphertext(environment, common.BytesToHash(input[0:32])) if ct == nil { logger.Error("reencrypt RequiredGas() input doesn't point to verified ciphertext", "input", hex.EncodeToString(input)) return 0 } - return environment.FhevmParams().GasCosts.FheReencrypt[ct.fheUintType()] + return environment.FhevmParams().GasCosts.FheReencrypt[ct.Type()] + loadGas } func getCiphertextRequiredGas(environment EVMEnvironment, input []byte) uint64 { @@ -44,9 +44,10 @@ func getCiphertextRequiredGas(environment EVMEnvironment, input []byte) uint64 { return 0 } - contractAddress := common.BytesToAddress(input[:32]) + // TODO + // contractAddress := common.BytesToAddress(input[:32]) handle := common.BytesToHash(input[32:]) - metadata := getCiphertextMetadataFromProtectedStorage(environment, contractAddress, handle) + metadata := loadCiphertextMetadata(environment, handle) if metadata == nil { return GetNonExistentCiphertextGas } @@ -73,12 +74,12 @@ func decryptRequiredGas(environment EVMEnvironment, input []byte) uint64 { logger.Error("decrypt RequiredGas() input len must be 32 bytes", "input", hex.EncodeToString(input), "len", len(input)) return 0 } - ct := getVerifiedCiphertext(environment, common.BytesToHash(input)) + ct, loadGas := loadCiphertext(environment, common.BytesToHash(input)) if ct == nil { logger.Error("decrypt RequiredGas() input doesn't point to verified ciphertext", "input", hex.EncodeToString(input)) return 0 } - return environment.FhevmParams().GasCosts.FheDecrypt[ct.fheUintType()] + return environment.FhevmParams().GasCosts.FheDecrypt[ct.Type()] + loadGas } func fhePubKeyRequiredGas(environment EVMEnvironment, input []byte) uint64 { diff --git a/fhevm/operators_rand.go b/fhevm/operators_rand.go index 8252b94..1a22ce9 100644 --- a/fhevm/operators_rand.go +++ b/fhevm/operators_rand.go @@ -63,7 +63,7 @@ func applyUpperBound(rand uint64, bitsInRand int, upperBound *uint64) uint64 { func generateRandom(environment EVMEnvironment, caller common.Address, resultType tfhe.FheUintType, upperBound *uint64) ([]byte, error) { // If we are doing gas estimation, skip execution and insert a random ciphertext as a result. if !environment.IsCommitting() { - return importRandomCiphertext(environment, resultType), nil + return insertRandomCiphertext(environment, resultType), nil } // Get the RNG nonce. @@ -131,7 +131,7 @@ func generateRandom(environment EVMEnvironment, caller common.Address, resultTyp randBigInt := big.NewInt(0) randBigInt.SetUint64(randUint) randCt.TrivialEncrypt(*randBigInt, resultType) - importCiphertext(environment, randCt) + insertCiphertextToMemory(environment, randCt) if err != nil { return nil, err diff --git a/fhevm/otel.go b/fhevm/otel.go index 26e4104..85026ef 100644 --- a/fhevm/otel.go +++ b/fhevm/otel.go @@ -18,15 +18,14 @@ type operand interface { } type plainOperand big.Int -type encryptedOperand verifiedCiphertext +type encryptedOperand tfhe.TfheCiphertext func (plainOperand) typeName() string { return "plainScalar" } func (op encryptedOperand) typeName() string { - ct := verifiedCiphertext(op) - return ct.fheUintType().String() + return op.FheUintType.String() } func otelDescribeOperands(span trace.Span, operands ...operand) { diff --git a/fhevm/params.go b/fhevm/params.go index 02a5be0..eccf96c 100644 --- a/fhevm/params.go +++ b/fhevm/params.go @@ -55,8 +55,8 @@ type GasCosts struct { FheIfThenElse map[tfhe.FheUintType]uint64 FheVerify map[tfhe.FheUintType]uint64 FheGetCiphertext map[tfhe.FheUintType]uint64 - ProtectedStorageSstoreGas map[tfhe.FheUintType]uint64 - ProtectedStorageSloadGas map[tfhe.FheUintType]uint64 + FheStorageSstoreGas map[tfhe.FheUintType]uint64 + FheStorageSloadGas map[tfhe.FheUintType]uint64 } func DefaultGasCosts() GasCosts { @@ -220,7 +220,7 @@ func DefaultGasCosts() GasCosts { // TODO: The values here are chosen somewhat arbitrarily. // Also, we don't take into account whether a ciphertext existed (either "current" or "original") for the given handle. // Finally, costs are likely to change in the future. - ProtectedStorageSstoreGas: map[tfhe.FheUintType]uint64{ + FheStorageSstoreGas: map[tfhe.FheUintType]uint64{ tfhe.FheUint4: SstoreFheUint4Gas, tfhe.FheUint8: SstoreFheUint4Gas * 2, tfhe.FheUint16: SstoreFheUint4Gas * 4, @@ -229,7 +229,7 @@ func DefaultGasCosts() GasCosts { tfhe.FheUint128: SstoreFheUint4Gas * 32, tfhe.FheUint160: SstoreFheUint4Gas * 40, }, - ProtectedStorageSloadGas: map[tfhe.FheUintType]uint64{ + FheStorageSloadGas: map[tfhe.FheUintType]uint64{ tfhe.FheUint4: SloadFheUint4Gas, tfhe.FheUint8: SloadFheUint4Gas * 2, tfhe.FheUint16: SloadFheUint4Gas * 4, diff --git a/tfhe-rs b/tfhe-rs index 0d7a88e..46115eb 160000 --- a/tfhe-rs +++ b/tfhe-rs @@ -1 +1 @@ -Subproject commit 0d7a88e640a98612c0743d01062bb81d2a7e4a23 +Subproject commit 46115eb9616ddaba2ae30509853e99891c44348d