Skip to content
Astrolune

ALVM v1

skeleton

A frame with the open questions fixed in writing. It records what existing code already constrains and what is genuinely undecided — it does not invent a specification to look finished.

Status: implemented and consensus-visible.

ALVM is a deterministic 64-bit stack machine. Values are unsigned u64. Arithmetic overflow, division by zero, invalid memory access, bad stack shape, unknown opcodes and unknown host calls trap. There is no floating point, clock, threading, filesystem, network, JIT or ambient process state.

Container

A deployed program is one canonical container:

FieldEncoding
magicfour bytes ALVM
container versionu16-le, exactly 1
ISA versionu16-le, exactly 1
flagsu32-le, zero in v1
function countminimal varint, 1..1024
functionscount descriptors
code lengthminimal varint, 1..1 MiB
codeinstruction bytes, no trailing data

A descriptor is offset:u32, parameters:u16, results:u16, max_stack:u16, reserved:u16. Reserved is zero. Function zero is the default entrypoint and has no parameters. A transaction may select any zero-parameter descriptor as its entrypoint. ABI names and source-language metadata are outside the consensus container.

Deployment validation

al_vm_validate and al_vm_program_load use caller-owned arena scratch and do not allocate through malloc/free. Validation predecodes the complete code section, then checks each function independently:

  • every opcode and numbered host is known;
  • immediates and function boundaries are complete and ordered;
  • jump targets stay inside the current function and land on an instruction;
  • every reachable merge has one identical stack height;
  • every path stays within descriptor and genesis stack limits;
  • internal call signatures match their declared pop/push effects;
  • function zero terminates with STOP, RETURN or REVERT;
  • functions reached through CALL follow the frame protocol and terminate with RET;
  • a non-zero function that no CALL targets may instead be a pure entrypoint: zero parameters, terminating with RETURN or REVERT so the transaction layer receives its return data. Mixing both protocols in one function would let RETURN tear down a caller's frames and is rejected;
  • every function's final instruction is a terminator.

Unreachable bytes are still decoded and must be valid. This prevents hiding a second interpretation behind control flow.

Execution

Execution uses a caller-provided arena for stack, linear memory, call frames, active-address tracking and return data. Linear memory has a genesis limit and is zero-initialized. LOAD64 and STORE64 are explicitly little-endian.

Internal calls are synchronous and limited to 64 frames by default. Contract calls are also synchronous. A child REVERT restores its staged state root and events, then returns status/data to the caller. Any other child trap terminates the transaction. The active-address stack rejects a call to any currently active contract with AL_ERR_REENTRANCY.

Host ABI

HOST carries a u16 host number. Arguments are popped from the VM stack and results are pushed in declaration order.

IDOperationStack shape
0write sender address to memory(offset) -> ()
1write current address(offset) -> ()
2block height() -> (height)
3protocol day() -> (day)
4account balance(address_offset) -> (balance)
5transfer from current contract(address_offset, amount) -> ()
6storage get(key_off,key_len,out_off,out_cap) -> (len)
7storage set(key_off,key_len,val_off,val_len) -> ()
8storage delete(key_off,key_len) -> ()
9emit event(topic_off,topic_len,data_off,data_len) -> ()
10tagged hash(data_off,data_len,out_off,tag_id) -> ()
11verify signature(hash_off,pubkey_off,signature_off) -> (valid)
12contract call(addr_off,value,in_off,in_len,out_off,out_cap) -> (status,len)

The tagged-hash host accepts only the stable al_vm_hash_domain IDs: contract data, address, storage key/value, event, PoTB record, transaction and block. Unknown IDs trap with AL_ERR_OUT_OF_RANGE; bytecode cannot supply an arbitrary domain string.

The PoTB system account is not reachable through storage hosts. Only native consensus transitions use the state system bridge.

Resources

Opcode and host compute costs come from al_vm_resource_schedule in genesis. Memory is the peak number of touched 4 KiB pages. Storage I/O is reported by the staged state transaction. Bandwidth is charged by the transaction layer. Every addition and limit comparison uses checked integer arithmetic.

Edit on GitHubSource: 03-vm/vm-spec.md