Requests from a receiving wallet to retrieve a message from a message delivery server.

If a CoinSpark-compatible wallet receives a transaction containing message metadata, and that metadata indicates that the message is intended for one of the transaction outputs that this wallet can spend, then the wallet should retrieve the message content from the delivery server whose address is provided in the metadata. In addition, any entity can use these methods to retrieve public messages.

Example message pre-retrieval request

To retrieve a message which is not public, coinspark_message_pre_retrieve must be called first. This allows the message delivery server to confirm that the message is available for retrieval, and to provide a nonce that the receiving wallet uses as the basis for a signature proving that they own the recipient bitcoin address.

{
  "id": "any_request_id",
  "method": "coinspark_message_pre_retrieve",
  "params": {
    "testnet": false,
    "txid": "7908b807decb3a4ce70bb07f0091a80bc1789777d7e512e677bac9d4e4f111f1",
    "recipient": "14719bzrTyMvEPcr7ouv9R8utncL9fKJyf"
  }
}

The recipient field must contain the bitcoin address used within the transaction output script that was destined for the receiving wallet (in the bitcoin testnet if testnet is true), rather than another bitcoin address that the receiving wallet might happen to own.

If a message is public (as indicated by the isPublic flag in the message metadata) then the coinspark_message_pre_retrieve request is not required and the coinspark_message_retrieve request can be used immediately.

Example message pre-retrieval successful response

If the message delivery server is willing and able to deliver the message for the txid and recipient given in the coinspark_message_pre_retrieve request, it responds as follows:

{
  "id": "any_request_id",
  "result": {
    "recipient": "14719bzrTyMvEPcr7ouv9R8utncL9fKJyf",
    "nonce": "retrieve 9847293739487492974"
   }
}

The recipient field contains the recipient address that was supplied in this request, and which must be used to sign the nonce in the subsequent coinspark_message_retrieve request. To avoid questions of encoding, the nonce may only use the ASCII characters 0x200x7E.

Example message pre-retrieval failure response

If the message delivery server is not willing to deliver the message outlined in the coinspark_message_pre_retrieve request, it responds as follows:

{
  "id": "any_request_id",
  "error": {
    "code": -12000,
    "message": "Transaction message unknown"
  }
}

The following global error codes may be present:

code message meaning
-32700 Parse error Could not parse the JSON input received
-32600 Invalid request The JSON received is not a valid JSON-RPC request
-32601 Method not found The method in the request is not available
-32602 Invalid params The method params in the request are not valid
-32603 Internal error Something went wrong internally
-12000 Transaction message unknown This server does not have any message for transaction txid.
-12001 Transaction message pending This server is still processing the incoming message for txid and it is not yet ready for delivery. Please try again in a few seconds.
-12002 Transaction message expired This server no longer has the message for txid, since it expired based on the storage time that was requested by the sender.
-12010 Recipient not accepted The provided recipient is not one of the permitted addresses for retrieving this message.
-12011 Recipient is suspended The provided recipient has been temporarily suspended from retrieving messages, e.g. because too many messages have been delivered to this recipient.

Example message retrieval request

If the coinspark_message_pre_retrieve request was successful, the receiving wallet can now call coinspark_message_retrieve to actually retrieve the message content. The payload of this request is identical to coinspark_message_pre_retrieve except the nonce, pubkey and signature fields, to authenticate the recipient wallet as the owner of the recipient address.

{
  "id": "any_request_id",
  "method": "coinspark_message_retrieve",
  "params": {
    "testnet": false,
    "txid": "7908b807decb3a4ce70bb07f0091a80bc1789777d7e512e677bac9d4e4f111f1",
    "recipient": "14719bzrTyMvEPcr7ouv9R8utncL9fKJyf",
    "nonce": "retrieve 9847293739487492974",
    "pubkey": "03ad21a2ced244adb67fa4dd279a89405e3d5d98e85b2bafba94b030217b489d2b",
    "signature": "H3+6CxI0edg4aPdLDCwyFX8iZEVMLXj6bsIeL81n7yWTGkxrPWROhZeoXQzFnn+72Sr/E+5XcnlIlF4h4n2QKJA="
  }
}

Both the recipient and nonce must match those received in the response to coinspark_message_pre_retrieve. The pubkey must contain the hexadecimal public key of the recipient bitcoin address, and the signature must contain a base64-encoded bitcoin signature of the nonce by the private key corresponding to pubkey and recipient.

Two types of signature content are supported: either (a) the output from Bitcoin Core’s signmessage command called with recipient and nonce, or (b) a regular bitcoin transaction input signature of nonce using the private key for recipient, as used in the scriptSig of transaction inputs.

If a message is public then the recipient, nonce, pubkey and signature fields can be omitted, leaving only testnet and txid.

Example message retrieval success response

If the coinspark_message_retrieve request was successful, the message delivery server sends back the message salt along with the full message content:

{
  "id": "any_request_id",
  "result": {
    "salt": "ZmhqZHNma2poZ3NkZmdramRzZmdramhkc2ZranNjdmtqbmRma25k",
    "message": [
      {
        "mimetype": "text/plain",
        "filename": null,
        "content": "UGF5bWVudCBmb3IgdGhlIGF0dGFjaGVkIGludm9pY2UgLSBCb2I="
      },
      {
        "mimetype": "application/pdf",
        "filename": "Invoice AB123.pdf",
        "content": "JVBERg== ..."
      }
    ]
  }
}

The salt and content elements contain raw binary, base64 encoded. If mimetype is text/plain then the corresponding content will contain the text in UTF-8 encoding, base64 encoded, rather than a plain JSON string.

Once it has received the salt and content, the receiving wallet should then calculate the message hash and verify that it matches the hash prefix inside the transaction’s message metadata. If not, there has either been a technical malfunction or the message delivery server has attempted to modify the message content – in either case the content should be ignored as invalid and an error should be shown in the recipient’s wallet.

Example message retrieval failure response

If the coinspark_message_retrieve request failed, the message delivery server responds as follows:

{
  "id": "any_request_id",
  "error": {
    "code": -12000,
    "message": "Transaction message unknown"
  }
}

The possible list of error codes includes everything that might appear in a pre-retrieval failure response, plus the following additional possibilities:

-13000 Nonce not found The nonce provided does not match a nonce that was previously supplied by the message delivery server in the response to a coinspark_message_pre_retrieve request.
-13010 Signature incorrect The signature field does not contain a base64-encoded bitcoin signature of the nonce by the owner of the recipient address.
-13011 Pubkey incorrect The pubkey field does not contain a valid bitcoin public key in hexadecimal.
-13012 Pubkey address mismatch The pubkey field does not match the recipient address.

Retrieving message part sizes only

In some cases the receiving wallet might need to check the size of a message before requesting it, e.g. to determine whether to download it, or to pre-allocate disk space. This is possible by adding an extra element sizesonly with value true to the params in the coinspark_message_retrieve call.

If coinspark_message_retrieve is called in this way, its response will contain bytes fields in place of the content fields, containing the sizes in bytes of each message part. If the receiving wallet decides to then retrieve the entire message, it will first need to call coinspark_message_pre_retrieve a second time, to receive a new nonce.