Resource Heap
The resource heap provides explicit state tracking for protocol resources. It stores content addressed resources, records consumption in a nullifier set, and can produce Merkle commitments.
Overview
The heap lives in telltale_choreography::heap. It is immutable by default, so operations return a new heap value and preserve deterministic behavior.
Resource Types
Resources are immutable values with content based identifiers.
#![allow(unused)]
fn main() {
pub struct ResourceId {
hash: [u8; 32],
counter: u64,
}
pub enum Resource {
Channel(ChannelState),
Message(Message),
Session { role: String, type_hash: u64 },
Value { tag: String, data: Vec<u8> },
}
}
ResourceId combines a content hash with an allocation counter. The hash is derived from a simple byte encoding of the resource, so identical resources with different counters still receive unique IDs.
Heap Structure
The heap stores resources and nullifiers in ordered maps.
#![allow(unused)]
fn main() {
pub struct Heap {
resources: BTreeMap<ResourceId, Resource>,
nullifiers: BTreeSet<ResourceId>,
counter: u64,
}
}
BTreeMap and BTreeSet provide deterministic iteration order for reproducible hashing and proofs.
Heap Operations
Allocate and consume resources using the functional API.
#![allow(unused)]
fn main() {
use telltale_choreography::heap::{Heap, Resource};
let heap = Heap::new();
let msg = Resource::message("Alice", "Bob", "Ping", vec![1, 2, 3], 0);
let (msg_id, heap) = heap.alloc(msg);
let heap = heap.consume(&msg_id)?;
}
The alloc method returns a new heap and the allocated resource ID. The consume method marks a resource as nullified while keeping it in the heap. The read method returns an error if the resource does not exist or has already been consumed.
Additional heap methods include size(), nullified_count(), contains(), is_consumed(), is_active(), and alloc_counter(). size() reports allocated resources, including consumed entries that are retained for auditability. The mutable variants alloc_mut and consume_mut modify the heap in place.
Merkle Commitments
Merkle trees commit to active resources and nullifiers.
#![allow(unused)]
fn main() {
use telltale_choreography::heap::{HeapCommitment, MerkleTree};
let tree = MerkleTree::from_heap(&heap);
let proof = tree.prove(0);
let commitment = HeapCommitment::from_heap(&heap);
}
MerkleTree::from_heap hashes active resources. HeapCommitment combines the resource root, nullifier root, and allocation counter.
Error Types
Heap operations return HeapError values.
#![allow(unused)]
fn main() {
pub enum HeapError {
NotFound(ResourceId),
AlreadyConsumed(ResourceId),
AlreadyExists(ResourceId),
TypeMismatch { expected: String, got: String },
Other(String),
}
}
Use these errors to distinguish missing resources from double consumption.
Determinism Notes
All operations are deterministic and avoid hash map iteration order. The resource byte encoding is currently a bespoke format, and future work may replace it with a canonical codec.
See Content Addressing for the type level content ID system and Choreography Effect Handlers for choreography runtime integration.