Lease Lifecycle

The states a compute lease moves through

A compute lease passes through three phases: creation, acceptance, and settlement. Each phase produces an on-chain block that the ledger validates.

#Phase 1: Lease creation (consumer)

The consumer creates a lease block on their account chain. This debits XUSD from their balance to pay for the requested resources.

json
{  "type": "lease",  "account": "<consumer pubkey>",  "previous": "<frontier hash>",  "balance": "<previous XUSD balance - cost>",  "asset": "XUSD",  "destination": "<provider pubkey>",  "amount": "<cost>",  "vcpus": 2,  "memory_mb": 4096,  "disk_gb": 50,  "duration": 3600,  "access_pub_key": "<ed25519 pubkey hex, 64 chars>"}

The block is signed, PoW-solved, and broadcast to the network via gossip.

#What happens on broadcast

The lease block creates a pending send to the provider. The provider's node sees this pending send and -- if configured with -provide -- automatically begins the acceptance flow.

#Phase 2: Lease acceptance (provider)

The provider creates a lease_accept block on their account chain. This stakes XUSD collateral and records timekeeper-attested start time.

json
{  "type": "lease_accept",  "account": "<provider pubkey>",  "previous": "<frontier hash>",  "balance": "<previous XUSD balance - stake>",  "asset": "XUSD",  "source": "<lease block hash>",  "amount": "<stake>",  "certificate_hash": "<performance certificate hash>",  "attestations": [...]}

#Acceptance steps

  1. Balance check — verify sufficient XUSD for the stake.
  2. Resource check — verify available vCPUs, memory, and disk (including resources reserved by in-flight provisions).
  3. Gather attestations — request signed timestamps from trusted timekeepers (see Attestations). Attestations are mandatory.
  4. Provision VM — start the virtual machine with the requested resources. This happens before the accept block is committed — if provisioning fails, the lease is not accepted.
  5. Create block — build the lease_accept block with certificate_hash referencing the provider's performance certificate.
  6. Validate certificate — the ledger verifies the certificate exists in the gossip cache, belongs to this provider, and is not expired.
  7. Broadcast — publish to the network via gossip.
  8. Send credentials — deliver VM access info to the consumer via direct messaging.

#Lease record

When the ledger processes a valid lease_accept, it creates a Lease record:

FieldSource
LeaseHashHash of the original lease block
ConsumerLease block's account (creator)
ProviderLease block's destination
VCPUsFrom the lease block
MemoryMBFrom the lease block
DiskGBFrom the lease block
DurationFrom the lease block (seconds)
CostLease block's amount (XUSD)
Stakelease_accept block's amount (XUSD)
StartTimeMedian attested timestamp (unix nanos)
AccessPubKeyFrom the lease block (ed25519 hex, for SSH access)
CertificateHashProvider's performance certificate hash
Settledfalse

#Phase 3: Settlement (provider)

After the lease duration expires, the provider creates a lease_settle block. This earns XE emission and returns the XUSD stake.

json
{  "type": "lease_settle",  "account": "<provider pubkey>",  "previous": "<frontier hash>",  "balance": "<previous XE balance + emission>",  "asset": "XE",  "source": "<lease block hash>",  "amount": "<XE emission>",  "attestations": [    {      "public_key": "<timekeeper pubkey hex>",      "timestamp": 1709658000000000000,      "signature": "<attestation signature hex>"    }  ]}

#Settlement steps

  1. Check expiry — the settleLoop() goroutine checks every 10 seconds whether now >= startTime + duration.
  2. Gather attestations — request signed timestamps for the settle time. Attestations are mandatory.
  3. Validate duration — the ledger verifies that attested_settleTime - startTime >= duration (in nanoseconds). Self-reported timestamps are not accepted.
  4. Create block — build the lease_settle block with XE emission.
  5. Broadcast — publish to the network.
  6. Teardown VM — synchronously stop and clean up the virtual machine (not fire-and-forget).
  7. Return stake — the XUSD stake is returned to the provider's balance.
  8. Orphan cleanup — the settle loop also cleans up any VMs whose leases are settled but teardown failed.

#Duration limits

LimitValueHuman
Minimum60 seconds1 minute
Maximum31,536,000 seconds365 days

The ledger rejects lease blocks with durations outside this range.

#Automatic settlement

The provider node runs a background settleLoop() goroutine that:

  1. Ticks every 10 seconds.
  2. Queries all leases where this node is the provider.
  3. Skips leases already settled.
  4. For each expired lease (now >= startTime + duration), calls settleLease().
  5. settleLease() gathers attestations, creates the lease_settle block, and tears down the VM.

#Lease struct

The Lease struct tracks the full state of an active or settled lease:

go
type Lease struct {    LeaseHash    string // hash of the lease block    Consumer     string // consumer account (lease block creator)    Provider     string // provider account (lease block destination)    VCPUs        uint64    MemoryMB     uint64    DiskGB       uint64    Duration     uint64 // seconds    AccessPubKey string // ed25519 pubkey hex for SSH access    Cost         uint64 // XUSD paid by consumer    Stake        uint64 // XUSD staked by provider    StartTime       int64  // unix nanos (median attested timestamp)    CertificateHash string // provider's performance certificate    Settled         bool}

#Sequence diagram

diagram
Consumer Node                  Network                  Provider Node     │                           │                           │     │  create lease block       │                           │     │  (debit XUSD)             │                           │     │ ─────────────────────────►│                           │     │                           │  gossip lease block       │     │                           │──────────────────────────►│     │                           │                           │  detect pending send     │                           │                           │  check resources available     │                           │                           │  gather start attestations     │                           │                           │  provision VM (before accept!)     │                           │                           │  create lease_accept     │                           │  gossip lease_accept      │  (stake XUSD + cert hash)     │                           │◄──────────────────────────│     │  receive VM credentials   │                           │  send credentials     │◄──────────────────────────│───────────────────────────│     │                           │                           │     │       ... lease duration elapses ...                  │     │                           │                           │     │                           │                           │  settleLoop detects expiry     │                           │                           │  gather settle attestations     │                           │                           │  create lease_settle     │                           │  gossip lease_settle      │  (earn XE, recover stake)     │                           │◄──────────────────────────│     │                           │                           │  teardown VM (synchronous)