Skip to content

Instantly share code, notes, and snippets.

@GeneFerneau
Last active October 22, 2021 04:05
Show Gist options
  • Save GeneFerneau/65b456d1730830b5ba7582197afc8b8a to your computer and use it in GitHub Desktop.
Save GeneFerneau/65b456d1730830b5ba7582197afc8b8a to your computer and use it in GitHub Desktop.
CoinSwap PTLC protocol

CoinSwap PTLC protocol

Below are two transaction flows for performing a CoinSwap.

  • key handover: based on 2pECDSA, used assuming both parties will complete the CoinSwap successfully
  • redeemscript: based on Taproot, used if an abort happens in key handover

Key handover

Let maker and taker be two parties initiating a CoinSwap using a key handover transaction.

The handover transaction can be spent:

  • with a signature under an aggregate 2pECDSA key: aggPK = 2pECDSA_KeyGen(makerPK, takerPK)
  • a signature under makerPK and expired timeout (OP_CSV or OP_CHECKLOCKTIME)

Gennaro-Goldfeder's 2pECDSA protocol enables identifiable aborts, consists of a single online communication round (offline setup rounds), and threshold M-of-N signatures. Full support for M-of-N is not required for basic CoinSwap, but could be utilised in more advanced versions of the protocol.

  • create a 2-of-2 2pECDSA contract with timelock abort

    • either <aggPK> CHECKSIG NOTIF <makerPK> CHECKSIG <rel-timelock> OP_CSV ENDIF
    • or <aggPK> CHECKSIG NOTIF <makerPK> CHECKSIG <abs-timelock> OP_CHECKLOCKTIME ENDIF
  • require signature under 2pECDSA key aggPK

  • maker and taker perform offline 2pECDSA rounds to establish aggPK

  • maker verifies contract, performs their half of the online signing round, and sends partial signature to taker

  • taker verifies the contract, and performs their half of the online signing round

  • taker broadcasts the transaction, and recovers funds from the contract

  • if protocol aborts

    • kick offending parties
    • retry key handover if non-offending parties remain
    • try redeemscript transaction if failed handover retry, or only offending parties remain
    • maker signs and broadcasts the transaction, and recovers funds after timelock expires

Redeemscript

Let maker and taker be two parties in a CoinSwap that uses a PTLC redeemscript with Taproot.

The internal_key used for the key path spend is an aggregate MuSig2 key: aggPK = makerPK + adaptor*takerPK

maker has knowledge of the secret key for the public key (makerPK), and the adaptor secret.

taker has knowledge of the secret key for the public key (takerPK).

The redeemscript can be spent:

  • with a signature under the aggregated Musig2 key aggPK
  • with a signature under makerPK and expired timelock

Key path spend

  • create Taproot contract with a single timelock TapBranch in the TapScript tree
    • might be required or desirable to add an unspendable TapBranch to balance the TapScript tree
    • <segwit-v1> <aggPK> <control-block>
  • require signature under Musig2 aggregate key aggPK
  • taker creates and sends contract to maker
  • maker verifies contract, and sends partial signature to taker
    • partial_sig = k - r*makerSK
  • taker verifies partial signature (stores to extract adaptor + aggregation)
  • taker sends proof of funding to maker
  • maker validates proof of funding, and sends adaptor signature to taker
    • adaptor_sig = partial_sig + adaptor = k - r*makerSK + adaptor
  • taker validates, and extracts adaptor secret
    • adaptor = adaptor_sig - partial_sig = (k - r*makerSK) - (k - r*makerSK) + adaptor
  • taker creates a partial signature under their public key tweaked with the adaptor secret
    • aggSK = adaptor*takerSK, aggPK = aggSK*G
  • taker aggregates the partial signatures, broadcasts the transaction, and recovers funds from the contract

Script path spend

  • use timelock script as the single TapBranch in a TapScript tree
    • OP_CSV-based or OP_CHECKLOCKTIME-based
    • either <makerPK> CHECKSIG <rel-timelock> OP_CSV
    • or <makerPK> CHECKSIG <abs-timelock> OP_CHECKLOCKTIME
  • require signature under the timelock key
  • maker waits for timelock to expire
  • maker calculates the output key for the TapScript spend path
    • <segwit-v1> <output-key> PUSH_DATA(script_len) <timelock-script> <control-block>
  • maker signs and broadcasts the transaction, and recovers funds from the contract

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment