The message types and transaction flow behind the Bitmarkets marketplace.
Bitmarkets is a protocol and example client for a decentralized marketplace which uses Bitcoin as its currency and Bitmessage as its transport. Mutual security deposits between buyer and seller are used to align incentives for completing transactions without the need for either reputation systems or trusted third parties.
This page describes the wire protocol: the message format, the message types, and the order in which they are exchanged over the course of a transaction. For a non-technical overview, see the White Paper.
Each message is a JSON dictionary. Every dictionary contains a _type field naming the message type, plus additional fields that depend on that type.
In the examples below, long field values are abbreviated to their first few characters followed by ... for readability.
A complete sale moves through four phases — posting, escrow lock, delivery, and either payment or refund. Each cell below shows one message and the direction it travels.
| Step | seller → channel | seller → buyer | buyer → seller | → bitcoin |
|---|---|---|---|---|
| 1 | post | |||
| 2 | bid | |||
| 3 | close post | accept bid | ||
| 4 | lock escrow 1 | |||
| 5 | lock escrow 2 | |||
| 6 | lock escrow 3 (seller) | |||
| 7 | delivery info | |||
| 8 | unlock escrow 1 | |||
| 9 | unlock escrow 2 | |||
| 10 | unlock escrow 3 (buyer) |
The three "lock escrow" steps build a single Bitcoin multi-signature transaction holding both deposits plus the payment: the seller sends a partial transaction with their deposit (SellLockEscrowMsg), the buyer adds their deposit and the payment, signs, and returns it (BuyLockEscrowMsg), then the seller signs and broadcasts it. The three "unlock escrow" steps build and broadcast the release transaction the same way but reversed: the buyer initiates (BuyPaymentMsg), the seller signs and returns it (SellAcceptPaymentMsg), then the buyer broadcasts. The refund path mirrors payment, returning the deposits to each party and the payment to the buyer.
Sellers post sales to a particular Bitmessage channel (a publicly known address) where they are picked up and browsed by other clients. This channel model also enables private markets: a hard-to-guess channel name (e.g. a large random number) lets only those who know the secret name send or receive messages.
Sent from seller to channel to post a sale.
{
"_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": []
}
}Sent from buyer to seller in response to a sale post.
{
"_type": "BidMsg",
"postUuid": "B160...",
"sellerAddress": "BM-2cVr...",
"buyerAddress": "BM-2cVr...",
"dateNumber": 1409004919
}Sent from seller to channel after accepting a bid or cancelling the sale, in order to remove the post.
{
"_type": "ClosePostMsg",
"postUuid": "B160...",
"sellerAddress": "BM-2cVr...",
"dateNumber": 1409004929
}Sent from seller to buyer to accept a bid.
{
"_type": "AcceptBidMsg",
"postUuid": "B160...",
"sellerAddress": "BM-2cVr...",
"buyerAddress": "BM-2cVr...",
"dateNumber": 1409004929
}Sent from seller to every potential buyer other than the one accepted, after accepting a bid.
{
"_type": "RejectBidMsg",
"postUuid": "B160...",
"sellerAddress": "BM-2cVr...",
"buyerAddress": "BM-2cVr...",
"dateNumber": 1409004929
}If the seller accepts a purchase request, buyer and seller together construct a Bitcoin escrow lock transaction in which each adds a security deposit and the buyer adds the payment amount. The transaction is built so the funds are unspendable by either party until both sign another transaction to release them.
Sent from seller to buyer. Contains an incomplete multi-signature transaction with the seller's unspent inputs for their security deposit.
{
"_type": "SellLockEscrowMsg",
"postUuid": "B160...",
"sellerAddress": "BM-2cVr...",
"buyerAddress": "BM-2cVr...",
"dateNumber": 1409005057,
"payload": {
"type": "BNTx",
"txHash": null,
"inputs": [
{
"type": "BNTxIn",
"previousTxHash": "0851...",
"previousOutIndex": 0,
"previousTxSerializedHex": "0100...",
"scriptSig": null
}
],
"outputs": [
{
"type": "BNTxOut",
"value": 110000,
"scriptPubKey": {
"type": "BNMultisigScriptPubKey",
"pubKeys": ["0389...", "0389..."]
}
}
],
"updateTime": null,
"fee": null,
"confirmations": null,
"error": null
}
}Sent from buyer to seller. Contains the multi-signature transaction including the buyer's inputs (for their security deposit and the payment) and the buyer's signature. On receipt the seller adds their signature and broadcasts the transaction to the Bitcoin network. Both parties watch the network to confirm the escrow transaction.
{
"_type": "BuyLockEscrowMsg",
"postUuid": "B160...",
"sellerAddress": "BM-2cVr...",
"buyerAddress": "BM-2cVr...",
"dateNumber": 1409005067,
"payload": {
"type": "BNTx",
"txHash": "c0b1...",
"inputs": [
{
"type": "BNTxIn",
"previousTxHash": "0851...",
"previousOutIndex": 0,
"previousTxSerializedHex": "0100...",
"scriptSig": null
},
{
"type": "BNTxIn",
"previousTxHash": "19e4...",
"previousOutIndex": 0,
"previousTxSerializedHex": "0100...",
"scriptSig": {
"type": "BNScriptSig",
"programHexBytes": "4730...",
"isMultisig": false
}
}
],
"outputs": [
{
"type": "BNTxOut",
"value": 310000,
"scriptPubKey": {
"type": "BNMultisigScriptPubKey",
"pubKeys": ["0389...", "02ff..."]
}
}
],
"updateTime": 0,
"netValue": -320000,
"serializedHex": "0100...",
"fee": 10000,
"confirmations": 0,
"error": null
}
}Cancellation. The client supports cancelling the lock on either side by broadcasting a transaction that sends one's own inputs back to oneself. Cancellation only works if the escrow lock transaction has not already been broadcast to the Bitcoin network.
After the buyer's client sees the escrow lock transaction confirmed on the blockchain, it prompts the buyer to send the seller their delivery details.
Sent from buyer to seller. Contains the address to which the good or service should be delivered. The seller views this address from their client.
{
"_type": "BuyerAddressMsg",
"postUuid": "B160...",
"sellerAddress": "BM-2cVr...",
"buyerAddress": "BM-2cVr...",
"dateNumber": 1409007460,
"payload": {
"addressee": "Me",
"address1": "Here",
"address2": "SF",
"country": " "
}
}After the seller provides the good or service, the buyer constructs an escrow release transaction that returns the security deposits to their respective parties and sends the payment to the seller. The seller signs and broadcasts it to accept payment.
Sent from buyer to seller. Contains an incomplete multi-signature transaction making payment to the seller and returning the security deposits.
{
"_type": "BuyPaymentMsg",
"postUuid": "B160...",
"sellerAddress": "BM-2cVr...",
"buyerAddress": "BM-2cVr...",
"dateNumber": 1409007687,
"payload": {
"type": "BNTx",
"txHash": null,
"inputs": [
{
"type": "BNTxIn",
"previousTxHash": "f9b2...",
"previousOutIndex": 0,
"previousTxSerializedHex": "0100...",
"scriptSig": null
}
],
"outputs": [
{
"type": "BNTxOut",
"value": 103333,
"scriptPubKey": {
"type": "BNPayToAddressScriptPubKey",
"address": "1MLps..."
}
}
],
"updateTime": null,
"fee": null,
"confirmations": null,
"error": null
}
}Sent from seller to buyer with the completed payment transaction. The buyer broadcasts it on the Bitcoin network.
{
"_type": "SellAcceptPaymentMsg",
"postUuid": "B160...",
"sellerAddress": "BM-2cVr...",
"buyerAddress": "BM-2cVr...",
"dateNumber": 1409007722,
"payload": {
"type": "BNTx",
"txHash": "3178...",
"inputs": [
{
"type": "BNTxIn",
"previousTxHash": "f9b2...",
"previousOutIndex": 0,
"previousTxSerializedHex": "0100...",
"scriptSig": {
"type": "BNScriptSig",
"programHexBytes": "0047...",
"isMultisig": true
}
}
],
"outputs": [
{
"type": "BNTxOut",
"value": 103333,
"scriptPubKey": {
"type": "BNPayToAddressScriptPubKey",
"address": "1MLps..."
}
},
{
"type": "BNTxOut",
"value": 196666,
"scriptPubKey": {
"type": "BNPayToAddressScriptPubKey",
"address": "1AiRT..."
}
}
],
"updateTime": 0,
"netValue": 299999,
"serializedHex": "0100...",
"fee": 10000,
"confirmations": 0,
"error": null
}
}If the good or service is not provided, the buyer can request a refund: a transaction that returns the security deposits to their respective parties and returns the payment to the buyer. If the seller agrees, they sign and broadcast it.
Sent from buyer to seller with the first half of the refund transaction.
{
"_type": "BuyRefundRequestMsg",
"postUuid": "1F343...",
"sellerAddress": "BM-2cTEk...",
"buyerAddress": "BM-2cTEk...",
"dateNumber": 1410879639,
"payload": {
"type": "BNTx",
"txHash": null,
"inputs": [
{
"type": "BNTxIn",
"previousTxHash": "9749d...",
"previousOutIndex": 0,
"previousTxSerializedHex": "0100...",
"scriptSig": null
}
],
"outputs": [
{
"type": "BNTxOut",
"value": 306666,
"scriptPubKey": {
"type": "BNPayToAddressScriptPubKey",
"address": "1JUFU..."
}
}
],
"updateTime": null,
"fee": null,
"confirmations": null,
"error": null
}
}Sent from seller to buyer with the completed refund transaction. The buyer broadcasts it on the Bitcoin network.
{
"_type": "SellAcceptRefundRequestMsg",
"postUuid": "1F3439...",
"sellerAddress": "BM-2cTEk...",
"buyerAddress": "BM-2cTEk...",
"dateNumber": 1410880002,
"payload": {
"type": "BNTx",
"txHash": "5a9f4...",
"inputs": [
{
"type": "BNTxIn",
"previousTxHash": "9749d...",
"previousOutIndex": 0,
"previousTxSerializedHex": "0100...",
"scriptSig": {
"type": "BNScriptSig",
"programHexBytes": "0047...",
"isMultisig": true
}
}
],
"outputs": [
{
"type": "BNTxOut",
"value": 306666,
"scriptPubKey": {
"type": "BNPayToAddressScriptPubKey",
"address": "1JUFU..."
}
},
{
"type": "BNTxOut",
"value": 143333,
"scriptPubKey": {
"type": "BNPayToAddressScriptPubKey",
"address": "12875..."
}
}
],
"updateTime": 0,
"netValue": 449999,
"serializedHex": "0100...",
"fee": 10000,
"confirmations": 0,
"error": null
}
}This content is in the public domain.