Sign & Inject

Signing

Before signing the operation bytes a watermark prefix must be appended. For regular operations used in a wallet this prefix will be 0x03. Operations associated to baking will have a different prefix. After the watermark have been added, the bytes will need to be hashed into a 32-byte generic hash. Then the hash can be signed with the private key from the signature scheme chosen.

Example of operation bytes to sign with a watermark attached:

03e89ad408711929f7006d6d796806fb9c51f55cf80903c475b41eb31e70eea3670801be6ae938b7dd8ad98bda 88bd8cd314cf5005f46700c60a05e8529502c08db701014228bd78294ca6ecff55908360b79dca4e7cf0af0000

Generic hash

72d0ee1c84e7619b1480e031a57e02641248870e090811b296bfb94d55b02a69

Signature (Ed25519):

fdb7e21e78397cfe301570f073a5459ce36c42a1e850a628f9256c7fe1a07a5b73ef06517704d46eb0945848ec8d2f7545b87f95f0fe9ee60037092e82911007

Injection

Before injecting an operation to the blockchain, it’s a good idea to validate that it doesn’t contain any errors. With the preapply RPC a simulation will be performed, and the effects of the operation(s) will be returned in an array.

With the transaction used in the signing example, this is how a response from the RPC would look:

[  
   {  
      "contents":[  
         {  
            "kind":"transaction",
            "source":"KT1Rwc2XBa5vcvSZZtPzA4aK4DJNfUEzwgro",
            "fee":"1350",
            "counter":"5",
            "gas_limit":"10600",
            "storage_limit":"277",
            "amount":"3000000",
            "destination":"KT1Ecay6hLAsGmVSaRawzF1iNt8beuk1djDF",
            "metadata":{  
               "balance_updates":[  
                  {  
                     "kind":"contract",
                     "contract":"KT1Rwc2XBa5vcvSZZtPzA4aK4DJNfUEzwgro",
                     "change":"-1350"
                  },
                  {  
                     "kind":"freezer",
                     "category":"fees",
                     "delegate":"tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU",
                     "cycle":279,
                     "change":"1350"
                  }
               ],
               "operation_result":{  
                  "status":"applied",
                  "balance_updates":[  
                     {  
                        "kind":"contract",
                        "contract":"KT1Rwc2XBa5vcvSZZtPzA4aK4DJNfUEzwgro",
                        "change":"-3000000"
                     },
                     {  
                        "kind":"contract",
                        "contract":"KT1Ecay6hLAsGmVSaRawzF1iNt8beuk1djDF",
                        "change":"3000000"
                     }
                  ],
                  "consumed_gas":"10200"
               }
            }
         }
      ],
      "signature":"edsigu6zzNT7eZ1mFZ3G3R5KQeGSTpccmtAsrkizKE5Vs9A7sG858G3AFCyEtHmRakZFbdDgNTA371YHcXLUsM1PuCQys5nDFgB"
   }
]

What we are interested in to see here is that a JSON object is being return and that the status value is set to applied. This means that the operation was successfully injected into a block in the simulation. Another thing to take notice on is that we can see how much gas was consumed during the simulation. So preapply can also be used to fine tune the gas and storage limits more accurately.

With the injection RPC the signed operation bytes can then be broadcasted to a node and propagate from there to other mempools. The signed operation in this case is the operations bytes with the signature appended to the end. From the previous example this would give us the following signed operation bytes:

e89ad408711929f7006d6d796806fb9c51f55cf80903c475b41eb31e70eea3670801be6ae938b7dd8ad98bda88bd8cd314cf5005f46700c60a05e8529502c08db701014228bd78294ca6ecff 55908360b79dca4e7cf0af0000fdb7e21e78397cfe301570f073a5459ce36c42a1e850a628f9256c7fe1a07a5b73ef06517704d46eb0945848ec8d2f7545b87f95f0fe9ee60037092e82911007

When the signed operation shell have been successfully injected we get the operation hash in response from the node RPC.

ooj6C4Mj1xZBtbMJzJM5ECupxQL8Tjj187Xw3PHju5MNia6PdrV