USD: $0.01 BTC: 0.00000120 Market Cap: $463,129.12 USD Supply: 38,609,425 PASC 1 Hr: -0.02% 1 Day: 0.63% 7 Days: 64.42%

Each operation in PascalCoin (transaction, buy account, etc.) holds a payload. This tech-tutorial will help you understand how to handle payloads with JSON RPC.

Each operation in PascalCoin (transaction, buy account, etc.) holds a payload that contains arbitrary data and can be defined when executing an operation.

It can hold values up to 2^8 - 1 bytes or can simply be left empty.

This is a powerful feature often misunderstood or simply not used at all. Exchanges for example use the payload to identify incoming transactions and can associate them with their users. Or an online shop can use the payload to identify a transaction and associate it with an order.

The possibilities are endless, but for now we will stick with explaining how the payload is constructed, what methods to decrypt/encrypt a payload are available and how one can use the JSON RPC API to create transactions with (un)encrypted payloads.

Payload format

The format of the payload is a hex string (PascalCoin jargon: HexaString) without the commonly used prefix 0x. The wallet does the job of transforming a string to a HexaString, but if you talk to the JSON RPC API directly, you'll need to encode the payload prior embedding it within an operation.

When transforming a string to a HexaString make sure you handle multi-byte characters. E.g. the character is transformed to E282AC.

You also need to make sure that the length of the resulting HexaString is even (mod 2). If a byte results in a single hex value (e.g. TAB => 9), please prepend an additional 0 (zero) to it => 09.

There should be a method available in each popular programming language, but if not here is some pseudo code to the rescue.

Pseudo Code string to HexaString:

originalString
hexaString

foreach 8BitChar in originalString
    byte = to-decimal(8BitChar)
    hex = to-hex(8BitChar)
    hex = pad-left(hex, length=2, '0')
    append hex to hexaString 
 end foreach

Pseudo Code HexaString to string:

hexaString
originalString

foreach 2chars in hexaString
    dec = to-decimal(2chars)
    8BitChar = to-ascii(dec)
    append 8BitChar to originalString
 end foreach

JSON RPC API

We assume that you know about JSON RPC and the implementation in PascalCoin. If not, please visit http://www.jsonrpc.org and https://github.com/PascalCoin/PascalCoin/wiki/JSON-RPC-API to make yourself comfortable with it.

Each call to a API endpoint that creates an operation expects a payload value as well as the encryption method. The payload value for each request is always defined in the payload field and is a HexaString. The encryption method is always defined in the payload_method field and can contain 4 possible values:

none - No encryption

No encryption will take place and the payload is added to the operation "as is". Everyone can read the payload.

dest - Destination public key

The encryption will be executed through the destination public key. PascalCoin will take the public key that owns the receiving account (destination) and encrypts the payload.

The payload can only be decrypted by the owner of the public key (the one that also knows the private key). No-one else will be able to decrypt the value.

sender - Sender public key

The encryption is done through the senders public key. PascalCoin will take the public key of the sender account and encrypts the payload.

The payload can only be decrypted by the owner of the public key (the one that also knows the private key). No-one else will be able to decrypt the value.

aes - AES256 with password

The third and last encryption method is to use a password. PascalCoin will take the defined password to create an initialization vector (IV) and Key to encrypts the payload using AES256-CBC. The payload can be decrypted by everyone who knows the password.

The password used for the encryption is defined in the pwd field of the JSON RPC request.


As said in the beginning of this article, the payload can contain up to 2^8 - 1 bytes. That's not entirely correct. When transforming a string to a HexaString, the length will be doubled. So the payload can hold a string of 2^9-2 (510) bytes.

The limit of 510 bytes must be taken into consideration when using one of the encryption methods above. An encrypted payload is always longer than the original payload and it must never exceed the allowed length. So a raw string with the length of 255 bytes can never be encrypted, as the resulting encrypted value will be larger than the allowed size.

Decrypting a payload

The JSON RPC API contains a method that tries to decrypt a payload using either one or more passwords (each will be tested) or the private keys available in the wallet (make sure the wallet is unlocked). We say try because the operation object gives no clue if, and if, how a payload is encrypted.

Please have a look at the following examples on how to use this method. (https://github.com/PascalCoin/PascalCoin/wiki/JSON-RPC-API#payloaddecrypt)

Examples

In the following examples we will examine how to create an operation (in these examples always transactions) using the 4 available payload_method methods and how we can possibly decrypt the payload of the operation. All operations will be executed from account 66033 to 55099 with an amount of 0.0001 PASC and a fee of 0.0001 PASC.

none - No encryption

For an operation with an unencrypted payload, we will set the payload_method field to none and the payload field to a HexaString from the ASCII string test_no_encryption (example). The HexaString for this payload is 746573745F6E6F5F656E6372797074696F6E.

Our JSON RPC request object now looks like this.

{
   "jsonrpc":"2.0",
   "method":"sendto",
   "params":{
      "sender":66033,
      "target":55099,
      "amount":0.0001,
      "fee":0.0001,
      "payload":"746573745F6E6F5F656E6372797074696F6E",
      "payload_method":"none"
   },
   "id":1
}

When executed against the API the resulting operation object looks like this:

{  
   "result":{  
      "block":0,
      "time":0,
      "opblock":-1,
      "maturation":null,
      "optype":1,
      "subtype":11,
      "account":66033,
      "signer_account":66033,
      "n_operation":39,
      "senders":[  
         {  
            "account":66033,
            "n_operation":39,
            "amount":-0.0002,
            "payload":"6E6F5F656E6372797074696F6E"
         }
      ],
      "receivers":[  
         {  
            "account":55099,
            "amount":0.0001,
            "payload":"6E6F5F656E6372797074696F6E"
         }
      ],
      "changers":[  

      ],
      "optxt":"Tx-Out 0.0001 PASC from 66033-39 to 55099-17",
      "fee":-0.0001,
      "amount":-0.0001,
      "payload":"6E6F5F656E6372797074696F6E",
      "balance":0,
      "sender_account":66033,
      "dest_account":55099,
      "ophash":"00000000F101010027000000955F236B446F2A8C05ED17AF20B89C2DDE2EF235",
      "old_ophash":""
   },
   "id":123,
   "jsonrpc":"2.0"
}

As you can see in the result->senders->payload and result->receivers->payload you can already view the unencrypted HexaString we sent and we can simply transform the HexaString back to a string to see the payload.

dest - Destination public key

To send an operation where the payload can only be decrypted by the receiving party (in our case the owner of the account 55099), we will set the payload_method field to dest and the payload field to a HexaString from the ASCII string test_dest (example). The HexaString for this payload is 746573745F64657374.

Our JSON RPC request object now looks like this:

{
   "jsonrpc":"2.0",
   "method":"sendto",
   "params":{
      "sender":66033,
      "target":55099,
      "amount":0.0001,
      "fee":0.0001,
      "payload":"746573745F64657374",
      "payload_method":"dest"
   },
   "id":1
}

When executed against the API the resulting operation object looks like this:

{  
   "result":{  
      "block":0,
      "time":0,
      "opblock":-1,
      "maturation":null,
      "optype":1,
      "subtype":11,
      "account":66033,
      "signer_account":66033,
      "n_operation":40,
      "senders":[  
         {  
            "account":66033,
            "n_operation":40,
            "amount":-0.0002,
            "payload": "2110090010000330C9D8CD35863BA22C3A53EEDFEEF48D1E63475A26BD5834FE24DE875F5961B7458A23597ABADBBD6908FCB3628F00FE88CFE74A3CE322720F648A5816E21B7A"
         }
      ],
      "receivers":[  
         {  
            "account":55099,
            "amount":0.0001,
            "payload": "2110090010000330C9D8CD35863BA22C3A53EEDFEEF48D1E63475A26BD5834FE24DE875F5961B7458A23597ABADBBD6908FCB3628F00FE88CFE74A3CE322720F648A5816E21B7A"
         }
      ],
      "changers":[  

      ],
      "optxt":"Tx-Out 0.0001 PASC from 66033-39 to 55099-17",
      "fee":-0.0001,
      "amount":-0.0001,
      "payload": "2110090010000330C9D8CD35863BA22C3A53EEDFEEF48D1E63475A26BD5834FE24DE875F5961B7458A23597ABADBBD6908FCB3628F00FE88CFE74A3CE322720F648A5816E21B7A",
      "balance":0,
      "sender_account":66033,
      "dest_account":55099,
      "ophash":"00000000F1010100280000009502ABE63171DEFB2A0B8851318276F17682BE09",
      "old_ophash":""
   },
   "id":1,
   "jsonrpc":"2.0"
}

You will notice this: The payload in result->senders->payload and result->receivers->payload is much longer than the payload we used when creating the operation. This is because it was encrypted. This value can only be decrypted with the private key connected to the public key of the account 55099 - and no-one else.

The receiver can now use the payloaddecrypt method to decrypted the value.

{
   "jsonrpc":"2.0",
   "method":"payloaddecrypt",
   "params":{
      "payload": "2110090010000330C9D8CD35863BA22C3A53EEDFEEF48D1E63475A26BD5834FE24DE875F5961B7458A23597ABADBBD6908FCB3628F00FE88CFE74A3CE322720F648A5816E21B7A"
   },
   "id":1
}

The response looks like this:

{  
   "result":{  
      "result":true,
      "enc_payload": "2110090010000330C9D8CD35863BA22C3A53EEDFEEF48D1E63475A26BD5834FE24DE875F5961B7458A23597ABADBBD6908FCB3628F00FE88CFE74A3CE322720F648A5816E21B7A",
      "unenc_payload":"test_dest",
      "unenc_hexpayload":"746573745F64657374",
      "payload_method":"key",
      "enc_pubkey": "CA022000B24DE3565D6717799D78635DDB7D6847E219D2B4745CE6DA4A0681DF2D6F1ABE2000353C4C2AEBB552C11CDA8A4EA5F1082FC90FE0243DCE33F16CCDFB4F84F5A78F"
   },
   "id":1,
   "jsonrpc":"2.0"
}

In the response you can 1. see the public key used to encrypt the payload (env_pubkey) and 2. see the decrypted payload (unenc_payload), which is test_dest.

sender - Sender public key

To send an operation where the payload can only be decrypted by the sending party (in our case the owner of the account 66033), we will set the payload_method field to sender and the payload field to a HexaString from the ASCII string test_sender. The HexaString for this payload is 746573745F73656E646572.

Our JSON RPC request object now looks like this:

{
   "jsonrpc":"2.0",
   "method":"sendto",
   "params":{
      "sender":66033,
      "target":55099,
      "amount":0.0001,
      "fee":0.0001,
      "payload":"746573745F73656E646572",
      "payload_method":"sender"
   },
   "id":1
}

When executed against the API the resulting operation object looks like this:

{  
   "result":{  
      "block":0,
      "time":0,
      "opblock":-1,
      "maturation":null,
      "optype":1,
      "subtype":11,
      "account":66033,
      "signer_account":66033,
      "n_operation":41,
      "senders":[  
         {  
            "account":66033,
            "n_operation":41,
            "amount":-0.0002,
            "payload": "21100B00100002784ABDC55F0C958DCEFF6FDD4BF70B55C809F0058E1CE381C5098B3613DFE7C65F20F57A2AE2ED05DE318107E17ED94BF9016A263086E360F891ADC85B20991C"
         }
      ],
      "receivers":[  
         {  
            "account":55099,
            "amount":0.0001,
            "payload": "21100B00100002784ABDC55F0C958DCEFF6FDD4BF70B55C809F0058E1CE381C5098B3613DFE7C65F20F57A2AE2ED05DE318107E17ED94BF9016A263086E360F891ADC85B20991C"
         }
      ],
      "changers":[  

      ],
      "optxt":"Tx-Out 0.0001 PASC from 66033-39 to 55099-17",
      "fee":-0.0001,
      "amount":-0.0001,
      "payload": "21100B00100002784ABDC55F0C958DCEFF6FDD4BF70B55C809F0058E1CE381C5098B3613DFE7C65F20F57A2AE2ED05DE318107E17ED94BF9016A263086E360F891ADC85B20991C",
      "balance":0,
      "sender_account":66033,
      "dest_account":55099,
      "ophash":"00000000F101010029000000DB216409EF93B660F700FD4903172807766B8466",
      "old_ophash":""
   },
   "id":1,
   "jsonrpc":"2.0"
}

Again, you will notice that the payload in result->senders->payload and result->receivers->payload is much longer than the payload we used when creating the operation. This is because it was encrypted using the senders public key. This value can only be decrypted by the owning private key of the account 66033 - no-one else.

The sender can use the payloaddecrypt method to decrypted the value.

{
   "jsonrpc":"2.0",
   "method":"payloaddecrypt",
   "params":{
      "payload": "21100B00100002784ABDC55F0C958DCEFF6FDD4BF70B55C809F0058E1CE381C5098B3613DFE7C65F20F57A2AE2ED05DE318107E17ED94BF9016A263086E360F891ADC85B20991C"
   },
   "id":1
}

The response looks like this:

{  
   "result":{  
      "result":true,
      "enc_payload": "21100B00100002784ABDC55F0C958DCEFF6FDD4BF70B55C809F0058E1CE381C5098B3613DFE7C65F20F57A2AE2ED05DE318107E17ED94BF9016A263086E360F891ADC85B20991C",
      "unenc_payload":"test_sender",
      "unenc_hexpayload":"746573745F73656E646572",
      "payload_method":"key",
      "enc_pubkey": "CA022000B24DE3565D6717799D78635DDB7D6847E219D2B4745CE6DA4A0681DF2D6F1ABE2000353C4C2AEBB552C11CDA8A4EA5F1082FC90FE0243DCE33F16CCDFB4F84F5A78F"
   },
   "id":1,
   "jsonrpc":"2.0"
}

In the response you can 1. see the public key used to encrypt the payload (enc_pubkey) and 2. see the decrypted payload (unenc_payload), which is test_sender.

aes - Password

Now the last possibility. We will send an operation where the payload can only be decrypted with a password. We will set the payload_method field to aes and the payload field to a HexaString from the ASCII string test_password and the password to secret. The HexaString for this payload is 746573745F70617373776F7264.

Our JSON RPC request object now looks like this:

{
   "jsonrpc":"2.0",
   "method":"sendto",
   "params":{
      "sender":66033,
      "target":55099,
      "amount":0.0001,
      "fee":0.0001,
      "payload":"746573745F70617373776F7264",
      "payload_method":"aes",
      "pwd": "secret"
   },
   "id":1
}

When executed against the API the resulting operation object looks like this:

{  
   "result":{  
      "block":0,
      "time":0,
      "opblock":-1,
      "maturation":null,
      "optype":1,
      "subtype":11,
      "account":66033,
      "signer_account":66033,
      "n_operation":42,
      "senders":[  
         {  
            "account":66033,
            "n_operation":42,
            "amount":-0.0002,
            "payload":"53616C7465645F5FE3A381879577006B76C9B9B73ABFF4E79036006E45405398"
         }
      ],
      "receivers":[  
         {  
            "account":55099,
            "amount":0.0001,
            "payload":"53616C7465645F5FE3A381879577006B76C9B9B73ABFF4E79036006E45405398"
         }
      ],
      "changers":[  

      ],
      "optxt":"Tx-Out 0.0001 PASC from 66033-39 to 55099-17",
      "fee":-0.0001,
      "amount":-0.0001,
      "payload":"53616C7465645F5FE3A381879577006B76C9B9B73ABFF4E79036006E45405398",
      "balance":0,
      "sender_account":66033,
      "dest_account":55099,
      "ophash":"00000000F10101002A000000596490B2C5D1019A992A3093BE25BA3103FA227E",
      "old_ophash":""
   },
   "id":1,
   "jsonrpc":"2.0"
}

The payload in the operation object is now encrypted using your password and AES256-CBC and it can only be decrypted if you know the password.

Anyone can use the payloaddecrypt method to decrypt the value with a correct password.

{
   "jsonrpc":"2.0",
   "method":"payloaddecrypt",
   "params":{
      "payload": "21100B00100002784ABDC55F0C958DCEFF6FDD4BF70B55C809F0058E1CE381C5098B3613DFE7C65F20F57A2AE2ED05DE318107E17ED94BF9016A263086E360F891ADC85B20991C"
   },
   "id":1
}

The response looks like this:

{  
   "result":{  
      "result":true,
      "enc_payload":"53616C7465645F5FE3A381879577006B76C9B9B73ABFF4E79036006E45405398",
      "unenc_payload":"test_password",
      "unenc_hexpayload":"746573745F70617373776F7264",
      "payload_method":"pwd",
      "pwd":"secret"
   },
   "id":123,
   "jsonrpc":"2.0"
}

In the response you can see that the decryption was successful and the payload of the recently generated operation was test_password.

Exchange Integration

If you are using payloads to identify your users in deposit transactions, you should support both public and encrypted payloads. This is because some users may encrypt their payload and others may not. For example, Poloniex withdrawals to your deposit address will always have encrypted payloads. However, deposits from wallet users may be public. In principle, it is up to the recipient to examine the payloads both in their raw public form and then in their decrypted form.

As a result, when processing user deposit transactions to your exchange, it is highly recommended that you:

  1. First check if the Operation Payload matches your users deposit code. If it matches, then the deposit can be accepted otherwise proceed to (2).

  2. Decrypt the payload using decryptpayload method as shown in the above examples.

  3. Repeat (1) using the decrypted payload code from (2). If it matches then deposit is accepted otherwise the deposit is unrecognised.

With this approach you can ensure deposits are never missed and that support requests are minimised

Conclusion

You know now that PascalCoin offers a variety of possibilities to encrypt the payload of operations and depending on the use case, one or the other method makes sense.

  • Use sender if you want to make sure only the sender can decrypt the payload.
  • Use dest if you want to make sure only the receiver can decrypt the payload.
  • Use aes if you want to make sure only parties that know the password can decrypt the payload.
  • Use none if you don't care about encryption at all and everyone should be able to read the payload.

To decrypt a payload the following way is advised:

  • Take the payload as is, transform the HexaString to a string and see if the value makes sense. "Makes sense" means: If you need the payload to react based on it, you should know the format of the resulting string, so you should be able to say if it makes sense.

  • If the resulting string does not make sense, try to decrypt the value using the payloaddecrypt RPC API and a possible set of passwords. PascalCoin will try to decrypt the payload with the available private keys and the possible passwords.

  • If everything fails, the payload got encrypted

    • using the payload_method sender and you are not the sender
    • using the payload_method dest and you are not the owner of the receiver.
    • using the payload_method aes and you used the wrong passwords

    Or.. there is a misunderstanding and the sender used the wrong encryption method.

Happy Coding!