Skip to Content

BSA Integration Guide

This guide intends to demonstrate the steps needed to lock and unlock native Bitcoin in the Bitcoin Smart Account architecture

Terminology

  • Smart Account Registry (SAR): The smart contract on Ethereum that records UTXOs and is used by the SC and AO to decide whether BTC should remain in a depositors self-custodial vault, or whether the BTC is allowed to be rebalanced to the Security Consortium.
  • Security Consortium (SC): Lombard’s Security Consortium, where a two-thirds quorum are required to authorize Lombard Protocol operations (mint, redeem, timelocked configuration changes). The SC has secured an average 14,000 BTC over the past 18 months.
  • Arbitration Oracle (AO): A Trusted Execution Environment which validates Bitcoin and SAR state, authorizing return of depositor funds if the Security Consortium performs a malicious act.
  • Lombard’s API: Used for non-critical co-ordination of activities with the Security Consortium and relaying transactions to Ethereum and Bitcoin (untrusted) for non-critical activites.

Prerequisites

  • Install the Go package go get github.com/lombard-finance/bsa-core@v0.0.1-rc8
    • Note: This is pre-release software, provide Github ID to Lombard team for access
    • Import with
      • import bsa "github.com/lombard-finance/bsa-core"
      • import bsalock "github.com/lombard-finance/bsa-core/lock"
      • import "github.com/btcsuite/btcd/wire"
      • import "github.com/btcsuite/btcd/btcutil/psbt"
  • A valid API_KEY issued by Lombard (contact institutional@lombard.finance if required).

Locking Bitcoin

1. Generate PSBTs and deposit transaction

bsalock.GenerateLock( depositorPK []byte, unlockAddressScript []byte, arbitrationPKs [][]byte, defiAddress []byte, defiChainID []byte, nonce uint32, tranches []uint64, fundingUTXOs []*bsalock.FundingUTXO, lockFeeRate *int64 ) (*btcutil.AddressTaproot, *psbt.Packet, map[string]*bsalock.PSBT, error)

where

// PSBT contains PSBTs related to a single deposit UTXO type PSBT struct { UnlockChallengePSBT *psbt.Packet // Unlocking → Unlock challenge RebalanceChallengePSBT *psbt.Packet // Vault → Rebalance challenge CooperativeUnlockPSBT *psbt.Packet // Vault → destination (coop unlock) } // FundingUTXO represents a UTXO used to fund the locked transaction type FundingUTXO struct { OutPoint *wire.OutPoint ScriptPubKey []byte Amount int64 }

Notes:

  • fundingUTXOs must be Segwit or Taproot
  • unlockAddressScript is the address where Bitcoin will be unlocked to. Any valid address type.
  • defiChainID can be retrieved as a constant value in the Ethereum value.

2. Sign PSBTs and deposit transaction

Use your existing cryptographic wallet infrastructure to sign all returned unsignedPSBTs and the deposit transaction.

3. Submit signed PSBTs to Lombard

Lombard’s API will co-ordinate in the background with the Security Consortium’s ledger to sign required PSBTs from the Security Consortium’s perspective, and publish on Ethereum.

Note: The signed deposit transaction is not submitted, this is relayed directly to the Bitcoin network in step 6 after state validation.

POST /api/v2/bsa/locks/initiate HEADER "X-Auth-Api-Key-Token" "API_KEY" { "signer_pk": "fa030...", "unlock_address": "bc1qabc...", "arbitration_pks": [ "6ff31..." ], "defi_address": "0x123abc...", "defi_chain_id": "0x0000...000aa36a7", "nonce": 0, "version" : 0, "vault_address": "tb1p....", "tranches": [ { "tranche": { "amount_sat": 100000, "outpoint": "bc2r3:4" }, "unlock_challenge_sig": "", "rebalance_challenge_sig": "", "cooperative_unlock_sig": "" } ] } RESPONSE 200 { "request_ids": ["12412"] }

4. Fetch the security state on Ethereum

Get tweaks and stored Security Consortium signature from SAR for each tranche using:

{ lockedAmount, defiAddress, operatorUnlockSig, unlockChallengeResolutionSig, rebalanceChallengeResolutionSig, rawTweak, minerFee, unlockAddressScript } = SAR.getUTXODetailsWithTweak(txId, vout)
  • Note: The data is available after BondPending (address account, bytes32 txId, uint32 vout, uint256 value) event is emitted by SAR.

5. Verify the security state

bsalock.VerifyLock( conf *Conf, txID []byte, vout uint32, lockedAmount int64, minerFee int64, unlockAddressScript []byte, rawTweak []byte, defiAddress []byte, sigs [3][]byte ) error
  • sigs is an ordered array of the values [operatorUnlockSig, unlockChallengeResolutionSig, rebalanceChallengeResolutionSig]. No error means the state is verified and safe.

6. Lock BTC on Bitcoin

Relay the deposit transaction previously generated to the Bitcoin network. After approximately 1 hour (6 Bitcoin block confirmations), BTC.b will be minted to the previously specified defiAddress.

If also running an AO, remember to monitor new Bitcoin Smart Accounts, to add the extra protection that AO’s provide for your clients’ funds.

Unlocking Bitcoin

Unlocking Bitcoin requires only one transaction on the destination chain (Ethereum).

To get all unlockable amounts from the SAR, for depositor selection of UTXO’s to unlock, use the SAR.getUTXOsForAccount(address) view function. Any UTXO’s with the status CollateralActive can be unlocked.

  1. On the SAR, call the write function SAR.unlock([]utxo). This will burn the corresponding amount of BTC.b from the DeFi Controller address and set the on-chain status to SpentOnRebalance.

Lombard will orchestrate all operations with the Security Consortium to authorize the return of Bitcoin and relay the transaction to the Bitcoin network.

Note: a web-based user interface tool will be provided via DeFi wallets (supporting WalletConnect).

(Optional) Unilateral Unlock on Bitcoin

If the Security Consortium does not co-operate within a reasonable timeframe after triggering an unlock on the SAR, a unilateral unlock procedure may be initiated.

  1. Get tweaks and stored Security Consortium signature from SAR using { lockedAmount, tweakKey, defiAddress, operatorUnlockSig, rawTweak, minerFee, unlockAddress } = SAR.getUTXODetailsWithTweak(txId, vout)
  2. bsa.CreateUnlockPSBT(conf *Conf, txID []byte, vout uint32, lockedAmount int64, minerFee int64, rawTweak []byte, defiAddress []byte)
  3. Use existing infrastructure to sign
  4. Combine with using bsa.ExtractUnlockTx(signedPsbt *psbt.Packet, rawTweak []byte, operatorUnlockSig []byte) to generate the Bitcoin transaction to relay to the network.

Confirm the depositor has requested unlock on the SAR before triggering a Unilateral Unlock, otherwise the state can be successfully challenged by the Security Consortium.

Last updated on