Lease Lifecycle¶
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.
{
"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.
Cost must match the formula
The ledger validates that amount exactly equals the deterministic cost computed from the resource dimensions and duration. See Cost Model.
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.
{
"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": [...]
}
Stake calculation
Stake = cost / 5, with a minimum of 1 XUSD. The provider must have sufficient XUSD balance to cover the stake.
Acceptance steps¶
- Balance check — verify sufficient XUSD for the stake.
- Resource check — verify available vCPUs, memory, and disk (including resources reserved by in-flight provisions).
- Gather attestations — request signed timestamps from trusted timekeepers (see Attestations). Attestations are mandatory.
- 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.
- Create block — build the
lease_acceptblock withcertificate_hashreferencing the provider's performance certificate. - Validate certificate — the ledger verifies the certificate exists in the gossip cache, belongs to this provider, and is not expired.
- Broadcast — publish to the network via gossip.
- 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:
| Field | Source |
|---|---|
LeaseHash |
Hash of the original lease block |
Consumer |
Lease block's account (creator) |
Provider |
Lease block's destination |
VCPUs |
From the lease block |
MemoryMB |
From the lease block |
DiskGB |
From the lease block |
Duration |
From the lease block (seconds) |
Cost |
Lease block's amount (XUSD) |
Stake |
lease_accept block's amount (XUSD) |
StartTime |
Median attested timestamp (unix nanos) |
AccessPubKey |
From the lease block (ed25519 hex, for SSH access) |
CertificateHash |
Provider's performance certificate hash |
Settled |
false |
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.
{
"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¶
- Check expiry — the
settleLoop()goroutine checks every 10 seconds whethernow >= startTime + duration. - Gather attestations — request signed timestamps for the settle time. Attestations are mandatory.
- Validate duration — the ledger verifies that
attested_settleTime - startTime >= duration(in nanoseconds). Self-reported timestamps are not accepted. - Create block — build the
lease_settleblock with XE emission. - Broadcast — publish to the network.
- Teardown VM — synchronously stop and clean up the virtual machine (not fire-and-forget).
- Return stake — the XUSD stake is returned to the provider's balance.
- Orphan cleanup — the settle loop also cleans up any VMs whose leases are settled but teardown failed.
XE emission
The XE reward uses the same formula as the XUSD cost: LeaseCost(vcpus, memoryMB, diskGB, duration). This means the provider earns an amount of XE numerically equal to the XUSD the consumer paid.
Duration limits¶
| Limit | Value | Human |
|---|---|---|
| Minimum | 60 seconds | 1 minute |
| Maximum | 31,536,000 seconds | 365 days |
The ledger rejects lease blocks with durations outside this range.
Automatic settlement¶
The provider node runs a background settleLoop() goroutine that:
- Ticks every 10 seconds.
- Queries all leases where this node is the provider.
- Skips leases already settled.
- For each expired lease (
now >= startTime + duration), callssettleLease(). settleLease()gathers attestations, creates thelease_settleblock, and tears down the VM.
No manual intervention needed
Providers do not need to manually settle leases. The settleLoop() handles it automatically as long as the node is running.
Lease struct¶
The Lease struct tracks the full state of an active or settled lease:
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¶
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)