KiiWORKS / Documentation

Kaspa BlockDAG Integration

SOURCE · docs/kaspa-integration.md · synced from the engineering repo

Kaspa BlockDAG Integration

KiiWORKS uses the Kaspa BlockDAG as its trust anchor — a high-throughput, proof-of-work blockchain with 1 block per second and GHOSTDAG consensus. This document covers how KiiWORKS interacts with Kaspa.


Why Kaspa?

PropertyValue
Block time1 second
ConsensusGHOSTDAG (parallel blocks, no orphans)
Throughput~500 TPS (post-hardfork)
Finality~10 seconds (10 confirmations)
Smart contractsKIP-17 Covenant introspection (Toccata hardfork, ~30 June 2026)
Signature schemeSchnorr over secp256k1
MiningkHeavyHash (optical mining compatible)

Kaspa’s speed and low fees make it practical to anchor every DPP state change individually, rather than batching into daily or weekly anchors.


Architecture

┌─────────────────────┐
│ KiiWORKS Platform   │
│                     │
│  kiiworks-anvil     │ ← HD keys, signing, UTXO selection
│  kiiworks-foundry   │ ← RPC client, TX builder
│  kiiworks-forge     │ ← DID:Kaspa, Verifiable Credentials
│  kiiworks-stamp     │ ← NFT/KRC-20 via anchoring
│  kiiworks-covenant  │ ← KIP-10 covenant scripts
│  kiiworks-vault     │ ← Key storage
└─────────┬───────────┘
          │ wRPC (Borsh)
          │ ws://127.0.0.1:17210
┌─────────┴───────────┐
│ kaspad (Rust node)   │
│ Testnet-12 / Main   │
└─────────────────────┘

Crate Reference

kiiworks-foundry — RPC Client & Transaction Builder

The foundry crate provides the low-level Kaspa interface:

  • KaspaRpc: wRPC client using Borsh serialisation
    • connect(url) → establish persistent connection
    • get_utxos_by_addresses(addresses) → query unspent outputs
    • submit_transaction(tx) → broadcast signed transaction
    • get_block_dag_info() → network status
  • TransactionBuilder: Fluent TX construction
    • .add_input(outpoint, utxo_entry)
    • .add_output(address, amount)
    • .with_change_address(address)
    • .with_fee(amount)
    • .build() → unsigned Transaction
  • NetworkId: Mainnet, Testnet10, Testnet11, Testnet12, Custom(String)

kiiworks-anvil — Keys, Signing, UTXO Selection

  • HdKeyDerivation: BIP-44 path m/44'/111111'/0'/0/{index}
    • From mnemonic → master key → derived keypair
  • SchnorrSigner: Transaction signing
    • sign_transaction(tx, private_keys, utxo_entries) → signed TX
    • BLAKE2b-256 sighash with key b"TransactionSigningHash"
  • UtxoSelector: Coin selection algorithms
    • Largest-first selection
    • Minimum change output (≥ 1 KAS to avoid KIP-9 mass penalty)
  • BurnAnchor: P2PK anchoring
    • build_anchor_script(anchor_type, hash) → script with hash embedded
    • extract_anchor_hash(script) → recover hash from script

kiiworks-forge — DID & Verifiable Credentials

  • DidKaspaMethod: DID operations
    • create(public_key, network)did:kaspa:{network}:{hex_pubkey}
    • resolve(did)DidDocument with verification methods
    • DID documents follow W3C DID Core 1.0
  • VcIssuer: Verifiable Credential issuance
    • issue(claims, issuer_did, private_key) → signed VC (JSON-LD)
    • verify(vc) → resolve issuer DID, verify Schnorr signature
  • TrustTag: Blockchain-anchored trust markers
    • Hash of VC → anchor on Kaspa → tag ID = TX ID

kiiworks-stamp — NFT & Token Operations

  • NFT minting: Create non-fungible tokens via on-chain anchoring
  • KRC-20: Kaspa token standard operations (mint, transfer, burn)
  • All operations use the P2PK burn strategy since Kaspa has no OP_RETURN

kiiworks-covenant-sdk — KIP-10 Covenants

Available after the Toccata hardfork (~30 June 2026, KIP-17 covenant introspection).

  • CovenantScript: Script compilation
    • Lock conditions: timelock, hash preimage, multisig, data check
    • Unlock proofs: satisfy one or more conditions
  • EscrowCovenant: Pre-built escrow pattern
    • Payer deposits → conditions met → payee withdraws
    • Automatic refund if conditions not met by expiry

On-Chain Anchoring

P2PK Burn Strategy

Kaspa does not support OP_RETURN (rejected as NonStandard by the mempool). KiiWORKS uses P2PK burn anchoring instead:

Script: [0x20][32-byte-hash][0xac]
         OP_DATA_32  data_hash  OP_CHECKSIG

This creates a valid P2PK script where the “public key” is actually the data hash. The output is computationally unspendable — functionally a burn output (no one has the private key for an arbitrary hash) — but the transaction is accepted by the network.

Anchor Flow

Data (DPP state, VC, etc.)


    SHA-256 hash (32 bytes)


  BurnAnchor::build_anchor_script(type, hash)


  TransactionBuilder
    .add_input(utxo)                    ← From wallet
    .add_output(burn_script, 1 KAS)     ← Minimum 1 KAS (KIP-9)
    .with_change_address(wallet)
    .with_fee(30_000 sompi)             ← Safe default
    .build()


  SchnorrSigner::sign_transaction(tx, keys, entries)


  KaspaRpc::submit_transaction(signed_tx)


  TX confirmed in ~10 seconds (10 blocks)

Verification

TX ID


KaspaRpc::get_transaction(tx_id)


BurnAnchor::extract_anchor_hash(output_script)


Compare hash with SHA-256(original_data)


Match → data existed at block timestamp

Merkle Batch Anchoring

For high-volume anchoring (e.g., hundreds of DPPs per hour), use the kiiworks-anchor-tree crate:

  1. Collect N items to anchor
  2. Compute SHA-256 of each item → leaf hashes
  3. Build Merkle tree → single root hash (32 bytes)
  4. Anchor the root hash on Kaspa (1 transaction)
  5. Generate inclusion proof for each item
  6. Distribute proofs to item owners

This reduces blockchain cost from O(N) to O(1) transactions while maintaining individual verifiability.


Wallet Management

HD Derivation

KiiWORKS uses BIP-39/BIP-44 hierarchical deterministic wallets:

BIP-39 Mnemonic (12 or 24 words)


    512-bit Seed


  Master Key (BIP-32)


  m/44'/111111'/0'/0/0  →  First address
  m/44'/111111'/0'/0/1  →  Second address
  m/44'/111111'/0'/0/N  →  Nth address
  • Coin type 111111 is the Kaspa BIP-44 identifier
  • Each derived key is a secp256k1 keypair
  • Addresses use Bech32 encoding: kaspa:qr... (mainnet) or kaspatest:qr... (testnet)

Transaction Construction

// 1. Query UTXOs
let utxos = rpc.get_utxos_by_addresses(&[address]).await?;

// 2. Select inputs
let selected = UtxoSelector::select(&utxos, amount + fee)?;

// 3. Build transaction
let tx = TransactionBuilder::new()
    .add_inputs(&selected)
    .add_output(recipient, amount)
    .with_change_address(address)
    .with_fee(30_000) // sompi
    .build()?;

// 4. Sign
let signed = SchnorrSigner::sign_transaction(tx, &[private_key], &selected)?;

// 5. Submit
let tx_id = rpc.submit_transaction(signed).await?;

KIP-9 Mass Considerations

Kaspa’s KIP-9 introduces storage mass — tiny outputs from large inputs trigger exponentially higher transaction mass (and thus fees). Always:

  • Use outputs ≥ 1 KAS (100,000,000 sompi) to avoid mass penalty
  • Use minimum_fee_for_mass() to calculate the correct fee
  • Default fee of 30,000 sompi is safe for simple transactions

DID:Kaspa Identity

Format

did:kaspa:{network}:{hex_public_key}

Examples:
  did:kaspa:mainnet:a1b2c3d4e5f6...   (64 hex chars = 32-byte x-only pubkey)
  did:kaspa:testnet-12:a1b2c3d4e5f6...

Resolution

DidKaspaMethod::resolve(did) produces a W3C DID Document:

{
  "@context": ["https://www.w3.org/ns/did/v1"],
  "id": "did:kaspa:testnet-12:a1b2c3...",
  "verificationMethod": [{
    "id": "did:kaspa:testnet-12:a1b2c3...#key-1",
    "type": "SchnorrSecp256k1VerificationKey2024",
    "controller": "did:kaspa:testnet-12:a1b2c3...",
    "publicKeyMultibase": "z..."
  }],
  "authentication": ["did:kaspa:testnet-12:a1b2c3...#key-1"],
  "assertionMethod": ["did:kaspa:testnet-12:a1b2c3...#key-1"]
}

Authentication Flow

  1. Client sends POST /api/identity-auth/challenge with their DID
  2. Server generates random nonce, stores with expiry
  3. Client signs nonce with their private key (Schnorr)
  4. Client sends POST /api/identity-auth/verify with DID + signature
  5. Server resolves DID → extracts public key → verifies Schnorr signature
  6. If valid → issue JWT token

Cross-Chain Anchoring

The kiiworks-bridge crate provides a ChainAdapter trait for multi-chain anchoring:

#[async_trait]
pub trait ChainAdapter: Send + Sync {
    fn chain_id(&self) -> ChainId;
    async fn anchor(&self, request: AnchorRequest) -> Result<AnchorReceipt>;
    async fn verify(&self, request: VerifyRequest) -> Result<VerifyResult>;
}

Supported chains:

  • Kaspa (native, full implementation)
  • EVM / EBSI (full implementation; see guides/ebsi-evm-anchor.md). One unified adapter covers:
    • EBSI — the EU-sovereign permissioned Besu network (regulator-facing pilots)
    • Public Ethereum L2s — Optimism, Arbitrum, Base, Linea, plus their Sepolia testnets
    • Ethereum mainnet + Sepolia

The BridgeRegistry enables anchoring the same hash on multiple chains simultaneously for redundancy. The EVM adapter signs EIP-1559 type-2 transactions and supports two anchor modes: calldata-only (the 32-byte payload hash is the transaction’s data field, sent to the zero address — ~21,500 gas, cheap, retrievable via eth_getTransactionByHash) and contract-call (the adapter calls AnchorRegistry.anchor(bytes32) at an operator-deployed registry address — ~50,000 gas, queryable via the isAnchored(hash, anchorer) view and the AnchorAdded event). EBSI networks require contract-call mode per the EBSI ledger v4 data-anchor RFC; the adapter enforces this at construction. See the EBSI / EVM Anchor Guide for the AnchorRegistry deployment procedure, cost analysis per network, and operational notes.


Covenants (KIP-17, Toccata)

Target: Kaspa Toccata hardfork (~30 June 2026, DAA 474,165,565; KIP-16/17/20/21)

Covenants enable smart contract-like functionality on Kaspa. KiiWORKS uses them for:

Escrow

Lock: "Release 10 KAS to address X when:
  1. DPP hash matches (proof of delivery), AND
  2. 3-of-5 multisig approval, AND
  3. Block time > 2026-04-01"

Time-Locked Disclosure

Lock: "Reveal encryption key when block time > target_date"

Supply Chain Gates

Lock: "Transfer ownership token when lifecycle stage >= 'shipped'"

The kiiworks-covenant-sdk compiles these conditions into Kaspa script and provides unlock proof construction.