Skip to content

feat: aztec.nr side of entity store#24139

Open
mverzilli wants to merge 2 commits into
martin/f-738-tx-resolution-oraclefrom
martin/expose-entity-store-oracles
Open

feat: aztec.nr side of entity store#24139
mverzilli wants to merge 2 commits into
martin/f-738-tx-resolution-oraclefrom
martin/expose-entity-store-oracles

Conversation

@mverzilli

@mverzilli mverzilli commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Adds oracles to consume EntityStore services from Aztec.nr, as well as some abstractions

Closes F-739

@mverzilli mverzilli requested a review from nchamo June 16, 2026 17:09
@mverzilli mverzilli requested a review from nventuro as a code owner June 16, 2026 17:09

@nchamo nchamo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!

This is going to be super helpful

{
let n = <T as Deserialize>::N;
assert_eq(self.body.len(), n, "entity body length mismatch");
let mut fields: [Field; <T as Deserialize>::N] = [0; <T as Deserialize>::N];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed?

Suggested change
let mut fields: [Field; <T as Deserialize>::N] = [0; <T as Deserialize>::N];
let mut fields = [0; <T as Deserialize>::N];

}

impl RawEntity {
/// Deserializes the raw body field-array into `T` and wraps it, with its location, as a typed [`Entity`].

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By location you mean contract addresS?


/// The identity a value carries when stored as an entity body.
///
/// Implementors supply the two ids the store needs to address an entity: a per-type `entity_type_id` shared by every

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think address has too other meanings already

Suggested change
/// Implementors supply the two ids the store needs to address an entity: a per-type `entity_type_id` shared by every
/// Implementors supply the two ids the store needs to reference an entity: a per-type `entity_type_id` shared by every

}

/// Returns a populated handle for every active entity of this kind, each carrying its `body` and `facts`.
pub unconstrained fn read_all(contract_address: AztecAddress, scope: AztecAddress) -> EphemeralArray<Entity<T>> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I didn't understand how it worked without passing the entity type id, but I understand now 👏

get_entities::<T>(contract_address, scope, T::entity_type_id())
}

/// Records a retractable fact about this entity, originated at `(block_number, block_hash)`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small suggestion, completely ignorable

Suggested change
/// Records a retractable fact about this entity, originated at `(block_number, block_hash)`.
/// Logs a retractable fact about this entity, originated at `(block_number, block_hash)`.

* Output mapping for a fact. Serializes to `[factTypeId, payloadSlot]`, where `payloadSlot` is the slot of the
* fact's payload (its own ephemeral array of fields). Output-only: facts are returned to Noir, never received.
*/
export const FACT: TypeMapping<FactOutput> = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm working on a STRUCT() type, that would help here


/**
* Output mapping for a fact. Serializes to `[factTypeId, payloadSlot]`, where `payloadSlot` is the slot of the
* fact's payload (its own ephemeral array of fields). Output-only: facts are returned to Noir, never received.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to specify the "output" part? Same question for the actual type name. I don't think we do that for other types, do we?

Comment on lines +393 to +396
/**
* Input mapping for an optional entity/fact origin block. Reads two ACVM slots `blockNumber` (u32) and `blockHash`
* (a field) into the store's `OriginBlock` shape. Used inside `OPTION(ORIGIN_BLOCK)`.
*/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, I would delete this doc. It doesn't add much value

Comment on lines +410 to +413
/**
* Output mapping for an entity. Serializes to `[bodySlot, factsSlot]`: the body as a slot of fields, and the facts as
* a slot of `[factTypeId, payloadSlot]` rows. Output-only: entities are returned to Noir, never received.
*/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same with unnecessary "output" term. I say we can also skip the docs since the type explains where it comes from

},
};

/** Returned by `getEntity`/`getEntities`: the entity body plus its facts. */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there something else we can say about this? Something that mentions the oracles or the service for example? I feel like "entity" is too generic and I wouldn't know where this is used in a month

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants