From 805bc134f05d99996afd80c20e3543ae5d98ee7a Mon Sep 17 00:00:00 2001 From: Petar Ivanov <29689712+dartdart26@users.noreply.github.com> Date: Wed, 19 Jun 2024 12:38:01 +0300 Subject: [PATCH] fix: missing gas costs and memory issues Add missing gas costs for multiple operations, mainly for FheBool, FheUint160 and FheUint2048. Note that verify for bool is more expensive due to lack of cast from 2048 bits to bool - doing not equal instead. Make `castTo()` fail and not panic on bad type input. Fixed a memory leak in `executeTernaryCiphertextOperation()` - the `first_ptr` pointer was never freed. Refactor some of the code such that it uses `defer` with destroy as close to the point where memory is allocated as possible - that fixes memory leaks on early returns in multiple places. C code needs to be refactored and reduced. Maybe we can use codegen or a tool for that. --- fhevm/contracts_test.go | 137 --------------- fhevm/fhelib.go | 12 -- fhevm/operators_crypto.go | 129 -------------- fhevm/operators_crypto_gas.go | 32 ---- fhevm/params.go | 108 ++++++------ fhevm/tfhe/tfhe_ciphertext.go | 315 +++++++++++++++++++--------------- 6 files changed, 223 insertions(+), 510 deletions(-) diff --git a/fhevm/contracts_test.go b/fhevm/contracts_test.go index a464e5c..49eeb14 100644 --- a/fhevm/contracts_test.go +++ b/fhevm/contracts_test.go @@ -3,8 +3,6 @@ package fhevm import ( "bytes" "context" - "encoding/hex" - "errors" "fmt" "math/big" "os" @@ -164,46 +162,6 @@ func toPrecompileInputNoScalar(isScalar bool, hashes ...common.Hash) []byte { return ret } -func decryptRunWithoutKms(environment EVMEnvironment, caller common.Address, addr common.Address, input []byte, readOnly bool) ([]byte, error) { - logger := environment.GetLogger() - // if not gas estimation and not view function fail if decryptions are disabled in transactions - if environment.IsCommitting() && !environment.IsEthCall() && environment.FhevmParams().DisableDecryptionsInTransaction { - msg := "decryptions during transaction are disabled" - logger.Error(msg, "input", hex.EncodeToString(input)) - return nil, errors.New(msg) - } - if len(input) != 32 { - msg := "decrypt input len must be 32 bytes" - logger.Error(msg, "input", hex.EncodeToString(input), "len", len(input)) - return nil, errors.New(msg) - } - 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) - } - - // 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). - if !environment.IsCommitting() && !environment.IsEthCall() { - return bytes.Repeat([]byte{0xFF}, 32), nil - } - - plaintext, err := ct.Decrypt() - if err != nil { - logger.Error("decrypt failed", "err", err) - return nil, err - } - - logger.Info("decrypt success", "plaintext", plaintext) - - // Always return a 32-byte big-endian integer. - ret := make([]byte, 32) - plaintext.FillBytes(ret) - return ret, nil -} - var scalarBytePadding = make([]byte, 31) func toLibPrecompileInput(method string, isScalar bool, hashes ...common.Hash) []byte { @@ -1943,31 +1901,6 @@ func LibDecrypt(t *testing.T, fheUintType tfhe.FheUintType) { } } -// TODO: can be enabled if mocking kms or running a kms during tests -// func TestLibReencrypt(t *testing.T) { -// signature := "reencrypt(uint256,uint256)" -// hashRes := crypto.Keccak256([]byte(signature)) -// signatureBytes := hashRes[0:4] -// depth := 1 -// environment := newTestEVMEnvironment() -// environment.depth = depth -// environment.ethCall = true -// toEncrypt := 7 -// fheUintType := tfhe.FheUint8 -// encCiphertext := loadCiphertextInTestMemory(environment, uint64(toEncrypt), depth, fheUintType).getHash() -// addr := tfheExecutorContractAddress -// readOnly := false -// input := make([]byte, 0) -// input = append(input, signatureBytes...) -// input = append(input, encCiphertext.Bytes()...) -// // just append twice not to generate public key -// input = append(input, encCiphertext.Bytes()...) -// _, err := FheLibRun(environment, addr, addr, input, readOnly) -// if err != nil { -// t.Fatalf("Reencrypt error: %s", err.Error()) -// } -// } - func TestLibCast(t *testing.T) { signature := "cast(uint256,bytes1)" hashRes := crypto.Keccak256([]byte(signature)) @@ -3122,41 +3055,6 @@ func FheIfThenElse(t *testing.T, fheUintType tfhe.FheUintType, condition uint64) } } -func Decrypt(t *testing.T, fheUintType tfhe.FheUintType) { - var value uint64 - switch fheUintType { - case tfhe.FheBool: - value = 1 - case tfhe.FheUint4: - value = 2 - case tfhe.FheUint8: - value = 2 - case tfhe.FheUint16: - value = 4283 - case tfhe.FheUint32: - value = 1333337 - case tfhe.FheUint64: - value = 133333777777777 - } - depth := 1 - environment := newTestEVMEnvironment() - environment.depth = depth - addr := tfheExecutorContractAddress - readOnly := false - hash := loadCiphertextInTestMemory(environment, value, depth, fheUintType).GetHash() - out, err := decryptRunWithoutKms(environment, addr, addr, hash.Bytes(), readOnly) - if err != nil { - t.Fatalf(err.Error()) - } else if len(out) != 32 { - t.Fatalf("decrypt expected output len of 32, got %v", len(out)) - } - result := big.Int{} - result.SetBytes(out) - if result.Uint64() != value { - t.Fatalf("decrypt result not equal to value, result %v != value %v", result.Uint64(), value) - } -} - func FheRand(t *testing.T, fheUintType tfhe.FheUintType) { depth := 1 environment := newTestEVMEnvironment() @@ -4677,22 +4575,6 @@ func TestFheScalarMax64(t *testing.T) { FheMax(t, tfhe.FheUint64, true) } -func TestDecrypt8(t *testing.T) { - Decrypt(t, tfhe.FheUint8) -} - -func TestDecrypt16(t *testing.T) { - Decrypt(t, tfhe.FheUint16) -} - -func TestDecrypt32(t *testing.T) { - Decrypt(t, tfhe.FheUint32) -} - -func TestDecrypt64(t *testing.T) { - Decrypt(t, tfhe.FheUint64) -} - func TestFheRand8(t *testing.T) { FheRand(t, tfhe.FheUint8) } @@ -4883,25 +4765,6 @@ func newInterpreterFromEnvironment(environment *MockEVMEnvironment) *vm.EVMInter return interpreter } -func TestDecryptInTransactionDisabled(t *testing.T) { - depth := 0 - environment := newTestEVMEnvironment() - environment.depth = depth - environment.commit = true - environment.ethCall = false - environment.fhevmParams.DisableDecryptionsInTransaction = true - addr := tfheExecutorContractAddress - readOnly := false - 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 { - t.Fatalf("expected to error out in test") - } else if err.Error() != "decryptions during transaction are disabled" { - t.Fatalf("unexpected error for disabling decryption transactions, got %s", err.Error()) - } -} - func TestFheLibGetCiphertextInvalidInputSize(t *testing.T) { environment := newTestEVMEnvironment() addr := tfheExecutorContractAddress diff --git a/fhevm/fhelib.go b/fhevm/fhelib.go index c31410f..0db2521 100644 --- a/fhevm/fhelib.go +++ b/fhevm/fhelib.go @@ -227,18 +227,6 @@ var fhelibMethods = []*FheLibMethod{ requiredGasFunction: trivialEncryptRequiredGas, runFunction: trivialEncryptRun, }, - { - name: "decrypt", - argTypes: "(uint256)", - requiredGasFunction: decryptRequiredGas, - runFunction: decryptRun, - }, - { - name: "reencrypt", - argTypes: "(uint256,uint256)", - requiredGasFunction: reencryptRequiredGas, - runFunction: reencryptRun, - }, { name: "verifyCiphertext", argTypes: "(bytes32,address,bytes,bytes1)", diff --git a/fhevm/operators_crypto.go b/fhevm/operators_crypto.go index c4dec87..4ce06b2 100644 --- a/fhevm/operators_crypto.go +++ b/fhevm/operators_crypto.go @@ -180,135 +180,6 @@ func verifyCiphertextRun(environment EVMEnvironment, caller common.Address, addr return handle[:], nil } -func reencryptRun(environment EVMEnvironment, caller common.Address, addr common.Address, input []byte, readOnly bool, runSpan trace.Span) ([]byte, error) { - input = input[:minInt(64, len(input))] - // precompileBytes, err := reencryptRun(environment, caller, addr, bwCompatBytes, readOnly) - - logger := environment.GetLogger() - if !environment.IsEthCall() { - msg := "reencrypt only supported on EthCall" - logger.Error(msg) - return nil, errors.New(msg) - } - if len(input) != 64 { - msg := "reencrypt input len must be 64 bytes" - logger.Error(msg, "input", hex.EncodeToString(input), "len", len(input)) - return nil, errors.New(msg) - } - handle := common.BytesToHash(input[0:32]) - ct, _ := loadCiphertext(environment, handle) - if ct != nil { - otelDescribeOperandsFheTypes(runSpan, ct.Type()) - - var fheType kms.FheType - switch ct.Type() { - case tfhe.FheBool: - fheType = kms.FheType_Bool - case tfhe.FheUint4: - fheType = kms.FheType_Euint4 - case tfhe.FheUint8: - fheType = kms.FheType_Euint8 - case tfhe.FheUint16: - fheType = kms.FheType_Euint16 - case tfhe.FheUint32: - fheType = kms.FheType_Euint32 - case tfhe.FheUint64: - fheType = kms.FheType_Euint64 - case tfhe.FheUint160: - fheType = kms.FheType_Euint160 - } - - pubKey := input[32:64] - - // TODO: generate merkle proof for some data - proof := &kms.Proof{ - Height: 3, - MerklePatriciaProof: []byte{}, - } - - reencryptionRequest := &kms.ReencryptionRequest{ - FheType: fheType, - Ciphertext: ct.Serialize(), - Request: pubKey, // TODO: change according to the structure of `Request` - Proof: proof, - } - - conn, err := grpc.Dial(kms.KmsEndpointAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - return nil, errors.New("kms unreachable") - } - defer conn.Close() - - ep := kms.NewKmsEndpointClient(conn) - - ctx, cancel := context.WithTimeout(context.Background(), time.Second) - defer cancel() - - res, err := ep.Reencrypt(ctx, reencryptionRequest) - if err != nil { - return nil, err - } - - // TODO: decide if `res.Signature` should be verified here - - var reencryptedValue = res.ReencryptedCiphertext - - logger.Info("reencrypt success", "input", hex.EncodeToString(input), "callerAddr", caller, "reencryptedValue", reencryptedValue, "len", len(reencryptedValue)) - reencryptedValue = toEVMBytes(reencryptedValue) - // pad according to abi specification, first add offset to the dynamic bytes argument - outputBytes := make([]byte, 32, len(reencryptedValue)+32) - outputBytes[31] = 0x20 - outputBytes = append(outputBytes, reencryptedValue...) - return padArrayTo32Multiple(outputBytes), nil - } - msg := "reencrypt could not load ciphertext handle" - logger.Error(msg, "input", hex.EncodeToString(input)) - return nil, errors.New(msg) -} - -func decryptRun(environment EVMEnvironment, caller common.Address, addr common.Address, input []byte, readOnly bool, runSpan trace.Span) ([]byte, error) { - input = input[:minInt(32, len(input))] - - logger := environment.GetLogger() - // if not gas estimation and not view function fail if decryptions are disabled in transactions - if environment.IsCommitting() && !environment.IsEthCall() && environment.FhevmParams().DisableDecryptionsInTransaction { - msg := "decryptions during transaction are disabled" - logger.Error(msg, "input", hex.EncodeToString(input)) - return nil, errors.New(msg) - } - if len(input) != 32 { - msg := "decrypt input len must be 32 bytes" - logger.Error(msg, "input", hex.EncodeToString(input), "len", len(input)) - return nil, errors.New(msg) - } - 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.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). - if !environment.IsCommitting() && !environment.IsEthCall() { - return bytes.Repeat([]byte{0xFF}, 32), nil - } - - plaintext, err := decryptValue(environment, ct) - if err != nil { - logger.Error("decrypt failed", "err", err) - return nil, err - } - - logger.Info("decrypt success", "plaintext", plaintext) - - // Always return a 32-byte big-endian integer. - ret := make([]byte, 32) - plaintext.FillBytes(ret) - return ret, nil -} - func getCiphertextRun(environment EVMEnvironment, caller common.Address, addr common.Address, input []byte, readOnly bool, runSpan trace.Span) ([]byte, error) { input = input[:minInt(32, len(input))] diff --git a/fhevm/operators_crypto_gas.go b/fhevm/operators_crypto_gas.go index 3a73700..ad15b34 100644 --- a/fhevm/operators_crypto_gas.go +++ b/fhevm/operators_crypto_gas.go @@ -18,22 +18,6 @@ func verifyCiphertextRequiredGas(environment EVMEnvironment, input []byte) uint6 return environment.FhevmParams().GasCosts.FheVerify[ct.Type()] } -func reencryptRequiredGas(environment EVMEnvironment, input []byte) uint64 { - input = input[:minInt(64, len(input))] - - logger := environment.GetLogger() - if len(input) != 64 { - logger.Error("reencrypt RequiredGas() input len must be 64 bytes", "input", hex.EncodeToString(input), "len", len(input)) - return 0 - } - 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 loadGas - } - return environment.FhevmParams().GasCosts.FheReencrypt[ct.Type()] + loadGas -} - func getCiphertextRequiredGas(environment EVMEnvironment, input []byte) uint64 { input = input[:minInt(32, len(input))] @@ -71,22 +55,6 @@ func castRequiredGas(environment EVMEnvironment, input []byte) uint64 { return environment.FhevmParams().GasCosts.FheCast + loadGas } -func decryptRequiredGas(environment EVMEnvironment, input []byte) uint64 { - input = input[:minInt(32, len(input))] - - logger := environment.GetLogger() - if len(input) != 32 { - logger.Error("decrypt RequiredGas() input len must be 32 bytes", "input", hex.EncodeToString(input), "len", len(input)) - return 0 - } - 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 loadGas - } - return environment.FhevmParams().GasCosts.FheDecrypt[ct.Type()] + loadGas -} - func fhePubKeyRequiredGas(environment EVMEnvironment, input []byte) uint64 { return environment.FhevmParams().GasCosts.FhePubKey } diff --git a/fhevm/params.go b/fhevm/params.go index 3ba5588..da772e6 100644 --- a/fhevm/params.go +++ b/fhevm/params.go @@ -22,21 +22,18 @@ const SloadFheUint4Gas = ColdSloadCostEIP2929 + 100 func DefaultFhevmParams() FhevmParams { return FhevmParams{ - GasCosts: DefaultGasCosts(), - DisableDecryptionsInTransaction: false, + GasCosts: DefaultGasCosts(), } } type FhevmParams struct { - GasCosts GasCosts - DisableDecryptionsInTransaction bool + GasCosts GasCosts } type GasCosts struct { FheCast uint64 FhePubKey uint64 FheAddSub map[tfhe.FheUintType]uint64 - FheDecrypt map[tfhe.FheUintType]uint64 FheBitwiseOp map[tfhe.FheUintType]uint64 FheMul map[tfhe.FheUintType]uint64 FheScalarMul map[tfhe.FheUintType]uint64 @@ -51,7 +48,6 @@ type GasCosts struct { FheScalarMinMax map[tfhe.FheUintType]uint64 FheNot map[tfhe.FheUintType]uint64 FheNeg map[tfhe.FheUintType]uint64 - FheReencrypt map[tfhe.FheUintType]uint64 FheTrivialEncrypt map[tfhe.FheUintType]uint64 FheRand map[tfhe.FheUintType]uint64 FheIfThenElse map[tfhe.FheUintType]uint64 @@ -72,13 +68,6 @@ func DefaultGasCosts() GasCosts { tfhe.FheUint32: 152000 + AdjustFHEGas, tfhe.FheUint64: 178000 + AdjustFHEGas, }, - FheDecrypt: map[tfhe.FheUintType]uint64{ - tfhe.FheUint4: 500000, - tfhe.FheUint8: 500000, - tfhe.FheUint16: 500000, - tfhe.FheUint32: 500000, - tfhe.FheUint64: 500000, - }, FheBitwiseOp: map[tfhe.FheUintType]uint64{ tfhe.FheBool: 16000 + AdjustFHEGas, tfhe.FheUint4: 22000 + AdjustFHEGas, @@ -130,12 +119,13 @@ func DefaultGasCosts() GasCosts { tfhe.FheUint64: 28000 + AdjustFHEGas, }, FheEq: map[tfhe.FheUintType]uint64{ - tfhe.FheUint4: 41000 + AdjustFHEGas, - tfhe.FheUint8: 43000 + AdjustFHEGas, - tfhe.FheUint16: 44000 + AdjustFHEGas, - tfhe.FheUint32: 72000 + AdjustFHEGas, - tfhe.FheUint64: 76000 + AdjustFHEGas, - tfhe.FheUint160: 80000 + AdjustFHEGas, + tfhe.FheUint4: 41000 + AdjustFHEGas, + tfhe.FheUint8: 43000 + AdjustFHEGas, + tfhe.FheUint16: 44000 + AdjustFHEGas, + tfhe.FheUint32: 72000 + AdjustFHEGas, + tfhe.FheUint64: 76000 + AdjustFHEGas, + tfhe.FheUint160: 80000 + AdjustFHEGas, + tfhe.FheUint2048: 160000 + AdjustFHEGas, }, FheArrayEqBigArrayFactor: 1000, FheLe: map[tfhe.FheUintType]uint64{ @@ -160,6 +150,7 @@ func DefaultGasCosts() GasCosts { tfhe.FheUint64: 182000 + AdjustFHEGas, }, FheNot: map[tfhe.FheUintType]uint64{ + tfhe.FheBool: 22000 + AdjustFHEGas, tfhe.FheUint4: 23000 + AdjustFHEGas, tfhe.FheUint8: 24000 + AdjustFHEGas, tfhe.FheUint16: 25000 + AdjustFHEGas, @@ -173,30 +164,26 @@ func DefaultGasCosts() GasCosts { tfhe.FheUint32: 150000 + AdjustFHEGas, tfhe.FheUint64: 189000 + AdjustFHEGas, }, - // TODO: Costs will depend on the complexity of doing reencryption/decryption by the oracle. - FheReencrypt: map[tfhe.FheUintType]uint64{ - tfhe.FheBool: 1000, - tfhe.FheUint4: 1000, - tfhe.FheUint8: 1000, - tfhe.FheUint16: 1100, - tfhe.FheUint32: 1200, - }, // As of now, verification costs only cover ciphertext deserialization and assume there is no ZKPoK to verify. FheVerify: map[tfhe.FheUintType]uint64{ - tfhe.FheBool: 200, - tfhe.FheUint4: 200, - tfhe.FheUint8: 200, - tfhe.FheUint16: 300, - tfhe.FheUint32: 400, - tfhe.FheUint64: 800, + tfhe.FheBool: 200 + 5000, // TODO: Requires an FheUint160 comparisson via FheEq. Make it cheaper than that, though. Need to fix that. + tfhe.FheUint4: 200 + 500, + tfhe.FheUint8: 200 + 500, + tfhe.FheUint16: 300 + 500, + tfhe.FheUint32: 400 + 500, + tfhe.FheUint64: 800 + 500, + tfhe.FheUint160: 1200 + 500, + tfhe.FheUint2048: 2000 + 500, }, FheTrivialEncrypt: map[tfhe.FheUintType]uint64{ - tfhe.FheBool: 100, - tfhe.FheUint4: 100, - tfhe.FheUint8: 100, - tfhe.FheUint16: 200, - tfhe.FheUint32: 300, - tfhe.FheUint64: 600, + tfhe.FheBool: 100, + tfhe.FheUint4: 100, + tfhe.FheUint8: 100, + tfhe.FheUint16: 200, + tfhe.FheUint32: 300, + tfhe.FheUint64: 600, + tfhe.FheUint160: 700, + tfhe.FheUint2048: 900, }, // TODO: These will change once we have an FHE-based random generaration. FheRand: map[tfhe.FheUintType]uint64{ @@ -214,31 +201,38 @@ func DefaultGasCosts() GasCosts { tfhe.FheUint64: 43000 + AdjustFHEGas, }, FheGetCiphertext: map[tfhe.FheUintType]uint64{ - tfhe.FheUint8: 12000, - tfhe.FheUint16: 14000, - tfhe.FheUint32: 18000, - tfhe.FheUint64: 28000, + tfhe.FheBool: 10000, + tfhe.FheUint8: 12000, + tfhe.FheUint16: 14000, + tfhe.FheUint32: 18000, + tfhe.FheUint64: 28000, + tfhe.FheUint160: 50000, + tfhe.FheUint2048: 100000, }, // 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. FheStorageSstoreGas: map[tfhe.FheUintType]uint64{ - tfhe.FheUint4: SstoreFheUint4Gas, - tfhe.FheUint8: SstoreFheUint4Gas * 2, - tfhe.FheUint16: SstoreFheUint4Gas * 4, - tfhe.FheUint32: SstoreFheUint4Gas * 8, - tfhe.FheUint64: SstoreFheUint4Gas * 16, - tfhe.FheUint128: SstoreFheUint4Gas * 32, - tfhe.FheUint160: SstoreFheUint4Gas * 40, + tfhe.FheBool: SstoreFheUint4Gas / 2, + tfhe.FheUint4: SstoreFheUint4Gas, + tfhe.FheUint8: SstoreFheUint4Gas * 2, + tfhe.FheUint16: SstoreFheUint4Gas * 4, + tfhe.FheUint32: SstoreFheUint4Gas * 8, + tfhe.FheUint64: SstoreFheUint4Gas * 16, + tfhe.FheUint128: SstoreFheUint4Gas * 32, + tfhe.FheUint160: SstoreFheUint4Gas * 40, + tfhe.FheUint2048: SstoreFheUint4Gas * 120, }, FheStorageSloadGas: map[tfhe.FheUintType]uint64{ - tfhe.FheUint4: SloadFheUint4Gas, - tfhe.FheUint8: SloadFheUint4Gas * 2, - tfhe.FheUint16: SloadFheUint4Gas * 4, - tfhe.FheUint32: SloadFheUint4Gas * 8, - tfhe.FheUint64: SloadFheUint4Gas * 16, - tfhe.FheUint128: SloadFheUint4Gas * 32, - tfhe.FheUint160: SloadFheUint4Gas * 40, + tfhe.FheBool: SloadFheUint4Gas / 2, + tfhe.FheUint4: SloadFheUint4Gas, + tfhe.FheUint8: SloadFheUint4Gas * 2, + tfhe.FheUint16: SloadFheUint4Gas * 4, + tfhe.FheUint32: SloadFheUint4Gas * 8, + tfhe.FheUint64: SloadFheUint4Gas * 16, + tfhe.FheUint128: SloadFheUint4Gas * 32, + tfhe.FheUint160: SloadFheUint4Gas * 40, + tfhe.FheUint2048: SloadFheUint4Gas * 120, // TODO: technically, it is more than 10 times bigger than 160 bits }, } } diff --git a/fhevm/tfhe/tfhe_ciphertext.go b/fhevm/tfhe/tfhe_ciphertext.go index f7e1eee..c49c9f5 100644 --- a/fhevm/tfhe/tfhe_ciphertext.go +++ b/fhevm/tfhe/tfhe_ciphertext.go @@ -477,20 +477,20 @@ func (ct *TfheCiphertext) executeUnaryCiphertextOperation(rhs *TfheCiphertext, case FheBool: ct_ptr := C.deserialize_fhe_bool(toDynamicBufferView((ct.Serialization))) if ct_ptr == nil { - return nil, errors.New("Bool unary op deserialization failed") + return nil, errors.New("bool unary op deserialization failed") } + defer C.destroy_fhe_bool(ct_ptr) res_ptr, err := opBool(ct_ptr) + defer C.destroy_fhe_bool(res_ptr) if err != nil { return nil, err } - C.destroy_fhe_bool(ct_ptr) if res_ptr == nil { - return nil, errors.New("Bool unary op failed") + return nil, errors.New("bool unary op failed") } ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { - return nil, errors.New("Bool unary op serialization failed") + return nil, errors.New("bool unary op serialization failed") } res.Serialization = C.GoBytes(unsafe.Pointer(res_ser.pointer), C.int(res_ser.length)) C.destroy_dynamic_buffer(res_ser) @@ -499,16 +499,16 @@ func (ct *TfheCiphertext) executeUnaryCiphertextOperation(rhs *TfheCiphertext, if ct_ptr == nil { return nil, errors.New("8 bit unary op deserialization failed") } + defer C.destroy_fhe_uint4(ct_ptr) res_ptr, err := op4(ct_ptr) + defer C.destroy_fhe_uint4(res_ptr) if err != nil { return nil, err } - C.destroy_fhe_uint4(ct_ptr) if res_ptr == nil { return nil, errors.New("8 bit unary op failed") } ret := C.serialize_fhe_uint4(res_ptr, res_ser) - C.destroy_fhe_uint4(res_ptr) if ret != 0 { return nil, errors.New("8 bit unary op serialization failed") } @@ -519,16 +519,16 @@ func (ct *TfheCiphertext) executeUnaryCiphertextOperation(rhs *TfheCiphertext, if ct_ptr == nil { return nil, errors.New("8 bit unary op deserialization failed") } + defer C.destroy_fhe_uint8(ct_ptr) res_ptr, err := op8(ct_ptr) + defer C.destroy_fhe_uint8(res_ptr) if err != nil { return nil, err } - C.destroy_fhe_uint8(ct_ptr) if res_ptr == nil { return nil, errors.New("8 bit unary op failed") } ret := C.serialize_fhe_uint8(res_ptr, res_ser) - C.destroy_fhe_uint8(res_ptr) if ret != 0 { return nil, errors.New("8 bit unary op serialization failed") } @@ -539,16 +539,16 @@ func (ct *TfheCiphertext) executeUnaryCiphertextOperation(rhs *TfheCiphertext, if ct_ptr == nil { return nil, errors.New("16 bit unary op deserialization failed") } + defer C.destroy_fhe_uint16(ct_ptr) res_ptr, err := op16(ct_ptr) + defer C.destroy_fhe_uint16(res_ptr) if err != nil { return nil, err } - C.destroy_fhe_uint16(ct_ptr) if res_ptr == nil { return nil, errors.New("16 bit op failed") } ret := C.serialize_fhe_uint16(res_ptr, res_ser) - C.destroy_fhe_uint16(res_ptr) if ret != 0 { return nil, errors.New("16 bit unary op serialization failed") } @@ -559,16 +559,16 @@ func (ct *TfheCiphertext) executeUnaryCiphertextOperation(rhs *TfheCiphertext, if ct_ptr == nil { return nil, errors.New("32 bit unary op deserialization failed") } + defer C.destroy_fhe_uint32(ct_ptr) res_ptr, err := op16(ct_ptr) + defer C.destroy_fhe_uint32(res_ptr) if err != nil { return nil, err } - C.destroy_fhe_uint32(ct_ptr) if res_ptr == nil { return nil, errors.New("32 bit op failed") } ret := C.serialize_fhe_uint32(res_ptr, res_ser) - C.destroy_fhe_uint32(res_ptr) if ret != 0 { return nil, errors.New("32 bit unary op serialization failed") } @@ -579,16 +579,16 @@ func (ct *TfheCiphertext) executeUnaryCiphertextOperation(rhs *TfheCiphertext, if ct_ptr == nil { return nil, errors.New("64 bit unary op deserialization failed") } + defer C.destroy_fhe_uint64(ct_ptr) res_ptr, err := op64(ct_ptr) + defer C.destroy_fhe_uint64(res_ptr) if err != nil { return nil, err } - C.destroy_fhe_uint64(ct_ptr) if res_ptr == nil { return nil, errors.New("64 bit op failed") } ret := C.serialize_fhe_uint64(res_ptr, res_ser) - C.destroy_fhe_uint64(res_ptr) if ret != 0 { return nil, errors.New("64 bit unary op serialization failed") } @@ -628,22 +628,21 @@ func (lhs *TfheCiphertext) executeBinaryCiphertextOperation(rhs *TfheCiphertext, if lhs_ptr == nil { return nil, errors.New("bool binary op deserialization failed") } + defer C.destroy_fhe_bool(lhs_ptr) rhs_ptr := C.deserialize_fhe_bool(toDynamicBufferView((rhs.Serialization))) if rhs_ptr == nil { - C.destroy_fhe_bool(lhs_ptr) return nil, errors.New("bool binary op deserialization failed") } + defer C.destroy_fhe_bool(rhs_ptr) res_ptr, err := opBool(lhs_ptr, rhs_ptr) + defer C.destroy_fhe_bool(res_ptr) if err != nil { return nil, err } - C.destroy_fhe_bool(lhs_ptr) - C.destroy_fhe_bool(rhs_ptr) if res_ptr == nil { return nil, errors.New("bool binary op failed") } ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { return nil, errors.New("bool binary op serialization failed") } @@ -654,29 +653,31 @@ func (lhs *TfheCiphertext) executeBinaryCiphertextOperation(rhs *TfheCiphertext, if lhs_ptr == nil { return nil, errors.New("4 bit binary op deserialization failed") } + defer C.destroy_fhe_uint4(lhs_ptr) rhs_ptr := C.deserialize_fhe_uint4(toDynamicBufferView((rhs.Serialization))) if rhs_ptr == nil { - C.destroy_fhe_uint4(lhs_ptr) return nil, errors.New("4 bit binary op deserialization failed") } + defer C.destroy_fhe_uint4(rhs_ptr) res_ptr, err := op4(lhs_ptr, rhs_ptr) + if returnBool { + defer C.destroy_fhe_bool(res_ptr) + } else { + defer C.destroy_fhe_uint4(res_ptr) + } if err != nil { return nil, err } - C.destroy_fhe_uint4(lhs_ptr) - C.destroy_fhe_uint4(rhs_ptr) if res_ptr == nil { return nil, errors.New("4 bit binary op failed") } if returnBool { ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { return nil, errors.New("bool binary op serialization failed") } } else { ret := C.serialize_fhe_uint4(res_ptr, res_ser) - C.destroy_fhe_uint4(res_ptr) if ret != 0 { return nil, errors.New("4 bit binary op serialization failed") } @@ -688,29 +689,31 @@ func (lhs *TfheCiphertext) executeBinaryCiphertextOperation(rhs *TfheCiphertext, if lhs_ptr == nil { return nil, errors.New("8 bit binary op deserialization failed") } + defer C.destroy_fhe_uint8(lhs_ptr) rhs_ptr := C.deserialize_fhe_uint8(toDynamicBufferView((rhs.Serialization))) if rhs_ptr == nil { - C.destroy_fhe_uint8(lhs_ptr) return nil, errors.New("8 bit binary op deserialization failed") } + defer C.destroy_fhe_uint8(rhs_ptr) res_ptr, err := op8(lhs_ptr, rhs_ptr) + if returnBool { + defer C.destroy_fhe_bool(res_ptr) + } else { + defer C.destroy_fhe_uint8(res_ptr) + } if err != nil { return nil, err } - C.destroy_fhe_uint8(lhs_ptr) - C.destroy_fhe_uint8(rhs_ptr) if res_ptr == nil { return nil, errors.New("8 bit binary op failed") } if returnBool { ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { return nil, errors.New("bool binary op serialization failed") } } else { ret := C.serialize_fhe_uint8(res_ptr, res_ser) - C.destroy_fhe_uint8(res_ptr) if ret != 0 { return nil, errors.New("8 bit binary op serialization failed") } @@ -722,29 +725,31 @@ func (lhs *TfheCiphertext) executeBinaryCiphertextOperation(rhs *TfheCiphertext, if lhs_ptr == nil { return nil, errors.New("16 bit binary op deserialization failed") } + defer C.destroy_fhe_uint16(lhs_ptr) rhs_ptr := C.deserialize_fhe_uint16(toDynamicBufferView((rhs.Serialization))) if rhs_ptr == nil { - C.destroy_fhe_uint16(lhs_ptr) return nil, errors.New("16 bit binary op deserialization failed") } + defer C.destroy_fhe_uint16(rhs_ptr) res_ptr, err := op16(lhs_ptr, rhs_ptr) + if returnBool { + defer C.destroy_fhe_bool(res_ptr) + } else { + defer C.destroy_fhe_uint16(res_ptr) + } if err != nil { return nil, err } - C.destroy_fhe_uint16(lhs_ptr) - C.destroy_fhe_uint16(rhs_ptr) if res_ptr == nil { return nil, errors.New("16 bit binary op failed") } if returnBool { ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { return nil, errors.New("bool binary op serialization failed") } } else { ret := C.serialize_fhe_uint16(res_ptr, res_ser) - C.destroy_fhe_uint16(res_ptr) if ret != 0 { return nil, errors.New("8 bit binary op serialization failed") } @@ -756,30 +761,32 @@ func (lhs *TfheCiphertext) executeBinaryCiphertextOperation(rhs *TfheCiphertext, if lhs_ptr == nil { return nil, errors.New("32 bit binary op deserialization failed") } + defer C.destroy_fhe_uint32(lhs_ptr) rhs_ptr := C.deserialize_fhe_uint32(toDynamicBufferView((rhs.Serialization))) if rhs_ptr == nil { - C.destroy_fhe_uint32(lhs_ptr) return nil, errors.New("32 bit binary op deserialization failed") } + defer C.destroy_fhe_uint32(rhs_ptr) res_ptr, err := op32(lhs_ptr, rhs_ptr) + if returnBool { + defer C.destroy_fhe_bool(res_ptr) + } else { + defer C.destroy_fhe_uint32(res_ptr) + } if err != nil { return nil, err } - C.destroy_fhe_uint32(lhs_ptr) - C.destroy_fhe_uint32(rhs_ptr) if res_ptr == nil { return nil, errors.New("32 bit binary op failed") } if returnBool { ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { return nil, errors.New("bool binary op serialization failed") } } else { ret := C.serialize_fhe_uint32(res_ptr, res_ser) - C.destroy_fhe_uint32(res_ptr) if ret != 0 { return nil, errors.New("32 bit binary op serialization failed") } @@ -791,29 +798,31 @@ func (lhs *TfheCiphertext) executeBinaryCiphertextOperation(rhs *TfheCiphertext, if lhs_ptr == nil { return nil, errors.New("64 bit binary op deserialization failed") } + defer C.destroy_fhe_uint64(lhs_ptr) rhs_ptr := C.deserialize_fhe_uint64(toDynamicBufferView((rhs.Serialization))) if rhs_ptr == nil { - C.destroy_fhe_uint64(lhs_ptr) return nil, errors.New("64 bit binary op deserialization failed") } + defer C.destroy_fhe_uint64(rhs_ptr) res_ptr, err := op64(lhs_ptr, rhs_ptr) + if returnBool { + defer C.destroy_fhe_bool(res_ptr) + } else { + defer C.destroy_fhe_uint64(res_ptr) + } if err != nil { return nil, err } - C.destroy_fhe_uint64(lhs_ptr) - C.destroy_fhe_uint64(rhs_ptr) if res_ptr == nil { return nil, errors.New("64 bit binary op failed") } if returnBool { ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { return nil, errors.New("bool binary op serialization failed") } } else { ret := C.serialize_fhe_uint64(res_ptr, res_ser) - C.destroy_fhe_uint64(res_ptr) if ret != 0 { return nil, errors.New("64 bit binary op serialization failed") } @@ -825,29 +834,31 @@ func (lhs *TfheCiphertext) executeBinaryCiphertextOperation(rhs *TfheCiphertext, if lhs_ptr == nil { return nil, errors.New("160 bit binary op deserialization failed") } + defer C.destroy_fhe_uint160(lhs_ptr) rhs_ptr := C.deserialize_fhe_uint160(toDynamicBufferView((rhs.Serialization))) if rhs_ptr == nil { - C.destroy_fhe_uint160(lhs_ptr) return nil, errors.New("160 bit binary op deserialization failed") } + defer C.destroy_fhe_uint160(rhs_ptr) res_ptr, err := op160(lhs_ptr, rhs_ptr) + if returnBool { + defer C.destroy_fhe_bool(res_ptr) + } else { + defer C.destroy_fhe_uint160(res_ptr) + } if err != nil { return nil, err } - C.destroy_fhe_uint160(lhs_ptr) - C.destroy_fhe_uint160(rhs_ptr) if res_ptr == nil { return nil, errors.New("160 bit binary op failed") } if returnBool { ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { return nil, errors.New("bool binary op serialization failed") } } else { ret := C.serialize_fhe_uint160(res_ptr, res_ser) - C.destroy_fhe_uint160(res_ptr) if ret != 0 { return nil, errors.New("160 bit binary op serialization failed") } @@ -859,29 +870,31 @@ func (lhs *TfheCiphertext) executeBinaryCiphertextOperation(rhs *TfheCiphertext, if lhs_ptr == nil { return nil, errors.New("2048 bit binary op deserialization failed") } + defer C.destroy_fhe_uint2048(lhs_ptr) rhs_ptr := C.deserialize_fhe_uint2048(toDynamicBufferView((rhs.Serialization))) if rhs_ptr == nil { - C.destroy_fhe_uint2048(lhs_ptr) return nil, errors.New("2048 bit binary op deserialization failed") } + defer C.destroy_fhe_uint2048(rhs_ptr) res_ptr, err := op2048(lhs_ptr, rhs_ptr) + if returnBool { + defer C.destroy_fhe_bool(res_ptr) + } else { + defer C.destroy_fhe_uint2048(res_ptr) + } if err != nil { return nil, err } - C.destroy_fhe_uint2048(lhs_ptr) - C.destroy_fhe_uint2048(rhs_ptr) if res_ptr == nil { return nil, errors.New("2048 bit binary op failed") } if returnBool { ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { return nil, errors.New("bool binary op serialization failed") } } else { ret := C.serialize_fhe_uint2048(res_ptr, res_ser) - C.destroy_fhe_uint2048(res_ptr) if ret != 0 { return nil, errors.New("2048 bit binary op serialization failed") } @@ -915,25 +928,23 @@ func (first *TfheCiphertext) executeTernaryCiphertextOperation(lhs *TfheCipherte if lhs_ptr == nil { return nil, errors.New("4 bit binary op deserialization failed") } + defer C.destroy_fhe_uint4(lhs_ptr) rhs_ptr := C.deserialize_fhe_uint4(toDynamicBufferView((rhs.Serialization))) if rhs_ptr == nil { - C.destroy_fhe_uint4(lhs_ptr) return nil, errors.New("4 bit binary op deserialization failed") } + defer C.destroy_fhe_uint4(rhs_ptr) first_ptr := C.deserialize_fhe_bool(toDynamicBufferView((first.Serialization))) if first_ptr == nil { - C.destroy_fhe_uint4(lhs_ptr) - C.destroy_fhe_uint4(rhs_ptr) - return nil, errors.New("Bool binary op deserialization failed") + return nil, errors.New("bool binary op deserialization failed") } + defer C.destroy_fhe_bool(first_ptr) res_ptr := op4(first_ptr, lhs_ptr, rhs_ptr) - C.destroy_fhe_uint4(lhs_ptr) - C.destroy_fhe_uint4(rhs_ptr) if res_ptr == nil { return nil, errors.New("4 bit binary op failed") } + defer C.destroy_fhe_uint4(res_ptr) ret := C.serialize_fhe_uint4(res_ptr, res_ser) - C.destroy_fhe_uint4(res_ptr) if ret != 0 { return nil, errors.New("4 bit binary op serialization failed") } @@ -944,25 +955,23 @@ func (first *TfheCiphertext) executeTernaryCiphertextOperation(lhs *TfheCipherte if lhs_ptr == nil { return nil, errors.New("8 bit binary op deserialization failed") } + defer C.destroy_fhe_uint8(lhs_ptr) rhs_ptr := C.deserialize_fhe_uint8(toDynamicBufferView((rhs.Serialization))) if rhs_ptr == nil { - C.destroy_fhe_uint8(lhs_ptr) return nil, errors.New("8 bit binary op deserialization failed") } + defer C.destroy_fhe_uint8(rhs_ptr) first_ptr := C.deserialize_fhe_bool(toDynamicBufferView((first.Serialization))) if first_ptr == nil { - C.destroy_fhe_uint8(lhs_ptr) - C.destroy_fhe_uint8(rhs_ptr) - return nil, errors.New("Bool binary op deserialization failed") + return nil, errors.New("bool binary op deserialization failed") } + defer C.destroy_fhe_bool(first_ptr) res_ptr := op8(first_ptr, lhs_ptr, rhs_ptr) - C.destroy_fhe_uint8(lhs_ptr) - C.destroy_fhe_uint8(rhs_ptr) if res_ptr == nil { return nil, errors.New("8 bit binary op failed") } + defer C.destroy_fhe_uint8(res_ptr) ret := C.serialize_fhe_uint8(res_ptr, res_ser) - C.destroy_fhe_uint8(res_ptr) if ret != 0 { return nil, errors.New("8 bit binary op serialization failed") } @@ -973,25 +982,23 @@ func (first *TfheCiphertext) executeTernaryCiphertextOperation(lhs *TfheCipherte if lhs_ptr == nil { return nil, errors.New("16 bit binary op deserialization failed") } + defer C.destroy_fhe_uint16(lhs_ptr) rhs_ptr := C.deserialize_fhe_uint16(toDynamicBufferView((rhs.Serialization))) if rhs_ptr == nil { - C.destroy_fhe_uint16(lhs_ptr) return nil, errors.New("16 bit binary op deserialization failed") } + defer C.destroy_fhe_uint16(rhs_ptr) first_ptr := C.deserialize_fhe_bool(toDynamicBufferView((first.Serialization))) if first_ptr == nil { - C.destroy_fhe_uint16(lhs_ptr) - C.destroy_fhe_uint16(rhs_ptr) - return nil, errors.New("Bool binary op deserialization failed") + return nil, errors.New("bool binary op deserialization failed") } + defer C.destroy_fhe_bool(first_ptr) res_ptr := op16(first_ptr, lhs_ptr, rhs_ptr) - C.destroy_fhe_uint16(lhs_ptr) - C.destroy_fhe_uint16(rhs_ptr) if res_ptr == nil { return nil, errors.New("16 bit binary op failed") } + defer C.destroy_fhe_uint16(res_ptr) ret := C.serialize_fhe_uint16(res_ptr, res_ser) - C.destroy_fhe_uint16(res_ptr) if ret != 0 { return nil, errors.New("16 bit binary op serialization failed") } @@ -1002,25 +1009,23 @@ func (first *TfheCiphertext) executeTernaryCiphertextOperation(lhs *TfheCipherte if lhs_ptr == nil { return nil, errors.New("32 bit binary op deserialization failed") } + defer C.destroy_fhe_uint32(lhs_ptr) rhs_ptr := C.deserialize_fhe_uint32(toDynamicBufferView((rhs.Serialization))) if rhs_ptr == nil { - C.destroy_fhe_uint32(lhs_ptr) return nil, errors.New("32 bit binary op deserialization failed") } + defer C.destroy_fhe_uint32(rhs_ptr) first_ptr := C.deserialize_fhe_bool(toDynamicBufferView((first.Serialization))) if first_ptr == nil { - C.destroy_fhe_uint32(lhs_ptr) - C.destroy_fhe_uint32(rhs_ptr) - return nil, errors.New("Bool binary op deserialization failed") + return nil, errors.New("bool binary op deserialization failed") } + defer C.destroy_fhe_bool(first_ptr) res_ptr := op32(first_ptr, lhs_ptr, rhs_ptr) - C.destroy_fhe_uint32(lhs_ptr) - C.destroy_fhe_uint32(rhs_ptr) if res_ptr == nil { return nil, errors.New("32 bit binary op failed") } + defer C.destroy_fhe_uint32(res_ptr) ret := C.serialize_fhe_uint32(res_ptr, res_ser) - C.destroy_fhe_uint32(res_ptr) if ret != 0 { return nil, errors.New("32 bit binary op serialization failed") } @@ -1031,25 +1036,23 @@ func (first *TfheCiphertext) executeTernaryCiphertextOperation(lhs *TfheCipherte if lhs_ptr == nil { return nil, errors.New("64 bit binary op deserialization failed") } + defer C.destroy_fhe_uint64(lhs_ptr) rhs_ptr := C.deserialize_fhe_uint64(toDynamicBufferView((rhs.Serialization))) if rhs_ptr == nil { - C.destroy_fhe_uint64(lhs_ptr) return nil, errors.New("64 bit binary op deserialization failed") } + defer C.destroy_fhe_uint64(rhs_ptr) first_ptr := C.deserialize_fhe_bool(toDynamicBufferView((first.Serialization))) if first_ptr == nil { - C.destroy_fhe_uint64(lhs_ptr) - C.destroy_fhe_uint64(rhs_ptr) - return nil, errors.New("Bool binary op deserialization failed") + return nil, errors.New("bool binary op deserialization failed") } + defer C.destroy_fhe_bool(first_ptr) res_ptr := op64(first_ptr, lhs_ptr, rhs_ptr) - C.destroy_fhe_uint64(lhs_ptr) - C.destroy_fhe_uint64(rhs_ptr) if res_ptr == nil { return nil, errors.New("64 bit binary op failed") } + defer C.destroy_fhe_uint64(res_ptr) ret := C.serialize_fhe_uint64(res_ptr, res_ser) - C.destroy_fhe_uint64(res_ptr) if ret != 0 { return nil, errors.New("64 bit binary op serialization failed") } @@ -1060,25 +1063,23 @@ func (first *TfheCiphertext) executeTernaryCiphertextOperation(lhs *TfheCipherte if lhs_ptr == nil { return nil, errors.New("160 bit binary op deserialization failed") } + defer C.destroy_fhe_uint160(lhs_ptr) rhs_ptr := C.deserialize_fhe_uint160(toDynamicBufferView((rhs.Serialization))) if rhs_ptr == nil { - C.destroy_fhe_uint160(lhs_ptr) return nil, errors.New("160 bit binary op deserialization failed") } + defer C.destroy_fhe_uint160(rhs_ptr) first_ptr := C.deserialize_fhe_bool(toDynamicBufferView((first.Serialization))) if first_ptr == nil { - C.destroy_fhe_uint160(lhs_ptr) - C.destroy_fhe_uint160(rhs_ptr) - return nil, errors.New("Bool binary op deserialization failed") + return nil, errors.New("bool binary op deserialization failed") } + defer C.destroy_fhe_bool(first_ptr) res_ptr := op160(first_ptr, lhs_ptr, rhs_ptr) - C.destroy_fhe_uint160(lhs_ptr) - C.destroy_fhe_uint160(rhs_ptr) if res_ptr == nil { return nil, errors.New("160 bit binary op failed") } + defer C.destroy_fhe_uint160(res_ptr) ret := C.serialize_fhe_uint160(res_ptr, res_ser) - C.destroy_fhe_uint160(res_ptr) if ret != 0 { return nil, errors.New("160 bit binary op serialization failed") } @@ -1114,21 +1115,21 @@ func (lhs *TfheCiphertext) executeBinaryScalarOperation(rhs *big.Int, case FheBool: lhs_ptr := C.deserialize_fhe_bool(toDynamicBufferView((lhs.Serialization))) if lhs_ptr == nil { - return nil, errors.New("Bool scalar op deserialization failed") + return nil, errors.New("bool scalar op deserialization failed") } + defer C.destroy_fhe_bool(lhs_ptr) scalar := C.bool(rhs_uint64 == 1) res_ptr, err := opBool(lhs_ptr, scalar) + defer C.destroy_fhe_bool(res_ptr) if err != nil { return nil, err } - C.destroy_fhe_bool(lhs_ptr) if res_ptr == nil { - return nil, errors.New("Bool scalar op failed") + return nil, errors.New("bool scalar op failed") } ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { - return nil, errors.New("Bool scalar op serialization failed") + return nil, errors.New("bool scalar op serialization failed") } res.Serialization = C.GoBytes(unsafe.Pointer(res_ser.pointer), C.int(res_ser.length)) C.destroy_dynamic_buffer(res_ser) @@ -1137,24 +1138,27 @@ func (lhs *TfheCiphertext) executeBinaryScalarOperation(rhs *big.Int, if lhs_ptr == nil { return nil, errors.New("4 bit scalar op deserialization failed") } + defer C.destroy_fhe_uint4(lhs_ptr) scalar := C.uint8_t(rhs_uint64) res_ptr, err := op4(lhs_ptr, scalar) + if returnBool { + defer C.destroy_fhe_bool(res_ptr) + } else { + defer C.destroy_fhe_uint4(res_ptr) + } if err != nil { return nil, err } - C.destroy_fhe_uint4(lhs_ptr) if res_ptr == nil { return nil, errors.New("4 bit scalar op failed") } if returnBool { ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { - return nil, errors.New("Bool scalar op serialization failed") + return nil, errors.New("bool scalar op serialization failed") } } else { ret := C.serialize_fhe_uint4(res_ptr, res_ser) - C.destroy_fhe_uint4(res_ptr) if ret != 0 { return nil, errors.New("4 bit scalar op serialization failed") } @@ -1166,24 +1170,27 @@ func (lhs *TfheCiphertext) executeBinaryScalarOperation(rhs *big.Int, if lhs_ptr == nil { return nil, errors.New("8 bit scalar op deserialization failed") } + defer C.destroy_fhe_uint8(lhs_ptr) scalar := C.uint8_t(rhs_uint64) res_ptr, err := op8(lhs_ptr, scalar) + if returnBool { + defer C.destroy_fhe_bool(res_ptr) + } else { + defer C.destroy_fhe_uint8(res_ptr) + } if err != nil { return nil, err } - C.destroy_fhe_uint8(lhs_ptr) if res_ptr == nil { return nil, errors.New("8 bit scalar op failed") } if returnBool { ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { - return nil, errors.New("Bool scalar op serialization failed") + return nil, errors.New("bool scalar op serialization failed") } } else { ret := C.serialize_fhe_uint8(res_ptr, res_ser) - C.destroy_fhe_uint8(res_ptr) if ret != 0 { return nil, errors.New("8 bit scalar op serialization failed") } @@ -1195,24 +1202,27 @@ func (lhs *TfheCiphertext) executeBinaryScalarOperation(rhs *big.Int, if lhs_ptr == nil { return nil, errors.New("16 bit scalar op deserialization failed") } + defer C.destroy_fhe_uint16(lhs_ptr) scalar := C.uint16_t(rhs_uint64) res_ptr, err := op16(lhs_ptr, scalar) + if returnBool { + defer C.destroy_fhe_bool(res_ptr) + } else { + defer C.destroy_fhe_uint16(res_ptr) + } if err != nil { return nil, err } - C.destroy_fhe_uint16(lhs_ptr) if res_ptr == nil { return nil, errors.New("16 bit scalar op failed") } if returnBool { ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { - return nil, errors.New("Bool scalar op serialization failed") + return nil, errors.New("bool scalar op serialization failed") } } else { ret := C.serialize_fhe_uint16(res_ptr, res_ser) - C.destroy_fhe_uint16(res_ptr) if ret != 0 { return nil, errors.New("16 bit scalar op serialization failed") } @@ -1224,24 +1234,27 @@ func (lhs *TfheCiphertext) executeBinaryScalarOperation(rhs *big.Int, if lhs_ptr == nil { return nil, errors.New("32 bit scalar op deserialization failed") } + defer C.destroy_fhe_uint32(lhs_ptr) scalar := C.uint32_t(rhs_uint64) res_ptr, err := op32(lhs_ptr, scalar) + if returnBool { + defer C.destroy_fhe_bool(res_ptr) + } else { + defer C.destroy_fhe_uint32(res_ptr) + } if err != nil { return nil, err } - C.destroy_fhe_uint32(lhs_ptr) if res_ptr == nil { return nil, errors.New("32 bit scalar op failed") } if returnBool { ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { - return nil, errors.New("Bool scalar op serialization failed") + return nil, errors.New("bool scalar op serialization failed") } } else { ret := C.serialize_fhe_uint32(res_ptr, res_ser) - C.destroy_fhe_uint32(res_ptr) if ret != 0 { return nil, errors.New("32 bit scalar op serialization failed") } @@ -1253,24 +1266,27 @@ func (lhs *TfheCiphertext) executeBinaryScalarOperation(rhs *big.Int, if lhs_ptr == nil { return nil, errors.New("64 bit scalar op deserialization failed") } + defer C.destroy_fhe_uint64(lhs_ptr) scalar := C.uint64_t(rhs_uint64) res_ptr, err := op64(lhs_ptr, scalar) + if returnBool { + defer C.destroy_fhe_bool(res_ptr) + } else { + defer C.destroy_fhe_uint64(res_ptr) + } if err != nil { return nil, err } - C.destroy_fhe_uint64(lhs_ptr) if res_ptr == nil { return nil, errors.New("64 bit scalar op failed") } if returnBool { ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { - return nil, errors.New("Bool scalar op serialization failed") + return nil, errors.New("bool scalar op serialization failed") } } else { ret := C.serialize_fhe_uint64(res_ptr, res_ser) - C.destroy_fhe_uint64(res_ptr) if ret != 0 { return nil, errors.New("64 bit scalar op serialization failed") } @@ -1282,26 +1298,33 @@ func (lhs *TfheCiphertext) executeBinaryScalarOperation(rhs *big.Int, if lhs_ptr == nil { return nil, errors.New("160 bit scalar op deserialization failed") } + defer C.destroy_fhe_uint160(lhs_ptr) scalar, err := bigIntToU256(rhs) + if err != nil { + return nil, err + } res_ptr, err := op160(lhs_ptr, *scalar) + if returnBool { + defer C.destroy_fhe_bool(res_ptr) + } else { + defer C.destroy_fhe_uint160(res_ptr) + } if err != nil { return nil, err } - C.destroy_fhe_uint160(lhs_ptr) + if res_ptr == nil { return nil, errors.New("160 bit scalar op failed") } if returnBool { ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { - return nil, errors.New("Bool scalar op serialization failed") + return nil, errors.New("bool scalar op serialization failed") } } else { ret := C.serialize_fhe_uint160(res_ptr, res_ser) - C.destroy_fhe_uint160(res_ptr) if ret != 0 { return nil, errors.New("160 bit scalar op serialization failed") } @@ -1313,33 +1336,39 @@ func (lhs *TfheCiphertext) executeBinaryScalarOperation(rhs *big.Int, if lhs_ptr == nil { return nil, errors.New("2048 bit scalar op deserialization failed") } + defer C.destroy_fhe_uint2048(lhs_ptr) scalar, err := bigIntToU2048(rhs) + if err != nil { + return nil, err + } res_ptr, err := op2048(lhs_ptr, *scalar) + if returnBool { + defer C.destroy_fhe_bool(res_ptr) + } else { + defer C.destroy_fhe_uint2048(res_ptr) + } if err != nil { return nil, err } - C.destroy_fhe_uint2048(lhs_ptr) + if res_ptr == nil { return nil, errors.New("2048 bit scalar op failed") } if returnBool { ret := C.serialize_fhe_bool(res_ptr, res_ser) - C.destroy_fhe_bool(res_ptr) if ret != 0 { return nil, errors.New("bool scalar op serialization failed") } } else { ret := C.serialize_fhe_uint2048(res_ptr, res_ser) - C.destroy_fhe_uint2048(res_ptr) if ret != 0 { return nil, errors.New("160 bit scalar op serialization failed") } } res.Serialization = C.GoBytes(unsafe.Pointer(res_ser.pointer), C.int(res_ser.length)) C.destroy_dynamic_buffer(res_ser) - default: panic("scalar op unexpected ciphertext type") } @@ -2283,7 +2312,7 @@ func (ct *TfheCiphertext) CastTo(castToType FheUintType) (*TfheCiphertext, error return nil, err } default: - panic("castTo: unexpected type to cast to") + return nil, fmt.Errorf("castTo: unexpected type to cast to") } case FheUint4: switch castToType { @@ -2352,7 +2381,7 @@ func (ct *TfheCiphertext) CastTo(castToType FheUintType) (*TfheCiphertext, error return nil, err } default: - panic("castTo: unexpected type to cast to") + return nil, fmt.Errorf("castTo: unexpected type to cast to") } case FheUint8: switch castToType { @@ -2421,7 +2450,7 @@ func (ct *TfheCiphertext) CastTo(castToType FheUintType) (*TfheCiphertext, error return nil, err } default: - panic("castTo: unexpected type to cast to") + return nil, fmt.Errorf("castTo: unexpected type to cast to") } case FheUint16: switch castToType { @@ -2490,7 +2519,7 @@ func (ct *TfheCiphertext) CastTo(castToType FheUintType) (*TfheCiphertext, error return nil, err } default: - panic("castTo: unexpected type to cast to") + return nil, fmt.Errorf("castTo: unexpected type to cast to") } case FheUint32: switch castToType { @@ -2559,7 +2588,7 @@ func (ct *TfheCiphertext) CastTo(castToType FheUintType) (*TfheCiphertext, error return nil, err } default: - panic("castTo: unexpected type to cast to") + return nil, fmt.Errorf("castTo: unexpected type to cast to") } case FheUint64: switch castToType { @@ -2628,12 +2657,12 @@ func (ct *TfheCiphertext) CastTo(castToType FheUintType) (*TfheCiphertext, error return nil, err } default: - panic("castTo: unexpected type to cast to") + return nil, fmt.Errorf("castTo: unexpected type to cast to") } case FheUint160: return castFheUint160To(ct, castToType) default: - panic("castTo: unexpected type to cast from") + return nil, fmt.Errorf("castTo: unexpected type to cast from") } res.computeHash() return res, nil @@ -2664,57 +2693,57 @@ func (ct *TfheCiphertext) Decrypt() (big.Int, error) { if ptr == nil { return *new(big.Int).SetUint64(0), errors.New("failed to deserialize FheUint4") } + defer C.destroy_fhe_uint4(ptr) var result C.uint8_t ret = C.decrypt_fhe_uint4(cks, ptr, &result) - C.destroy_fhe_uint4(ptr) value = uint64(result) case FheUint8: ptr := C.deserialize_fhe_uint8(toDynamicBufferView(ct.Serialization)) if ptr == nil { return *new(big.Int).SetUint64(0), errors.New("failed to deserialize FheUint8") } + defer C.destroy_fhe_uint8(ptr) var result C.uint8_t ret = C.decrypt_fhe_uint8(cks, ptr, &result) - C.destroy_fhe_uint8(ptr) value = uint64(result) case FheUint16: ptr := C.deserialize_fhe_uint16(toDynamicBufferView(ct.Serialization)) if ptr == nil { return *new(big.Int).SetUint64(0), errors.New("failed to deserialize FheUint16") } + defer C.destroy_fhe_uint16(ptr) var result C.uint16_t ret = C.decrypt_fhe_uint16(cks, ptr, &result) - C.destroy_fhe_uint16(ptr) value = uint64(result) case FheUint32: ptr := C.deserialize_fhe_uint32(toDynamicBufferView(ct.Serialization)) if ptr == nil { return *new(big.Int).SetUint64(0), errors.New("failed to deserialize FheUint32") } + defer C.destroy_fhe_uint32(ptr) var result C.uint32_t ret = C.decrypt_fhe_uint32(cks, ptr, &result) - C.destroy_fhe_uint32(ptr) value = uint64(result) case FheUint64: ptr := C.deserialize_fhe_uint64(toDynamicBufferView(ct.Serialization)) if ptr == nil { return *new(big.Int).SetUint64(0), errors.New("failed to deserialize FheUint64") } + defer C.destroy_fhe_uint64(ptr) var result C.uint64_t ret = C.decrypt_fhe_uint64(cks, ptr, &result) - C.destroy_fhe_uint64(ptr) value = uint64(result) case FheUint160: ptr := C.deserialize_fhe_uint160(toDynamicBufferView(ct.Serialization)) if ptr == nil { return *new(big.Int).SetUint64(0), errors.New("failed to deserialize FheUint160") } + defer C.destroy_fhe_uint160(ptr) var result C.U256 ret = C.decrypt_fhe_uint160(cks, ptr, &result) if ret != 0 { return *new(big.Int).SetUint64(0), errors.New("failed to decrypt FheUint160") } - C.destroy_fhe_uint160(ptr) resultBigInt := *u256ToBigInt(&result) return resultBigInt, nil case FheUint2048: @@ -2722,12 +2751,12 @@ func (ct *TfheCiphertext) Decrypt() (big.Int, error) { if ptr == nil { return *new(big.Int).SetUint64(0), errors.New("failed to deserialize FheUint2048") } + defer C.destroy_fhe_uint2048(ptr) var result C.U2048 ret = C.decrypt_fhe_uint2048(cks, ptr, &result) if ret != 0 { return *new(big.Int).SetUint64(0), errors.New("failed to decrypt FheUint160") } - C.destroy_fhe_uint2048(ptr) resultBigInt := *u2048ToBigInt(&result) return resultBigInt, nil default: