From 3456142b898f77401656c15890bdc66566e4ec05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Thu, 4 Jan 2024 09:25:17 +0000 Subject: [PATCH 1/5] chore: adding some clarification after a question on discourse --- docs/docs/concepts/foundation/state_model/storage_slots.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/concepts/foundation/state_model/storage_slots.md b/docs/docs/concepts/foundation/state_model/storage_slots.md index 4ad490100949..e11582726809 100644 --- a/docs/docs/concepts/foundation/state_model/storage_slots.md +++ b/docs/docs/concepts/foundation/state_model/storage_slots.md @@ -28,7 +28,7 @@ For structs and arrays, we are logically using a similar storage slot computatio Private storage is a different beast. As you might remember from [State Model](./main.md), private state is stored in encrypted logs and the corresponding private state commitments in append-only tree where each leaf is a commitment. Being append-only, means that leaves are never updated or deleted; instead a nullifier is emitted to signify that some note is no longer valid. A major reason we used this tree, is that lookups at a specific storage slot would leak information in the context of private state. If you could look up a specific address balance just by looking at the storage slot, even if encrypted you would be able to see it changing! That is not good privacy. -Following this, the storage slot as we know it doesn't really exist. The leaves of the note hashes tree are just commitments to content (think of it as a hash of its content). +Following this, the storage slot as we know it doesn't really exist. The leaves of the note hashes tree are just commitments to content (think of it as a hash of its content). One could think "wait, then if someone encrypts a log to me with the details of a transaction, can I decrypt it before the sequencer adds its commitment to the note hash tree"? Well, yes. You cannot "un-see it" even if the transaction gets reorg'd out of the chain later, but you cannot use it because the sequencer doesn't have it in the global state. The log is part of the transaction and is revealed when it is broadcasted. Nevertheless, the concept of a storage slot is very useful when writing applications, since it allows us to reason about distinct and disjoint pieces of data. For example we can say that the balance of an account is stored in a specific slot and that the balance of another account is stored in another slot with the total supply stored in some third slot. By making sure that these slots are disjoint, we can be sure that the balances are not mixed up and that someone cannot use the total supply as their balance. From 6e0b2144b0ce1491a14bedb4db0880723f934eb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Fri, 5 Jan 2024 09:59:52 +0000 Subject: [PATCH 2/5] chore: moving to a more appropriate place --- .../foundation/state_model/storage_slots.md | 2 +- .../contracts/resources/common_patterns/main.md | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/docs/docs/concepts/foundation/state_model/storage_slots.md b/docs/docs/concepts/foundation/state_model/storage_slots.md index e11582726809..0f67af9ec11b 100644 --- a/docs/docs/concepts/foundation/state_model/storage_slots.md +++ b/docs/docs/concepts/foundation/state_model/storage_slots.md @@ -28,7 +28,7 @@ For structs and arrays, we are logically using a similar storage slot computatio Private storage is a different beast. As you might remember from [State Model](./main.md), private state is stored in encrypted logs and the corresponding private state commitments in append-only tree where each leaf is a commitment. Being append-only, means that leaves are never updated or deleted; instead a nullifier is emitted to signify that some note is no longer valid. A major reason we used this tree, is that lookups at a specific storage slot would leak information in the context of private state. If you could look up a specific address balance just by looking at the storage slot, even if encrypted you would be able to see it changing! That is not good privacy. -Following this, the storage slot as we know it doesn't really exist. The leaves of the note hashes tree are just commitments to content (think of it as a hash of its content). One could think "wait, then if someone encrypts a log to me with the details of a transaction, can I decrypt it before the sequencer adds its commitment to the note hash tree"? Well, yes. You cannot "un-see it" even if the transaction gets reorg'd out of the chain later, but you cannot use it because the sequencer doesn't have it in the global state. The log is part of the transaction and is revealed when it is broadcasted. +Following this, the storage slot as we know it doesn't really exist. The leaves of the note hashes tree are just commitments to content (think of it as a hash of its content). Nevertheless, the concept of a storage slot is very useful when writing applications, since it allows us to reason about distinct and disjoint pieces of data. For example we can say that the balance of an account is stored in a specific slot and that the balance of another account is stored in another slot with the total supply stored in some third slot. By making sure that these slots are disjoint, we can be sure that the balances are not mixed up and that someone cannot use the total supply as their balance. diff --git a/docs/docs/dev_docs/contracts/resources/common_patterns/main.md b/docs/docs/dev_docs/contracts/resources/common_patterns/main.md index 0c69517fcb83..d1b1f9868ddf 100644 --- a/docs/docs/dev_docs/contracts/resources/common_patterns/main.md +++ b/docs/docs/dev_docs/contracts/resources/common_patterns/main.md @@ -66,10 +66,10 @@ contract Bridge { This leaks information about the private function being called and the data which has been read. ::: -### Writing public storage from private: when updating public state from private, you can call a public function from private, just make sure you mark public as internal +### Writing public storage from private +When calling a private function, you can update public state by calling a public function. -When calling a public function from private, try to mark the public function as `internal` -This ensures your flow works as intended and that no one can call the public function without going through the private function first! +In this situation, try to mark the public function as `internal`. This ensures your flow works as intended and that no one can call the public function without going through the private function first! ### Moving public data into the private domain Let's say you have some storage in public and want to move them into the private domain. If you pass your aztec address that should receive the data, then that leaks privacy (as everyone will know who has the private notes). So what do you do? @@ -91,6 +91,16 @@ When you send someone a note, the note hash gets added to the [note hash tree](. In the token contract, TransparentNotes are stored in a set called "pending_shields" which is in storage slot 5. See [here](../../../tutorials/writing_token_contract.md#contract-storage) +### Revealing encrypted logs conditionally + +An encrypted log can contain the details of a transaction. One could think this log is emitted as part of the transaction execution, so it wouldn't be revealed if the transaction fails. + +This is not true for Aztec, as the encrypted log is part of the transaction broadcast itself. If an encrypted log is broadcasted together with a commitment, there could be a situation where the commitment fails to be added to the note hash tree, or is reorg'd out of the chain later on. + +Example: + +> Alice and Bob want to reveal a shared secret if they both answer a question correctly. Alice can't simply send a note to Bob together with her answer, because Bob could immediately see Alice's part of the secret even if Alice's answer fails to be added to the note hash tree. + ### Randomness in notes Notes are hashed and stored in the merkle tree. While notes do have a header with a `nonce` field that ensure two exact notes still can be added to the note hash tree (since hashes would be different), preimage analysis can be done to reverse-engineer the contents of the note. From 5a33d358e90b5f0875e314d16fcfaf074c9e4519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Mon, 8 Jan 2024 10:06:34 +0000 Subject: [PATCH 3/5] Update docs/docs/dev_docs/contracts/resources/common_patterns/main.md Co-authored-by: Santiago Palladino --- docs/docs/dev_docs/contracts/resources/common_patterns/main.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/dev_docs/contracts/resources/common_patterns/main.md b/docs/docs/dev_docs/contracts/resources/common_patterns/main.md index d1b1f9868ddf..98f4af18fbd2 100644 --- a/docs/docs/dev_docs/contracts/resources/common_patterns/main.md +++ b/docs/docs/dev_docs/contracts/resources/common_patterns/main.md @@ -93,7 +93,7 @@ In the token contract, TransparentNotes are stored in a set called "pending_shie ### Revealing encrypted logs conditionally -An encrypted log can contain the details of a transaction. One could think this log is emitted as part of the transaction execution, so it wouldn't be revealed if the transaction fails. +An encrypted log can contain any information for a recipient, typically in the form of a note. One could think this log is emitted as part of the transaction execution, so it wouldn't be revealed if the transaction fails. This is not true for Aztec, as the encrypted log is part of the transaction broadcast itself. If an encrypted log is broadcasted together with a commitment, there could be a situation where the commitment fails to be added to the note hash tree, or is reorg'd out of the chain later on. From 62771f20306b41e5fa99716ba61302ce8bb3032c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Mon, 8 Jan 2024 10:06:39 +0000 Subject: [PATCH 4/5] Update docs/docs/dev_docs/contracts/resources/common_patterns/main.md Co-authored-by: Santiago Palladino --- docs/docs/dev_docs/contracts/resources/common_patterns/main.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/dev_docs/contracts/resources/common_patterns/main.md b/docs/docs/dev_docs/contracts/resources/common_patterns/main.md index 98f4af18fbd2..7248cf88326c 100644 --- a/docs/docs/dev_docs/contracts/resources/common_patterns/main.md +++ b/docs/docs/dev_docs/contracts/resources/common_patterns/main.md @@ -95,7 +95,7 @@ In the token contract, TransparentNotes are stored in a set called "pending_shie An encrypted log can contain any information for a recipient, typically in the form of a note. One could think this log is emitted as part of the transaction execution, so it wouldn't be revealed if the transaction fails. -This is not true for Aztec, as the encrypted log is part of the transaction broadcast itself. If an encrypted log is broadcasted together with a commitment, there could be a situation where the commitment fails to be added to the note hash tree, or is reorg'd out of the chain later on. +This is not true for Aztec, as the encrypted log is part of the transaction object broadcasted to the network. So if a transaction with an encrypted log and a note commitment is broadcasted, there could be a situation where the transaction is not mined or reorg'd out, so the commitment is never added to the note hash tree, but the recipient could still have read the encrypted log from the transaction in the mempool. Example: From ee069b8e7fa9569fb98f0dad660ecada43e36889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro=20Sousa?= Date: Mon, 8 Jan 2024 10:06:43 +0000 Subject: [PATCH 5/5] Update docs/docs/dev_docs/contracts/resources/common_patterns/main.md Co-authored-by: Santiago Palladino --- docs/docs/dev_docs/contracts/resources/common_patterns/main.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/dev_docs/contracts/resources/common_patterns/main.md b/docs/docs/dev_docs/contracts/resources/common_patterns/main.md index 7248cf88326c..96f78323f161 100644 --- a/docs/docs/dev_docs/contracts/resources/common_patterns/main.md +++ b/docs/docs/dev_docs/contracts/resources/common_patterns/main.md @@ -99,7 +99,7 @@ This is not true for Aztec, as the encrypted log is part of the transaction obje Example: -> Alice and Bob want to reveal a shared secret if they both answer a question correctly. Alice can't simply send a note to Bob together with her answer, because Bob could immediately see Alice's part of the secret even if Alice's answer fails to be added to the note hash tree. +> Alice and Bob agree to a trade, where Alice sends Bob a passcode to collect funds from a web2 app, in exchange of on-chain tokens. Alice should only send Bob the passcode if the trade is successful. But just sending the passcode as an encrypted log doesn't work, since Bob could see the encrypted log from the transaction as soon as Alice broadcasts it, decrypt it to get the passcode, and withdraw his tokens from the trade to make the transaction fail. ### Randomness in notes Notes are hashed and stored in the merkle tree. While notes do have a header with a `nonce` field that ensure two exact notes still can be added to the note hash tree (since hashes would be different), preimage analysis can be done to reverse-engineer the contents of the note.