Skip to content

Commit

Permalink
feat: size-efficient list-based ciphertext inputs
Browse files Browse the repository at this point in the history
Add support for list-based ciphertext inputs. Two types are supported:
 * CompactFheUint160List
 * CompactFheUint2048List

No other input types are supported. Instead, the `fhevmjs` library
encodes any type other than the FheUint2048 type as FheUint160. In
fhevm-go during ciphertext verification, we cast it homomorphically to
the requested data type. FheUint2048 values are expanded as is, without
any casts.

The API of the verifyCiphertext precompile changes such that now it
accepts two inputs (through TFHE.asEuintXX() library function in
fhevm):
 * bytes32 Handle
 * serialized compact FHE list

Handle format changes and is no longer the hash of the expanded
ciphertext. Instead, input handles have the following format:
 * byte 0 to 28: first 29 bytes of
   keccak256(keccak256(serialized compact FHE list) || index)
 * byte 29: index in the serialized compact FHE list (0-indexed)
 * byte 30: type of the ciphertext
 * byte 31: version

Non-input handles have the following format:
* byte 0 to 29: first 30 bytes of keccak256(serialized compact FHE list)
 * byte 30: type of the ciphertext
 * byte 31: version

Above allows us to pack multiple inputs in one or more
CompactFheUint160Lists.

Add support for equality and non-equality of FheUint2048 values.

Cleanup should be done in a future commit in order to remove unused
code, duplication and to simplify the implementation and the tests,
especially around tfhe-rs handling.
  • Loading branch information
dartdart26 committed Jun 18, 2024
1 parent 8165b6d commit d22f070
Show file tree
Hide file tree
Showing 19 changed files with 1,236 additions and 403 deletions.
22 changes: 11 additions & 11 deletions fhevm/ciphertext_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func loadCiphertextMetadata(env EVMEnvironment, handle common.Hash) *ciphertextM
return newCiphertextMetadata(metadataInt.Bytes32())
}

// Returns the ciphertext for the given `handle and the gas needed to laod the ciphertext.
// 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) {
Expand Down Expand Up @@ -99,31 +99,31 @@ func loadCiphertext(env EVMEnvironment, handle common.Hash) (ct *tfhe.TfheCipher
return ct, env.FhevmParams().GasCosts.FheStorageSloadGas[ct.Type()]
}

func insertCiphertextToMemory(env EVMEnvironment, ct *tfhe.TfheCiphertext) {
env.FhevmData().loadedCiphertexts[ct.GetHash()] = ct
func insertCiphertextToMemory(env EVMEnvironment, handle common.Hash, ct *tfhe.TfheCiphertext) {
env.FhevmData().loadedCiphertexts[handle] = ct
}

// Persist the given ciphertext.
func persistCiphertext(env EVMEnvironment, ct *tfhe.TfheCiphertext) {
func persistCiphertext(env EVMEnvironment, handle common.Hash, ct *tfhe.TfheCiphertext) {
logger := env.GetLogger()
if isCiphertextPersisted(env, ct.GetHash()) {
if isCiphertextPersisted(env, handle) {
// 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())
logger.Info("ciphertext already persisted to storage", "handle", handle.Hex())
return
}

metadata := ciphertextMetadata{}
metadata.length = uint64(tfhe.ExpandedFheCiphertextSize[ct.FheUintType])
metadata.fheUintType = ct.FheUintType
metadata.length = uint64(tfhe.ExpandedFheCiphertextSize[ct.Type()])
metadata.fheUintType = ct.Type()

// Persist the metadata in storage.
env.SetState(ciphertextStorage, ct.GetHash(), metadata.serialize())
env.SetState(ciphertextStorage, handle, metadata.serialize())

ciphertextSlot := newInt(ct.GetHash().Bytes())
ciphertextSlot := newInt(handle.Bytes())
ciphertextSlot.AddUint64(ciphertextSlot, 1)
if env.IsCommitting() {
logger.Info("persisting new ciphertext",
"handle", hex.EncodeToString(ct.GetHash().Bytes()),
"handle", hex.EncodeToString(handle.Bytes()),
"type", metadata.fheUintType,
"len", metadata.length,
"ciphertextSlot", hex.EncodeToString(ciphertextSlot.Bytes()))
Expand Down
Loading

0 comments on commit d22f070

Please sign in to comment.