Skip to content
  • Watch
  • Fork

/bips forked from bitcoin/bips

Find file
2014161
466 lines (282 sloc) 19.9 KB

  BIP: XX
  Title: Atomic Cross Chain Transfers
  Author: Noel Tiernan <tier.nolan@gmail.com>
  Status: Draft
  Type: Standards Track
  Created: 2014-04-29

Table of Contents

Abstract

This BIP describes a method for atomically trading coins between Bitcoin and a Bitcoin-like alternative coin (altcoin).

Motivation

There are many coin trading exchanges. These websites allow users to trade Bitcoins for altcoin, and also to trade one type altcoin for another.

These sites are centralised in nature. A p2p coin trading system requires a way for traders to trade their coins in an atomic way.

Protocol Overview

The protocol defined in this BIP consists of two stages. In the first stage, the parties cooperate to generate a set of transactions, without broadcasting. In the second stage, the transactions are broadcast in a specific ordering. Communication between the parties is only required during the first stage.

Each party has an incentive to participate in the defined broadcast ordering. If the protocol stops at any stage before the transaction is committed, both parties can recover their funds using timelocked refund transactions.

It is assumed that Bob wishes to buy A altcoins (ATC) from Alice for B Bitcoins (BTC). Transaction fees are assumed to be fb for the Bitcoin network and fa for the altcoin network. Bob will pay all Bitcoin fees and Alice will pay all altcoin fees. The exchange price agreed between the parties will take this into account.

Public keys are referred to as pub-AN for Alice's keys and pub-BN for Bob's keys. An optional 3rd party signature is also possible, designated pub-T.

The third party is only required to protect against transaction malleability. Once transaction malleability is resolved, the third party will not be necessary.

An additional standard transaction type is required on one of the networks for the protocol to operate. Trades can be performed between a network which supports P2SH and other that supports OP_HASH160 transaction locking.

Transaction Creation

1) Alice sends Bob three public keys (pub-A1, ..., pub-A3)

2) Bob sends Alice three public keys (pub-B1, ..., pub-B3) and Hash160(x)

    x = serialized{pub-B4 OP_CHECKSIG}

3) Both parties creates their "bail-in" transaction.

Transaction output 0 can only be spent with both parties' signatures. Transaction output 1 can only be spent by Bob, but it results in x being revealed.

    Name: Bob.Bail.In
    Input value:     B + 2*fb + change
    Input source:    (From Bob's coins, multiple inputs are allowed)
    Output 0 value:  B
    ScriptPubKey 0:  OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL
    Output 1 value:  fb
    ScriptPubKey 1:  OP_HASH160 Hash160(x) OP_EQUALVERIFY pub-A1 OP_CHECKSIG
    Output 2 value:  change
    ScriptPubKey 2:  <= 100 bytes

    P2SH Redeem:  OP_2 pub-A1 pub-B1 OP_2 OP_CHECKMULTISIG
    P2SH Redeem:  OP_2 pub-A1 pub-B1 pub-T OP_3 OP_CHECKMULTISIG

Transaction output 0 can only be spent with both parties' signatures. Transaction 1 can only be spent by Alice, but it requires x to be reveals by Bob first.

    Name: Alice.Bail.In
    Input value:  A + 2*fa + change
    Input source: (From Alice's altcoins, multiple inputs are allowed)
    Output 0 value: A
    ScriptPubKey 0: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL
    Output 1 value: fa
    ScriptPubKey 1: OP_HASH160 Hash160(x) OP_EQUAL
    Output 2 value: change
    ScriptPubKey 2: <= 100 bytes

    P2SH Redeem:    OP_2 pub-A1 pub-B1 OP_2 OP_CHECKMULTISIG
    P2SH Redeem:    OP_2 pub-A1 pub-B1 pub-T OP_3 OP_CHECKMULTISIG

Note: x = serialized{pub-B4 OP_CHECKSIG}

The shorter version of P2SH Redeem should be used when a third party is not used.

Output 1 uses P2SH, this means that Bob must provide x in order to spend it.

If a third party isn't used, then pub-T is not included and the key count (OP_3) is replaced by OP_2.

4) Bob and Alice exchange bail-in transaction hashes

Bob sends Alice Hash256(Bob.Bail.In)

Alice sends Bob Hash256(Alice.Bail.In)

Note: The outputs in the bail-in transaction do not need to be ordered as given in steps 1 and 2.

5) Both parties create the payout transactions

This transaction can be spent by Alice. Since it has Bob.Bail.In:1 as an input, it cannot be signed unless Bob reveals x.

    Name: Alice.Payout
    Input value:  B
    Input source: Bob.Bail.In:0
    Input value:  fb
    Input source: Bob.Bail.In:1
    Output value: B
    ScriptPubKey: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL

    P2SH Redeem:  pub-A2 OP_CHECKSIG

This transaction can be spent by Bob. However, since it has Alice.Bail.In:1 as an input, he cannot sign the inputs unless he reveals x.

    Name: Bob.Payout
    Input value:  A
    Input source: Alice.Bail.In:0
    Input value:  fa
    Input source: Alice.Bail.In:1
    Output value: A
    ScriptPubKey: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL

    P2SH Redeem:  pub-B2 OP_CHECKSIG

6) Both parties create the refund transactions

This transaction is timelocked, so that it can't be spent until the timeout (T) has passed. This transaction does not require Bob.Bail.In:B, so Bob does not have to reveal x in order to spend it.

    Name: Bob.Refund
    Input value:  B
    Input source: Bob.Bail.In:0
    Output value: B - fb
    ScriptPubKey: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL
    Locktime:     (current block height) + (T / 10 minutes)

    P2SH Redeem:  pub-B3 OP_CHECKSIG

This transaction is timelocked, so that it can't be spent until half the timeout (T/2) has passed. This transaction does not require Alice.Bail.In:B, so Alice can spend it without x being revealed.

    Name: Alice.Refund
    Input value: A
    Input source: Alice.Bail.In:0
    Output value: A - fa
    ScriptPubKey: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL
    Locktime:     current block height + ((T/2)/(altcoin block rate))

    P2SH Redeem:  pub-A3 OP_CHECKSIG

7) Bob and Alice exchange signatures

Bob sends Alice signatures for Alice.Payout (Input: Bob.Bail.In:0) and Alice.Refund.

Alice signs all three and now has 3 signed transactions. Alice.Payout cannot be fully signed until x is revealed.

Alice sends Bob signatures for Bob.Payout (Input: Alice.Bail.In:0), Bob.Refund and Bob.Trusted.Refund.

Bob signs all three and has 3 fully signed transactions.

8) Exchange of bail-in transactions

The parties can safely exchange bail-in transactions at this point. This is not necessary for the protocol, but would allow both parties to verify that the other party at least has a valid bail-in transaction before locking their funds.

No further communication is required between the parties. Bob and Alice can determine the state of the transaction by monitoring both chains.

Transaction Broadcast

The transactions must be broadcast in a specific order for the composite transaction to be atomic.

Bob has the following transactions:

  • Bob.Bail.In: Bob's bail-in transaction
  • Bob.Refund: Bob's refund transaction (timelocked until the timeout has passed)
  • Bob.Payout: Bob's altcoin payout transaction (can only be spent by revealing x)
Alice has the following transactions

  • Alice.Payout: Alice's Bitcoin payout transaction (can only be spent if Bob reveals x)
  • Alice.Bail.In: Alice's bail-in transaction
  • Alice.Refund: Alice's refund transaction (timelocked until half the timeout has passed)

Step 1: Bail-in by Bob

Bob broadcasts Bob.Bail.In.

Bob's has no option other than waiting

  • He cannot broadcast Bob.Refund since it is timelocked
  • He cannot broadcast Bob.Payout since it has Alice.Bail.In as an input
Alice's only broadcast option is to move to step 2
  • She cannot broadcast Alice.Payout since she doesn't know x
  • She cannot broadcast Alice.Refund since it is timelocked
  • She can broadcast Alice.Bail.In, which moves the protocol to step 2
If the protocol ends at this point, Bob can use his refund transaction to recover his Bitcoins after the timeout has expired.

Step 2: Bail in by Alice

Alice broadcasts Alice.Bail.In.

Alice has no option other than waiting

  • She cannot broadcast Alice.Refund since it is timelocked
  • She cannot broadcast Alice.Payout since she doesn't know x
Bob's only broadcast option is to move to step 3
  • He cannot broadcast Bob.Refund since it is timelocked
  • He can broadcast Bob.Payout since Alice.Bail.In has been broadcast
It is recommended that Bob wait until Alice.Bail.In has been confirmed by a few blocks before proceeding to step 3.

Step 3: Bob commits to the transaction

Bob broadcasts Bob.Payout to claim his altcoins. To spend the 2nd output of Alice.Bail.In requires that Bob reveal x.

This completes Bob's participation in the protocol.

Once Alice.Bail.In has been confirmed to a sufficient depth, Bob should broadcast Bob.Payout as soon as possible. Since broadcasting Bob.Payout reveals x, if Bob waits until the the locktime on Alice.Refund has expired (or is near to expire), then it creates a race condition. Alice could broadcast Alice.Refund to get her altcoins back and also broadcast Alice.Payout to claim Bob's Bitcoins.

If he broadcasts immediately, he has half the timeout time for his transction to be confirmed.

Alice has only one broadcast option

  • She cannot broadcast Alice.Refund since it is timelocked
  • She can broadcast Alice.Payout since she knows x, which moved the protocol to step 4

Step 4: Alice completes the transaction

Alice broadcasts Alice.Payout to claim her Bitcoins.

If Alice doesn't claim her Bitcoins before the timeout on Bob.Refund ends, then Bob could use Bob.Refund to recover the Bitcoins he used in the trade.

Since Bob can wait at most half the timeout (T/2) before completing step 3 and Bob.Refund has a timelock of T, Alice has at least half the timeout (T/2) to broadcast Alice.Payout.

Specification

JSON-RPC shall be used for communication between the parties.

Hex encoding shall be used for all byte arrays.

Public keys must be serialized using strict SEC format:

    byte(0x02) byte_array(32):                Compressed even key
    byte(0x03) byte_array(32):                Compressed odd key

Compressed keys are mandatory.

When included in transactions, hash_type must be set to 1.

Signatures must be serialized using strict DER format.

    byte(0x30) byte(total_length) byte(0x02) byte(len(R)) byte_array(len(R)) byte(len(s)) byte_array(len(s))

total_length is equal to 3 + len(R) + len(S).

R and S are represented in signed Big Endian format without leading zeros, except that exactly one leading zero is mandatory, if the number would otherwise be negative. This occurs if the MSB in the first non-zero byte is set.

Transactions shall be serialized using the bitcoin protocol serialization. Transactions that are not timelocked should have a lock_time and sequence number of 0. Timelocked inputs should have a sequence number of UINT_MAX (0xFFFFFFFF).

One party shall act as server and one party shall act as client.

The party which selects x and has the longer timeout is defined as the slow trader. The other party is the fast trader.

Request Message

Each message shall have the following format.

    {"id":1, "method": "method.name", "params": [param1, param2]}

id: The method id, it should increment for each method call method: The name of the method params: The method parameters

Result Message

The server shall reply to Request methods with a response message.

    {"id": 1, "result": result, "error: Null}

Error Message

The server shall reply with an error message, if the request is invalid.

    {"id": 1, "result": Null, "error: [error_code, "error_string"]}

Methods

The following methods must be supported.

Trade Request

This method is used to initiate the protocol.

    {"id":1, "method": "trade.request", [version, long_deposit, [third_parties], k_client,
                                         sell_magic_value, sell_coin_amount, sell_coin_fee, 
                                         sell_locktime,
                                         buy_magic_value, buy_coin_amount, buy_coin_fee, 
                                         buy_locktime]}

The parameters are defined as

    version:                        Integer version of the handshake (should be set to 1)
    slow_trader (boolean):          True if the server is the slow trader, false otherwise
    third_party (list of string):   Hex encoding of acceptable 3rd parties' public key (or Null for no 3rd party)
    k_client (string):              A random hex encoded byte array (32 bytes)
    sell_coin_magic_value (string): Hex encoding of the network magic value for the coin being sold
    sell_coin_amount (number):      An integer count of the number of coins being sold (in the smallest units)
    sell_locktime (number):         The int locktime for the client's refund transaction
    buy_coin_magic_value (string):  Hex encoding of the network magic value for the coin being bought
    buy_coin_amount (number):       An integer count of the number of coins being bought (in the smallest units)
    buy_locktime (number):          The int locktime for the server's refund transaction

The server can decide if the trade is acceptable.

For altcoins with irregular block rates, ensuring that the timeouts occur in the correct order may be difficult. It is recommended that the more stable chain act as slow trader. This prevents the slow trader having to wait an extended period if the altcoin's block rate collapses.

Note: The locktime can mean timestamp and block height depending on value.

The response for the method has a subset of the trade information.

    {"id":1, "result": [version, slow_trader, [third_parties], k_server,
                        sell_coin_amount, sell_coin_fee, sell_locktime,
                        buy_coin_amount, buy_coin_fee, buy_locktime]
             "error": Null}

If the returned values match the request, then the trade is accepted. Otherwise, it is a counteroffer.

If the server doesn't support the protocol version requested by the client, the version in the response should be equal to the highest supported version, and no other parameters included. Otherwise, the server should respond with the requested version.

An accepted offer should have at most one 3rd party's public key in the public key list.

If the server does not wish to trade in that coin at all, then the buy_coin_amount, _fee and _locktime should be set to Null in the response.

If the exchange rate is insufficient, servers should modify the sell_coin_amount in preference to modifying the buy_coin_amount.

Servers should accept trades if the client echos back the response to the server.

A trade-id is generated for each transaction (| means concatenation).

    tr_id = SHA-256(k_client | k_server)

The result of the SHA-256 operation is considered a big endian encoded unsigned integer.

If tr_id falls outside the elliptic curve finite field, the server should select a different byte array and repeat until success.

The third party's public key is modified to give

    third_party_key_modified = tr-id * third_party_key

This key should be used to generate the third party's refund transaction.

Exchange Keys

This method is used to exchange public keys between the parties. Each party has to provide 5 public keys and the long trader must provide hash_x. The slow trader should set hash_x to Null.

    {"id": 1, "method":"keys.request", "params": [tr_id, key1, key2, ... key5, hash_x]}

The server responds with 5 public keys and hash_x.

    {"id": 1, "result": [key1, key2, ... key5, hash_x], "error": Null}

Exchange Bail-in Transaction Hashes

This method is for exchanging bail-in transaction hashes and the A and B indexes.

    {"id": 1, "method":"k, bail_in_hash.request", "params": [tr_id, client_bail_in_hash]}

The server responds with its own bail-in transaction hash.

    {"id": 1, "result":"server_bail_in_hash", "error": Null}

Both hashes should be encoded as 64 character (32 byte) hashes.

Note 1: This is the transaction id hash, not hash160. Note 2: The fast and slow trader's bail-in transactions are constructed differently.

Exchange Signatures

This method is for the parties to exchange signatures.

    {"id": 1, "method": "exchange.signatures", "params": [tr_id, server_payout_signature, server_refund_signature, server_third_party_signature]

The parameters are defined as

    server_payout_signature:          This is the signature for the server's payout transaction (input A)
    server_refund_signature:          This is the signature for the server's timelocked refund transactions
    server_third_party_signature:     This is the signature for the server's transaction to direct the output to a third party 

The response is of the same form

    {"id": 1, "result": [client_payout_signature, client_refund_signature, client_third_party_signature], "error": Null}

The parameters are defined as

    client_payout_signature:          This is the signature for the client's payout transaction (input A)
    client_refund_signature:          This is the signature for the client's timelocked refund transactions
    client_third_party_signature:     This is the signature for the client's transaction to direct the output to a third party

Once the 3 signatures are exchanged, no further communication is required.

Exchange Bail-in Transactions

This method is for the parties to exchange bail-in transactions. This allows both parties to broadcast both bail-in transactions.

Broadcasting the bail-in transaction prior to this step reduces malleability risk by the other party.

    {"id": 1, "method": "exchange.bail.in", params: [tr_id, server_bail_in]}

The response is of the same form

    {"id": 1, "result": [client_bail_in], "error": Null}

Trade Cancel

This allows the parties to back out of a trade before the timeouts are completed. It is a courtesy and not enforceable.

    {"id": 1, "method": "cancel.transaction", "params": "unlocked_server_refund_signature"}

The parameters are defined as

    unlocked_server_refund_signature:   This is the signature for the server's refund transaction with locktime set to zero.

The response is

    {"id": 1, "result": [unlocked_client_refund_signature]}

The parameters are defined as

    unlocked_client_refund_signature:   This is the signature for the client's refund transaction with locktime set to zero.

Since this method is only a courtesy, it doesn't matter that the server could fail to provide the client with the refund transaction.

Once this method is used, the parties should not proceed to step 3.

Third Party Arbitration

This method is for submitting transactions to third parties.

    {"id": 1, method:"arbitrate", "params": [tr_id third_party_key bail_in_p2sh_redeem refund_transaction new_transaction]}

The parameters are defined as

    tr_id:                  The tr_id parameter encoded as a integer
    third_party_key:        The third party's unmodified public key
    bail_in_p2sh_redeem:    The P2SH Redeem script for the bail-in transction
    refund_transaction:     The refund transactions, fully signed
    new_transaction:        This is the new refund transaction

The third party must

 * Verify that the refund transaction spends the p2sh_redeem script
 * Verify that the refund and new transaction are identical except for tx-in hashes

The new transaction may have additional outputs. This allows the third party to be paid.

The response is

    {"id": 1, "result": [new_transaction_signature], "error": Null}

The third party doesn't have to monitor all the chains. As long as it doesn't allow the locktime to be modified or outputs to be redirected, the system remains secure.

Compatibility

The protocol outlined in this BIP requires the use of a single non-standard scriptPubKey.

The Bob.Bail.In transaction has a scriptPubKey of the following form.

    OP_HASH160 Hash160(x) OP_EQUAL_VERIFY pub-A1 OP_CHECKSIG

All the other scriptPubKeys are standard transactions.

If the transaction is only standard on one of the two networks, then the party selling coin on that network should be the fast trader.

Reference Implementation

TBD

References

[1] https://bitcointalk.org/index.php?topic=193281.0

Copyright

This document is placed in the public domain.

Jump to Line
Something went wrong with that request. Please try again.