emit_event
Overview
Section titled “Overview”The emit_event syscall records an event in the transaction’s event log. Events are stored in anonymous memory and become part of the transaction’s output for external consumption.
Syscall Code
Section titled “Syscall Code”Code: 0x0D (TN_SYSCALL_CODE_EMIT_EVENT)
C SDK Function
Section titled “C SDK Function”ulong tsys_emit_event(void const* data, ulong data_sz);Arguments
Section titled “Arguments”data · void const · required*
Pointer to the event data to be recorded.
data_sz · ulong · required
Size of the event data in bytes. Must not exceed the maximum event size.
Return Value
Section titled “Return Value”Returns a syscall result code:
Success · ulong
TN_VM_SYSCALL_SUCCESS(0) - Event recorded successfully
Error Codes · ulong
TN_VM_ERR_SYSCALL_EVENT_IS_ZERO_SIZE(-46) - Event size must be greater than zeroTN_VM_ERR_SYSCALL_EVENT_TOO_LARGE(-31) - Event size exceeds maximum allowedTN_VM_ERR_SYSCALL_INVALID_ADDRESS(-22) - Invalid virtual address for event dataTN_VM_ERR_SYSCALL_INSUFFICIENT_PAGES(-26) - Not enough pages to expand event storage
Resource Consumption
Section titled “Resource Consumption”Compute Units
Section titled “Compute Units”- Base cost:
TN_VM_SYSCALL_BASE_COST(512 units) - Event cost: Additional units equal to event data size in bytes
- Total formula:
base_cost + data_sz
Memory Pages
Section titled “Memory Pages”- Event storage: Pages allocated for event storage in anonymous memory segment
- Automatic expansion: Event storage segment grows as needed (page-aligned)
- Metadata overhead: Additional space for event metadata per event
Side Effects
Section titled “Side Effects”- Event storage: Copies event data to transaction’s event log
- Memory allocation: May expand event storage segment if needed
- Event counter: Increments the transaction’s event count
Event Metadata
Section titled “Event Metadata”The runtime automatically adds internal metadata to each emitted event before exposing it in transaction output. That metadata is not part of the public C SDK surface, so programs should treat the event payload they pass to tsys_emit_event() as the only SDK-facing input.
The metadata attached by the runtime includes:
- Event size: Size of the event data
- Call index: Unique identifier for the program invocation
- Program account index: Index of the program that emitted the event
Storage Management
Section titled “Storage Management”- Events are stored in a grow-up anonymous memory segment
- Storage automatically expands as needed (page-aligned)
- Events are stored sequentially in the order emitted
- Multiple events can be emitted by the same program
Size Limitations
Section titled “Size Limitations”- Maximum event size:
UINT_MAXbytes (4GB) - Practical limits imposed by available memory pages
- Event storage competes with other memory allocations
Usage Notes
Section titled “Usage Notes”- Events are included in transaction output for external consumption
- Event order is preserved within the transaction
- Events from different programs are distinguished by metadata
- Event data format is application-defined
Example
Section titled “Example”#include <thru-sdk/c/tn_sdk_syscall.h>#include <string.h>#include <stdint.h>
// Emit a simple text eventchar event_msg[] = "Account created successfully";ulong result = tsys_emit_event(event_msg, strlen(event_msg));
// Emit structured event datastruct account_created_event { uint64_t account_id; uint64_t initial_balance; char account_type[16];} event = { .account_id = 12345, .initial_balance = 1000000, .account_type = "savings"};
result = tsys_emit_event(&event, sizeof(event));
// Emit multiple related eventsfor (int i = 0; i < transfer_count; i++) { struct transfer_event { uint64_t from_account; uint64_t to_account; uint64_t amount; } transfer = { .from_account = transfers[i].from, .to_account = transfers[i].to, .amount = transfers[i].amount };
result = tsys_emit_event(&transfer, sizeof(transfer)); if (result != TN_VM_SYSCALL_SUCCESS) break;}