Skip to content

Latest commit

 

History

History
139 lines (98 loc) · 4.86 KB

File metadata and controls

139 lines (98 loc) · 4.86 KB

AIP-0006: FlightLock — On‑Chain TOTP Verification (OP_CHECKTOTP) for Avian

AIP:     0006
Title:   FlightLock — On-Chain TOTP Verification (OP_CHECKTOTP) for Avian
Author:  Craig Donnachie <craig.donnachie@gmail.com>
Status:  Draft
Type:    Consensus (soft fork)
Created: 2025-08-11
License: BSD-2-Clause

Abstract

This AIP introduces FlightLock, a consensus feature by introducing a new opcode, OP_CHECKTOTP, that verifies RFC‑6238 TOTP codes on‑chain using Median‑Time‑Past (MTP) as the time base. It enables P2SH/P2WSH scripts that require a valid authenticator app code plus a signature to spend cold‑storage UTXOs.

Motivation

Cold‑storage spends are planned and infrequent. Requiring a TOTP code from an offline device adds a strong second factor without any server. Doing the validation in Script removes trust in wallet software and prevents bypass via off‑chain mistakes.

HOTP vs TOTP

HOTP (HMAC‑based One‑Time Password, RFC 4226) generates codes from a shared secret K and an incrementing counter C:


HOTP(K, C) = Truncate( HMAC(K, C) ) mod 10^digits

The counter increments for each new code. Validation requires the verifier to track and synchronize the counter.

TOTP (Time‑based One‑Time Password, RFC 6238) is built on HOTP but uses time to derive the counter:


T = floor( (current_time − T0) / step )
TOTP(K) = HOTP(K, T)

This removes the need to store counters; both sides just need reasonably synchronized clocks. OP_CHECKTOTP computes HOTP with a time‑derived counter using the blockchain’s MTP.

Specification

New Opcode: OP_CHECKTOTP

Stack before (top → bottom):


<K_i> <code> <hashK_i> <t0> <step> <digits> <skew> <algo>

Where:

  • K_i = per‑UTXO TOTP key (raw bytes)
  • code = integer from authenticator app
  • hashK_i = SHA256(K_i) committed in script
  • t0, step, digits, skew, algo = minimally‑encoded integers

Operation:

  1. Key binding: require SHA256(K_i) == hashK_i.
  2. Time source: compute epoch index T = floor((MTP(parent_of_spend_block) − t0) / step) where MTP is the Median‑Time‑Past of the parent block (BIP113‑style).
  3. Window: for w ∈ {−skew … +skew}, compute code C_w per RFC‑6238 (HOTP truncate) with HMAC(algo, K_i, T+w) and accept if any match.
  4. Result: push 1 on success, else 0.

Fail if digits/step/skew/algo are out of bounds or if any pop/parse step underflows the stack.

Argument bounds / policy:

  • digits ∈ {6,8}
  • step ∈ [15,120] seconds
  • skew ≤ 1
  • algo ∈ {0=HMAC‑SHA1, 1=HMAC‑SHA256, 2=HMAC‑SHA512}

Transactions are non‑standard if arguments are outside these bounds. Standard relay requires spend in P2WSH; non‑segwit spends may be non‑standard if witness/script size is large.

Script Templates

2‑factor single‑sig


OP_SHA256 <hashK_i> OP_SWAP OP_SWAP
<t0> <step> <digits> <skew> <algo>
OP_CHECKTOTP OP_VERIFY
OP_DUP OP_HASH160 <RecipientPKH> OP_EQUALVERIFY
OP_CHECKSIG

Spend stack: &lt;sig&gt; &lt;pubkey&gt; &lt;K_i&gt; &lt;code&gt;

With timeout recovery


OP_IF
  OP_SHA256 <hashK_i> OP_SWAP OP_SWAP
  <t0> <step> <digits> <skew> <algo>
  OP_CHECKTOTP OP_VERIFY
  OP_DUP OP_HASH160 <RecipientPKH> OP_EQUALVERIFY OP_CHECKSIG
OP_ELSE
  <locktime> OP_CHECKLOCKTIMEVERIFY OP_DROP
  OP_DUP OP_HASH160 <RecoveryPKH> OP_EQUALVERIFY OP_CHECKSIG
OP_ENDIF

Key Hygiene

Wallets MUST NOT reuse K_i. Revealing K_i on spend is expected. Derive a unique K_i per UTXO from a master secret K_master:


K_i = HKDF‑SHA256(IKM = K_master,
                  info = "FlightLock" || outpoint || scriptHash,
                  L = 20 or 32)  # 20 for SHA1, 32 for SHA256/512

Wallets should present a QR for K_i compatible with standard authenticator apps.

Deployment

  • VersionBits: use bit 26 (bit 27 = dual‑algo; bit 28 = FlightPath SPV)
  • Threshold: 90% over a 2016‑block window
  • Activation: BIP9‑style state machine

Security Considerations

  • Miner influence: using MTP(parent) limits single‑miner clock control.
  • Replay/guessing: 6/8‑digit window with skew ≤ 1 and per‑UTXO keys make brute force infeasible; signature required.
  • Key reuse: must derive unique K_i per UTXO to avoid cross‑UTXO compromise.
  • Loss of authenticator: recovery path with CLTV is recommended.

Reference Implementation Notes

  • Interpreter: implement constant‑time HMAC for SHA1/256/512 and HOTP truncate; expose parent block MTP to Script.
  • Tests: RFC‑6238 vectors (SHA1/256/512, step=30, digits=6), window edge cases, invalid parameters, policy enforcement, segwit/non‑segwit spends.

Backwards Compatibility

Soft fork: older nodes remain compatible; upgraded miners enforce opcode rules.

Diagram

center|700px


End of AIP‑0006