-
Notifications
You must be signed in to change notification settings - Fork 611
refactor: offchain reception on entity store #24142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: martin/expose-entity-store-oracles
Are you sure you want to change the base?
Changes from all commits
feb4d7b
6e65d9c
8f91b77
fb13865
7fe3f81
64bca4e
92b7ca6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| use crate::{ | ||
| entities::EntityBody, | ||
| messages::encoding::MESSAGE_CIPHERTEXT_LEN, | ||
| protocol::{address::AztecAddress, hash::{poseidon2_hash, sha256_to_field}, traits::{Deserialize, Serialize}}, | ||
| }; | ||
|
|
||
| /// Entity type id shared by every offchain message reception entity in the entity store. | ||
| pub(crate) global OFFCHAIN_RECEPTION_ENTITY: Field = sha256_to_field("AZTEC_NR::OFFCHAIN_RECEPTION_ENTITY".as_bytes()); | ||
|
|
||
| /// A message delivered via the `offchain_receive` utility function. | ||
| #[derive(Serialize, Deserialize)] | ||
| pub struct OffchainMessage { | ||
| /// The encrypted message payload. | ||
| pub ciphertext: BoundedVec<Field, MESSAGE_CIPHERTEXT_LEN>, | ||
| /// The intended recipient of the message. | ||
| pub recipient: AztecAddress, | ||
| /// The hash of the transaction that produced this message. `Option::none` indicates a tx-less message. | ||
| pub tx_hash: Option<Field>, | ||
| /// Anchor block timestamp at message emission. | ||
| pub anchor_block_timestamp: u64, | ||
| } | ||
|
|
||
| /// Number of fields produced by serializing a `BoundedVec<Field, MESSAGE_CIPHERTEXT_LEN>`. | ||
| /// | ||
| /// A `BoundedVec` serializes as its storage fields followed by a trailing length field, so the total is | ||
| /// `MESSAGE_CIPHERTEXT_LEN + 1`. | ||
| global SERIALIZED_CIPHERTEXT_LEN: u32 = MESSAGE_CIPHERTEXT_LEN + 1; | ||
|
Comment on lines
+23
to
+27
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think you need this? this value doesn't seem to be used anywhere except inside a fn body: let serialized_ciphertext: [Field; SERIALIZED_CIPHERTEXT_LEN] = self.ciphertext.serialize();and there it should be inferred from the retun type. |
||
|
|
||
| impl EntityBody for OffchainMessage { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not well versed in Rust idioms so I'm not sure what a good pattern here would be, I just find this slightly strange. I'm personally tempted to do |
||
| /// All offchain messages share the reception state-machine entity type. | ||
| fn entity_type_id() -> Field { | ||
| OFFCHAIN_RECEPTION_ENTITY | ||
| } | ||
|
|
||
| /// Computes the entity id that identifies this message's reception entity in the entity store. | ||
| /// | ||
| /// The id is a poseidon2 hash over the serialized ciphertext fields and the normalized tx hash (0 when absent). | ||
| /// Re-delivering the same `(ciphertext, tx_hash)` pair therefore maps to the same entity, making `receive` | ||
| /// idempotent. The `recipient` and `anchor_block_timestamp` fields are intentionally excluded, so identity depends | ||
| /// only on the message content and its originating transaction. | ||
| fn entity_id(self) -> Field { | ||
|
Comment on lines
+35
to
+41
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think trait impls get docstrings, so these don't make it to the docs. The second paragraph is an implementation detail, so I'd put it in the body. The overall explanation of what the id represents ('all offchain messages, regardless of content') sounds more like it should go in the docs for |
||
| let serialized_ciphertext: [Field; SERIALIZED_CIPHERTEXT_LEN] = self.ciphertext.serialize(); | ||
| let mut inputs: [Field; SERIALIZED_CIPHERTEXT_LEN + 1] = [0; SERIALIZED_CIPHERTEXT_LEN + 1]; | ||
| for i in 0..SERIALIZED_CIPHERTEXT_LEN { | ||
| inputs[i] = serialized_ciphertext[i]; | ||
| } | ||
| inputs[SERIALIZED_CIPHERTEXT_LEN] = self.tx_hash.unwrap_or(0); | ||
| poseidon2_hash(inputs) | ||
|
Comment on lines
+42
to
+48
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the goal is to make the id be 1-1 with the content, then we could request that If we don't, like we do here (because recipient and anchor block are not included) then we should definitely explain what it means for there to be multiple entities with the same id and different recipients / anchor blocks. (incidentally I think we would not actually support that? Because the entity store only checks for pre-existence of the entity id and then does nothing if there's a match, regardless of content. So e.g. same message for multiple recipients would result in the latter ones being dropped) |
||
| } | ||
| } | ||
|
|
||
| mod test { | ||
| use crate::{ | ||
| messages::encoding::MESSAGE_CIPHERTEXT_LEN, | ||
| protocol::{address::AztecAddress, traits::{Deserialize, FromField, Serialize}}, | ||
| }; | ||
| use super::OffchainMessage; | ||
|
|
||
| #[test] | ||
| unconstrained fn pack_unpack_round_trips_offchain_message() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is just testing that |
||
| let ciphertext: BoundedVec<Field, MESSAGE_CIPHERTEXT_LEN> = BoundedVec::new(); | ||
| let msg = OffchainMessage { | ||
| ciphertext, | ||
| recipient: AztecAddress::from_field(42), | ||
| tx_hash: Option::some(99), | ||
| anchor_block_timestamp: 12345, | ||
| }; | ||
| let packed = msg.serialize(); | ||
| let roundtripped: OffchainMessage = Deserialize::deserialize(packed); | ||
| assert_eq(roundtripped.recipient, msg.recipient); | ||
| assert_eq(roundtripped.tx_hash, msg.tx_hash); | ||
| assert_eq(roundtripped.anchor_block_timestamp, msg.anchor_block_timestamp); | ||
| assert_eq(roundtripped.ciphertext.len(), msg.ciphertext.len()); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.