System Architecture
End-to-end view of how Bitcoin, the SPV Relayer, the four Soroban contracts, and the browser interact.
- Bitcoin — P2WSH locks collateral; two spending paths (cooperative co-sign or CLTV timelock)
- SPV Relayer — watches Bitcoin, produces Merkle inclusion proofs on demand
- Soroban contracts —
bitcoin-spv,zk-verifier,commitment-tree,private-lendverify proofs and manage positions - Browser — generates all ZK proofs locally; private witness values never leave the device
Deposit Flow
Step-by-step path from connecting a Bitcoin wallet to having an active position on Stellar.
- Connect Bitcoin wallet (Xverse) and Stellar wallet (Freighter)
- Derive unique P2WSH address from protocol key + user key + timelock height
- Send BTC to that address on-chain
- Relayer produces SPV proof (block headers + Merkle path)
- Browser generates Groth16 ZK proof binding commitment to the Bitcoin txid
commitment-tree.deposit()verifies SPV proof + ZK proof on Soroban- Admin calls
insert_commitment()— position becomes active
Borrow & Repay Flow
How the protocol updates the Merkle commitment on every borrow or repay, preserving privacy throughout.
- Borrow:
delta = amount_stroops,is_borrow = 1 - Repay:
delta = (FIELD_PRIME − amount) mod FIELD_PRIME,is_borrow = 0 - The nonce rotates on every action; the commitment
Poseidon(collateral, debt, secret, nonce)is replaced in the tree
BTC Release Flow (Path A)
Cooperative co-signed release after full repayment.
- The server (
/api/cosign) verifies the commitment is no longer pending before signing PROTOCOL_SIGNING_KEYis server-only — never exposed to the browser- Final witness:
[user_sig, protocol_sig, 0x01, redeemScript]
ZK Circuits
All three Groth16 circuits (Circom / BN254), their private inputs, public inputs, and public outputs.
Commitment State Machine
Complete lifecycle of a position from pending to BTC release (or liquidation).
Soroban Contract Interactions
How the four live testnet contracts call each other.
Regenerating Diagrams
docs/diagrams/output/*.svg and *.png