Skip to content

Transaction

This is the specification for transactions, which includes signed transactions from users and executable events, which are spawned by the blockchain.

You can learn more about how interactions work on the blockchain here.

A signed transaction is an instruction from a user containing information, which is used to change the state of the blockchain. After constructing a binary signed transaction it can be delivered to any node producing blocks in the private network through their REST API.

The following is the specification of the binary format of signed transactions.

The easiest way of creating a binary signed transaction is by using one of the available client libraries. This specification can help you if you want to make your own implementation, for instance if you are targeting another programming language.

::= {

signature: [Signature](#signature)

transaction: Transaction

}

::= {

recoveryId: 0xnn

valueR: 0xnn×32

(big-endian)

valueS: 0xnn×32

(big-endian)

}

The Signature includes:

  • A recovery id between 0 and 3 used to recover the public key when verifying the signature
  • The r value of the ECDSA signature
  • The s value of the ECDSA signature

::= {

nonce: 0xnn×8

(big-endian)

validToTime: 0xnn×8

(big-endian)

gasCost: 0xnn×8

(big-endian)

address: [Address](#address)
rpc: [Rpc](#rpc)

}

::= len:0xnn×4 payload:0xnn×len

(len is big-endian)

The Transaction includes:

  • The signer’s nonce
  • Milliseconds after the unix-epoch that is used to defined how long the transaction is valid to be executed.
  • The amount of gas allocated to executing the transaction, for a deployment no gas is needed, so the amount should be 0.
  • The address of the smart contract that is the target of the transaction.
  • The Rpc payload of the transaction. See Smart Contract Binary Formats for a way to build the rpc payload.

The signature is an ECDSA signature, using secp256k1 as the curve, on a sha256 hash of the transaction and the chain ID of the blockchain.

The chain id is a unique identifier for the blockchain. For example, the chain id for the private deployment is Private Blockchain.

An executable event is spawned by the blockchain, and not by a user. It can be created from other events or when the blockchain receives a signed transaction. The executable event contains the information about which action to perform to a smart contract.

The following is the specification of the binary format of executable events.

::= {

originShard: [Option](#option--t)<[String](#string)> transaction: [EventTransaction](#eventtransaction)

}

The originShard is an Option<String>, the originating shard of the event.

::= {

originatingTransaction: [Hash](#hash) inner: [InnerEvent](#innerevent) shardRoute: [ShardRoute](#shardroute) committeeId: [Long](#long) governanceVersion: [Long](#long)

height: [Byte](#byte)

(unsigned)

returnEnvelope: [Option](#option--t)<[ReturnEnvelope](#returnenvelope)>

}

The transaction, EventTransaction, includes:

  • The originating transaction: the SignedTransaction initiating the tree of events that this event is a part of.
  • The event type, InnerEvent.
  • The ShardRoute describes which shard the event should be executed on.
  • The id of the committee that produced the block where the event was spawned.
  • The governance version when this event was produced.
  • The height of the event tree, which is increased for each event spawned after a signed transaction.
  • If there is a callback registered to the event, the result of the event is returned in a ReturnEnvelope.

::=

0x00 [InnerTransaction](#innertransaction)

| 0x01 [CallbackToContract](#callbacktocontract)

| 0x02 [InnerSystemEvent](#innersystemevent)

| 0x03 [SyncEvent](#syncevent)

The InnerEvent of an EventTransaction is divided into four types of events: InnerTransaction, CallbackToContract, InnerSystemEvent and SyncEvent.

A transaction is sent by the user or the contract, meaning that it represents the actions the user can activate. Transactions can either deploy contracts or interact with them. Each transaction also carries an associated sender and an associated cost.

::= {

from: [Address](#address) cost: [Long](#long) transaction: [Transaction](#transaction)

}

::=

0x00 => [CreateContractTransaction](#createcontracttransaction)

| 0x01 => [InteractWithContractTransaction](#interactwithcontracttransaction)

::= {

address: [Address](#address) binderJar: [DynamicBytes](#dynamicbytes) contractJar: [DynamicBytes](#dynamicbytes) abi: [DynamicBytes](#dynamicbytes) rpc: [DynamicBytes](#dynamicbytes)

}

::= {

contractId: [Address](#address) payload: [DynamicBytes](#dynamicbytes)

}

Callback transactions call the callback methods in contracts.

::= {

address: [Address](#address) callbackIdentifier: [Hash](#hash) from: [Address](#address) cost: [Long](#long) callbackRpc: [DynamicBytes](#dynamicbytes)

}

System events can manipulate the system state of the blockchain. These are primarily sent by system/governance contracts.

::= {

systemEventType: [SystemEventType](#systemeventtype)

}

::=

0x00 [CreateAccountEvent](#createaccountevent)

| 0x01 [CheckExistenceEvent](#checkexistenceevent)

| 0x02 [SetFeatureEvent](#setfeatureevent)

| 0x03 [UpdateLocalPluginStateEvent](#updatelocalpluginstateevent)

| 0x04 [UpdateGlobalPluginStateEvent](#updateglobalpluginstateevent)

| 0x05 [UpdatePluginEvent](#updatepluginevent)

| 0x06 [CallbackEvent](#callbackevent)

| 0x07 [CreateShardEvent](#createshardevent)

| 0x08 [RemoveShardEvent](#removeshardevent)

| 0x09 [UpdateContextFreePluginState](#updatecontextfreepluginstate)

| 0x0A [UpgradeSystemContractEvent](#upgradesystemcontractevent)

| 0x0B [RemoveContract](#removecontract)

::= {

toCreate: [Address](#address)

}

::= {

contractOrAccountAddress: [Address](#address)

}

::= {

key: [String](#string) value: [Option](#option--t)<[String](#string)>

}

::= {

type: [ChainPluginType](#chainplugintype) update: [LocalPluginStateUpdate](#localpluginstateupdate)

}

::=

0x00 => Account

| 0x01 => Consensus

| 0x02 => Routing

| 0x03 => SharedObjectStore

::= {

context: [Address](#address) rpc: [DynamicBytes](#dynamicbytes)

}

::= {

type: [ChainPluginType](#chainplugintype) update: [GlobalPluginStateUpdate](#globalpluginstateupdate)

}

::= {

rpc: [DynamicBytes](#dynamicbytes)

}

::= {

type: [ChainPluginType](#chainplugintype) jar: [Option](#option--t)<[DynamicBytes](#dynamicbytes)> invocation: [DynamicBytes](#dynamicbytes)

}

::= {

returnEnvelope: [ReturnEnvelope](#returnenvelope) completedTransaction: [Hash](#hash) success: [Boolean](#boolean) returnValue: [DynamicBytes](#dynamicbytes)

}

::= {

shardId: [String](#string)

}

::= {

shardId: [String](#string)

}

::= {

type: [ChainPluginType](#chainplugintype) rpc: [DynamicBytes](#dynamicbytes)

}

::= {

contractAddress: [Address](#address) binderJar: [DynamicBytes](#dynamicbytes) contractJar: [DynamicBytes](#dynamicbytes) abi: [DynamicBytes](#dynamicbytes) rpc: [DynamicBytes](#dynamicbytes)

}

::= {

contractAddress: [Address](#address)

}

### Sync Event

A sync event is used for moving information from one shard to another when changing the shard configuration. That is, when adding or removing shards or when changing routing logic.

::= {

accounts: [List](#list-t)<[AccountTransfer](#accounttransfer)> contracts: [List](#list-t)<[ContractTransfer](#contracttransfer)> stateStorage: [List](#list-t)<[DynamicBytes](#dynamicbytes)>

}

::= {

address: [Address](#address) accountStateHash: [Hash](#hash) pluginStateHash: [Hash](#hash)

}

::= {

address: [Address](#address) ContractStateHash: [Hash](#hash) pluginStateHash: [Hash](#hash)

}

::= {

targetShard: [Option](#option--t)<[String](#string)> nonce: [Long](#long)

}

::= addressType:[AddressType](#addresstype) identifier:0xnn×20

(identifier is big-endian)

::=

0x00 => Account

| 0x01 => System

| 0x02 => Public

| 0x03 => Zk

| 0x04 => Gov

::= b:0xnn

(false if b==0, true otherwise)

::= 0xnn

::= len:0xnn×4 payload:0xnn×len

(big-endian)

::= 0xnn×32

(big-endian)

::= len:0xnn×4 elems:T×len

(len is big-endian)

::= 0xnn×8

(big-endian)

::=

0x00 => None

 

| b:0xnn t:T => Some(t)

(b != 0)

::= Address

::= len:0xnn×4 uft8:0xnn×len

(big-endian)