RequantTESTNET
Requant documentation

Spending conditions, swaps and channels

Requant has limited smart contracts in the Bitcoin sense: fixed templates in consensus, not a script language. They cover what atomic swaps and payment channels need — one-way and two-way, with a penalty for cheating — so the protocols can be built in software without a later hard fork.

TemplateWhat it doesActive on the test network from
2-of-2two keys must both signheight 1400
HTLCclaim with a secret, or refund after a timeoutheight 1400
Time locksabsolute (a block height) and relative (blocks after the coin) on any inputheight 1400
Revocable outputthe owner after a relative delay, or the revocation key at onceheight 4700
Revocable HTLCan HTLC with delays on its claim and refund paths and a revocation pathheight 4700
Anyone-can-paya signature over its own input and all outputs, so others may add inputsheight 4700
k-of-noff chain: FROST or MuSig2 aggregate ed25519 keys into one ordinary keyalways

On a main network all of them are active from genesis. Nodes older than 0.16.0 leave the test network at the first block that uses the templates of height 4700.

How a condition looks on the chain

An output always pays a 32-byte hash. Besides a key's pkh, it may be the hash of a condition, revealed only by the input that spends it. Until then a locked coin looks like any other, and locking coins is an ordinary transfer to the condition's address.

multi2           = H("requant/multi2", pubkey_a || pubkey_b)
htlc             = H("requant/htlc", hash || claim_pkh || refund_pkh || LE64 timeout)
delayed          = H("requant/delayed", owner_pkh || revoke_pkh || LE32 delay)
htlc-revocable   = H("requant/htlc-revocable", hash || claim_pkh || refund_pkh || revoke_pkh
                     || LE64 timeout || LE32 claim_delay || LE32 refund_delay)

Spending paths

A transfer that uses a condition or a lock is kind 2. Each input carries its locks (after_height, after_blocks) and an unlock:

UnlockSpendsNeeds
0 keya key's outputthe key
1 multi2a 2-of-2both keys, signing the same message
2 htlc claiman HTLCthe claim key and the 32-byte secret whose SHA-256 is hash
3 htlc refundan HTLCthe refund key and after_height ≥ timeout
4 delayed ownera revocable outputthe owner key and after_blocks ≥ delay
5 delayed revokea revocable outputthe revocation key
6 revocable claima revocable HTLCclaim key, the secret and after_blocks ≥ claim_delay
7 revocable refunda revocable HTLCrefund key, after_height ≥ timeout, after_blocks ≥ refund_delay
8 revocable revokea revocable HTLCthe revocation key

The top bit of the unlock byte is the anyone-can-pay flag. Such an input signs H("requant/sighash-acp", chain_id || version || its own input || all outputs) instead of the whole transaction, so others may add inputs later; changing an output breaks the signature.

Time locks are checked for the block at height h that contains the transfer and the spent coin's height c: h ≥ after_height and h − c ≥ after_blocks. A pre-signed transfer with a lock cannot enter a block or a node's mempool early.

Design details that matter:

  • The txid omits signatures, so pre-signed refund and commitment transactions keep their references.
  • The secret is exactly 32 bytes and hash its plain SHA-256, as Bitcoin-family OP_SHA256 and EVM sha256 contracts check it.
  • A kind-2 encoding without any condition, lock or flag is invalid, so every transaction has exactly one encoding.

From the wallet

requant-wallet 0.5.0 describes conditions, locks coins under them and spends them along any path, with the time locks the path needs:

requant-wallet secret                                      # a 32-byte secret and its sha256
requant-wallet pubkey my.wallet                            # public key of the current address
requant-wallet condition htlc <sha256> <claim> <refund> <timeout height> --out htlc.json
requant-wallet condition multi2 <pubkey A> <pubkey B> --out m2.json
requant-wallet condition delayed <owner> <revoke> <delay blocks> --out d.json
requant-wallet condition htlc-revocable <sha256> <claim> <refund> <revoke> <timeout> <claim delay> <refund delay> --out r.json
requant-wallet send my.wallet <condition address> 1        # lock 1 RQT under it
requant-wallet spend-condition my.wallet htlc.json claim <to> --preimage <secret>
requant-wallet spend-condition my.wallet htlc.json refund <to>
requant-wallet spend-condition a.wallet m2.json both <to> --out part.json   # first signature
requant-wallet cosign b.wallet part.json                   # second signature, then send

--anyone-can-pay signs only the input and the outputs. The condition file holds the parameters and the address and is checked when it is read. The node's conditionaddress RPC computes the same addresses.

Fees on pre-signed transfers

Refunds and channel states are signed long before they are sent. Node 0.16.0 gives three ways to get them in when fees rise:

  • Child pays for parent: blocks take transactions by the rate of the package they complete with their ancestors, so a child spending one of their outputs can pay for both.
  • Anyone-can-pay: a transfer signed with the flag accepts an extra input that raises the fee.
  • Replace by fee: a single-signer transfer can be replaced by one that pays more in total and at a higher rate.

Every transaction must still pay the minimum relay rate (1 atom per byte) on its own: nodes do not yet relay packages with a cheaper parent.

What can be built

HTLC swaps with Bitcoin-family and EVM chains

Party A picks a secret and publishes its SHA-256 hash. Both lock coins under that hash; the RQT timeout must be well after the other chain's. Claiming one side reveals the secret, which unlocks the other. The shared hash, amounts and timing link the two halves.

Monero swaps with adaptor signatures

RQT is locked in a 2-of-2 output, with cancel, refund and punish transfers on relative time locks. Requant and Monero both use ed25519, so no cross-curve proof is needed. Still to build: ed25519 adaptor signatures, MuSig2 aggregation, the protocol state machine and an external review.

One-way payment channels

A client deposits into a 2-of-2 with a refund to itself after an expiry height, signed by the server, and then signs ever larger payments to the server. A newer state always pays the server more, so no revocation is needed. This is the basis for paying network services such as MagnetGate per use.

Two-way channels with a penalty

Each party holds its own version of the latest commitment transfer from the 2-of-2 deposit. In it, its own balance pays a revocable output — itself after a delay, or the other party's revocation key at once — and the other party's balance pays the other party directly. Moving to a new state, each side gives the other the secret of its revocation key for the old one. Publishing a revoked state then lets the other side take the publisher's balance through the revocation path before the delay ends. Payments routed through channels sit in revocable HTLCs.

Status

  • Built: the consensus templates and their tests, the pool policy, the wallet commands and conditionaddress.
  • Not built: swap tools, a maker bot, channel software and package relay.
  • Needed before real value: confirmation depth scaled to amount and hashrate, and an external review of the templates and the protocols.

Design notes: SWAPS.md. Normative rules: CHAIN.md §4.1–4.3.