From fc3f85c99c5dbc089e6a538d63f68dd00586038a Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Wed, 21 Jan 2026 15:30:59 -0500 Subject: [PATCH 01/26] work --- aips/aip-x.md | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 aips/aip-x.md diff --git a/aips/aip-x.md b/aips/aip-x.md new file mode 100644 index 00000000..ae6e2b2c --- /dev/null +++ b/aips/aip-x.md @@ -0,0 +1,206 @@ +--- +aip: (this is determined by the AIP Manager, leave it empty when drafting) +title: Encrypted Mempool +author: Rex Fernando (rex.fernando@aptoslabs.com) +discussions-to (*optional): +Status: Draft +last-call-end-date (*optional): +type: +created: 01/09/2026 +updated (*optional): +requires (*optional): +--- + +# AIP-X - Encrypted Mempool + + +## Summary + +When a user submits a transaction, it is added to a list of pending +transactions maintained by the validators, commonly called the "mempool", +from which the validators choose transactions to build the next block. +These transactions are public to all validators; this means that the block +leader may choose to order or censor these transactions based on their +behavior in a way that is most profitable for them. This phenomenon is +known as MEV; it has been widely documented and studied in the past several +years, and more adversarial forms of MEV such as sandwich attacks are +recognized as a major problem for on-chain trading. + +This AIP describes a new system to protect users on the Aptos network from +harmful forms of MEV (i.e., frontrunning/sandwich attacks, censorship) by +allowing them the option to submit to an encrypted mempool. Specifically: + +* Using this option means that the transaction's payload will be encrypted + client-side before submission, and that the block leader will order these + transactions while being completely blind to their payloads. +* The transactions will only be decrypted after consensus on the block's + contents is finished, just before execution. +* This decryption will happen directly on the validators via a threshold + stake-weight vote, meaning that the system introduces no additional trust + assumptions beyond those under which the network already operates. + +Previously, performing threshold decryption on the validators would +have been prohibitively expensive in terms of both communication and +computation, requiring `O(stake weight threshold)` communication per +encrypted payload. This proposal avoids a similar blowup via a new _batch +threshold encryption scheme_. Using this scheme, along with heavy +pipelining, means that the encrypted mempool will support >1000 TPS, with +minimal latency overhead for the network. + +### Out of scope + +The goal of the first version of this system is to hide transaction +_payloads_. Hiding the transaction _sender and other metadata_ is +currently out-of-scope. + +This AIP aims to give a high-level overview of the system. There are +several new cryptographic schemes which were built as part of this effort, +including a new batch threshold encryption scheme, a new ZK range proof, +and a new PVSS scheme. A formal description of the cryptography of these +schemes is out-of-scope for this AIP. + +## High-level Overview + + > Define the straw man solution with enough details to make it clear why this is the preferred solution. + > Please write a 2-3 paragraph high-level overview here and defer writing a more detailed description in [the specification section](#specification-and-implementation-details). + +The encrypted mempool comprises the following components: + +**A new _batch threshold encryption scheme_.** This allows validators to + perform a single threshold reconstruction of constant size per block, + regardless of the number of encrypted pending transactions confirmed. It + also allows for much of the computation required for decryption to be + pipelined off the critical path. + +**A new distributed key generation (DKG) protocol** for the +* Integration of +* Modification of the SDK + +Components: + +- Batch threshold encryption +- DKG + - PVSS +- Modified SDK + +Goal: ~2000 tps + + +## Impact + + > Which audiences are impacted by this change? What type of action does the audience need to take? + > What might occur if we do not accept this proposal? + > List out other AIPs this AIP is dependent on + +- Audience: traders on Aptos network, interacting with Decibel and w/ any + other DEX on-chain +- If we do not accept: users will have no protection from frontrunning. + +## Alternative Solutions + + > Explain why you submitted this proposal specifically over alternative solutions. Why is this the best possible outcome? + +Many alternatives for encrypted mempool: +- naive threshold decryption: communication inefficient, conservative + estimate is at least 5x more computation on critical path + - Could offload to an external service. This would introduce additional + trust assumptions. We want to avoid introducing any trust assumptions, + so our system must run directly on our validators +- naive IBE: does not provide correct security guarantees +- BEAT-MEV: avenues for censorship + +## Specification and Implementation Details + + > How will we solve the problem? Describe in detail precisely how this proposal should be implemented. Include proposed design principles that should be followed in implementing this feature. Make the proposal specific enough to allow others to build upon it and perhaps even derive competing implementations. + +- Write out batch threshold encryption interface spec (essentially what's + in the trait) +- txn format spec +- PVSS spec? (show how it connects to batch threshold encryption) +- trusted setup: file plan, ceremony + +## Reference Implementation + + > This is an optional yet highly encouraged section where you may include an example of what you are seeking in this proposal. This can be in the form of code, diagrams, or even plain text. Ideally, we have a link to a living repository of code exemplifying the standard, or, for simpler cases, inline code. + > What is the feature flag(s)? If there is no feature flag, how will this be enabled? + +Point to all PRs + +## Testing + + > - What is the testing plan? (other than load testing, all tests should be part of the implementation details and won’t need to be called out. Some examples include user stories, network health metrics, system metrics, E2E tests, unit tests, etc.) + > - When can we expect the results? + > - What are the test results and are they what we expected? If not, explain the gap. + +e2e benchmark results + +## Risks and Drawbacks + + > - Express here the potential risks of taking on this proposal. What are the hazards? What can go wrong? + > - Can this proposal impact backward compatibility? + > - What is the mitigation plan for each risk or drawback? + +Risks are discussed in the next section. + +## Security, Liveness, and Privacy Considerations + + > - How can this AIP potentially impact the security of the network and its users? How is this impact mitigated? + > - Are there specific parts of the code that could introduce a security issue if not implemented properly? + > - Link tests (e.g. unit, end-to-end, property, fuzz) in the reference implementation that validate both expected and unexpected behavior of this proposal + > - Include any security-relevant documentation related to this proposal (e.g. protocols or cryptography specifications) + +failed decryption could potentially halt the chain +- describe how we implement in a way that prevents this from happening + +Simulation of encrypted txns is harder +- trusted simulation-only nodes, run by foundation + +Max possible TPS is lower than unencrypted txn max TPS +- We are making this feature optional. So max chain TPS will be unaffected + +Has effect on e2e latency of chain +- but net effect should be <10 milliseconds. And we can skip decryption if + no encrypted txns are in a block, so blocks that don't use this feature + will have no effect + +## Future Potential + + > Think through the evolution of this proposal well into the future. How do you see this playing out? What would this proposal result in one year? In five years? + +- potentially could support more general-purpose on-chain decryption. + +## Timeline + +### Suggested implementation timeline + + > Describe how long you expect the implementation effort to take, perhaps splitting it up into stages or milestones. + + +### Suggested developer platform support timeline + + > **Optional:** Describe the plan to have SDK, API, CLI, Indexer support for this feature, if applicable. + +sdk design + +### Suggested deployment timeline + + > **Optional:** Indicate a future release version as a *rough* estimate for when the community should expect to see this deployed on our three networks (e.g., release 1.7). + > You are responsible for updating this AIP with a better estimate, if any, after the AIP passes the gatekeeper’s design review. + > + > - On devnet? + > - On testnet? + > - On mainnet? + +- devnet: end of jan/early feb? +- mainnet?? + +... + + +## Open Questions (Optional) + + > Q&A here, some of them can have answers some of those questions can be things we have not figured out, but we should + +- future plans: hide sender? + +... From 19ec81999369f782b854b7862a5e491f98b4e3db Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Wed, 21 Jan 2026 17:41:46 -0500 Subject: [PATCH 02/26] work --- aips/aip-x.md | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index ae6e2b2c..7665d4f6 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -66,31 +66,42 @@ schemes is out-of-scope for this AIP. The encrypted mempool comprises the following components: -**A new _batch threshold encryption scheme_.** This allows validators to - perform a single threshold reconstruction of constant size per block, - regardless of the number of encrypted pending transactions confirmed. It - also allows for much of the computation required for decryption to be - pipelined off the critical path. +**A new batch threshold encryption scheme.** The scheme allows validators +to perform a single threshold reconstruction of constant size per block, +regardless of the number of encrypted pending transactions confirmed. It +also allows for much of the computation required for decryption to be +pipelined off the critical path. -**A new distributed key generation (DKG) protocol** for the -* Integration of -* Modification of the SDK +**A new distributed key generation (DKG) protocol,** which the validators +will run to generate a new encryption key for each epoch, and for which +transaction payloads will be encrypted. This DKG makes use of a new +publicly-verifiable secret sharing scheme (PVSS) designed for the system. -Components: +**Integration into consensus.** During consensus, the validators will send +additional messages in order to enable decryption of the payloads which +were included in the block. -- Batch threshold encryption -- DKG - - PVSS -- Modified SDK +**Modification of the fullnode API to support receiving transactions with +encrypted payloads.** We add a new transaction payload variant which +represents encrypted payloads throughout their lifecycle (encrypted, +successful decryption, decryption failure). -Goal: ~2000 tps +**Modification of the SDK to support sending encrypted transaction +payloads.** The SDK will handle fetching the current encryption key, +generating the payload ciphertext, and submitting the transaction with this +encrypted payload. +**A trusted setup ceremony.** The batch threshold encryption scheme +requires running a one-time trusted setup ceremony, which each validator +must store and use during decryption. ## Impact > Which audiences are impacted by this change? What type of action does the audience need to take? > What might occur if we do not accept this proposal? > List out other AIPs this AIP is dependent on + + - Audience: traders on Aptos network, interacting with Decibel and w/ any other DEX on-chain From 4e7352e5058b1fc513b73e59263287852ccbc7ad Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Wed, 21 Jan 2026 19:05:36 -0500 Subject: [PATCH 03/26] work --- aips/aip-x.md | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index 7665d4f6..ec0d0712 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -86,10 +86,13 @@ encrypted payloads.** We add a new transaction payload variant which represents encrypted payloads throughout their lifecycle (encrypted, successful decryption, decryption failure). -**Modification of the SDK to support sending encrypted transaction -payloads.** The SDK will handle fetching the current encryption key, -generating the payload ciphertext, and submitting the transaction with this -encrypted payload. +**Modification of the SDK and wallet standard to support sending encrypted +transaction payloads.** Both the SDK and wallets supporting the feature +will be modified for allowing submission of transactions with +encrypted payloads. To do this, they will handle fetching the current +encryption key, generating the payload ciphertext, and submitting the +transaction with this encrypted payload. Submission with encrypted payload +will be optional, to be determined by the user. **A trusted setup ceremony.** The batch threshold encryption scheme requires running a one-time trusted setup ceremony, which each validator @@ -101,16 +104,33 @@ must store and use during decryption. > What might occur if we do not accept this proposal? > List out other AIPs this AIP is dependent on - - -- Audience: traders on Aptos network, interacting with Decibel and w/ any - other DEX on-chain -- If we do not accept: users will have no protection from frontrunning. + - Dapp developers + - Familiarize themselves with the SDK modifications. + - Wallet developers + - If they choose to support sending transactions to the encrypted + mempool natively from their wallet, implement the new wallet standard + feature. +- Audience: traders on Aptos network, interacting with Decibel and with any + other DEX on-chain. +- If we do not accept this AIP: users will have no protection from frontrunning. ## Alternative Solutions > Explain why you submitted this proposal specifically over alternative solutions. Why is this the best possible outcome? +**Classical threshold encryption.** Using a classical threshold encryption +scheme would mean that for every encrypted pending transaction included in +a block, the keyshare holders (in our case, the validators) would be +required to perform a threshold decryption protocol. This means +(1) generating and broadcasting a partial decryption per transaction, and (2) after +receiving a stake-weight threshold of partial decryptions for that +transaction, combining them to reconstruct the plaintext payload. This +would cause prohibitively large computation and communication overheads for +the validators. + +**Identity-based encryption (IBE).** IBE allows for + + Many alternatives for encrypted mempool: - naive threshold decryption: communication inefficient, conservative estimate is at least 5x more computation on critical path From fc6d2be969dc65bfd718163268582d2178e69b99 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Thu, 22 Jan 2026 11:13:33 -0500 Subject: [PATCH 04/26] work --- aips/aip-x.md | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index ec0d0712..84d0a4b8 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -128,17 +128,39 @@ transaction, combining them to reconstruct the plaintext payload. This would cause prohibitively large computation and communication overheads for the validators. -**Identity-based encryption (IBE).** IBE allows for - - -Many alternatives for encrypted mempool: -- naive threshold decryption: communication inefficient, conservative - estimate is at least 5x more computation on critical path - - Could offload to an external service. This would introduce additional - trust assumptions. We want to avoid introducing any trust assumptions, - so our system must run directly on our validators -- naive IBE: does not provide correct security guarantees -- BEAT-MEV: avenues for censorship +One option for dealing with this cost is to offload it from the validators, +and to trust some other committee of parties for decryption of transactions that +make it into each block. But this would introduce a completely new trust +assumption to the system in the form of this committee. A major goal of our +system is to avoid introducing new trust assumptions. In addition to this, +it seems difficult to instantiate this idea in a way that avoids a large +latency overhead for encrypted pending transactions. The most natural way +would be to have a contract on-chain that keeps a queue of confirmed encrypted +pending transactions, and to have the committee decrypt transactions as +soon as they reach this queue. But this would mean that these transactions +would wait several rounds after they are confirmed in order to be executed. + +**Identity-based encryption (IBE).** IBE allows for encrypting with respect +to an arbitrary tag, called an ID, along with a master public key. The +corresponding master secret key holder (or a threshold of keyshare holders) +can generate a decryption key, also with respect to an ID, that decrypts +all ciphertexts encrypted to that ID. Setting the ID to be block height, +one could attempt to use this to build an encrypted mempool with a single +threshold reconstruction per block: during consensus, the validators +reconstruct a decryption key with ID equal to the current block's height, +which can decrypt all encrypted payloads submitted with respect to that +height. Unfortunately, this fails to provide a meaningful notion of +security. This is because any encrypted transaction which _targets_ a specific +block is completely revealed, even _if it fails to be included in the +block_, for instance because of congestion, or because the fullnode decides +to censor it. + +**Previous batch threshold encryption schemes.** Several previous works [cite] +(including one by our team) study batch threshold encryption. Although they +solve the problems discussed above, all previous works either have +user-experience issues related to transaction resubmission, are +computationally expensive, or have problems related to denial-of-service +(or some combination of the three). ## Specification and Implementation Details From 36808628570a096cac5f5c468c8cba12093c54c5 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Thu, 22 Jan 2026 11:27:30 -0500 Subject: [PATCH 05/26] work --- aips/aip-x.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index 84d0a4b8..04f125f9 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -139,6 +139,7 @@ would be to have a contract on-chain that keeps a queue of confirmed encrypted pending transactions, and to have the committee decrypt transactions as soon as they reach this queue. But this would mean that these transactions would wait several rounds after they are confirmed in order to be executed. +[Rex: should I mention Shutter network by name here?] **Identity-based encryption (IBE).** IBE allows for encrypting with respect to an arbitrary tag, called an ID, along with a master public key. The @@ -153,7 +154,7 @@ height. Unfortunately, this fails to provide a meaningful notion of security. This is because any encrypted transaction which _targets_ a specific block is completely revealed, even _if it fails to be included in the block_, for instance because of congestion, or because the fullnode decides -to censor it. +to censor it. [Rex: should I mention fairblock by name here?] **Previous batch threshold encryption schemes.** Several previous works [cite] (including one by our team) study batch threshold encryption. Although they @@ -166,6 +167,8 @@ computationally expensive, or have problems related to denial-of-service > How will we solve the problem? Describe in detail precisely how this proposal should be implemented. Include proposed design principles that should be followed in implementing this feature. Make the proposal specific enough to allow others to build upon it and perhaps even derive competing implementations. +- Discuss technical goals of the system? (need to figure out how/where to discuss context-dependence) + - Write out batch threshold encryption interface spec (essentially what's in the trait) - txn format spec @@ -202,19 +205,19 @@ Risks are discussed in the next section. > - Link tests (e.g. unit, end-to-end, property, fuzz) in the reference implementation that validate both expected and unexpected behavior of this proposal > - Include any security-relevant documentation related to this proposal (e.g. protocols or cryptography specifications) -failed decryption could potentially halt the chain +**failed decryption could potentially halt the chain** - describe how we implement in a way that prevents this from happening -Simulation of encrypted txns is harder +**Simulation of encrypted txns is harder** - trusted simulation-only nodes, run by foundation -Max possible TPS is lower than unencrypted txn max TPS -- We are making this feature optional. So max chain TPS will be unaffected +**Max possible TPS is lower than unencrypted txn max TPS** +- We are making this feature optional. So max chain TPS will be unaffected. +- List exploratory efforts to increase TPS? -Has effect on e2e latency of chain -- but net effect should be <10 milliseconds. And we can skip decryption if - no encrypted txns are in a block, so blocks that don't use this feature - will have no effect +**Has effect on e2e latency of chain** +- but net effect should be <10 milliseconds. +- We will skip all decryption computation if no encrypted txns are in a block, so blocks that don't use this feature will see no effect on latency ## Future Potential From 70dcf4ac7c9f4b52e99f12e0da30acf349dc97a1 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Thu, 22 Jan 2026 13:33:16 -0500 Subject: [PATCH 06/26] work --- aips/aip-x.md | 187 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 186 insertions(+), 1 deletion(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index 04f125f9..e6a2955c 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -165,7 +165,186 @@ computationally expensive, or have problems related to denial-of-service ## Specification and Implementation Details - > How will we solve the problem? Describe in detail precisely how this proposal should be implemented. Include proposed design principles that should be followed in implementing this feature. Make the proposal specific enough to allow others to build upon it and perhaps even derive competing implementations. + > How will we solve the problem? Describe in detail precisely how this + > proposal should be implemented. Include proposed design principles that + > should be followed in implementing this feature. Make the proposal + > specific enough to allow others to build upon it and perhaps even derive + > competing implementations. + +## Batch threshold encryption scheme + +The scheme is described in detail in the academic paper[^FPTX25e]. Below, +we present the interface which the scheme provides. + +```rust +pub trait BatchThresholdEncryption { + type ThresholdConfig: aptos_crypto::SecretSharingConfig; + type SubTranscript: Subtranscript; + + /// An encryption key for the scheme. Allows for generating ciphertexts. If we want to actually + /// deploy this scheme, the functionality here will have to be implemented in the SDK. + type EncryptionKey; + + /// A digest key for the scheme. Allows for generating digests given a list of ciphertexts. + /// Internally, this is a modified KZG setup. + type DigestKey: Serialize + DeserializeOwned; + + /// A ciphertext for the scheme. Internally, this is encrypted w.r.t. an ID and a round number, + /// but I think it makes sense not to expose the ID as part of the interface. (The round number + /// must be exposed since it must be given as input to [`PublicKey::encrypt`], and must agree + /// with the round number used when computing a decryption key.) + type Ciphertext: Serialize + DeserializeOwned + Eq + PartialEq + Serialize + Hash; + + type PreparedCiphertext: Serialize + DeserializeOwned + Eq + PartialEq + Serialize; + + /// The round number used when generating a digest. For security to hold, validators must only + /// generate a single decryption key corresponding to a round number. + type Round; + + /// Internally, a KZG commitment to a set of IDs. + type Digest; + + type EvalProofsPromise; + + /// The eval proofs required for decryption. + type EvalProofs; + + /// An individual eval proof. + type EvalProof; + + /// A share of the master secret key, which allows for deriving + /// decryption key shares. + type MasterSecretKeyShare; + + /// Used to verify whether a specific player's decryption key share is valid w.r.t. a specific + /// digest. + type VerificationKey: VerificationKey; + + type DecryptionKeyShare: DecryptionKeyShare; + + /// A decryption key that has been reconstructed by a threshold of decryption key shares. + type DecryptionKey; + type Id: PartialEq + Eq; + + fn setup( + digest_key: &Self::DigestKey, + pvss_public_params: &::PublicParameters, + subtranscript: &Self::SubTranscript, + threshold_config: &Self::ThresholdConfig, + current_player: Player, + sk_share_decryption_key: &::DecryptPrivKey, + ) -> Result<( + Self::EncryptionKey, + Vec, + Self::MasterSecretKeyShare, + )>; + + /// Generates an (insecure) setup for the batch threshold encryption scheme. Consists of + /// a [`PublicKey`] which can be used to encrypt messages and to compute a digest from a list + /// of ciphertexts, along with a vector of shares of type [`MasterSecretKeyShare`], which share + /// the secret key according to the [`ThresholdConfig`] given as input. Eventually, this will + /// need to be replaced by a DKG. + fn setup_for_testing( + seed: u64, + max_batch_size: usize, + number_of_rounds: usize, + threshold_config: &Self::ThresholdConfig, + ) -> Result<( + Self::EncryptionKey, + Self::DigestKey, + Vec, + Vec, + )>; + + /// Encrypt a plaintext with respect to any arbitrary associated data. This associated data is + /// "bound" to the resulting CT, such that it will only verify with respect to the same + /// associated data. + fn encrypt( + ek: &Self::EncryptionKey, + rng: &mut R, + msg: &impl Plaintext, + associated_data: &impl AssociatedData, + ) -> Result; + + /// Derive a digest from a [`DigestKey`] and a slice of ciphertexts. + fn digest( + digest_key: &Self::DigestKey, + cts: &[Self::Ciphertext], + round: Self::Round, + ) -> Result<(Self::Digest, Self::EvalProofsPromise)>; + + /// Validators *must* verify each ciphertext before approving it to be decrypted, in order to + /// prevent malleability attacks. Verification happens w.r.t. some associated data that was + /// passed into the encrypt fn. + fn verify_ct(ct: &Self::Ciphertext, associated_data: &impl AssociatedData) -> Result<()>; + + /// Although I'd like to expose as little of the identities as possible, Daniel told me that + /// knowing the ID of a ciphertext will potentially help with deduplication. + fn ct_id(ct: &Self::Ciphertext) -> Self::Id; + + /// Compute KZG eval proofs. This will be the most expensive operation in the scheme. + fn eval_proofs_compute_all( + proofs: &Self::EvalProofsPromise, + digest_key: &Self::DigestKey, + ) -> Self::EvalProofs; + + /// Compute KZG eval proofs. This will be the most expensive operation in the scheme. This + /// version uses a different (slower for our parameter regime) multi-point-eval algorithm, + /// from von zur Gathen and Gerhardt. Currently for benchmarking only, not for production use. + fn eval_proofs_compute_all_vzgg_multi_point_eval( + proofs: &Self::EvalProofsPromise, + digest_key: &Self::DigestKey, + ) -> Self::EvalProofs; + + fn eval_proof_for_ct( + proofs: &Self::EvalProofs, + ct: &Self::Ciphertext, + ) -> Option; + + /// Derive a decryption key share given a [`SuccinctDigest`] and a round number, whose + /// corresponding reconstructed decryption key will be able to decrypt any ciphertext encrypted + /// to that round number and committed to by that digest. + fn derive_decryption_key_share( + msk_share: &Self::MasterSecretKeyShare, + digest: &Self::Digest, + ) -> Result; + + fn verify_decryption_key_share( + verification_key: &Self::VerificationKey, + digest: &Self::Digest, + decryption_key_share: &Self::DecryptionKeyShare, + ) -> Result<()>; + + /// Reconstruct a decryption key from a set of [`DecryptionKeyShare`]s assuming the set of + /// shares surpasses the threshold. + fn reconstruct_decryption_key( + shares: &[Self::DecryptionKeyShare], + config: &Self::ThresholdConfig, + ) -> Result; + + // TODO: verify decryption key? + + fn prepare_cts( + cts: &[Self::Ciphertext], + digest: &Self::Digest, + eval_proofs: &Self::EvalProofs, + ) -> Result>; + + /// Decrypt a set of ciphertext using a decryption key and advice. + fn decrypt( + decryption_key: &Self::DecryptionKey, + cts: &[Self::PreparedCiphertext], + ) -> Result>; + + fn decrypt_individual( + decryption_key: &Self::DecryptionKey, + ct: &Self::Ciphertext, + digest: &Self::Digest, + eval_proof: &Self::EvalProof, + ) -> Result

; +} +``` + - Discuss technical goals of the system? (need to figure out how/where to discuss context-dependence) @@ -260,3 +439,9 @@ sdk design - future plans: hide sender? ... + +## References + +[^FPTX25e]: **TrX: Encrypted Mempools in High Performance BFT Protocols**, +by Rex Fernando, Guru-Vamsi Policharla, Andrei Tonkikh, and Zhuolun Xiang, +2025, [[URL]](https://eprint.iacr.org/2025/2032.pdf) From fdfaa8f770449aa344a19b32e7914e17da5de7b8 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Thu, 22 Jan 2026 13:46:00 -0500 Subject: [PATCH 07/26] work --- aips/aip-x.md | 108 ++++++++++++++------------------------------------ 1 file changed, 30 insertions(+), 78 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index e6a2955c..3cbcad5b 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -170,91 +170,43 @@ computationally expensive, or have problems related to denial-of-service > should be followed in implementing this feature. Make the proposal > specific enough to allow others to build upon it and perhaps even derive > competing implementations. + +### Background on Aptos blockchain + +As described in +[AIP-79](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-79.md#background-on-aptos-blockchain): + +> Aptos is a **proof-of-stake (PoS)** blockchain with a consensus algorithm +> that operates in periodic two-hour intervals known as **epochs**. The set +> of validators and their stake distribution remain fixed within each +> epoch, and can change across epoch boundaries. The validators of the next +> epoch do not come online until the new epoch starts. +> +> The blockchain also decouples **consensus** (i.e., currently a BFT +> consensus protocol named [Jolteon](https://arxiv.org/abs/2106.10362)) +> from **execution** (i.e., an optimistic concurrency control execution +> engine +> named [BlockSTM](https://medium.com/aptoslabs/block-stm-how-we-execute-over-160k-transactions-per-second-on-the-aptos-blockchain-3b003657e4ba)), +> where each block is first finalized by consensus and then executed to +> update the blockchain state. This consensus-execution decoupling is +> especially important for on-chain randomness, because it allows the +> network to first commit to an ordering of transactions before computing +> and revealing randomness later on, which ensures the randomness is +> unbiasable and unpredictable. -## Batch threshold encryption scheme +### Batch threshold encryption scheme The scheme is described in detail in the academic paper[^FPTX25e]. Below, -we present the interface which the scheme provides. - -```rust -pub trait BatchThresholdEncryption { - type ThresholdConfig: aptos_crypto::SecretSharingConfig; - type SubTranscript: Subtranscript; - - /// An encryption key for the scheme. Allows for generating ciphertexts. If we want to actually - /// deploy this scheme, the functionality here will have to be implemented in the SDK. - type EncryptionKey; - - /// A digest key for the scheme. Allows for generating digests given a list of ciphertexts. - /// Internally, this is a modified KZG setup. - type DigestKey: Serialize + DeserializeOwned; - - /// A ciphertext for the scheme. Internally, this is encrypted w.r.t. an ID and a round number, - /// but I think it makes sense not to expose the ID as part of the interface. (The round number - /// must be exposed since it must be given as input to [`PublicKey::encrypt`], and must agree - /// with the round number used when computing a decryption key.) - type Ciphertext: Serialize + DeserializeOwned + Eq + PartialEq + Serialize + Hash; - - type PreparedCiphertext: Serialize + DeserializeOwned + Eq + PartialEq + Serialize; +we present an abbreviated form of the interface which the scheme provides, taken from [here](https://github.com/aptos-labs/aptos-core/blob/1b896ef2a971b917ecfccef7322fd074d6cc7425/crates/aptos-batch-encryption/src/traits.rs#L10). - /// The round number used when generating a digest. For security to hold, validators must only - /// generate a single decryption key corresponding to a round number. - type Round; +At a high level, the scheme allows for the following flow: - /// Internally, a KZG commitment to a set of IDs. - type Digest; +* At the beginning of the ech - type EvalProofsPromise; - - /// The eval proofs required for decryption. - type EvalProofs; - - /// An individual eval proof. - type EvalProof; - - /// A share of the master secret key, which allows for deriving - /// decryption key shares. - type MasterSecretKeyShare; - - /// Used to verify whether a specific player's decryption key share is valid w.r.t. a specific - /// digest. - type VerificationKey: VerificationKey; - - type DecryptionKeyShare: DecryptionKeyShare; - - /// A decryption key that has been reconstructed by a threshold of decryption key shares. - type DecryptionKey; - type Id: PartialEq + Eq; +```rust +pub trait BatchThresholdEncryption { - fn setup( - digest_key: &Self::DigestKey, - pvss_public_params: &::PublicParameters, - subtranscript: &Self::SubTranscript, - threshold_config: &Self::ThresholdConfig, - current_player: Player, - sk_share_decryption_key: &::DecryptPrivKey, - ) -> Result<( - Self::EncryptionKey, - Vec, - Self::MasterSecretKeyShare, - )>; - - /// Generates an (insecure) setup for the batch threshold encryption scheme. Consists of - /// a [`PublicKey`] which can be used to encrypt messages and to compute a digest from a list - /// of ciphertexts, along with a vector of shares of type [`MasterSecretKeyShare`], which share - /// the secret key according to the [`ThresholdConfig`] given as input. Eventually, this will - /// need to be replaced by a DKG. - fn setup_for_testing( - seed: u64, - max_batch_size: usize, - number_of_rounds: usize, - threshold_config: &Self::ThresholdConfig, - ) -> Result<( - Self::EncryptionKey, - Self::DigestKey, - Vec, - Vec, - )>; + // The trait's associated types are omitted from this description. /// Encrypt a plaintext with respect to any arbitrary associated data. This associated data is /// "bound" to the resulting CT, such that it will only verify with respect to the same From 0053dee6d43cb3924c1f413e29be7bb1a5c8a810 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Thu, 22 Jan 2026 14:08:47 -0500 Subject: [PATCH 08/26] work --- aips/aip-x.md | 56 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index 3cbcad5b..e0e42cd8 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -171,10 +171,20 @@ computationally expensive, or have problems related to denial-of-service > specific enough to allow others to build upon it and perhaps even derive > competing implementations. +- Discuss technical goals of the system? (need to figure out how/where to discuss context-dependence) + +- Write out batch threshold encryption interface spec (essentially what's + in the trait) +- txn format spec +- PVSS spec? (show how it connects to batch threshold encryption) +- trusted setup: file plan, ceremony + ### Background on Aptos blockchain -As described in -[AIP-79](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-79.md#background-on-aptos-blockchain): + +[AIP-79](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-79.md#background-on-aptos-blockchain) gives an overview of the Aptos blockchain, quoted below, +which is useful for understanding the modifications made by the encrypted +mempool. > Aptos is a **proof-of-stake (PoS)** blockchain with a consensus algorithm > that operates in periodic two-hour intervals known as **epochs**. The set @@ -194,30 +204,37 @@ As described in > and revealing randomness later on, which ensures the randomness is > unbiasable and unpredictable. -### Batch threshold encryption scheme +### The flow of transactions through the encrypted mempool + +We describe at a high level the flow which the system enables. This touches +on every component of the system. Then, in the following sections, we +elaborate on these components, the interfaces which they provide, and the +manner in which they interact. + +The flow description introduces the terminology for the system. In the +following, **bold terms** are nouns, or types, and _italic terms_ are +verbs, or functions. + +* At the beginning of the epoch, the validators obtain the **encryption + key** for this epoch, which was generated and posted on-chain by the + previous epoch's validators during the **DKG**. Each validator also + obtains an encryption of its **master secret key share**, which it can + decrypt with its consensus key. +* At any time, a client may send a transaction with an encrypted payload. + To _encrypt_ the payload, the client must fetch the current **encryption + key** from on-chain. + +### The batch threshold encryption scheme The scheme is described in detail in the academic paper[^FPTX25e]. Below, we present an abbreviated form of the interface which the scheme provides, taken from [here](https://github.com/aptos-labs/aptos-core/blob/1b896ef2a971b917ecfccef7322fd074d6cc7425/crates/aptos-batch-encryption/src/traits.rs#L10). -At a high level, the scheme allows for the following flow: - -* At the beginning of the ech ```rust pub trait BatchThresholdEncryption { // The trait's associated types are omitted from this description. - /// Encrypt a plaintext with respect to any arbitrary associated data. This associated data is - /// "bound" to the resulting CT, such that it will only verify with respect to the same - /// associated data. - fn encrypt( - ek: &Self::EncryptionKey, - rng: &mut R, - msg: &impl Plaintext, - associated_data: &impl AssociatedData, - ) -> Result; - /// Derive a digest from a [`DigestKey`] and a slice of ciphertexts. fn digest( digest_key: &Self::DigestKey, @@ -298,13 +315,6 @@ pub trait BatchThresholdEncryption { ``` -- Discuss technical goals of the system? (need to figure out how/where to discuss context-dependence) - -- Write out batch threshold encryption interface spec (essentially what's - in the trait) -- txn format spec -- PVSS spec? (show how it connects to batch threshold encryption) -- trusted setup: file plan, ceremony ## Reference Implementation From 68af081423db672a625ed655e447c78502fbaa15 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Thu, 22 Jan 2026 14:35:20 -0500 Subject: [PATCH 09/26] work --- aips/aip-x.md | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index e0e42cd8..5ca70596 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -220,46 +220,46 @@ verbs, or functions. previous epoch's validators during the **DKG**. Each validator also obtains an encryption of its **master secret key share**, which it can decrypt with its consensus key. -* At any time, a client may send a transaction with an encrypted payload. +* At any time, a client may submit a transaction with an encrypted payload. To _encrypt_ the payload, the client must fetch the current **encryption key** from on-chain. +* Whenever a validator receives a block proposal from the leader which + contains encrypted pending transactions, + * _Compute a **digest**_ asfd ### The batch threshold encryption scheme The scheme is described in detail in the academic paper[^FPTX25e]. Below, we present an abbreviated form of the interface which the scheme provides, taken from [here](https://github.com/aptos-labs/aptos-core/blob/1b896ef2a971b917ecfccef7322fd074d6cc7425/crates/aptos-batch-encryption/src/traits.rs#L10). +Efficiency properties: +* constant-sized digest, constant-sized decryption key shares, + reconstruction independent of batch size + +Security guarantees: +* + ```rust pub trait BatchThresholdEncryption { // The trait's associated types are omitted from this description. - /// Derive a digest from a [`DigestKey`] and a slice of ciphertexts. fn digest( digest_key: &Self::DigestKey, cts: &[Self::Ciphertext], round: Self::Round, ) -> Result<(Self::Digest, Self::EvalProofsPromise)>; - /// Validators *must* verify each ciphertext before approving it to be decrypted, in order to - /// prevent malleability attacks. Verification happens w.r.t. some associated data that was - /// passed into the encrypt fn. fn verify_ct(ct: &Self::Ciphertext, associated_data: &impl AssociatedData) -> Result<()>; - /// Although I'd like to expose as little of the identities as possible, Daniel told me that - /// knowing the ID of a ciphertext will potentially help with deduplication. fn ct_id(ct: &Self::Ciphertext) -> Self::Id; - /// Compute KZG eval proofs. This will be the most expensive operation in the scheme. fn eval_proofs_compute_all( proofs: &Self::EvalProofsPromise, digest_key: &Self::DigestKey, ) -> Self::EvalProofs; - /// Compute KZG eval proofs. This will be the most expensive operation in the scheme. This - /// version uses a different (slower for our parameter regime) multi-point-eval algorithm, - /// from von zur Gathen and Gerhardt. Currently for benchmarking only, not for production use. fn eval_proofs_compute_all_vzgg_multi_point_eval( proofs: &Self::EvalProofsPromise, digest_key: &Self::DigestKey, @@ -270,9 +270,6 @@ pub trait BatchThresholdEncryption { ct: &Self::Ciphertext, ) -> Option; - /// Derive a decryption key share given a [`SuccinctDigest`] and a round number, whose - /// corresponding reconstructed decryption key will be able to decrypt any ciphertext encrypted - /// to that round number and committed to by that digest. fn derive_decryption_key_share( msk_share: &Self::MasterSecretKeyShare, digest: &Self::Digest, @@ -284,14 +281,11 @@ pub trait BatchThresholdEncryption { decryption_key_share: &Self::DecryptionKeyShare, ) -> Result<()>; - /// Reconstruct a decryption key from a set of [`DecryptionKeyShare`]s assuming the set of - /// shares surpasses the threshold. fn reconstruct_decryption_key( shares: &[Self::DecryptionKeyShare], config: &Self::ThresholdConfig, ) -> Result; - // TODO: verify decryption key? fn prepare_cts( cts: &[Self::Ciphertext], @@ -299,7 +293,6 @@ pub trait BatchThresholdEncryption { eval_proofs: &Self::EvalProofs, ) -> Result>; - /// Decrypt a set of ciphertext using a decryption key and advice. fn decrypt( decryption_key: &Self::DecryptionKey, cts: &[Self::PreparedCiphertext], @@ -314,6 +307,17 @@ pub trait BatchThresholdEncryption { } ``` +### Integration into consensus + +TODO. + +### The DKG + +TODO. + +### The new transaction format + +### The SDK modifications ## Reference Implementation From 871fdb609b5cc2a6c74ac99f517f5aa94436a714 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Thu, 22 Jan 2026 15:00:24 -0500 Subject: [PATCH 10/26] work --- aips/aip-x.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index 5ca70596..02f191c1 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -215,6 +215,10 @@ The flow description introduces the terminology for the system. In the following, **bold terms** are nouns, or types, and _italic terms_ are verbs, or functions. +[Rex: idea is to ease into things here. Describe outline in broad terms, +but defer pieces (i.e., in which consensus rounds the eval proof +computation is computed)] + * At the beginning of the epoch, the validators obtain the **encryption key** for this epoch, which was generated and posted on-chain by the previous epoch's validators during the **DKG**. Each validator also @@ -225,7 +229,16 @@ verbs, or functions. key** from on-chain. * Whenever a validator receives a block proposal from the leader which contains encrypted pending transactions, - * _Compute a **digest**_ asfd + * _Compute a succint_ **digest** which commits to the the transaction + payload ciphertexts. + * Using this digest, _derive a_ **decryption key share**. + * While waiting for consensus on the block, perform other computation to + prepare the ciphertexts for being decrypted. This step is crucial for + achieving expanded upon in the next section. +* Once consensus is reached on the block, each validator broadcasts the + _decryption key_ share to all other validators. +* After receiving decryption keys [from](from) a threshold of validators, [Rex: + talk about stake weight here?] ### The batch threshold encryption scheme @@ -237,7 +250,8 @@ Efficiency properties: reconstruction independent of batch size Security guarantees: -* +* Non-malleability +* Context-dependence ```rust From 418d12c011e686f7be9807c9babd164df02ee3b1 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Mon, 26 Jan 2026 15:01:12 -0500 Subject: [PATCH 11/26] work --- aips/aip-x.md | 95 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 76 insertions(+), 19 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index 02f191c1..a39b9b7a 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -234,24 +234,86 @@ computation is computed)] * Using this digest, _derive a_ **decryption key share**. * While waiting for consensus on the block, perform other computation to prepare the ciphertexts for being decrypted. This step is crucial for - achieving expanded upon in the next section. + achieving a fast decryption time, and is expanded upon in the next section. * Once consensus is reached on the block, each validator broadcasts the - _decryption key_ share to all other validators. -* After receiving decryption keys [from](from) a threshold of validators, [Rex: - talk about stake weight here?] + **decryption key share** to all other validators. +* After receiving decryption keys from a threshold of validators, each + validator _reconstructs_ the **decryption key** for the block, which is + able to decrypt all ciphertexts in the block. It adds this decryption key + to the block metadata, so that fullnodes can verify correct decryption. + [Rex: talk about stake weight here?] +* Finally, each validator _decrypts_ all ciphertexts in the block. This + decryption is the only operation on the critical path. ### The batch threshold encryption scheme -The scheme is described in detail in the academic paper[^FPTX25e]. Below, -we present an abbreviated form of the interface which the scheme provides, taken from [here](https://github.com/aptos-labs/aptos-core/blob/1b896ef2a971b917ecfccef7322fd074d6cc7425/crates/aptos-batch-encryption/src/traits.rs#L10). - -Efficiency properties: -* constant-sized digest, constant-sized decryption key shares, - reconstruction independent of batch size - -Security guarantees: -* Non-malleability -* Context-dependence +The scheme is described in detail in the academic paper[^FPTX25e], and its +cryptographic details are out-of-scope for this AIP. Below, we discuss the +scheme and its required efficiency and security properties at a high level, +and then we present an abbreviated form of the interface which the scheme +provides, taken from [the source +code](https://github.com/aptos-labs/aptos-core/blob/1b896ef2a971b917ecfccef7322fd074d6cc7425/crates/aptos-batch-encryption/src/traits.rs#L10). + +**Flow.** The scheme is integrated into consensus, allowing the validators +to agree on a set of ciphertexts, and to decrypt this set immediately after +consensus is reached on the block. Specifically: +* After receiving a block proposal from the leader, each validator first + invokes `verify_ciphertext` on each ciphertext uses the + `digest` method on the set of ciphertexts in the block to compute + a constant-sized `Digest` and an `EvalProofsPromise`. `digest` + additionally requires as input a `DigestKey`, which is a file generated by the + trusted setup ceremony and loaded by each validator. +* During the voting rounds, each validators performs computation to prepare + for decryption. Specifically: + * It invokes `eval_proofs_compute_all` on the `EvalProofsPromise` to + obtain `EvalProofs`. + * It invokes `prepare_cts`, which takes as input the ciphertexts, the + `Digest`, and the `EvalProofs`, and outputs + a `Vec`. +* After the block is finalized, each validators invokes + `derive_decryption_key_share`, which takes as input the `Digest` and the + validator's `MasterSecretKeyShare`, and outputs a `DecryptionKeyShare`. + It broadcasts this to the other validators. +* Finally, after receiving a threshold of `DecryptionKeyShare`s, each + validators runs `reconstruct_decryption_key` to obtain the + `DecryptionKey` for the block, and uses this to `decrypt` all of the + `PreparedCiphertext`s. + +**Efficiency properties.** +* The digest should be constant-sized, independent of the number of + ciphertexts in the batch. +* The decryption key shares and decryption key should also be + constant-sized. +* The amount of work to derive shares and reconstruct the decryption key + should be constant. + +**Security guarantees.** We describe informally the guarantees our scheme +provides, and defer a formal description to the academic paper[^FPTX25e]. +* Robustness: As long as a specified threshold of decryption key shares are + computed honestly, the (honest) validators should all produce the same + plaintexts at the end of consensus. This should be the case even in the + presence of malicious ciphertexts, or malicious decryption key shares, or + both. +* Rogue ciphertext security: Honest parties' ciphertexts should be + decryptable even if an adversary adds arbitrary other malicious + ciphertexts to the batch. +* Hiding of non-decrypted ciphertexts: A decryption key should have the + power only to decrypt ciphertexts that were committed to as part of the + digest. Any other ciphertexts should reveal nothing about the plaintexts + even in the presence of the decryption key. +* Non-malleability: We must rule out attacks where an adversary (say + a malicious fullnode) receives a ciphertext from a user, changes it + slightly, and then submits it for decryption. +* Context-dependence: An adversary must not be able to combine decryption + key shares across different rounds to derive any new valid decryption + key. + + +#### Non-malleability + +As listed above, one important security property require is +non-malleability of ciphertexts. Because this property is both important +and relatively nuanced, we discuss some attack scenarios. ```rust @@ -274,11 +336,6 @@ pub trait BatchThresholdEncryption { digest_key: &Self::DigestKey, ) -> Self::EvalProofs; - fn eval_proofs_compute_all_vzgg_multi_point_eval( - proofs: &Self::EvalProofsPromise, - digest_key: &Self::DigestKey, - ) -> Self::EvalProofs; - fn eval_proof_for_ct( proofs: &Self::EvalProofs, ct: &Self::Ciphertext, From ffb098840129ec1fbd011e7ca8c0d06029ce647d Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Mon, 26 Jan 2026 15:59:17 -0500 Subject: [PATCH 12/26] work --- aips/aip-x.md | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index a39b9b7a..607b6336 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -254,15 +254,21 @@ and then we present an abbreviated form of the interface which the scheme provides, taken from [the source code](https://github.com/aptos-labs/aptos-core/blob/1b896ef2a971b917ecfccef7322fd074d6cc7425/crates/aptos-batch-encryption/src/traits.rs#L10). -**Flow.** The scheme is integrated into consensus, allowing the validators -to agree on a set of ciphertexts, and to decrypt this set immediately after -consensus is reached on the block. Specifically: +**The batch threshold encryption flow, in more detail.** As explained +above, the scheme is integrated into consensus, allowing the validators to +agree on a set of ciphertexts, and to decrypt this set immediately after +consensus is reached on the block. Specifically, the points in the above +outline which involve the batch encryption scheme can be expanded as +follows: +* The leader proposes a block containing encrypted transactions. Each of + these transactions should be verified using `verify_ct`. * After receiving a block proposal from the leader, each validator first - invokes `verify_ciphertext` on each ciphertext uses the - `digest` method on the set of ciphertexts in the block to compute - a constant-sized `Digest` and an `EvalProofsPromise`. `digest` - additionally requires as input a `DigestKey`, which is a file generated by the - trusted setup ceremony and loaded by each validator. + invokes `verify_ct` on each ciphertext. If all ciphertexts are + valid, the validator uses the `digest` method + on the set of ciphertexts in the block to compute a constant-sized + `Digest` and an `EvalProofsPromise`. `digest` additionally requires as + input a `DigestKey`, which is a file generated by the trusted setup + ceremony and loaded by each validator. * During the voting rounds, each validators performs computation to prepare for decryption. Specifically: * It invokes `eval_proofs_compute_all` on the `EvalProofsPromise` to @@ -315,6 +321,24 @@ As listed above, one important security property require is non-malleability of ciphertexts. Because this property is both important and relatively nuanced, we discuss some attack scenarios. +**Submitting a mauled ciphertext:** Imagine that a malicious fullnode +receives a transaction with an encrypted payload from a user, then "mauls" +the payload, i.e., replaces it with a modified ciphertext based on the +original. It then resigns the modified transaction using its own key, and +submits to the validators. After decryption, the plaintext is close enough +to the user's original plaintext payload to reveal the user's intent, but +via the ciphertext modification is mangled just enough to not be valid. + +It is clear that we must prevent this scenario. Specifically, we ensure +that any modification to a ciphertext which would change the underlying +plaintext immediately renders it invalid, so that `verify_ct` fails. + +**Claiming ownership of a ciphertext:** + +#### The interface spec + +The rust code which describes the interface that the batch encryption +scheme provides is below. ```rust pub trait BatchThresholdEncryption { From d6c3740fac70292d38e393b7d1c88d06b931730f Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Mon, 26 Jan 2026 20:11:40 -0500 Subject: [PATCH 13/26] work --- aips/aip-x.md | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index 607b6336..aabb2679 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -227,23 +227,12 @@ computation is computed)] * At any time, a client may submit a transaction with an encrypted payload. To _encrypt_ the payload, the client must fetch the current **encryption key** from on-chain. -* Whenever a validator receives a block proposal from the leader which - contains encrypted pending transactions, - * _Compute a succint_ **digest** which commits to the the transaction - payload ciphertexts. - * Using this digest, _derive a_ **decryption key share**. - * While waiting for consensus on the block, perform other computation to - prepare the ciphertexts for being decrypted. This step is crucial for - achieving a fast decryption time, and is expanded upon in the next section. -* Once consensus is reached on the block, each validator broadcasts the - **decryption key share** to all other validators. -* After receiving decryption keys from a threshold of validators, each - validator _reconstructs_ the **decryption key** for the block, which is - able to decrypt all ciphertexts in the block. It adds this decryption key - to the block metadata, so that fullnodes can verify correct decryption. - [Rex: talk about stake weight here?] -* Finally, each validator _decrypts_ all ciphertexts in the block. This - decryption is the only operation on the critical path. +* Whenever the validators receives a block proposal from the leader which + contains valid encrypted pending transactions, they use the batch + threshold encryption scheme to generate decryption key shares, which they + then broadcast after reaching consensus on the block. Finally, they use + these shares to reconstruct the decryption key and to decrypt the + ciphertexts. ### The batch threshold encryption scheme @@ -261,7 +250,9 @@ consensus is reached on the block. Specifically, the points in the above outline which involve the batch encryption scheme can be expanded as follows: * The leader proposes a block containing encrypted transactions. Each of - these transactions should be verified using `verify_ct`. + these transactions should be verified using `verify_ct` before proposing; + if verification fails on some of the ciphertexts in a block, the block is + considered invalid. * After receiving a block proposal from the leader, each validator first invokes `verify_ct` on each ciphertext. If all ciphertexts are valid, the validator uses the `digest` method @@ -315,11 +306,12 @@ provides, and defer a formal description to the academic paper[^FPTX25e]. key. -#### Non-malleability +#### Non-malleability, and associated data As listed above, one important security property require is non-malleability of ciphertexts. Because this property is both important -and relatively nuanced, we discuss some attack scenarios. +and relatively nuanced, we pay special attention to it in this AIP Below we +discuss some attack scenarios related to non-malleability. **Submitting a mauled ciphertext:** Imagine that a malicious fullnode receives a transaction with an encrypted payload from a user, then "mauls" @@ -333,7 +325,19 @@ It is clear that we must prevent this scenario. Specifically, we ensure that any modification to a ciphertext which would change the underlying plaintext immediately renders it invalid, so that `verify_ct` fails. -**Claiming ownership of a ciphertext:** +**Claiming ownership of a ciphertext:** Besides modifying an encrypted +payload, a malicious fullnode may simply pass the payload off as its own. +That is, when it receives a transaction with an encrypted payload from +a user, it can simply construct a new transaction with same encrypted +payload as-is, sign the transaction as its own, and submit. + +We must also present this type of payload theft. We do this using the +notion of _encryption with associated data._ When encrypting, the user +specifies some "associated data," in our case, the sending address. The +resulting ciphertext is then verified with respect to this same sending +address. We ensure that just as above, any change in the sending address +immediately renders the `(ct, sender)` pair invalid, so that `verify_ct` +fails. #### The interface spec @@ -412,8 +416,11 @@ TODO. ### The new transaction format +TODO. + ### The SDK modifications +TODO. ## Reference Implementation From 9ce4fd35c46296797c8c53d8dcfb9f03aac69510 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Tue, 27 Jan 2026 16:47:16 -0500 Subject: [PATCH 14/26] work --- aips/aip-x.md | 85 +++++++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index aabb2679..c8145b17 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -192,47 +192,38 @@ mempool. > epoch, and can change across epoch boundaries. The validators of the next > epoch do not come online until the new epoch starts. > -> The blockchain also decouples **consensus** (i.e., currently a BFT -> consensus protocol named [Jolteon](https://arxiv.org/abs/2106.10362)) -> from **execution** (i.e., an optimistic concurrency control execution -> engine -> named [BlockSTM](https://medium.com/aptoslabs/block-stm-how-we-execute-over-160k-transactions-per-second-on-the-aptos-blockchain-3b003657e4ba)), -> where each block is first finalized by consensus and then executed to -> update the blockchain state. This consensus-execution decoupling is -> especially important for on-chain randomness, because it allows the -> network to first commit to an ordering of transactions before computing -> and revealing randomness later on, which ensures the randomness is -> unbiasable and unpredictable. +> The blockchain also decouples **consensus** from **execution**, where +> each block is first finalized by consensus and then executed to update +> the blockchain state. This consensus-execution decoupling is especially +> important for on-chain randomness, because it allows the network to first +> commit to an ordering of transactions before computing and revealing +> randomness later on, which ensures the randomness is unbiasable and +> unpredictable. ### The flow of transactions through the encrypted mempool -We describe at a high level the flow which the system enables. This touches -on every component of the system. Then, in the following sections, we +We describe at a high level the flow which the system enables, and how it +touches each component of the system. Then, in the following sections, we elaborate on these components, the interfaces which they provide, and the manner in which they interact. -The flow description introduces the terminology for the system. In the -following, **bold terms** are nouns, or types, and _italic terms_ are -verbs, or functions. - -[Rex: idea is to ease into things here. Describe outline in broad terms, -but defer pieces (i.e., in which consensus rounds the eval proof -computation is computed)] - -* At the beginning of the epoch, the validators obtain the **encryption - key** for this epoch, which was generated and posted on-chain by the - previous epoch's validators during the **DKG**. Each validator also - obtains an encryption of its **master secret key share**, which it can +* At the beginning of the epoch, the validators obtain the encryption + key for this epoch, which was generated and posted on-chain by the + previous epoch's validators during the DKG. Each validator also + obtains an encryption of its master secret key share, which it can decrypt with its consensus key. * At any time, a client may submit a transaction with an encrypted payload. - To _encrypt_ the payload, the client must fetch the current **encryption - key** from on-chain. + To encrypt the payload, the client must fetch the current encryption + key from on-chain. Both the fetching of the encryption key and the + encryption of the payload will be handled by the Aptos typescript SDK. * Whenever the validators receives a block proposal from the leader which contains valid encrypted pending transactions, they use the batch threshold encryption scheme to generate decryption key shares, which they then broadcast after reaching consensus on the block. Finally, they use these shares to reconstruct the decryption key and to decrypt the - ciphertexts. + ciphertexts. These computations are integrated into consensus in + a pipelined manner, to avoid as much as possible computation on the + critical path. ### The batch threshold encryption scheme @@ -250,9 +241,9 @@ consensus is reached on the block. Specifically, the points in the above outline which involve the batch encryption scheme can be expanded as follows: * The leader proposes a block containing encrypted transactions. Each of - these transactions should be verified using `verify_ct` before proposing; - if verification fails on some of the ciphertexts in a block, the block is - considered invalid. + these transactions should be verified by the leader using `verify_ct` + before proposing; if verification fails on some of the ciphertexts in + a block, the block is considered invalid. * After receiving a block proposal from the leader, each validator first invokes `verify_ct` on each ciphertext. If all ciphertexts are valid, the validator uses the `digest` method @@ -260,27 +251,33 @@ follows: `Digest` and an `EvalProofsPromise`. `digest` additionally requires as input a `DigestKey`, which is a file generated by the trusted setup ceremony and loaded by each validator. -* During the voting rounds, each validators performs computation to prepare - for decryption. Specifically: +* During the voting rounds, each validators performs precomputation to + prepare for decryption. Specifically: * It invokes `eval_proofs_compute_all` on the `EvalProofsPromise` to obtain `EvalProofs`. * It invokes `prepare_cts`, which takes as input the ciphertexts, the `Digest`, and the `EvalProofs`, and outputs a `Vec`. -* After the block is finalized, each validators invokes +* Also during voting rounds, each validators invokes `derive_decryption_key_share`, which takes as input the `Digest` and the validator's `MasterSecretKeyShare`, and outputs a `DecryptionKeyShare`. - It broadcasts this to the other validators. + _It does not broadcast this share until it receives consensus votes + confirming the block._ +* Once the block is confirmec, each validator broadcasts this to the other + validators. * Finally, after receiving a threshold of `DecryptionKeyShare`s, each validators runs `reconstruct_decryption_key` to obtain the `DecryptionKey` for the block, and uses this to `decrypt` all of the - `PreparedCiphertext`s. + `PreparedCiphertext`s. This is the only computation on the critical path, + and is sped up greatly by the precomputation described above. **Efficiency properties.** +* The ciphertexts should have a small additive overhead relative to payload + plaintexts. [Rex: fill in concrete sizes] * The digest should be constant-sized, independent of the number of - ciphertexts in the batch. + ciphertexts in the batch. Specifically, in our scheme, it is 48 bytes. * The decryption key shares and decryption key should also be - constant-sized. + constant-sized. Specifically, in our scheme, they are 48 bytes each. * The amount of work to derive shares and reconstruct the decryption key should be constant. @@ -308,10 +305,10 @@ provides, and defer a formal description to the academic paper[^FPTX25e]. #### Non-malleability, and associated data -As listed above, one important security property require is -non-malleability of ciphertexts. Because this property is both important -and relatively nuanced, we pay special attention to it in this AIP Below we -discuss some attack scenarios related to non-malleability. +Although all security properties are formalized and proven in the academic +paper, non-malleability particularly important and nuanced. Because of +this, we pay special attention to it in the AIP. Below, we discuss some +attack scenarios related to non-malleability. **Submitting a mauled ciphertext:** Imagine that a malicious fullnode receives a transaction with an encrypted payload from a user, then "mauls" @@ -339,10 +336,12 @@ address. We ensure that just as above, any change in the sending address immediately renders the `(ct, sender)` pair invalid, so that `verify_ct` fails. + #### The interface spec The rust code which describes the interface that the batch encryption -scheme provides is below. +scheme provides is below. For clarity, the trait's associated types are +omitted. ```rust pub trait BatchThresholdEncryption { From 4c4912575809e759ba5153dc096af1a251a17eb3 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Tue, 27 Jan 2026 16:48:25 -0500 Subject: [PATCH 15/26] work --- aips/aip-x.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/aips/aip-x.md b/aips/aip-x.md index c8145b17..b485f2c9 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -165,6 +165,9 @@ computationally expensive, or have problems related to denial-of-service ## Specification and Implementation Details +------------------------------- +START READING HERE + > How will we solve the problem? Describe in detail precisely how this > proposal should be implemented. Include proposed design principles that > should be followed in implementing this feature. Make the proposal @@ -405,6 +408,9 @@ pub trait BatchThresholdEncryption { } ``` +------------------------------- +STOP READING HERE + ### Integration into consensus TODO. From 643e840a63ad22d7aa9d8ffa53bb32b0e8bbe9c8 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Tue, 27 Jan 2026 18:05:26 -0500 Subject: [PATCH 16/26] work --- aips/aip-x.md | 85 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 5 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index b485f2c9..88a02275 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -283,6 +283,8 @@ follows: constant-sized. Specifically, in our scheme, they are 48 bytes each. * The amount of work to derive shares and reconstruct the decryption key should be constant. +* The on-critical path computation should be as efficient as possible, to + avoid affecting latency of the network. **Security guarantees.** We describe informally the guarantees our scheme provides, and defer a formal description to the academic paper[^FPTX25e]. @@ -339,6 +341,11 @@ address. We ensure that just as above, any change in the sending address immediately renders the `(ct, sender)` pair invalid, so that `verify_ct` fails. +**Formalizing these and other attack scenarios.** In the paper[^FPTX25e], +we formalize a variant of CCA2-security, adapted to batch threshold +encryption, which captures security against these and other types of +attacks. We give a formal proof that our scheme satisfies this security +definition. #### The interface spec @@ -411,17 +418,85 @@ pub trait BatchThresholdEncryption { ------------------------------- STOP READING HERE -### Integration into consensus - -TODO. - ### The DKG TODO. ### The new transaction format -TODO. +The fullnode will accept a new type of transaction with an encrypted +payload. This new encrypted payload type `EncryptedPayload` is defined +[here](https://github.com/aptos-labs/aptos-core/blob/main/types/src/transaction/encrypted_payload.rs), and is presented below. + +``` +pub enum EncryptedPayload { + Encrypted { + ciphertext: Ciphertext, + extra_config: TransactionExtraConfig, + payload_hash: HashValue, + }, + FailedDecryption { + ciphertext: Ciphertext, + extra_config: TransactionExtraConfig, + payload_hash: HashValue, + eval_proof: EvalProof, + }, + Decrypted { + ciphertext: Ciphertext, + extra_config: TransactionExtraConfig, + payload_hash: HashValue, + eval_proof: EvalProof, + + // decrypted things + executable: TransactionExecutable, + decryption_nonce: u64, + }, +} +``` + +``` +pub struct PayloadAssociatedData { + sender: AccountAddress, +} +``` + + +The goals of this payload format are: +* to represent the transaction throughout its lifecycle (encrypted when + first received, then decrypted, or failed to decrypt after consensus). +* to authenticate the plaintext payload contents. Note that +* to ensure we are using the non-malleability features of the batch + threshold encryption scheme in order to avoid vulnerabilities. +* to integrate well with account abstraction. + +[Rex: I don't remember why the encrypt->sign design integrates better with +account abstraction than the sign->encrypt->sign design. Need to ask +someone about this.] + +To achieve these goals, we layer encryption and signing in the following +manner. +1. First, a single-use `decryption_nonce: u64` chosen at random. +2. Then, the pair `(executable, decryption_nonce)` is encrypted, with + associated data `PayloadAssociatedData` containing the `sender`. +3. The value `payload_hash = H(decryption_nonce, executable, sender, + sequence_number)` is computed. This is a hiding commitment to + `(executable, sender, sequence_number)`. +4. Finally, the `EncryptedPayload::Encrypted` enum variant is initialized + with the `ciphertext` and the `payload_hash`. This is signed by the + user's signing key as part of the final transaction being submitted. + [Rex: explain extra_config?] + + +This design means that the user signs both the ciphertext and a hiding +commitment to the transaction payload contents. After decryption, +since the commitment randomness `decryption_nonce` is revealed as part of +the plaintext, validators and fullnodes may verify the signature and the +commitment computation to establish authenticity of the payload, without +touching the ciphertext. Inclusion of the `sender` in the +`PayloadAssociatedData` means that authenticity of the ciphertext can be +verified with respect to whatever signed the transaction, which precludes +attacks such as the one described in the previous section. + ### The SDK modifications From 6884aca070bb7e8c69a6eda5529478335fabcbc9 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Tue, 27 Jan 2026 18:06:08 -0500 Subject: [PATCH 17/26] work --- aips/aip-x.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index 88a02275..7a45f913 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -428,7 +428,7 @@ The fullnode will accept a new type of transaction with an encrypted payload. This new encrypted payload type `EncryptedPayload` is defined [here](https://github.com/aptos-labs/aptos-core/blob/main/types/src/transaction/encrypted_payload.rs), and is presented below. -``` +```rust pub enum EncryptedPayload { Encrypted { ciphertext: Ciphertext, @@ -454,7 +454,7 @@ pub enum EncryptedPayload { } ``` -``` +```rust pub struct PayloadAssociatedData { sender: AccountAddress, } From d2ca04ce31e16ecda4428c00da5256e1a5ba74f0 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Tue, 27 Jan 2026 18:07:34 -0500 Subject: [PATCH 18/26] work --- aips/aip-x.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index 7a45f913..6d2b06d1 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -464,7 +464,7 @@ pub struct PayloadAssociatedData { The goals of this payload format are: * to represent the transaction throughout its lifecycle (encrypted when first received, then decrypted, or failed to decrypt after consensus). -* to authenticate the plaintext payload contents. Note that +* to authenticate the plaintext payload contents. * to ensure we are using the non-malleability features of the batch threshold encryption scheme in order to avoid vulnerabilities. * to integrate well with account abstraction. @@ -497,6 +497,12 @@ touching the ciphertext. Inclusion of the `sender` in the verified with respect to whatever signed the transaction, which precludes attacks such as the one described in the previous section. +[TODO: talk about +* verifying failed decryption on fullnodes +* account abstraction +* `extra_config`? +* Double-check hash computation (is it actually implemented yet?) +] ### The SDK modifications From f7e8e3314dea83765fa32b6e91d1b981b4287ee0 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Tue, 27 Jan 2026 18:07:55 -0500 Subject: [PATCH 19/26] work --- aips/aip-x.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index 6d2b06d1..86697299 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -415,8 +415,6 @@ pub trait BatchThresholdEncryption { } ``` -------------------------------- -STOP READING HERE ### The DKG @@ -497,6 +495,9 @@ touching the ciphertext. Inclusion of the `sender` in the verified with respect to whatever signed the transaction, which precludes attacks such as the one described in the previous section. +------------------------------- +STOP READING HERE + [TODO: talk about * verifying failed decryption on fullnodes * account abstraction From 1efee2105ccb37d2f0c6ede11eb1b6653c8f3637 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Tue, 27 Jan 2026 18:16:14 -0500 Subject: [PATCH 20/26] work --- aips/aip-x.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index 86697299..2192ae49 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -331,7 +331,11 @@ plaintext immediately renders it invalid, so that `verify_ct` fails. payload, a malicious fullnode may simply pass the payload off as its own. That is, when it receives a transaction with an encrypted payload from a user, it can simply construct a new transaction with same encrypted -payload as-is, sign the transaction as its own, and submit. +payload as-is, sign the transaction as its own, and submit. Even if the +plaintext contains the sender public key, this is not verifiable until +after decryption. As soon as the fullnode's malicious transaction gets +included in a block and decrypted, the user's transaction intent is +revealed. We must also present this type of payload theft. We do this using the notion of _encryption with associated data._ When encrypting, the user From 27712da93306f0e86c43b72f23aa780121836923 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Fri, 30 Jan 2026 11:09:51 -0500 Subject: [PATCH 21/26] work --- aips/aip-x.md | 140 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 108 insertions(+), 32 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index 2192ae49..a37e0963 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -174,18 +174,11 @@ START READING HERE > specific enough to allow others to build upon it and perhaps even derive > competing implementations. -- Discuss technical goals of the system? (need to figure out how/where to discuss context-dependence) - -- Write out batch threshold encryption interface spec (essentially what's - in the trait) -- txn format spec -- PVSS spec? (show how it connects to batch threshold encryption) -- trusted setup: file plan, ceremony ### Background on Aptos blockchain -[AIP-79](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-79.md#background-on-aptos-blockchain) gives an overview of the Aptos blockchain, quoted below, +AIP-79[^AIP-79] gives an overview of the Aptos blockchain, quoted below, which is useful for understanding the modifications made by the encrypted mempool. @@ -210,6 +203,8 @@ touches each component of the system. Then, in the following sections, we elaborate on these components, the interfaces which they provide, and the manner in which they interact. +* Before the system is deployed, a trusted setup ceremony is run. The + validators must load the result of this ceremony before starting. * At the beginning of the epoch, the validators obtain the encryption key for this epoch, which was generated and posted on-chain by the previous epoch's validators during the DKG. Each validator also @@ -398,6 +393,11 @@ pub trait BatchThresholdEncryption { config: &Self::ThresholdConfig, ) -> Result; + fn verify_decryption_key( + encryption_key: &Self::EncryptionKey, + digest: &Self::Digest, + decryption_key: &Self::DecryptionKey, + ) -> Result<()>; fn prepare_cts( cts: &[Self::Ciphertext], @@ -420,9 +420,52 @@ pub trait BatchThresholdEncryption { ``` + ### The DKG -TODO. +The batch threshold encryption scheme requires the validators to share +a field-element secret key. Clients must encrypt to the corresponding +group-element public key. The Aptos network already runs a DKG every epoch +which establishes a shared secret key for on-chain randomness[^AIP-79], but +this secret key is a _group element_, and thus is incompatible with our +scheme. Because of this, we construct a new DKG which is also run by the +validators every epoch. + +As with the randomness DKG, our DKG is based on non-interactive PVSS, this +time for field elements. The new PVSS scheme is described in a technical +blog post[^chunky], and its formal description is out-of-scope for this +AIP. Aside from being a field-element PVSS instead of a group-element PVSS, +two key differences separate it from the randomness PVSS: + +* It is not aggregatable. That is, it is not possible to aggregate many + transcripts into one in a way that sums the corresponding secrets and + shares and maintains verifiability. +* Although it is not aggregatable, it has an aggregatable but + non-verifiable subtranscript. + +We design the new DKG around these differences. The DKG will have an +agreement phase designed to work with a non-aggregatable PVSS scheme. +Specifically: + +1. As with the previous DKG, each party will start by disseminating + a transcript. +2. One of the validators (e.g. the consensus leader) broadcast a _proposal_ + $(Q, \mathsf{subtrx})$ consisting of a set $Q$ of party indices along + with subtranscript $\mathsf{subtrx}$, which is claimed to be the + aggregation of the transcripts from the parties in $Q$. Note that this + proposal is succinct; the proposer does not send the individual + subtranscripts which were aggregated to produce $\mathsf{subtrx}$. +3. + + +Details of this agreement phase are in the technical blog post.[^chunky] + + +### The trusted setup + +The trusted setup consists of many shifts of a single powers-of-tau setup. +Its specific structure is described in the paper[^FPTX25e]; more details on +the ceremony design and implementation will follow. ### The new transaction format @@ -489,36 +532,66 @@ manner. [Rex: explain extra_config?] -This design means that the user signs both the ciphertext and a hiding -commitment to the transaction payload contents. After decryption, -since the commitment randomness `decryption_nonce` is revealed as part of -the plaintext, validators and fullnodes may verify the signature and the -commitment computation to establish authenticity of the payload, without -touching the ciphertext. Inclusion of the `sender` in the +This design means that by signing the transaction, the user signs both the +ciphertext and a hiding commitment to the transaction payload contents. +After decryption, since the commitment randomness `decryption_nonce` is +revealed as part of the plaintext, validators and fullnodes may verify the +signature and the commitment computation to establish authenticity of the +payload, without touching the ciphertext. Inclusion of the `sender` in the `PayloadAssociatedData` means that authenticity of the ciphertext can be verified with respect to whatever signed the transaction, which precludes attacks such as the one described in the previous section. -------------------------------- -STOP READING HERE +In the case of a failed decryption, the result is stored in the +`FailedDecryption` variant. During replay, fullnodes may verify the block +decryption key using `verify_decryption_key`, and then may verify the +decryption failure. + [TODO: talk about -* verifying failed decryption on fullnodes -* account abstraction * `extra_config`? * Double-check hash computation (is it actually implemented yet?) ] ### The SDK modifications -TODO. +The goal of the encrypted mempool project is privacy of transaction +payloads, and we achieve this by encrypting payloads before they reach the +fullnode. It follows that *this encryption must be done client-side.* +Specifically, either the user’s wallet or the SDK must allow for performing +this encryption. + +We will support three different client-side flows: + +- **Without wallet interaction:** encrypt and then sign on SDK side. + - Comparatively, this requires the highest level trust in the dApp, + since it’s assumed the dApp (i.e., the SDK) has access to the signing + key. +- **With a wallet that has support for our feature:** encrypt and then + sign, all on the wallet side. + - This is the best in terms of trust (i.e., user only needs to trust + the wallet). The wallet can present the transaction in the clear to + the user for approval. + - Requires modifying the [wallet standard](https://github.com/aptos-labs/wallet-standard/blob/main/src/features/aptosSignAndSubmitTransaction.ts) + to add a new feature (e.g. `aptosEncryptSignAndSubmitTransaction`), + and then implementing that feature in e.g. Petra. +- **With wallet interaction, but with a wallet that doesn’t support this + feature natively:** encrypt on SDK side, then sign on the wallet side. + - This is a backup option which would not provide good UX. Although the + wallet has final control, it is signing an encrypted payload. This + means the confirmation screen will be unintelligible, and the wallet + will not be able to simulate. + + +------------------------------- +STOP READING HERE ## Reference Implementation > This is an optional yet highly encouraged section where you may include an example of what you are seeking in this proposal. This can be in the form of code, diagrams, or even plain text. Ideally, we have a link to a living repository of code exemplifying the standard, or, for simpler cases, inline code. > What is the feature flag(s)? If there is no feature flag, how will this be enabled? -Point to all PRs +TODO Point to all PRs ## Testing @@ -526,7 +599,7 @@ Point to all PRs > - When can we expect the results? > - What are the test results and are they what we expected? If not, explain the gap. -e2e benchmark results +Unit tests for each component, smoke tests, forge tests/benchmarks. ## Risks and Drawbacks @@ -569,12 +642,11 @@ Risks are discussed in the next section. > Describe how long you expect the implementation effort to take, perhaps splitting it up into stages or milestones. - -### Suggested developer platform support timeline - - > **Optional:** Describe the plan to have SDK, API, CLI, Indexer support for this feature, if applicable. - -sdk design +- Finishing validator code now, expect to be done end of January. +- Afterwards, SDK engineer will finish SDK. Integration must wait for the + validator code to hit devnet in order to test. Estimate is that final + integration will take a couple days. +- Plan to run trusted setup ceremony sometime in February. ### Suggested deployment timeline @@ -585,10 +657,8 @@ sdk design > - On testnet? > - On mainnet? -- devnet: end of jan/early feb? -- mainnet?? - -... +Devnet end of Jan/early February, mainnet end of Feburary/early march, +testnet somewhere in between. ## Open Questions (Optional) @@ -604,3 +674,9 @@ sdk design [^FPTX25e]: **TrX: Encrypted Mempools in High Performance BFT Protocols**, by Rex Fernando, Guru-Vamsi Policharla, Andrei Tonkikh, and Zhuolun Xiang, 2025, [[URL]](https://eprint.iacr.org/2025/2032.pdf) + +[^AIP-79]: **AIP-79: Implementation of instant on-chain randomness,**, +by Alin Tomescu, Zhuolun Xiang, and Zhoujun Ma. +2024, [[URL]](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-79.md#background-on-aptos-blockchain) + +[^chunky]: [https://alinush.github.io/chunky](https://alinush.github.io/chunky). From c5b689e1ff4859ad6a9b27c0a15d215e9aa650ed Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Fri, 30 Jan 2026 11:40:17 -0500 Subject: [PATCH 22/26] work --- aips/aip-x.md | 83 ++++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index a37e0963..1696546b 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -444,19 +444,23 @@ two key differences separate it from the randomness PVSS: non-verifiable subtranscript. We design the new DKG around these differences. The DKG will have an -agreement phase designed to work with a non-aggregatable PVSS scheme. -Specifically: +agreement phase designed to work with a non-aggregatable PVSS scheme, and +to prevent unnecessary communication overhead. Specifically: 1. As with the previous DKG, each party will start by disseminating a transcript. 2. One of the validators (e.g. the consensus leader) broadcast a _proposal_ - $(Q, \mathsf{subtrx})$ consisting of a set $Q$ of party indices along - with subtranscript $\mathsf{subtrx}$, which is claimed to be the - aggregation of the transcripts from the parties in $Q$. Note that this - proposal is succinct; the proposer does not send the individual + $(Q, H(\mathsf{subtrx}))$ consisting of a set $Q$ of party indices along + with the hash of a subtranscript $\mathsf{subtrx}$, which is claimed to + be the aggregation of the transcripts from the parties in $Q$. Note that + this proposal is succinct; the proposer does not send the individual subtranscripts which were aggregated to produce $\mathsf{subtrx}$. -3. - +3. Each validator signs the proposal if the following hold: + - the weights of the parties in $Q$ pass the threshold + - it has received the transcript from every party in $Q$ and has + verified them + - It has verified that the subtranscripts from parties in $Q$ aggregate + to $\mathsf{subtrx}$ (checked via the hash). Details of this agreement phase are in the technical blog post.[^chunky] @@ -588,17 +592,12 @@ STOP READING HERE ## Reference Implementation - > This is an optional yet highly encouraged section where you may include an example of what you are seeking in this proposal. This can be in the form of code, diagrams, or even plain text. Ideally, we have a link to a living repository of code exemplifying the standard, or, for simpler cases, inline code. - > What is the feature flag(s)? If there is no feature flag, how will this be enabled? - -TODO Point to all PRs +* The batch encryption scheme is located at [https://github.com/aptos-labs/aptos-core/tree/main/crates/aptos-batch-encryption](https://github.com/aptos-labs/aptos-core/tree/main/crates/aptos-batch-encryption). +* The PVSS scheme is located at [https://github.com/aptos-labs/aptos-core/tree/main/crates/aptos-dkg/src/pvss/chunky](https://github.com/aptos-labs/aptos-core/tree/main/crates/aptos-dkg/src/pvss/chunky). +* The typescript encrypt function is located at [https://github.com/aptos-labs/aptos-core/tree/enc_txn_typescript_tests_3/crates/aptos-batch-encryption/ts-batch-encrypt](https://github.com/aptos-labs/aptos-core/tree/enc_txn_typescript_tests_3/crates/aptos-batch-encryption/ts-batch-encrypt). ## Testing - > - What is the testing plan? (other than load testing, all tests should be part of the implementation details and won’t need to be called out. Some examples include user stories, network health metrics, system metrics, E2E tests, unit tests, etc.) - > - When can we expect the results? - > - What are the test results and are they what we expected? If not, explain the gap. - Unit tests for each component, smoke tests, forge tests/benchmarks. ## Risks and Drawbacks @@ -616,25 +615,39 @@ Risks are discussed in the next section. > - Link tests (e.g. unit, end-to-end, property, fuzz) in the reference implementation that validate both expected and unexpected behavior of this proposal > - Include any security-relevant documentation related to this proposal (e.g. protocols or cryptography specifications) -**failed decryption could potentially halt the chain** -- describe how we implement in a way that prevents this from happening - -**Simulation of encrypted txns is harder** -- trusted simulation-only nodes, run by foundation - -**Max possible TPS is lower than unencrypted txn max TPS** -- We are making this feature optional. So max chain TPS will be unaffected. -- List exploratory efforts to increase TPS? - -**Has effect on e2e latency of chain** -- but net effect should be <10 milliseconds. -- We will skip all decryption computation if no encrypted txns are in a block, so blocks that don't use this feature will see no effect on latency - -## Future Potential +**The max possible encrypted transaction TPS is lower than the max TPS for +unencrypted transactions.** +- We are making this feature optional. So the max chain TPS will be unaffected. +- We are also exploring efforts to increase TPS with this system: + - Issuing multiple decryption keys per block + - Cryptography algorithmic improvements to increase performance + +**This system has an effect on end-to-end latency of chain.** +- This net effect should be <10 milliseconds though. +- We will skip all decryption computation if no encrypted txns are in + a block, so blocks that don't use this feature will see no effect on + latency. + +**Privacy-preserving simulation of encrypted transactions.** Currently in +the SDK, the default behavior is to send a transaction to the same fullnode +both for simulation and for submission. Since transactions sent for +simulation must be sent in the clear, this means the fullnode might be able +to use a statistical/timing analysis to associate the final encrypted +transaction with the cleartext version, breaking privacy. +- We plan to fix this issue by providing sane defaults. Some options: + - When building a transaction with the encryption feature on, we can + default to sending to a different fullnode for simulation than the one + that will be used for submission. Taking this further, we can spin up + "simulation-only" fullnodes which take care of simulating encrypted + transactions. + - Simply disable simulation by default when encryption is on. + + +## Future Potential/Open Questions > Think through the evolution of this proposal well into the future. How do you see this playing out? What would this proposal result in one year? In five years? -- potentially could support more general-purpose on-chain decryption. +- future plans: hide sender? ## Timeline @@ -661,12 +674,6 @@ Devnet end of Jan/early February, mainnet end of Feburary/early march, testnet somewhere in between. -## Open Questions (Optional) - - > Q&A here, some of them can have answers some of those questions can be things we have not figured out, but we should - -- future plans: hide sender? - ... ## References From f3eff669dc2e97cd81bc359e2f8ddb76217b3355 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Fri, 30 Jan 2026 11:42:24 -0500 Subject: [PATCH 23/26] work --- aips/aip-x.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aips/aip-x.md b/aips/aip-x.md index 1696546b..e7309b57 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -615,6 +615,8 @@ Risks are discussed in the next section. > - Link tests (e.g. unit, end-to-end, property, fuzz) in the reference implementation that validate both expected and unexpected behavior of this proposal > - Include any security-relevant documentation related to this proposal (e.g. protocols or cryptography specifications) +**Liveness issues.** TODO + **The max possible encrypted transaction TPS is lower than the max TPS for unencrypted transactions.** - We are making this feature optional. So the max chain TPS will be unaffected. From fdc9ef4618d93b876957cdc054745e09e52d49e1 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Fri, 30 Jan 2026 14:47:42 -0500 Subject: [PATCH 24/26] work --- aips/aip-x.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index e7309b57..4953cbc1 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -615,7 +615,6 @@ Risks are discussed in the next section. > - Link tests (e.g. unit, end-to-end, property, fuzz) in the reference implementation that validate both expected and unexpected behavior of this proposal > - Include any security-relevant documentation related to this proposal (e.g. protocols or cryptography specifications) -**Liveness issues.** TODO **The max possible encrypted transaction TPS is lower than the max TPS for unencrypted transactions.** @@ -630,6 +629,11 @@ unencrypted transactions.** a block, so blocks that don't use this feature will see no effect on latency. +**The system is directly integrated into consensus, and a failure could +lead to the chain halting in the worst case.** In such a catastrophic +failure scenario, the validators can disable encrypted mempool while waiting for +a hotfix. + **Privacy-preserving simulation of encrypted transactions.** Currently in the SDK, the default behavior is to send a transaction to the same fullnode both for simulation and for submission. Since transactions sent for From 854e00fc21e9dd767584c7264f4b48792d53dff9 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Mon, 2 Feb 2026 12:04:54 -0500 Subject: [PATCH 25/26] work --- aips/aip-x.md | 60 ++++++++++++++++----------------------------------- 1 file changed, 18 insertions(+), 42 deletions(-) diff --git a/aips/aip-x.md b/aips/aip-x.md index 4953cbc1..b3215b19 100644 --- a/aips/aip-x.md +++ b/aips/aip-x.md @@ -61,9 +61,6 @@ schemes is out-of-scope for this AIP. ## High-level Overview - > Define the straw man solution with enough details to make it clear why this is the preferred solution. - > Please write a 2-3 paragraph high-level overview here and defer writing a more detailed description in [the specification section](#specification-and-implementation-details). - The encrypted mempool comprises the following components: **A new batch threshold encryption scheme.** The scheme allows validators @@ -100,10 +97,6 @@ must store and use during decryption. ## Impact - > Which audiences are impacted by this change? What type of action does the audience need to take? - > What might occur if we do not accept this proposal? - > List out other AIPs this AIP is dependent on - - Dapp developers - Familiarize themselves with the SDK modifications. - Wallet developers @@ -116,8 +109,6 @@ must store and use during decryption. ## Alternative Solutions - > Explain why you submitted this proposal specifically over alternative solutions. Why is this the best possible outcome? - **Classical threshold encryption.** Using a classical threshold encryption scheme would mean that for every encrypted pending transaction included in a block, the keyshare holders (in our case, the validators) would be @@ -165,16 +156,6 @@ computationally expensive, or have problems related to denial-of-service ## Specification and Implementation Details -------------------------------- -START READING HERE - - > How will we solve the problem? Describe in detail precisely how this - > proposal should be implemented. Include proposed design principles that - > should be followed in implementing this feature. Make the proposal - > specific enough to allow others to build upon it and perhaps even derive - > competing implementations. - - ### Background on Aptos blockchain @@ -587,34 +568,26 @@ We will support three different client-side flows: will not be able to simulate. -------------------------------- -STOP READING HERE - ## Reference Implementation * The batch encryption scheme is located at [https://github.com/aptos-labs/aptos-core/tree/main/crates/aptos-batch-encryption](https://github.com/aptos-labs/aptos-core/tree/main/crates/aptos-batch-encryption). * The PVSS scheme is located at [https://github.com/aptos-labs/aptos-core/tree/main/crates/aptos-dkg/src/pvss/chunky](https://github.com/aptos-labs/aptos-core/tree/main/crates/aptos-dkg/src/pvss/chunky). * The typescript encrypt function is located at [https://github.com/aptos-labs/aptos-core/tree/enc_txn_typescript_tests_3/crates/aptos-batch-encryption/ts-batch-encrypt](https://github.com/aptos-labs/aptos-core/tree/enc_txn_typescript_tests_3/crates/aptos-batch-encryption/ts-batch-encrypt). +All cryptographic schemes are implemented over the BLS12-381 curve. The +curve was chosen to match the validators' consensus keypairs, so that these +keypairs may be reused as encryption keypairs during the DKG. + ## Testing Unit tests for each component, smoke tests, forge tests/benchmarks. ## Risks and Drawbacks - > - Express here the potential risks of taking on this proposal. What are the hazards? What can go wrong? - > - Can this proposal impact backward compatibility? - > - What is the mitigation plan for each risk or drawback? - Risks are discussed in the next section. ## Security, Liveness, and Privacy Considerations - > - How can this AIP potentially impact the security of the network and its users? How is this impact mitigated? - > - Are there specific parts of the code that could introduce a security issue if not implemented properly? - > - Link tests (e.g. unit, end-to-end, property, fuzz) in the reference implementation that validate both expected and unexpected behavior of this proposal - > - Include any security-relevant documentation related to this proposal (e.g. protocols or cryptography specifications) - **The max possible encrypted transaction TPS is lower than the max TPS for unencrypted transactions.** @@ -653,15 +626,25 @@ transaction with the cleartext version, breaking privacy. > Think through the evolution of this proposal well into the future. How do you see this playing out? What would this proposal result in one year? In five years? -- future plans: hide sender? +There are several potential improvements and extensions to the scheme +itself. We can improve the efficiency of the batch encryption scheme to +support more TPS. We are also exploring allowing for hiding both the +payload and the sender when submitting to the encrypted mempool. Finally, +it is interesting to think about supporting more general-purpose on-chain +encryption efficiently with ideas similar to those in our system. + +This AIP also enables more generic threshold cryptography on the Aptos +network. Specifically, the DKG for field elements can be used to +instantiate many standard threshold cryptographic schemes over the +validators. + ## Timeline ### Suggested implementation timeline - > Describe how long you expect the implementation effort to take, perhaps splitting it up into stages or milestones. -- Finishing validator code now, expect to be done end of January. +- Finishing validator code now, expect to be done very early February. - Afterwards, SDK engineer will finish SDK. Integration must wait for the validator code to hit devnet in order to test. Estimate is that final integration will take a couple days. @@ -669,14 +652,7 @@ transaction with the cleartext version, breaking privacy. ### Suggested deployment timeline - > **Optional:** Indicate a future release version as a *rough* estimate for when the community should expect to see this deployed on our three networks (e.g., release 1.7). - > You are responsible for updating this AIP with a better estimate, if any, after the AIP passes the gatekeeper’s design review. - > - > - On devnet? - > - On testnet? - > - On mainnet? - -Devnet end of Jan/early February, mainnet end of Feburary/early march, +Devnet early February, mainnet end of Feburary/early march, testnet somewhere in between. From 7971a6c6308c9060621250fa12b7ff381b9cf3c8 Mon Sep 17 00:00:00 2001 From: Rex Fernando Date: Mon, 2 Feb 2026 12:08:31 -0500 Subject: [PATCH 26/26] rename --- aips/{aip-x.md => encrypted-mempool.md} | 2 -- 1 file changed, 2 deletions(-) rename aips/{aip-x.md => encrypted-mempool.md} (99%) diff --git a/aips/aip-x.md b/aips/encrypted-mempool.md similarity index 99% rename from aips/aip-x.md rename to aips/encrypted-mempool.md index b3215b19..c5d7a281 100644 --- a/aips/aip-x.md +++ b/aips/encrypted-mempool.md @@ -656,8 +656,6 @@ Devnet early February, mainnet end of Feburary/early march, testnet somewhere in between. -... - ## References [^FPTX25e]: **TrX: Encrypted Mempools in High Performance BFT Protocols**,