`version` forces a developer to leak application concerns (encryption used on payload) to the routing layer.
This is unnecessary, as the content topic should be used to discriminate what
messages to decrypt with what scheme and key (as it is application dependent).
The UTXO model in the NSSA architecture underpins privacy-preserving executions for three transaction types: private transactions, Shielded Execution (SE) transactions, and Decoupled Execution (DE) transactions.
By utilizing cryptographic methods and structured components,
That is, the sum of the token amounts in all input UTXOs must be congruent (modulo $p$) to the sum of the token amounts in all output UTXOs.
- **Decimal compatibility:**
- Since decimals are represented as rational numbers in $\mathbb {F}_{p}$ the zkVM multiplies by the least common denominator before performing modular balance checks,
this guarantees precision without introducing inconsistencies.
### Security considerations
The token amount component is safeguarded against manipulation through cryptographic commitments and zkVM proofs.
- **Commitments:**
- Token amounts are included in the UTXO commitment, ensuring they cannot be altered without invalidating the proof.
- For example, in Pedersen commitments, the Token Amount is hidden as part of the commitment:
$$
C = g^{\text{Token Amount}} \cdot h^r \mod p
$$
where $r$ is a randomly chosen blinding factor.
- **Anonymity:**
- Since the token amount is embedded in commitments, its value is hidden from external observers unless explicitly revealed by the user.
- **Resistance to overflow:**
- The maximum supply of token value in the system should be less than the maximum value allowed in the amount field. This way we prevent overflows in the balance check, as both sides of the equality will always be less than the total supply of the system. The modular nature of $\mathbb{F}_p$ ensures that operations involving large Token Amounts do not lead to overflows, a common issue in fixed-width integer systems.
### Storage slots
Storage slots in a UTXO serve as a link between private states and programmable privacy.
They represent hashed references to variable data tied to private smart contracts,
enabling state modifications without exposing raw information.
This mechanism supports both confidentiality and data integrity in private executions, SE, and DE transitions.
A storage slot is represented as an element of the finite field $\mathbb{F}_p$, derived as the output of a cryptographic hash function. The hash ensures that:
1. Arbitrary-length input data (e.g., a list of variables) is compactly represented.
2. The hashed value integrates seamlessly into zkVM operations and proofs.
3. Integrity is preserved during storage updates, as any mismatch invalidates the commitment.
### Functional role in NSSA executions
1.**Private execution:** Storage slots enable modifications to private smart contract states by embedding references to hashed data. During private execution, the actual data is transmitted off-chain, and the hash is validated against the UTXO.
2.**SE execution:** SE executions often involve state updates reflected in both private and public states. Storage slots help maintain consistency by synchronizing private state changes with public updates without exposing sensitive details.
3.**DE execution:** In DE executions, storage slots are critical for linking consumed private UTXOs to their public counterparts. This ensures that decommitment transitions preserve data integrity.
### Hashing mechanism
Storage slots rely on a secure cryptographic hash function, denoted as `hash`.
The function transforms input data into an element of $\mathbb{F}_p$, ensuring:
- **Compactness:** Arbitrary-length input is reduced to a fixed-length output.
- **Collision resistance:** Different inputs produce distinct hashes, safeguarding against tampering.
- **Pre-image resistance:** Given a hash, it is computationally infeasible to reverse-engineer the input.
**Example:**
For storage data containing variables $x$, $y$, and $z$, the storage slot is computed as:
$$
\text{Storage Slot} = \text{hash}(x \| y \| z).
$$
### Integration with zkVM proofs
Unlike the token amount component, storage slots are not inherently validated during zkVM proofs.
This design decision balances performance with flexibility:
1.**Default behavior:** Storage slot integrity is assumed to be verified off-chain. This reduces the complexity of zkVM proofs, focusing only on balance checks and ownership validations.
2.**Optional validation:** For applications requiring on-chain verification, storage slot checks can be enforced within the zkVM. This involves recomputing the hash during the proof to ensure consistency.
#### Ownership
Ownership ensures that a UTXO can only be consumed by its designated recipient. This is achieved by linking the UTXO to the nullifier public key ($N_{pk}$) of the intended owner. The ownership mechanism is critical for maintaining privacy and access control within NSSA’s privacy-preserving framework.
The ownership component is represented as an element of $\mathbb{F}_p$, corresponding to the recipient’s $N_{pk}$, derived from their private key (check NSSA key protocol).
### Functional role in NSSA
1.**Recipient eligibility:** The zkVM validates that the consumer of a UTXO possesses the corresponding private key linked to its $N_{pk}$. This prevents unauthorized access while preserving the anonymity of ownership.
2.**Sender anonymity:** UTXOs do not include any sender information. This design ensures that transactions remain unlinkable, even if multiple UTXOs are sent to the same recipient.
3.**Transfer of ownership:** During UTXO creation, the sender embeds the recipient’s $N_{pk}$ in the UTXO. The recipient can later consume the UTXO by proving possession of the corresponding private key.
### Validation in zkVM (UTXO)
The zkVM ensures that only the rightful owner can consume a UTXO:
1.**Proof of ownership:** The zkVM verifies $g^x \equiv N_{pk} \pmod{p}$ where $x$ is the recipient’s private key.
2.**Unlinkability:** To maintain unlinkability, $N_{pk}$ is typically combined with randomization (e.g., blinding factors) during zk proofs. This ensures that ownership validation cannot be correlated across transactions.
#### Randomness
Randomness introduces entropy into UTXOs, ensuring that they are cryptographically secure and resistant to pre-image attacks. This randomness obscures deterministic patterns, preventing adversaries from deducing transaction details or correlating inputs and outputs.
The randomness component is a field element $r \in \mathbb{F}_p$, chosen uniformly at random. It is combined with other UTXO attributes (e.g., token amount, ownership) to produce cryptographic commitments:
$$
C = g^{\text{Token Amount}} \cdot h^r \mod p
$$
where $g$ and $h$ are generator points on the elliptic curve.
### Functional role in NSSA (UTXO)
1.**Commitment schemes:** Randomness ensures that identical inputs produce distinct commitments, preserving privacy and unlinkability.
2.**Proof isolation:** Each UTXO is uniquely randomized, ensuring that zk proofs are isolated and cannot be reused in different contexts.
3.**Entropy enhancement:** Randomness mitigates the risk of brute-force or enumeration attacks, even if some UTXO attributes are partially revealed.
### Validation in zkVM (randomness)
The zkVM validates the randomness indirectly by verifying the commitment:
$$
C = g^{\text{Token Amount}} \cdot h^r \mod p
$$
The proof ensures that $r$ was chosen appropriately without revealing its actual value.
### Privacy flags
The privacy flag determines whether a UTXO is confined to the private state or can transition to the public state. This enables **selective privacy**, allowing users to balance confidentiality and transparency depending on the transaction context.
#### Types of privacy flags
1.**True (private state only):**
- UTXOs remain exclusively in the private state.
- They are manually consumed or nullified during private executions.
- These UTXOs are never revealed to the public state, ensuring maximal confidentiality.
2.**False (synchronizable with public state):**
- These UTXOs can be revealed during public state synchronization (e.g., SE executions).
- The associated storage data is exposed selectively, allowing integration with public smart contract states.
### Functional role in NSSA (randomness)
1.**Private transactions:** Privacy flags enable UTXOs to remain isolated in private state transitions, ensuring that sensitive data is not inadvertently exposed.
2.**Hybrid transactions:** In SE executions, privacy flags allow users to selectively reveal UTXOs necessary for public state updates while keeping others private.
3.**Public updates:** DE executions leverage UTXOs with false privacy flags to synchronize private state changes with public contracts.
### Validation in zkVM (UTXO) consumption
The zkVM validates privacy flags during execution by enforcing constraints on UTXO consumption:
- **True flag:** Ensures that UTXOs with a true flag are only consumed in private state transitions. It also prevents such UTXOs from being revealed in public synchronization steps.
- **False flag:** Allows UTXOs to participate in public state updates but requires the associated storage data to be verified during synchronization.
### Construction
NSSA offers a selective privacy feature, allowing users to choose the privacy level for smart contract invocations, including private, public, shielded, or deshielded modes. However, this flexibility necessitates a synchronisation mechanism to ensure fairness across all users. Without such a mechanism, the system risks fragmenting into two separate decentralised applications, operating independently in public and private states.
To address this, NSSA employs privacy flags. All private states of contracts (receivers) are composed of UTXOs labelled with privacy flags as either `true` or `false`. UTXOs with a `true` flag remain private and are never revealed to the public state. In contrast, UTXOs with a `false` flag must be revealed to the public state and subsequently nullified to prevent further use. This approach ensures proper synchronisation between private and public states.
The revealing phase of the FFUs follows this process:
- Users transfer both types of UTXOs to the receiver, adhering to the lifecycle.
- During the block time, receivers accumulate each FFU using the homomorphic properties of Pedersen commitments.
- At the end of the block, the receiver interacts with the zkVM to generate a ZK proof, which demonstrates the following:
- Input UTXOs are verified as FFUs, ensuring that UTXOs with a `true` privacy flag remain concealed.
- Only the amount and storage are revealed, while the owner remains private.
- The receiver proves that the revealed amount and storage match the original FFU, ensuring no discrepancies.
- Nullifiers for the input FFUs are created to ensure they cannot be reused, as they remain in the commitment tree but are not yet in the nullifier tree.
- The receiver submits the proof to the sequencer. Upon successful verification of the proof, the sequencer synchronises the revealed amounts and storage with the public state of the receivers and contracts.
### Privacy and unlinkability
UTXO exchanges are limited to private and shielded executions. In these cases, only the amount and storage components of the UTXO are revealed. The storage component remains arbitrary, within the constraints allowed by the application, which ensures sender unlinkability.
Additionally, the revealing operation is performed synchronously, and no information is visible before the process is completed, further preserving unlinkability. The use of ZKPs ensures that no information beyond the revealed parts (amount and storage) is leaked. Critical components such as the owner remain entirely hidden during this process.
However, it is not advisable to use FFUs in shielded executions (SE) with the amount component, as this can compromise unlinkability. In SE, the sending amount is fully visible alongside the executor's identity, making it possible to correlate this information with the public state after the FFUs are synchronised. This potential linkage undermines the unlinkability guarantees and should be avoided.
### Functional role of UTXOs in NSSA
In the NSSA architecture, UTXOs are integral to both private executions and the interplay between private and public states. They carry information necessary for balance validation, programmable privacy, and secure state transitions. The ability to selectively reveal or conceal components like storage slots or ownership keys underpins the hybrid nature of SE and DE executions. During private execution, UTXOs facilitate balance checks and ownership validation in zkVM proofs. In SE executions, freshly minted UTXOs establish a link between private inputs and public updates. In DE executions, consumed UTXOs are nullified, preventing reuse while ensuring unlinkability between public and private states.
### Storage and bandwidth considerations
Each UTXO in the NSSA architecture is structured with four primary components—token amount, storage slot, ownership key, and randomness—each represented as a 256-bit field element. This results in a total size of 128 bytes per UTXO. The compact size ensures compatibility with cryptographic operations, but the aggregated bandwidth demands of large-scale deployments require careful consideration. For private transactions generating multiple UTXOs, bandwidth consumption scales linearly with transaction throughput. For example:
- If each transaction produces 4 UTXOs, the total UTXO data per transaction is:
4 × 128 bytes = 512 bytes.
- At 100 transactions per second (TPS), the bandwidth requirement is:
$$
512\ \text{bytes/transaction} \times 100\ \text{TPS} = 51.2\ \text{kilobytes per second}.
$$
### Components affecting bandwidth
1.**Storage slots:**
- Each storage slot contains hashed data representing private smart contract variables.
- While the hash itself is compact (256 bits), the original data must also be transmitted during exchanges for verification by the recipient.
2.**Proofs:**
- zkVM proofs for balance validation, membership, and non-membership checks are transmitted alongside UTXOs.
- The size of these proofs varies depending on the proof system used, but they typically range from 128 bytes to several kilobytes.
3.**Transaction metadata:**
- Metadata, such as privacy flags and protocol-specific identifiers, adds a minor overhead to each transaction but can accumulate across high-throughput systems.
### How to commit a UTXO
The commitment for a UTXO is computed using multiexponentiation, where each input to the commitment corresponds to a specific generator from the `generators[]` array. The mapping of components to generators is as follows:
- Compress storage slot data during transmission, reducing its size while preserving integrity. Methods like:
- Run-Length Encoding (RLE) for repetitive data.
- Delta Encoding for incremental updates.
- Lossless Compression Algorithms (e.g., Zstandard or Brotli).
- For transactions involving minimal state changes, optimize storage slots by only transmitting updated variables instead of the full state.
- Divide large storage states into smaller, independently verifiable units. Only the relevant partition is transmitted and verified during a transaction.
- Use hierarchical Merkle trees for storage slots, enabling compact proofs for specific subtrees instead of transmitting all data.
### Conclusion
While each UTXO is compactly designed, large-scale deployments face challenges due to the cumulative impact of high TPS and complex storage requirements. Strategic optimizations like compression, batching, and selective updates can mitigate bandwidth demands, ensuring NSSA's scalability in both private and hybrid execution environments. Further enhancements to proof systems and protocol-level efficiency measures will be critical for supporting future adoption.
@@ -42,7 +43,7 @@ This specification attempts to provide for these various requirements.
## Semantics
The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”,
The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”,
“SHOULD NOT”, “RECOMMENDED”, “MAY”, and
“OPTIONAL” in this document are to be interpreted as described in[2119](https://www.ietf.org/rfc/rfc2119.txt).
@@ -72,9 +73,10 @@ This attribute can be utilized to convey supplementary details
to various [10/WAKU2](/waku/standards/core/10/waku2.md) protocols,
thereby enabling customized processing based on its contents.
- The `version` attribute, if present,
contains a version number to discriminate different types of payload encryption.
If omitted, the value SHOULD be interpreted as version 0.
- The `version` attribute SHOULD NOT be written or read.
If omitted, the value SHOULD be interpreted as version `0`.
Its usage is now deprecated, and may return if routing-level discrimination is needed.
Versions `1` and `2` SHOULD NOT be used and considered deprecated.
- The `timestamp` attribute, if present,
signifies the time at which the message was generated by its sender.
@@ -113,26 +115,10 @@ An example proto file following this specification can be found [here (vacp2p/wa
## Payload encryption
The `WakuMessage` payload MAY be encrypted.
The message `version` attribute indicates
the schema used to encrypt the payload data.
- **Version 0:**
The payload SHOULD be interpreted as unencrypted; additionally,
it CAN indicate that the message payload has been encrypted
at the application layer.
- **Version 1:**
The payload SHOULD be encrypted using [6/WAKU1](/waku/standards/legacy/6/waku1.md) payload encryption specified in [26/WAKU-PAYLOAD](/waku/standards/application/26/payload.md).
This provides asymmetric and symmetric encryption.
The key agreement is performed out of band.
And provides an encrypted signature and padding for some form of unlinkability.
- **Version 2:**
The payload SHOULD be encoded according to [WAKU2-NOISE](https://github.com/waku-org/specs/blob/master/standards/application/noise.md).
The Waku Noise protocol provides symmetric encryption and asymmetric key exchange.
Any `version` value not included in this list is reserved for future specification.
And, in this case, the payload SHOULD be interpreted as unencrypted by the Waku layer.
It is up to the application developer to determine encryption schemes and mechanisms.
Whether a message is encrypted does not need to be expressed at the routing layer.
An application developer SHOULD use the message content topics to segregate messages encrypted in different manner,
@@ -15,16 +16,19 @@ that can be associated with a [10/WAKU2](/waku/standards/core/10/waku2.md) node.
## Metadata Protocol
Waku specifies a req/resp protocol that provides information about the node's medatadata.
Such metadata is meant to be used by the node to decide if a peer is worth connecting
or not.
The keywords “MUST”, // List style “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”,
“NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt).
Waku specifies a req/resp protocol that provides information about the node's capabilities.
Such metadata MAY be used by other peers for subsequent actions such as light protocol requests or disconnection.
The node that makes the request,
includes its metadata so that the receiver is aware of it,
without requiring an extra interaction.
without requiring another round trip.
The parameters are the following:
*`clusterId`: Unique identifier of the cluster that the node is running in.
*`shards`: Shard indexes that the node is subscribed to.
*`shards`: Shard indexes that the node is subscribed to via [`11/WAKU2-RELAY`](/waku/standards/core/11/relay.md).
***Protocol Identifier***
@@ -48,6 +52,51 @@ message WakuMetadataResponse {
}
```
## Implementation Suggestions
### Triggering Metadata Request
A node SHOULD proceed with metadata request upon first connection to a remote node.
A node SHOULD use the remote node's libp2p peer id as identifier for this heuristic.
A node MAY proceed with metadata request upon reconnection to a remote peer.
A node SHOULD store the remote peer's metadata information for future reference.
A node MAY implement a TTL regarding a remote peer's metadata, and refresh it upon expiry by initiating another metadata request.
It is RECOMMENDED to set the TTL to 6 hours.
A node MAY trigger a metadata request after receiving an error response from a remote note
stating they do not support a specific cluster or shard.
For example, when using a request-response service such as [`19/WAKU2-LIGHTPUSH`](/waku/standards/core/19/lightpush.md).
### Providing Cluster Id
A node MUST include their cluster id into their metadata payload.
It is RECOMMENDED for a node to operate on a single cluster id.
### Providing Shard Information
* Nodes that mount [`11/WAKU2-RELAY`](/waku/standards/core/11/relay.md) MAY include the shards they are subscribed to in their metadata payload.
* Shard-relevant services are message related services,
such as [`13/WAKU2-STORE`](/waku/standards/core/13/store.md), [12/WAKU2-FILTER](/waku/standards/core/12/filter.md)
and [`19/WAKU2-LIGHTPUSH`](/waku/standards/core/19/lightpush.md)
but not [`34/WAKU2-PEER-EXCHANGE`](/waku/standards/core/34/peer-exchange.md)
* Nodes that mount [`11/WAKU2-RELAY`](/waku/standards/core/11/relay.md) and a shard-relevant service SHOULD include the shards they are subscribed to in their metadata payload.
* Nodes that do not mount [`11/WAKU2-RELAY`](/waku/standards/core/11/relay.md) SHOULD NOT include any shard information
### Using Cluster Id
When reading the cluster id of a remote peer, the local node MAY disconnect if their cluster id is different from the remote peer.
### Using Shard Information
It is NOT RECOMMENDED to disconnect from a peer based on the fact that their shard information is different from the local node.
Ahead of doing a shard-relevant request,
a node MAY use the previously received metadata shard information to select a peer that support the targeted shard.
For non-shard-relevant requests, a node SHOULD NOT discriminate a peer based on medata shard information.
## Copyright
Copyright and related rights waived via
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.