Trading_protocol.md

BCExchange / doc / Trading_protocol.md

Message format

All the messages below are emitted through BKC transactions. The transactions can have any number of inputs, but must have only 2 outputs: the change and the operation.

The operation output must have a value of zero and a redeem script with this form: OP_TRADE <operation type> <data> [<signature>]

  • OP_TRADE is a new opcode that behaves like OP_RETURN if evaluated. The difference is when a transaction with such an output is received: the trading message must be valid for the node to accept the whole transaction.
  • <operation type> is a single integer indicating the message type
  • <data> is the serialized parameters of the operation
  • <signature> is the signature of the operation hash. The signatory depends on the message. His public key is included in the data. Some message types may not require a signature.

The operation hash is made from <operation type> <data> <prevout hash> <prevout n>. The <prevout hash> and <prevout n> are the hash and output index of the previous output of the first input of the BKC transaction (to avoid replay).

There are 2 groups of emitters :

  • The signers are identified by the pubkey of the BKS address used in the reputation votes.
  • The users are identified by a pubkey that may or may not be associated with a BKS or a BKC address.

The pubkeys are compressed public keys that take 33 bytes.

On all the messages below that mention an asset id the message is invalid if the asset is not active.

Requesting a deposit address

Key list

A signer able to handle an asset publishes a key list.

  • operation type: TRADEOP_KEY_LIST
  • data:
    • signer's pubkey
    • asset id
    • vector of compressed public keys
  • signed by the signer's pubkey

To be accepted this message must:

  • be sent by a signer with a positive reputation (effective in the previous block)
  • not include any address already published (by any signer on any asset)
  • not make the signer have more than MAX_SIGNER_KEYS_PER_ASSET (1000?) available keys on this asset

Deposit address request

An user sends a request to acquire a deposit address. He selects the pubkeys among the available ones and publishes his request.

  • operation type: TRADEOP_DEPOSIT_REQUEST
  • data:
    • user's pubkey
    • asset id
    • vector of pubkeys
  • signed by the user's pubkey

Conditions:

  • the user must not already have a deposit address on this asset
  • the number of pubkeys must be equal to the total number signatures required by this asset (the n in m-of-n)
  • each pubkey must have been published by a distinct signer
  • the pubkeys must not have been already used by any deposit address request
  • the pubkeys must have been published by the current top n reputed signers who have available keys on this asset (or 2 * n?)

Deposit address confirmation

To make sure the signers are available and agree on the final address they each confirm the request while publishing the deposit address.

  • operation type: TRADEOP_CONFIRM_DEPOSIT_ADDRESS
  • data:
    • signer's pubkey
    • user's pubkey
    • asset id
    • deposit address (string)
  • signed by the signer's pubkey

Conditions:

  • the user must have made a request
  • the signer must have published one of the pubkeys included in the request
  • the signer must not have already confirmed this request

The deposit address can be used when m signers have confirmed the same multisig address. It's fully confirmed when n signers have done so and the confirmations have been included in multiple blocks.

If the signers provide different deposit addresses the client must issue a warning and not consider any of the addresses usable.

Declaring a withdrawal address

An user sends a message to indicate the address on which he wants to receive funds for a specific asset. It's the user's responsibility to make sure this address is valid. It won't be confirmed by the signers. If something wrong happens when the signers try to send funds to this address, it's up to the signers to decide what to do with the funds.

  • operation type: TRADEOP_WITHDRAWAL_ADDRESS
  • data:
    • user's pubkey
    • asset id
    • withdrawal address (string)
  • signed by the user's pubkey

Orders

Order

An user sends an Order message to place an order.

  • operation type: TRADEOP_ORDER
  • data:
    • user's pubkey
    • sold asset id
    • bought asset id
    • sold amount (in asset satoshis)
    • bought amount (in asset satoshis)
    • order id (a random uint160)
  • signed by the user's pubkey

Conditions:

  • the amounts must match the effective min/max trade of the corresponding asset in the previous block
  • the user must have:
    • a deposit address on the sold asset id
    • a withdrawal address on the bought asset id
  • the order id must not match any existing order

Order confirmation

An order must be confirmed by the signers of the sold asset.

An order is considered confirmed when at least N signers have confirmed it. N being either ceil(n/2) or m+2, whichever is the highest. m and n are the number of signers on the m-of-n multisig deposit address of the user on the sold asset.

  • operation type: TRADEOP_ORDER_CONFIRMATION
  • data:
    • signer's pubkey
    • order id
  • signed by the signer's pubkey

Conditions:

  • the order id must match an order sent by an user
  • the signer must have published one of the pubkeys used in the deposit address of the user on the sold asset
  • the signer must not already have confirmed this order

Order fill

When two active orders match (even partially) an order fill message is broadcasted by any node in the network.

Order matching rules are described in Order_matching.md.

This message doesn't require any fee or signature. The transaction has only one special input:

  • prevout.hash: 0
  • prevout.n: -3
  • scriptSig: TRADEOP_FREE

And only one output: the message itself with an amount of 0.

  • operation type: TRADEOP_ORDER_FILL
  • data:
    • first order id
    • second order id
    • first asset amount (asset sold by the first order and bought by the second order)
    • second asset amount (asset bought by the first order and sold by the second order)

Conditions:

  • both orders must be confirmed
  • both orders must not be already filled

Additional conditions to make these transactions as deterministic as possible to prevent the network from generating multiple similar (and conflicting) order fills:

  • the first order is the one with the lowest sold id
  • the transaction date is the transaction date of the most recent date of the 2 order transactions

Order fill validation

Signers involved in an order fill must confirm it.

The order fill is considered confirmed when at least N signers of each order have confirmed the fill. Like in the order confirmation message N is either ceil(n/2) or m+2, whichever is the highest. m and n are the number of signers on the m-of-n multisig deposit address of the sold asset of the matching orders.

  • operation type: TRADEOP_ORDER_FILL_CONFIRMATION
  • data:
    • signer's pubkey
    • order fill hash (generated with the data of the order fill message)
  • signed by the signer's pubkey

Conditions:

  • an order fill with the same hash must exist
  • the signer must be one of the signers of the orders
  • the signer must not already have confirmed the order fill

Order fill signature exchange

When an order fill is confirmed the signers must exchange the transaction data and their signatures. They do that by sending an order fill signature message. These messages must be propagated by the nodes but not be included in the blockchain.

On assets based on Bitcoin the signers will probably use createrawtransaction and signrawtransaction to generate the transaction data and combine signature of other signers. When there's enough signature the signers broadcast the transaction on the asset's network.

  • operation type: TRADEOP_ORDER_FILL_SIGNATURE
  • data:
    • signer's pubkey
    • order fill hash (generated with the data of the order fill message)
    • transaction data (raw binary)
  • signed by the signer's pubkey

Conditions:

  • the signer must have confirmed the order fill
  • a limit could restrict the transaction data size (maybe user configurable)
  • not valid inside a block