Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nitrogen - updates #54

Merged
merged 12 commits into from
Nov 13, 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
7 changes: 6 additions & 1 deletion docs/devdocs/Fhenix Testnet/Details/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ Here you can find a list of changes between different versions of the Fhenix Tes

### Nitrogen

TBD
- Fixed casts between eaddress and different euints
- Introduced Security zones
- Introduced Threshold Network as default for security zone 0
- Introduced Parallel decryptions
- Introduced new precompiles for operations with encrypted uints: random, rotate right, rotate left, square
- General bug fixes and stability improvements

### Helium

Expand Down
6 changes: 0 additions & 6 deletions docs/devdocs/Fhenix Testnet/Details/Limitations.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ real sensitive data or private keys on the testnet.
The current iteration of the network does not include multiple components (such as input knowledge proofs, threshold decryption, execution proofs, etc.) that are critical for the security of data and network keys.
These features will be added iteratively as we move towards full release - this should be obvious, but please **do not store any valuable information on the network as long as it is in the testnet phase**.

## Randomness

Randomness as a service is planned as a future addition. Until we can guarantee a secure source of randomness, we do not
want to make such a function available as a network service. For demos and development that require a source of randomness, we encourage
the use of external oracles, or usage of a [mock random number generator](../../Writing%20Smart%20Contracts/Useful-Tips.md#randomness).

## Gas Costs

All gas costs are subject to change, and are being evaluated for optimization. The current gas costs are not final, and may change.
Expand Down
24 changes: 24 additions & 0 deletions docs/devdocs/Fhenix Testnet/Threshold-Network.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
sidebar_position: 5
title: 🔒 Treshold Network
---

In principle, a Threshold Network is a cryptographic system designed to enhance security and trust by distributing control and decision-making across multiple parties. In such a network, sensitive operations, such as decryption or signing, require collaboration among a subset of participants, rather than relying on a single entity.

## Concept

In Fhenix’s Nitrogen testnet, the Threshold Network performs decryption operations. The Threshold Network is currently initialized by a Trusted Dealer (in the future, we plan to eliminate the Trusted Dealer). The Trusted Dealer initially generates a key. Then, the Dealer uses Shamir's Secret Sharing cryptographic algorithm to generate Secret Shares of the key to share among individual members. Each member holds exactly one secret share. To perform a decryption, the secret shares are used to perform partial decryptions through a multiparty computation (MPC) protocol. These partial decryptions are then combined into the final plaintext. The protocol uses a T-out-f-N scheme, meaning that T parties out of a total of N existing parties need to agree and work together to perform a decryption. The benefit of this approach is that a single entity (Threshold Network “member”) cannot decrypt the ciphertext, since it is necessary to have a consensus in order to decrypt, which provides the end user with additional protection from malicious actors.

:::note[Note]
The Threshold Network in Nitrogen requires 3 out of 4 parties to decrypt ciphertexts.
:::


## Authentication

A Threshold Network authentication mechanism is important to differentiate between valid and invalid (or malicious) decryption requests. The authentication mechanism ensures that no party can decrypt data that is not supposed to be decrypted.
Authentication is currently under development and not yet included in this testnet. It will be added in future Fhenix versions.

## Threshold Network in Nitrogen

In Nitrogen, the Threshold Network is used by [Security Zone](../Writing%20Smart%20Contracts/Security-Zones.md) 0 (which is the default).
106 changes: 106 additions & 0 deletions docs/devdocs/Writing Smart Contracts/Parallel-Decryptions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
---
sidebar_position: 300
title: 🔀 Parallel Decryptions
---

In Fully Homomorphic Encryption (FHE) schemes, decryption can be slow and computationally expensive, especially when using a [Threshold Network](../Fhenix%20Testnet/Threshold-Network.md). Additionally, since a Threshold Network functions as a sort of network in itself and serves as an oracle for the main blockchain, it cannot perform decryption synchronously, since decryptions may take too long to be practical or the Threshold Network might be busy or unavailable.
To address this issue, Nitrogen introduces Parallel Decryptions. This feature performs asynchronous decryption while providing the experience of synchronous decryption. Instead of using callbacks, as in traditional oracle-based protocols, Fhenix allows developers to write code normally, without needing to be concerned that a decryption request is being sent to an external component.

### Better developer and user experience

This approach improves the whole experience in two key ways:
* Developers can write clean, cohesive code without worrying about asynchronous decryption.
* Users and dApps avoid the need for multiple transactions to handle decryption callbacks.


```solidity
euint32 encrypted;
uint32 decrypted;

function decryptInFhenix() public {
// Beginning of function logic ..

decrypted = FHE.decrypt(encrypted);

// Continue of function logic..
}

// -------- Otherwise.. --------
// (*simplified* example of callback-based decryption)

function requestDecrypt() public {
// Beginning of function logic ..
FHE.decryptWithCallback(encrypted);
}

// This function will be called after some time in a different TX
function receiveDecryptCallback(uint32 result) public {
decrypted = result;
// Continue of function logic..
}
```

As shown in the example above, Fhenix's parallel decryption approach allows for clean, straightforward code that reads like normal synchronous operations. Developers can write their business logic in a natural flow, with decryption seamlessly integrated into their functions. This makes the code more maintainable and easier to understand, while Fhenix handles all the complexity of asynchronous decryption behind the scenes.

### In depth

Behind the scenes, decryption requests are detected in transactions and sent to the appropriate decrypting party (whether Threshold Network or local decryptor). While these decryption requests are processed, the transactions are pushed to a special queue (a sort of tx-mempool). After all the decryption requests for a transaction are completed, the transaction is included in a block and executed.

:::note
Since Fhenix is an L2 solution with a sequencer, no traditional mempool is in place. As a result, there may be a slight delay before the transaction is included and executed in a block, potentially leading to a timeout of the original transaction (tx) receipt. To handle this, periodically query the tx hash in your UI.
:::

```javascript
// Example of handling parallel decryption transactions in a frontend application
async function handleDecryptTransaction(contract, methodName, ...args) {
try {
// Send the transaction that includes decryption
const tx = await contract[methodName](...args);

// Get initial transaction receipt
let receipt = await tx.wait();

// If the receipt times out, periodically check the transaction status
if (!receipt || receipt.status === 'pending') {
receipt = await pollTransactionStatus(tx.hash);
}

return receipt;
} catch (error) {
console.error('Transaction failed:', error);
throw error;
}
}

// Helper function to poll transaction status
async function pollTransactionStatus(txHash, maxAttempts = 20) {
let attempts = 0;

while (attempts < maxAttempts) {
const receipt = await provider.getTransactionReceipt(txHash);

if (receipt && receipt.status === 1) {
return receipt;
}

// Wait 3 seconds before next attempt
await new Promise(resolve => setTimeout(resolve, 3000));
attempts++;
}

throw new Error('Transaction timeout: Decryption taking longer than expected');
}

// Usage example
const contract = new ethers.Contract(address, abi, signer);

try {
const receipt = await handleDecryptTransaction(
contract,
'decryptInFhenix'
);
console.log('Transaction completed:', receipt);
} catch (error) {
console.log('Failed to process decryption:', error);
}
```
75 changes: 75 additions & 0 deletions docs/devdocs/Writing Smart Contracts/Security-Zones.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
sidebar_position: 200
title: 🛡️ Security Zones
---

## Why we need Security Zones

In various use cases, scenarios, and applications, different levels of security, trust, and performance may be required. However, it is preferable to have everything operate within a single blockchain, as deploying across multiple networks (blockchains) is cumbersome and has its own unique challenges, such as bridging, coordination and more. Furthermore, different parts of a single application may require unique combinations of various configurations. Settling on a single configuration would typically compromise overall security and performance—leaving the application only as secure as its weakest or as fast as its slowest component.

## What are Security Zones

Fhenix developed Security Zones to address this problem. With Fhenix, multiple encryption key sets (i.e., Security Zones) can coexist on a single network. Previously, we were limited to optimizing a single cryptographic key set to meet average security and performance needs. Now, with multiple Security Zones, Fhenix can tailor encryption configurations to specific use cases, eliminating the need to compromise on security, performance, or trust.

For example, highly sensitive information can be protected with maximum security guarantees by using a Threshold Network for encryption. For less sensitive data, a local key set controlled by the sequencer may suffice, offering better performance with slightly lower but acceptable trust assumptions. Similarly, some applications may prefer an encryption scheme that specializes in small ciphertext sizes but slower computation, while apps may need to optimize for transaction price above everything else. Security zones will allow having different schemes with different configurations, all under one roof (or rather, one network - Fhenix).

:::warning[Important Dev Hint]
An important nuance of Security Zones is that two ciphertexts that are encrypted using two different security zones are not compatible, since every Zone represents a different set of **FHE keys**. For example, we cannot compute enc(a) + enc(b), where a and b were encrypted using different Zones.
:::
:::info[Note]
Currently, creating new Security Zones is not dynamically supported, which means that users cannot implement this feature on their own. Rather, they must choose between the existing, pre-generated Security Zones available with Nitrogen on launch. However, we may add a dynamic Security Zones feature in the future.
:::

## Security Zone in Nitrogen

In Nitrogen, we introduce two Security Zones to demonstrate the concept:

### Threshold Network (zone 0 - default)
This zone uses a Threshold Network. The benefit of this approach is that it provides the end user with additional protection from malicious actors. For further reading on the Threshold network, [see here](../Fhenix%20Testnet/Threshold-Network.md).

### Local (zone 1)
This zone uses a local key set held by the sequencer (this is how previous Fhenix testnets handled the decryption key). The intention of this zone is to offer faster decryption but require more trust from the user with the tradeoff of assuming a trusted sequencer.

:::info[Dev Hint]
Whether you are porting a contract from a previous Fhenix version, or creating a new one - you don't have to do anything in particular to use the Threshold Network. Security Zone 0 is the default one - meaning that you don't need to modify your code to use it! See the code example below 👇
:::

## Code Example

```sol title="Contract.sol"
function addSecZone0(n1 inEuint32, n2 inEuint32) {
euint32 first = FHE.asEuint32(n1); // This implicitly uses Security Zone 0
euint32 second = FHE.asEuint32(n2, 0); // This also uses Security Zone 0

euint32 result = first + second; // `result` will be marked 'security zone 0' automatically
}

function addSecZone1(n1 inEuint32, n2 inEuint32) {
euint32 first = FHE.asEuint32(n1, 1); // To use a non-default SZ, you have to be explicit
euint32 second = FHE.asEuint32(n2, 1);

euint32 result = first + second; // `result` will be marked 'security zone 1' automatically
}
```

```js title="index.js"
const client = new FhenixClient({ provider });

let first = await client.encrypt_uint32(5); // This implicitly uses Security Zone 0
let second = await client.encrypt_uint32(1332, 0); // This implicitly uses Security Zone 0
await contract.addSecZone0(first, second);

first = await client.encrypt_uint32(5, 1); // To use a non-default SZ, you have to be explicit
econd = await client.encrypt_uint32(1332, 1);
await contract.addSecZone1(first, second);
```

## When can I specify a Security Zone?

In **Solidity**, you will notice that you can specify a Security Zone only when calling functions that are creating `eunitX` types, meaning in `FHE.asEuintX()` functions. This is because the `euintX` types include metadata about the Security Zone that the ciphertext was encrypted with.

In **fhenix.js**, you can specify a Security Zone only in the `encrypt()` functions because you need to encrypt the data with the desired Security Zone's public key.

:::info[Note]
The current security zones are implemented to demonstrate the concept with tradeoffs between security and performance. However, they are not indicative of a production deployment.
:::
10 changes: 8 additions & 2 deletions docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,17 @@ const config: Config = {
'classic',
{
docs: {
lastVersion: 'current',
lastVersion: 'Helium',
versions: {
current: {
label: 'Nitrogen',
path: 'nitrogen',
banner: 'unreleased',
badge: true
},
Helium: {
label: 'Helium',
path: '.'
badge: false
}
},
sidebarPath: './sidebars.ts',
Expand Down
Loading