Skip to content
This repository has been archived by the owner on Dec 23, 2024. It is now read-only.

fix(gas): add utils for protected storage gas cost #110

Merged
merged 1 commit into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions fhevm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ func getVerifiedCiphertextFromEVM(environment EVMEnvironment, ciphertextHash com
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 {
Expand Down
10 changes: 0 additions & 10 deletions fhevm/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,3 @@ func (vc *verifiedCiphertext) serialization() []byte {
func (vc *verifiedCiphertext) hash() common.Hash {
return vc.ciphertext.GetHash()
}

type PrivilegedMemory struct {
// A map from a ciphertext hash to itself and stack depths at which it is verified
VerifiedCiphertexts map[common.Hash]*verifiedCiphertext
}

var PrivilegedMempory *PrivilegedMemory = &PrivilegedMemory{
make(map[common.Hash]*verifiedCiphertext),
}

96 changes: 55 additions & 41 deletions fhevm/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,10 @@ const ColdSloadCostEIP2929 uint64 = 2100

const GetNonExistentCiphertextGas uint64 = 1000

var (
// TODO: The values here are chosen somewhat arbitrarily (at least the 8 bit ones). 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.
FheUint8ProtectedStorageSstoreGas uint64 = EvmNetSstoreInitGas + 2000
FheUint16ProtectedStorageSstoreGas uint64 = FheUint8ProtectedStorageSstoreGas * 2
FheUint32ProtectedStorageSstoreGas uint64 = FheUint16ProtectedStorageSstoreGas * 2

// TODO: We don't take whether the slot is cold or warm into consideration.
FheUint8ProtectedStorageSloadGas uint64 = ColdSloadCostEIP2929 + 200
FheUint16ProtectedStorageSloadGas uint64 = FheUint8ProtectedStorageSloadGas * 2
FheUint32ProtectedStorageSloadGas uint64 = FheUint16ProtectedStorageSloadGas * 2
)
// Base costs of fhEVM SSTORE and SLOAD operations.
// TODO: We don't take whether the slot is cold or warm into consideration.
const SstoreFheUint4Gas = EvmNetSstoreInitGas + 1000
const SloadFheUint4Gas = ColdSloadCostEIP2929 + 100

func DefaultFhevmParams() FhevmParams {
return FhevmParams{
Expand All @@ -40,29 +31,31 @@ type FhevmParams struct {
}

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
FheScalarDiv map[tfhe.FheUintType]uint64
FheScalarRem map[tfhe.FheUintType]uint64
FheShift map[tfhe.FheUintType]uint64
FheScalarShift map[tfhe.FheUintType]uint64
FheEq map[tfhe.FheUintType]uint64
FheLe map[tfhe.FheUintType]uint64
FheMinMax map[tfhe.FheUintType]uint64
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
FheVerify map[tfhe.FheUintType]uint64
FheGetCiphertext map[tfhe.FheUintType]uint64
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
FheScalarDiv map[tfhe.FheUintType]uint64
FheScalarRem map[tfhe.FheUintType]uint64
FheShift map[tfhe.FheUintType]uint64
FheScalarShift map[tfhe.FheUintType]uint64
FheEq map[tfhe.FheUintType]uint64
FheLe map[tfhe.FheUintType]uint64
FheMinMax map[tfhe.FheUintType]uint64
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
FheVerify map[tfhe.FheUintType]uint64
FheGetCiphertext map[tfhe.FheUintType]uint64
ProtectedStorageSstoreGas map[tfhe.FheUintType]uint64
ProtectedStorageSloadGas map[tfhe.FheUintType]uint64
}

func DefaultGasCosts() GasCosts {
Expand Down Expand Up @@ -132,11 +125,11 @@ 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.FheUint4: 41000 + AdjustFHEGas,
tfhe.FheUint8: 43000 + AdjustFHEGas,
tfhe.FheUint16: 44000 + AdjustFHEGas,
tfhe.FheUint32: 72000 + AdjustFHEGas,
tfhe.FheUint64: 76000 + AdjustFHEGas,
tfhe.FheUint160: 80000 + AdjustFHEGas,
},
FheLe: map[tfhe.FheUintType]uint64{
Expand Down Expand Up @@ -220,6 +213,27 @@ func DefaultGasCosts() GasCosts {
tfhe.FheUint32: 18000,
tfhe.FheUint64: 28000,
},
// 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{
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,
},
ProtectedStorageSloadGas: 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,
},
}
}

Expand Down
10 changes: 10 additions & 0 deletions fhevm/protected_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ type ciphertextData struct {
bytes []byte
}

// Returns the type of the persisted ciphertext for `handle` in protected storage or nil if `handle`doesn't point to a persisted ciphertext.
func GetTypeOfPersistedCiphertext(env EVMEnvironment, contractAddress common.Address, handle common.Hash) *tfhe.FheUintType {
metadata := getCiphertextMetadataFromProtectedStorage(env, contractAddress, handle)
if metadata == nil {
return nil
}
t := metadata.fheUintType
return &t
}

func getCiphertextMetadataKey(handle common.Hash) common.Hash {
return crypto.Keccak256Hash(handle.Bytes())
}
Expand Down
Loading