Skip to content

Latest commit

 

History

History
85 lines (53 loc) · 11.2 KB

atomic_transfer.md

File metadata and controls

85 lines (53 loc) · 11.2 KB

Atomic transfer protocols

Multiple statecoins atomic transfer

The purpose of the atomic transfer protocol is to enable two (or more) coin transfers to be completed in a way that they all complete or none of them do. This effectively means that the transfer-receiver function and key update is only completed if both receivers have the correct information to proceed. Once each receiver has verified that the transfer message they have received is valid, then the other parties can be allowed to complete transfer-receiver.

To enable this there needs to be a mechanism to prevent the transfer-receiver being completed before the other parties have verified and confirmed their transfer messages. If all parties verify, then transfer-receiver can proceed, otherwise the key shares are not updated and ownership of the coins remains with the inital owner.

The process is performed by each party in the atomic transfer supplying a batch_id in the transfer-sender message. The use of this (as opposed to leaving this null) is that the statecoin is put into a special locked state for a configured timeout period after the first batch_id is submitted. During this locked status two things are prevented 1) The sender cannot perform another /transfer/sender operation on the same coin (i.e. to send to a different address) and 2) /transfer/receiver cannot be performed until all coins with the same batch_id are unlocked by all the owners unlocking the coins with a new /transfer/unlock function. At the end of the timeout (if all coins with a specified batch_id have not been unlocked), the /transfer/receiver function will still be blocked (i.e. return error) but the original owner can repeat /transfer/sender again with a null batch_id to regain control of the coin.

Protocol

The statechain_transfer DB table can have 3 additional columns: batch_id (string), batch-time (integer) and locked (boolen). By default batch_id, batch-time are null and locked is false. The server is configured with batch-timeout parameter in seconds (in practice this will be some number of minutes). This is set in the server Settings.

The atomic transfer will then proceed as follows:

  1. The two or more parties that want to engage in an atomic transfer cooperate and share a batch_id (this is just a random UUID generated by one of the participants and shared with the other). One party can generate it and share with the others.
  2. The parties each generate a ml1 address that they want the coin they will recieve paid to and send to the sender.
  3. Each party performs /transfer/sender {statechain_id, batch_id, auth_sig, new_user_auth_key} with the batch_id paying to the receiving party new_user_auth_key and then create and upload the transfer message.
  4. If the batch_id is set in a /transfer/sender call (and not null) the server adds this to the batch_id DB column for the specified statechain_id and updates the locked status to true.
  5. The server then checks all other statecoins to see if the same batch_id is used for any other coin in the table.
  6. If there are no other coins with this batch_id, then it adds the current time (unix epoch time in seconds) to the batch-time column.
  7. If there are any other coin(s) with this same batch_id then the batch-time of those coin(s) is copied to the specified coin batch-time column.

This means that all coins where /transfer/sender have the same batch_id will have the same batch-time set.

With this logic, it does not mater which order the coins call /transfer/sender, the first call with a specific batch_id will set the initial batch-time for the atomic transfer.

When /transfer/sender is called for any coin, if batch-time + batch-timeout (as read from the DB table) is greater than or equal to the current time (i.e. the coin is still within the timeout period) then it will return an error (ERROR: statecoin batch locked).

When /transfer/sender is called for any coin, if batch-time + batch-timeout (as read from the DB table) is less the current time (i.e. the timeout period has ended) the server will check the DB table for any other coins have the same batch_id. For each coin that shares the samebatch_id, if all locked values are false, then the transfer-sender returns with an error (ERROR: batch transfer completed) (in this case all participants have verified the transfer message and the atomic transfer must complete - all parties must perform transfer-receiver). If all locked values are NOT false /transfer/sender can be called again with a null or different batch_id. If called with null batch_id then batch-time is set to null and locked to false.

  1. Each participant in the atomic transfer then polls /transfer/get_msg_addr with their receive address within the timeout period. If they receive a transfer message, they fully verify as usual. If the verification passes, then the participant calls a function /transfer/unlock {statechain_id, auth_sig} which changes the locked status of the coin (statechain_id) in the DB table to false. If the batch-time + batch-timeout is less than the current time, then the /transfer/unlock function should not unlock and instead return an error.

  2. Each participant then calls transfer-reciever. If /transfer/receiver is called on any coin and batch_id and batch-time are set (not null) and locked is false, then the server checks if any other coins in the DB table have the same batch_id. For alls coin that share the same batch_id, if all locked are false, then the function proceeds with the key update, otherwise it returns with an error (ERROR: coin in locked state). If /transfer/receiver is called on any coin and batch_id and batch-time are set (not null) and locked is true, then this function should return an error.

The outcomes of this protocol:

Any coins where /transfer/sender is called with a specific batch-id within the batch-time of the first one to call, will be added to the batch transfer.

Then, if all parties coins progress to call /transfer/unlock within the batch-time then /transfer/receiver can be performed for all coins by each party.

If any single participant doesn't call /transfer/unlock within the batch-time then no-one can call /transfer/receiver but after the batch-time expiry each owner can call /transfer/sender again to recover the coin (i.e. send to to their own address with null batch_id and then calling transfer-receiver).

Lightning Latch atomic transfer

A latch transfer enables a statecoin to be transferred on condition of the sucessful payment of a Lightning network invoice. This is a protocol that enforces atomicity of a statecoin transfer and lightning payment - it can be used for the sale of a statecoin UTXO for an arbtrary amount of bitcoin in a private and non-custodial way without counterparty risk.

The latch transfer protocol uses the method of Hodl invoices (https://guide.bolt.fun/guide/invoices/hodl-invoice) where funds are locked until the payment hash pre-image is revealed. A hodl invoice can be resolved in one of two ways:

  1. The payment is complete when the recipient releases the preimage (to the payment route).
  2. The payment is canceled if the recipient does not release the preimage and the invoice expires.

Using this mechanism, a lightning network payment can be made but only completed if some condition is met - specifically if a specified statecoin transfer is made and verified. In this case the statechain entity (i.e. the mercury server) can both generate and release the payment hash pre-image on successful completion of the statecoin transfer in order to enforce atomicity. In this case the mercury server is trusted, but never has custody of any assets and never learns anything about the payment.

Protocol

The statecoin server database will have 4 additional values for each statechain_id: batch_id (string), batch-time (integer), pre-image (string), locked_1 (boolen) and locked_2 (boolen). By default batch_id, batch-time are null and locked is false. The server is configured with batch-timeout parameter in seconds (in practice this will be some number of minutes to enable both parties to complete the trade).

The transfer will then proceed as follows:

  1. There are two parties: party 1 has a statecoin they want to sell and party 2 wants to receivie it and pay an agreed price via LN.
  2. Party 1 generates a batch_id (this is just a random UUID) and shares with party 2.
  3. Party 1 calls /transfer/paymenthash with the batch_id and authenticated statechain_id for the coin. The server generates a secret preimage and stores it in the statecoin table with a new row and batch-time set as current time and locked_1 to true and locked_2 to true, and returns the paymenthash to Party 1.
  4. Party 2 generates a sc addresses that they want the UTXO sent to. This is sent to Party 1.
  5. Party 1 generates an invoice with the paymenthash and sends to Party 2. Party 2 can verify that the server has generated the pre-image to this by calling /transfer/paymenthash with the batch_id provided by Party 1.
  6. Party 1 performs /transfer/sender {statechain_id, batch_id, auth_sig, new_user_auth_key} with the batch_id paying to the party 1 new_user_auth_key (derived from their address) and then creates and uploads the encrypted transfer message.
  7. Party 2 makes the LN payment for the invoice, but cannot complete this as they don't know the pre-image.
  8. Party 1 verifies the payment is pending and calls /transfer/unlock with statechain_id and signed with their auth_key. If time is within batch-time + batch-timeout this sets the locked_1 value to false.
  9. Party 2 retrives and verifies the transfer message for the UTXO with their new_user_auth_key and calls /transfer/unlock with statechain_id and signed with their new_user_auth_key. If time is within batch-time + batch-timeout this sets the locked_2 value to false.
  10. Party 1 then calls /transfer/preimage with statechain_id and signed with their new_user_auth_key. If locked_1 and locked_2 and both false, then the preimage is returned and the LN payment can be finalised.
  11. Party 2 completes /transfer/receiver. If locked_1 and locked_2 and both false then the keyupdate is completed. If either is true then /transfer/receiver will return an error.

If both of the /transfer/unlock operations are not completed within the batch-timeout then both: 1. the LN invoice will timeout and cancel and 2. Party 1 performs another /transfer/sender and /transfer/receiver operation returning control of the coin.

The outcomes of this protocol:

All participants call /transfer/unlock within the batch-time then /transfer/receiver can be performed and the pre-image revealed.

Any participant doesn't call /transfer/unlock within the batch-time (because they have failed to verify either that the transfer message is incorrect, or the LN payment was not made correctly) then no-one can call /transfer/receiver but party 1 can call /transfer/sender again to recover the coin, and the LN payment will fail.

Calling /transfer/sender on the coin a second time will be blocked until batch-time expires.