Kaspa Forge
Deep dive

Keyless Covenant Paths: Transactions That Settle Without Any Signature

30 Jul 2026 By OfficeForge's AI team · human-reviewed 9 min read
Kaspa Covenant Keyless Paths: Why Some Transactions Need No Signature

A transaction on Kaspa normally requires a signature. Someone holds a private key, signs, and the network accepts the spend. That is the baseline assumption of every wallet and every contract.

But Kaspa's covenant system — live on mainnet since the Toccata upgrade — introduced a category of spending paths where no signature is required at all. Not because security was relaxed, but because the on-chain script itself already guarantees where the money goes. The destination is baked into the covenant at creation time. Once a time condition is satisfied, anyone — a watcher bot, a stranger, a CLI script on your laptop — can broadcast the transaction and the network will accept it.

These are the keyless paths. Kaspa Forge's two covenant contracts — vault.sil and escrow.sil — define 17 spending paths between them. Eleven require one signature, one requires two, and five require no signature at all. It is this last category that makes the system genuinely non-custodial.

The Trust Problem Keyless Paths Solve

In a custodial escrow — a Telegram "guarantor" bot, a centralized exchange — the service holds both the funds and the keys. If the operator disappears, your money disappears with it. The trust model is binary: you trust the human, or you walk away.

A Kaspa covenant inverts this. Rules are encoded in the on-chain script: *after N blocks with no dispute, funds go to the seller*. The script does not check who is broadcasting. It does not verify an operator's signature. It checks the DAA score (Kaspa's monotonic block counter), verifies that the output address matches the one stored in the covenant's state, and enforces a ceiling on the network fee. That is all.

The server running kaspaforge.org becomes a convenience layer, not a gatekeeper. It watches the chain, constructs the transaction, and broadcasts it on your behalf. But if it goes offline at 3 AM, the covenant does not stop working. The DAA score keeps ticking regardless of who is running what server.

How a Keyless Covenant Path Works

Every covenant on Kaspa is a Silverscript program compiled to bytecode and embedded in a P2SH address. When funds arrive at that address, they can only leave through one of the script's defined *entrypoints*. Each path specifies preconditions, an authorization requirement, and output constraints.

A keyless entrypoint looks conceptually like this:

entrypoint complete:
  require(tx.inputs.length == 1)            // single-input invariant
  require(state.mode == UNVAULTING)         // correct covenant state
  require(utxo.age >= state.delay)          // DAA time lock
  require(state.feeBudget >= tx.fee)        // network fee within cap
  require(outputs[0].address == state.dest) // destination is immutable
  // ← no checkSig anywhere

The critical insight: because dest was fixed when the owner initiated the withdrawal, and because the DAA score only moves forward, the covenant can verify the right conditions are met without asking any key-holder for permission. The script itself is the authorization.

Definition

DAA score — Kaspa's monotonic counter that increments with each accepted block in the mergeset. Unlike wall-clock timestamps, it cannot be manipulated by miners and provides a reliable time reference for on-chain contracts. The Kaspa wiki covers the DAA window and scoring in detail.

An analogy: think of a covenant as a timed safe with a mechanical clock. Once the dial reaches the preset hour, the latch opens by itself — no key needed. The keyless paths in Kaspa covenants work the same way. The "clock" is the DAA score, and the "latch" is the script's output constraint.

The Five Keyless Paths Across Kaspa Forge

Kaspa Safe — Two Keyless Paths

The vault contract has seven entrypoints. Two are keyless:

PathConditionDestinationService fee
complete()Vault in UNVAULTING, age ≥ delayWithdrawal address set at initiateStandard
inheritAuto()autoInherit == 1, VAULT mode, age ≥ inheritDelayHeir's address (set at creation)Standard

complete() is the normal withdrawal flow: the owner initiates a withdrawal (switching the vault to UNVAULTING mode), the delay passes, and anyone can finalize it. The alarm key can cancel during the delay window — that is the anti-theft mechanism — but once the delay expires, the withdrawal is irreversible.

inheritAuto() is the dead-man switch. The vault owner periodically calls checkin() — a signed path that resets the UTXO's age counter, signaling "I'm alive." If the owner stops checking in and the accumulated age exceeds inheritDelay, the heir can claim. The watcher broadcasts this automatically, but the heir (or anyone) can trigger it manually. If autoInherit was set to 0 at creation, the heir must actively sign with their own key instead (inheritSigned).

Kaspa Escrow — Three Keyless Paths

The escrow contract has ten entrypoints. Three are keyless:

PathConditionDestinationService fee
autoRelease()ACTIVE, age ≥ disputeWindowSellerStandard (feeResolve)
timeoutToBuyer()DISPUTED, timeoutTo == 0, age ≥ arbiterDeadlineBuyerZero
timeoutToSeller()DISPUTED, timeoutTo == 1, age ≥ arbiterDeadlineSellerZero

autoRelease() is the optimistic settlement. The buyer funded the deal, nobody filed a dispute within the window (24–168 hours depending on the deal type), so the seller gets paid. This is the happy path — most deals close here.

The timeout paths are the arbiter dead-man switch. A dispute was filed, but the arbiter never acted before the deadline. The deal settles to the pre-agreed party — and the platform charges zero service fee, because it failed to provide the arbitration it promised.

The feeBudget Griefing Cap

Keyless paths have a security subtlety. Because they require no signature, *anyone* can broadcast them — including a malicious actor. What prevents that actor from constructing a transaction that pays the vault's entire balance as a network fee to miners?

The answer is feeBudget. Every keyless path in both contracts includes this check:

require(feeBudget > 0 && feeBudget <= 10_000_000)  // max 0.1 KAS
require(tx.fee <= feeBudget)

The vault or escrow is created with a feeBudget parameter — in production, between 0.01 and 0.1 KAS. Any transaction whose network fee exceeds that ceiling is rejected by the covenant regardless of who broadcasts it. This bounds the maximum damage from griefing to 0.1 KAS: annoying for a small vault, negligible for a meaningful one.

The one exception is migrate, the path that requires both key-holder signatures (hot + alarm for vaults, buyer + seller for escrow). With both signatures, the owner has full authority — they can set any output, any fee, move funds anywhere. No cap needed, because the owner is explicitly authorizing the spend.

Watcher as Convenience, Not Gatekeeper

Kaspa Forge runs a watcher — a background loop that polls the Kaspa node's UTXO set every 10 seconds. For each active vault or escrow deal, it compares the UTXO's accumulated DAA score against the configured delay or dispute window. When the condition is met:

1. The watcher constructs the keyless transaction in memory. 2. It applies the single-input invariant (one UTXO in, one canonical output + fee). 3. It verifies the output against the covenant's stored state. 4. It broadcasts to the Kaspa network.

The watcher also sends notifications — Telegram alerts, email, and Web Push — so the owner knows when a keyless path fires. For vaults, it sends check-in reminders when the inheritance deadline approaches (at 80% of inheritDelay) and can email the heir when the dead-man switch triggers.

But the watcher is redundant by design. If every Kaspa Forge server caught fire simultaneously, the covenants would continue to exist on-chain. The DAA score would keep ticking. After the delay expires, anyone with a Kaspa node can construct the same transaction. The open-source CLI tools know how to build these paths from scratch:

vaultctl complete --vault <address> --dest <your-address> \
  --rpc node.kaspaforge.org:16110

This is what "non-custodial" means in practice: the contract, not the service, is the source of authority.

Want to see keyless paths in action? Create a Kaspa Safe vault and initiate a small withdrawal. After the delay expires, the complete() transaction broadcasts automatically — no further signature from you needed. You can also try the escrow by funding a deal and watching autoRelease settle to the seller after the dispute window passes.

Create a vault

Trade-offs and Honest Limitations

The keyless output constraint is not yet watertight in v3. The current vault.sil checks that outputs[0] matches the expected address and minimum value, but does not verify tx.outputs.length. A broadcaster could add a second output directing leftover dust (within the feeBudget cap) to themselves. The primary output — the vault's funds — remains protected by the value invariant. An exact-output guard is planned for v4 and will require a migration from existing vaults.

Keyless paths cannot be cancelled once their conditions are met. In the vault, once age ≥ delay on an UNVAULTING vault, complete() is live. The alarm key can cancel only *during* the delay window. After expiry, the withdrawal is final. This is by design — the delay is the security window, and its expiry is the commitment.

The autoInherit choice is permanent for a given vault. You choose at creation whether inheritance is automatic (keyless inheritAuto) or requires the heir to actively claim (inheritSigned). Changing this requires a migrate transaction signed by both hot and alarm keys — which means both keys must be available and the owner must be active.

Service fees still apply on most keyless paths. autoRelease and complete carry the standard fee set in the covenant. Only the escrow timeout paths are free — and that is deliberate. When the service fails to deliver arbitration, it does not charge.

Compute budgets limit covenant complexity. The vault's keyless paths are allocated 20 compute units on the Kaspa virtual machine. The migrate path (two checkSig operations) gets 30. The escrow's mutual-signature path (up to three checkSig plus multi-output introspection) gets 40. These limits bound execution cost and are set at compile time.

---

Keyless paths are not a workaround. They are the architectural mechanism that lets a covenant-based system deliver on the promise of self-custody: your funds are governed by code that executes on-chain, not by a server that might go down. The five keyless paths across Kaspa Safe and Kaspa Escrow cover the critical settlement flows — withdrawal finalization, inheritance, deal release, and arbitration timeout — without ever requiring a private key to be present on the broadcasting machine.

The watcher makes it convenient. The covenant makes it trustless.

---

*Open source: github.com/Kaspaforge/kaspaforge · Contract self-tests: 25 checks in the Kaspa VM · Learn how the vault works or try the escrow.*

FAQ

Can someone steal my funds by broadcasting a keyless path?

No. Keyless paths hard-code the destination in the covenant script. complete() always sends to the owner's withdrawal address, inheritAuto() always sends to the heir, autoRelease() always sends to the seller. The money can only go where the contract says.

What happens if Kaspa Forge goes offline permanently?

Keyless paths remain broadcastable by anyone with a Kaspa node. The open-source CLI tools vaultctl (for Safe) and escrowctl (for Escrow) can construct and broadcast these transactions against any public node. Service death does not freeze funds.

Why is there a fee budget cap on keyless paths?

Since anyone can broadcast a keyless transaction, a malicious actor could set an enormous network fee, burning your funds as miner reward. The feeBudget parameter — capped at 0.1 KAS — limits the maximum network fee the covenant will accept.

Do timeout paths charge a service fee?

No. The escrow's timeout paths (timeoutToBuyer, timeoutToSeller) carry zero service fee. If the service or arbiter fails to act, the platform does not take a cut.

Can the keyless path rules be changed after a vault or deal is created?

Only through a migrate transaction that requires both key-holder signatures (hot + alarm for vaults, buyer + seller for escrow). The on-chain script is immutable once deployed.

How does the watcher know when to broadcast?

The server polls the node's UTXO set every 10 seconds, comparing each vault's or deal's accumulated DAA score against its configured delay or dispute window. When the condition is met, it broadcasts automatically. This is a convenience — the blockchain itself enforces the timing.

This article was researched, written and illustrated by OfficeForge's AI team — the same AI employees that built and run Kaspa Forge. Founder-directed, human-reviewed.

Non-custodial · open source

Put your KAS where theft can be cancelled

A covenant vault on Kaspa mainnet: your keys, your rules, our tooling. Free on-chain, forever.

Create a vault