Voluntary
Labs
Free, open source projects
promoting voluntary interactions.

Projects
/
Bitmarkets
/
protocol
Overview
Bitmarkets is a protocol and example client for a decentralized marketplace which uses Bitcoin as it's currency and Bitmessage as it's transport protocol. Mutual security deposits are used ensure incentives are aligned for completing transactions without the need for either reputation systems or trusted 3rd parties.
Message Format
Each message contains a JSON formatted dictionary and this dictionary contains a _type field which specifies the message type and other data fields depending on the message type. Text strings are UTF8 encoded and strings containing binary data are Base64 encoded. All date fields are in Unix time format (seconds since UTC 1970) and rounded to the nearest integer.




Posting
Sellers post sales to a particular Bitmessage channel (a publicly known public/private key pair Bitmessage address) where they are picked up and can be browsed by other clients. Using a client, potential buyers can request a purchase. This channel model also allows for private markets where hard to guess channel names (e.g. a large random numbers) can be used to only allow those those knowing the secret channel name to send or receive channel messages.
PostMsg
Sent from seller to Bitmarkets channel to post a sale.
example
{ "_type" : "PostMsg", "postUuid" : "B160...", "sellerAddress" : "BM-2cVr...", "dateNumber" : 1409004883, "payload" : { "postUuid" : "B160...", "regionPath" : ["North America", "US"], "categoryPath" : ["Electronics", "Laptops"] "title" : "Macbook Air 13” 128GB", "priceInSatoshi" : 100000, "sellerAddress" : "BM-2cVr...", "description" : "Test", "attachments" : [], }, }

BidMsg
Sent from buyer to seller in response to a sale post.
example
{ "_type" : "BidMsg", "postUuid" : "B160...", "sellerAddress" : "BM-2cVr...", "buyerAddress" : "BM-2cVr...", "dateNumber" : 1409004919, }

ClosePostMsg
Sent from seller to channel. Sent after accepting a bid or cancelling the sale in order to remove the post.
example
{ "_type" : "ClosePostMsg", "postUuid" : "B160...", "sellerAddress" : "BM-2cVr...", "dateNumber" : 1409004929, }

AcceptBidMsg
Sent from seller to buyer to accept a bid.
example
{ "_type" : "AcceptBidMsg", "postUuid" : "B160...", "sellerAddress" : "BM-2cVr...", "buyerAddress" : "BM-2cVr...", "dateNumber" : 1409004929, }

RejectBidMsg
Sent from seller to all potential buyers other than the one that was accepted, after accepting a bid.
example
{ "_type" : "RejectBidMsg", "postUuid" : "B160...", "sellerAddress" : "BM-2cVr...", "buyerAddress" : "BM-2cVr...", "dateNumber" : 1409004929, }

Escrow Lock
If the seller accepts a purchase request, buyer and seller together construct a bitcoin escrow lock transaction where each adds a security deposit and the buyer adds the payment amount. This transaction is constructed such that the funds are unspendable by both parties until both sign another transaction to release the funds.
SellLockEscrowMsg
Sent from seller to buyer. Contains incomplete multi-signature transaction with sellers unspent inputs to be used for their security deposit.
example
{ "_type" : "SellLockEscrowMsg", "postUuid" : "B160..." "sellerAddress" : "BM-2cVr...", "buyerAddress" : "BM-2cVr...", "dateNumber" : 1409005057, "payload" : { "inputs" : [ { "previousOutIndex" : 0, "previousTxSerializedHex" : "0100...", "scriptSig" : null, "type" : "BNTxIn", "previousTxHash" : "0851..." } ], "txHash" : null, "outputs" : [ { "type" : "BNTx" "value" : 110000, "type" : "BNTxOut", "scriptPubKey" : { "type" : "BNMultisigScriptPubKey" "pubKeys" : [ "0389...", "0389..." ], } } ], "updateTime" : null, "counterParty" : null, "netValue" : null, "serializedHex" : null, "fee" : null, "confirmations" : null, "error" : null, }, }

BuyLockEscrowMsg
Sent from buyer to seller. Contains the the multi-signature transaction including the buyer's inputs (for their security deposit and potential payment) and signature. When the seller receives this message, they add their signature to the transaction and broadcast it to the bitcoin network. Both parties observe the Bitcoin network to see that the escrow transaction is confirmed.
example
{ "_type" : "BuyLockEscrowMsg", "postUuid" : "B160...", "sellerAddress" : "BM-2cVr...", "buyerAddress" : "BM-2cVr...", "dateNumber" : 1409005067, "payload" : { "txHash" : "c0b1...", "inputs" : [ { "previousOutIndex" : 0, "previousTxSerializedHex" : "0100...", "scriptSig" : null, "type" : "BNTxIn", "previousTxHash" : "0851..." }, { "type" : "BNTxIn", "previousTxHash" : "19e4...", "previousOutIndex" : 0, "previousTxSerializedHex" : "0100...", "scriptSig" : { "type" : "BNScriptSig", "programHexBytes" : "4730...", "isMultisig" : false }, } ], "outputs" : [ { "type" : "BNMultisigScriptPubKey" "value" : 310000, "type" : "BNTxOut", "scriptPubKey" : { "pubKeys" : [ "0389...", "02ff..." ], } } ], "type" : "BNTx" "updateTime" : 0, "counterParty" : null, "netValue" : -320000, "serializedHex" : "0100...", "fee" : 10000, "confirmations" : 0, "error" : null, }, }

Cancellation
The client application supports canceling the lock (on both sides) by broadcasting transaction to send their own inputs back to themselves. Cancellation can effectively only work if the escrow lock was not broadcast to the Bitcoin network.



Delivery
After the buyer's client sees that the lock escrow transaction is confirmed in the bitcoin blockchain, they are prompted to send the seller their delivery details.
BuyerAddressMsg
Sent from buyer to seller. This contains the address to which the seller should delivery the good or service. The seller can view this address from their client.
example
{ "_type" : "BuyerAddressMsg", "postUuid" : "B160...", "sellerAddress" : "BM-2cVr...", "buyerAddress" : "BM-2cVr...", "dateNumber" : 1409007460, "payload" : { "address2" : "SF", "country" : " ", "addressee" : "Me", "address1" : "Here" }, }


Payment
After the seller provides the good or service to the buyer, the buyer constructs an escrow release transaction which sends the security deposits back to their respective parties and sends the payment to the seller. The seller can then sign this transaction and broadcast it to the bitcoin network to accept payment.
BuyPaymentMsg
Sent from buyer to seller. Contains incomplete multi-signature transaction to make payment to seller and return security deposits to respective parties.
example
{ "_type" : "BuyPaymentMsg", "postUuid" : "B160...", "sellerAddress" : "BM-2cVr...", "buyerAddress" : "BM-2cVr...", "dateNumber" : 1409007687, "payload" : { "type" : "BNTx", "updateTime" : null, "counterParty" : null, "netValue" : null, "serializedHex" : null, "fee" : null, "confirmations" : null, "error" : null, "txHash" : null, "inputs" : [ { "previousOutIndex" : 0, "previousTxSerializedHex" : "0100...", "scriptSig" : null, "type" : "BNTxIn", "previousTxHash" : "f9b2..." } ], "outputs" : [ { "value" : 103333, "type" : "BNTxOut", "scriptPubKey" : { "address" : "1MLps...", "type" : "BNPayToAddressScriptPubKey" } } ], }, }

SellAcceptPaymentEscrowMsg
Sent from seller to buyer with completed payment transaction.
Buyer broadcasts this on bitcoin network.
example
{ "_type" : "SellAcceptPaymentMsg", "postUuid" : "B160...", "sellerAddress" : "BM-2cVr...", "buyerAddress" : "BM-2cVr...", "dateNumber" : 1409007722, "payload" : { "type" : "BNTx", "updateTime" : 0, "counterParty" : null, "netValue" : 299999, "serializedHex" : "0100...", "fee" : 10000, "confirmations" : 0, "error" : null, "inputs" : [ { "type" : "BNTxIn", "previousTxHash" : "f9b2..." "previousOutIndex" : 0, "previousTxSerializedHex" : "0100...", "scriptSig" : { "type" : "BNScriptSig", "programHexBytes" : "0047...", "isMultisig" : true }, } ], "txHash" : "3178...", "outputs" : [ { "value" : 103333, "type" : "BNTxOut", "scriptPubKey" : { "address" : "1MLps...", "type" : "BNPayToAddressScriptPubKey" } }, { "value" : 196666, "type" : "BNTxOut", "scriptPubKey" : { "address" : "1AiRT...", "type" : "BNPayToAddressScriptPubKey" } } ], }, }


Refund
If the good or service is not provided, the seller can construct a refund request which returns the security deposits to their respective parties and returns the payment to the buyer. If the seller chooses, they can then sign this transaction and broadcast it to the bitcoin network to refund the payment.
BuyRequestRefundEscrowMsg
Sent from buyer to seller with first half of refund transaction.
example
{ "_type" : "BuyRefundRequestMsg", "buyerAddress" : "BM-2cTEk...", "sellerAddress" : "BM-2cTEk...", "dateNumber" : 1410879639.567544, "postUuid" : "1F343..." "payload" : { "type" : "BNTx", "updateTime" : null, "counterParty" : null, "netValue" : null, "serializedHex" : null, "fee" : null, "confirmations" : null, "error" : null, "txHash" : null, "inputs" : [ { "type" : "BNTxIn", "previousOutIndex" : 0, "previousTxSerializedHex" : "01000...", "scriptSig" : null, "previousTxHash" : "9749d..." } ], "outputs" : [ { "type" : "BNTxOut", "value" : 306666, "scriptPubKey" : { "address" : "1JUFU...", "type" : "BNPayToAddressScriptPubKey" } } ], }, }

SellAcceptRefundEscrowMsg
Sent from seller to buyer with completed refund transaction.
Buyer broadcasts this on bitcoin network.
example
{ "_type" : "SellAcceptRefundRequestMsg", "buyerAddress" : "BM-2cTEkZNv2...", "sellerAddress" : "BM-2cTEkZNv2...", "dateNumber" : 1410880002.148085, "postUuid" : "1F3439..." "payload" : { "type" : "BNTx", "txHash" : "5a9f4...", "updateTime" : 0, "counterParty" : null, "netValue" : 449999, "serializedHex" : "0100000...", "fee" : 10000, "confirmations" : 0, "error" : null, "inputs" : [ { "type" : "BNTxIn", "previousTxHash" : "9749d...", "previousOutIndex" : 0, "previousTxSerializedHex" : "01000...", "scriptSig" : { "type" : "BNScriptSig", "programHexBytes" : "00473...", "isMultisig" : true }, } ], "outputs" : [ { "type" : "BNTxOut", "value" : 306666, "scriptPubKey" : { "address" : "1JUFU...", "type" : "BNPayToAddressScriptPubKey" } }, { "type" : "BNTxOut", "value" : 143333, "scriptPubKey" : { "address" : "12875...", "type" : "BNPayToAddressScriptPubKey" } } ], }, }