Skip to content

Limits, capabilities & roles

This is a reference page of the fixed numbers and bitsets a Calimero context enforces: how big a value can be, how large a signed governance op may grow, what each role is allowed to do, and which bits make up a capability or an operation mask. Every figure here is sourced from a named constant in the codebase — when the code and this page disagree, the code wins.

Cross-links: Build gotchas (the limits you hit in practice), Governance (how roles and capabilities are assigned), and Capability inheritance (how capability bits flow through subgroups).

These bound a single WASM execution. Defaults live in crates/runtime/src/logic.rs (VMLimits::default); a node may override them, but these are what ship.

Limit (VMLimits field) Default Notes
max_memory_pages 1024 pages = 64 MiB One WASM page is 64 KiB; 1024 × 64 KiB.
max_stack_size 200 KiB Guest call stack.
max_registers 100 Number of host-call registers.
max_register_size 100 MiB Per-register data cap (constrained < u64::MAX).
max_registers_capacity 1 GiB Total across all registers.
max_logs 1024 Log-line count per execution.
max_log_size 16 KiB Per line; an over-long line traps (LogLengthOverflow), it is not truncated.
max_events 100 Emitted events per execution.
max_event_kind_size 100 bytes Event “kind” string.
max_event_data_size 16 KiB Event data payload.
max_xcalls 100 Cross-context calls per execution.
max_xcall_function_size 100 bytes Cross-context call function name.
max_xcall_params_size 16 KiB Cross-context call params.
max_storage_key_size 1 MiB Per storage key (NonZeroU64).
max_storage_value_size 10 MiB Per storage value (NonZeroU64).
max_blob_handles 100 Concurrent open blob handles.
max_blob_chunk_size 10 MiB Per read/write chunk against a blob.
max_method_name_length 256 bytes Entrypoint method name.
max_module_size 20 MiB WASM module size before compilation (anti-DoS).
max_artifact_size 16 MiB Commit artifact copied out of guest memory onto the Outcome (anti-DoS); over-size traps with ArtifactSizeOverflow.

Caps on what crosses the network — RPC requests, signed governance ops, sync snapshot transfers, and DAG-head sets. Snapshot constants are in crates/node/primitives/src/sync/snapshot.rs; the governance DAG-head cap is in crates/context/config/src/types.rs; request-validation caps are in crates/server/primitives/src/validation.rs.

Limit Value Constant / source
RPC call args (args_json) 10 MiB (10 × 1024 × 1024) MAX_ARGS_JSON_SIZE (validation.rs)
Signed governance-op payload 64 KiB (64 × 1024) MAX_SIGNED_GROUP_OP_PAYLOAD_BYTES (snapshot.rs)
Group/member/context metadata 64 KiB MAX_METADATA_SIZE (validation.rs)
TEE quote (base64) 64 KiB MAX_QUOTE_B64_LENGTH (validation.rs)
Governance DAG heads 32 MAX_GOVERNANCE_DAG_HEADS (context/config/types.rs)
Sync DAG heads (per snapshot) 100 MAX_DAG_HEADS (snapshot.rs)
Snapshot page size — default 256 KiB (256 × 1024) DEFAULT_SNAPSHOT_PAGE_SIZE
Snapshot page size — max 4 MiB (4 × 1024 × 1024) MAX_SNAPSHOT_PAGE_SIZE
Entities per snapshot page 1000 MAX_ENTITIES_PER_PAGE
Entity data size (per record) 1 MiB MAX_ENTITY_DATA_SIZE
Total pages per snapshot 10 000 MAX_SNAPSHOT_PAGES (≈2.5 GB at 256 KiB/page)
Compressed page payload 8 MiB MAX_COMPRESSED_PAYLOAD_SIZE

Bounds on the sync subsystem: how many in-flight deltas a node buffers while it catches up, how long a buffered delta waits for governance before it is dropped, and the per-message / per-session ceilings the incremental state-transfer protocols enforce so a peer cannot demand an unbounded walk. These are about liveness and DoS resistance, not the wire-format sizes above.

While a node is uninitialized or applying a snapshot, incoming gossip deltas are held in a FIFO buffer and replayed once the node has the state to apply them against. A separate buffer holds deltas whose authorizing governance hasn’t been folded yet.

Cap Value Behaviour at the limit Constant / source
Snapshot-sync delta buffer 10 000 deltas / context Oldest evicted first (FIFO); the drops counter increments DEFAULT_BUFFER_CAPACITY (node/primitives/delta_buffer.rs:29)
Minimum recommended buffer 100 Below this a startup warning is logged — small buffers drop under normal load MIN_RECOMMENDED_CAPACITY (delta_buffer.rs:35)
Zero-capacity buffer 0 Valid but drops every delta immediately (DroppedZeroCapacity) delta_buffer.rs (push, the capacity == 0 arm)
Governance-pending drain attempts 16 After 16 re-buffer passes the delta is permanently dropped with a warn (dropped_max_attempts) MAX_GOVERNANCE_DRAIN_ATTEMPTS (delta_buffer.rs:158), enforced in handlers/state_delta/buffering.rs:195

The drain counter advances on both drain triggers — a governance op applying and new state-delta traffic arriving — so 16 attempts is well past any legitimate partition-recovery delay; a still-orphaned delta is dropped rather than retained forever (a later gossip rebroadcast or snapshot would re-deliver it if valid).

Incremental state transfer (HashComparison / LevelWise)

Section titled “Incremental state transfer (HashComparison / LevelWise)”

The two tree-walking protocols clamp every request and response so a malicious or buggy peer cannot force an arbitrarily expensive traversal. Note the two depth caps differ by protocol.

Cap Value Behaviour at the limit Constant / source
HashComparison nodes per response 1000 Response with more nodes is rejected as invalid MAX_NODES_PER_RESPONSE (node/primitives/sync/hash_comparison.rs:20)
HashComparison request depth 16 max_depth MUST be validated against this before processing MAX_TREE_REQUEST_DEPTH (node/primitives/sync/wire.rs:47)
LevelWise nodes per level 10 000 Responder bails (errors the session) if a level response exceeds it MAX_NODES_PER_LEVEL (sync/levelwise.rs:83; checked in sync/level_sync.rs:306)
LevelWise parents per request 1000 Truncated to the cap and truncation_occurred is set — sync may be incomplete MAX_PARENTS_PER_REQUEST (levelwise.rs:77; clamped in level_sync.rs:523)
LevelWise requests per session 128 Further requests are refused, bounding how long a peer can hold the session open MAX_REQUESTS_PER_SESSION (levelwise.rs:90; checked in level_sync.rs:813)
LevelWise traversal depth 64 max_depth clamped to this (LevelWise targets depth ≤ 2; the ceiling is headroom) MAX_LEVELWISE_DEPTH (levelwise.rs:71)

A member’s capabilities are a u32 bitset (crates/context/config/src/lib.rs, also exported via crates/primitives/src/context.rs). These gate governance actions beyond the implicit default-write that membership already grants. Capabilities flow through open subgroups — see Capability inheritance.

Bit Constant Grants
1 << 0 CAN_CREATE_CONTEXT Create a context within the group.
1 << 1 CAN_INVITE_MEMBERS Issue invitations to the group.
1 << 2 CAN_JOIN_OPEN_SUBGROUPS Be inherited as a member of Open subgroups beneath this group. Granted to non-admins by default; admins revoke it as a deny-list.
1 << 3 MANAGE_MEMBERS Add/remove members and manage their roles.
1 << 4 MANAGE_APPLICATION Manage the group’s application (e.g. upgrades).
1 << 5 CAN_CREATE_SUBGROUP Create a subgroup directly under the namespace root (the “any member can start a channel” knob).
1 << 6 CAN_DELETE_SUBGROUP Cascade-delete a subgroup and its subtree. A delegation knob, not a default.
1 << 7 CAN_MANAGE_VISIBILITY Flip a subgroup’s OpenRestricted visibility without full admin.
1 << 8 CAN_MANAGE_METADATA Set group/member/context metadata (*MetadataSet ops) without full admin. A member may always set their own member metadata regardless.

A member’s role (crates/primitives/src/context.rs) is the coarse classification; capability bits refine what a non-admin can additionally do.

Role Read Write default data Governance Notes
Admin Yes Yes Yes — holds management capabilities implicitly (add/remove members, roles, metadata, visibility). Removal is guarded so a group is never left without another admin.
Member Yes Yes (DEFAULT_MEMBER_MASK on non-restricted entities) Only what their capability bits grant. The ordinary participant; the write boundary for default data.
ReadOnly Yes No No Holds the group key to decrypt and read, but cannot author write ops.
ReadOnlyTee Yes No No A TEE-attested fleet read replica admitted by hardware attestation, not invitation. Removal cascades an in-band self-purge. See TEE Attestation.

Separate from governance capabilities, the data plane authorizes individual writes through a 3-bit OpMask (crates/storage/src/entities.rs). It answers “may this author perform this kind of operation on this entity?”

Bit Constant Meaning
0b001 OpMask::WRITE Create/update (upsert) an entity.
0b010 OpMask::DELETE Delete an entity.
0b100 OpMask::ADMIN Change an entity’s writer set (rotate its ACL / ownership).
0b000 OpMask::NONE No rights.
0b111 OpMask::FULL WRITE + DELETE + ADMIN.

Membership implicitly grants WRITE | DELETE (DEFAULT_MEMBER_MASK) on any non-restricted entity — but not ADMIN, so a plain member can write and delete default data yet cannot lock others out by rotating an object’s writer set. Restricted objects override this with an explicit per-object ACL. The full authorization story is in Governance and the Security & threat model.