Skip to content
Document

Transaction Binary Format

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.

Signed Transaction

A signed transaction is an instruction from a user containing information used to change the state of the blockchain. After constructing a binary signed transaction it can be delivered to any baker node in the 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.

SignedTransaction

::= {

signature: Signature
transaction: Transaction

}


Signature

::= {

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
Transaction

::= {

nonce: 0xnn×8

(big-endian)

validToTime: 0xnn×8

(big-endian)

gasCost: 0xnn×8

(big-endian)

address: Address
rpc: DynamicBytes

}

The Transaction includes:

  • The signer's nonce
  • A unix time that the transaction is valid to
  • The amount of gas allocated to executing the transaction
  • 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.

Creating the signature

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.

ToBeHashed

::= transaction:Transaction chainId:ChainId

The chain id is a unique identifier for the blockchain. For example, the chain id for Partisia Blockchain mainnet is Partisia Blockchain and the chain id for the testnet is Partisia Blockchain Testnet.

Executable Event Binary Format

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.

ExecutableEvent

::= {

originShard: Option<String>
transaction: EventTransaction

}

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

EventTransaction

::= {

originatingTransaction: Hash
inner: InnerEvent
shardRoute: ShardRoute
committeeId: Long
governanceVersion: Long
height: Byte
returnEnvelope: Option<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 committee id is used to find the correct committee for validating a finalization proof sent from one shard to another. The committee id of an event must be larger than the latest committee id.
  • The governance version when this event was produced. The governance version is incremented when the global state is changes, e.g. when updating a plugin. The governance version of the event must be up-to-date with the local governance version.
  • 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.
ShardRoute

::= {

targetShard: Option<String>
nonce: Long

}

A ShardRoute, the unique routing to a shard, contains the id of a target shard and a nonce.

Event Types

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

Inner Transaction

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.

InnerTransaction

::= {

from: Address
cost: Long
transaction: Transaction

}

The InnerTransaction contains an associated sender and an associated cost, as well as the transaction.

A Transaction is either a CreateContractTransaction used to deploy contracts, or an InteractWithContractTransaction used to interact with contracts.

Create Contract Transaction

CreateContractTransaction

::= {

address: Address
binderJar: DynamicBytes
contractJar: DynamicBytes
abi: DynamicBytes
rpc: DynamicBytes

}

A CreateContractTransaction contains the Address where the contract should be deployed, and the binding jar, the contract jar, the contract ABI and the RPC of the create-invocation.

Interact with Contract Transaction

An InteractWithContractTransaction contains the Address of the contract to interact with, as well as a payload (RPC) defining the interaction.

Callback to Contract

Callback transactions call the callback methods in contracts.

CallbackToContract

::= {

address: Address
callbackIdentifier: Hash
from: Address
cost: Long
callbackRpc: DynamicBytes

}

A CallbackToContract contains the Address of the contract to target, as well as information about the callback: The event transactions that has been awaited and is completed, the sender, the allocated cost for the callback event, and the callback RPC.

Inner System Event

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

InnerSystemEvent

::= {

systemEventType: SystemEventType

}

An InnerSystemEvent has a SystemEventType.

Create Account Event

CreateAccountEvent

::= {

toCreate: Address

}

A CreateAccountEvent contains the address of the account to create.

Check Existence Event

CheckExistenceEvent

::= {

contractOrAccountAddress: Address

}

A CheckExistenceEvent is an event for checking the existence of a contract or account address.

Set Feature Event

SetFeatureEvent

::= {

key: String
value: Option<String>

}

A SetFeatureEvent is an event for setting a feature in the state. The key indicates the feature to set, and the value is the value to set on the feature.

Update Local Plugin State Event

A UpdateLocalPluginStateEvent updates the local state of the plugin, and its fields are a plugin type ChainPluginType and a plugin state LocalPluginStateUpdate.

ChainPluginType

::=

0x00 => Account

| 0x01 => Consensus

| 0x02 => Routing

| 0x03 => SharedObjectStore

A ChainPluginType can have the following types:

  • The Account plugin controls additional information about account and fees.
  • The Consensus plugin validates block proposals and finalizes correct blocks.
  • The Routing plugin selects the right shard for any transaction.
  • The SharedObjectStore plugin stores binary objects across all shards.

A LocalPluginStateUpdate contains the Address of the contract where the state should be updated, as well as RPC with the update.

Update Global Plugin State Event

A UpdateGlobalPluginStateEvent contains a chain plugin type ChainPluginType and a state update GlobalPluginStateUpdate.

The GlobalPluginStateUpdate contains the RPC of the update to execute globally.

Update Plugin Event

An UpdatePluginEvent constructs a new event for updating an active plugin. It takes the type of the chain plugin to update, the jar to use as plugin, and RPC of global state migration.

Callback Event

CallbackEvent

::= {

returnEnvelope: ReturnEnvelope
completedTransaction: Hash
success: Boolean
returnValue: DynamicBytes

}

A CallbackEvent is the callback sent when a transaction has been executed. It contains the following fields:

  • A ReturnEnvelope with the destination for the callback.
  • A Hash of the transaction which has been executed.
  • A Boolean indicating whether the transaction was successful.
  • The return value of the callback event.

Create Shard Event

CreateShardEvent

::= {

shardId: String

}

A CreateShardEvent is an event for creating a shard. The shardId is the id of the shard to create.

Remove Shard Event

RemoveShardEvent

::= {

shardId: String

}

A RemoveShardEvent is an event for removing a shard. The shardId is the id of the shard to remove.

Update Context Free Plugin State

An UpdateContextFreePluginState updates the local state of a plugin without context on a named shard. Its fields are the type of plugin to update, i.e. ChainPluginType, and the local state migration RPC.

Upgrade System Contract Event

UpgradeSystemContractEvent

::= {

contractAddress: Address
binderJar: DynamicBytes
contractJar: DynamicBytes
abi: DynamicBytes
rpc: DynamicBytes

}

An UpgradeSystemContractEvent upgrades a contract. It contains the contract address, the binder jar, the contract jar, the contract ABI, and the upgrade RPC.

Remove Contract

RemoveContract

::= {

contractAddress: Address

}

The RemoveContract event removes an existing contract from the state. The contract to remove is specified by the Address of the contract.

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.

SyncEvent

::= {

accounts: List<AccountTransfer>
contracts: List<ContractTransfer>
stateStorage: List<DynamicBytes>

}

The SyncEvent contains a lists of account transfer objects, contract transfer objects and serialized data of stored states.

AccountTransfer

::= {

address: Address
accountStateHash: Hash
pluginStateHash: Hash

}

An AccountTransfer consists of an account Address, a Hash of the account state and a Hash of the plugin state.

ContractTransfer

::= {

address: Address
contractStateHash: Hash
pluginStateHash: Hash

}

An ContractTransfer consists of a contract Address, a Hash of the contract state and a Hash of the plugin state.

Common Types

Address Type

An Address is encoded as 21 bytes. The first byte is the AddressType, and the remaining 20 bytes are the address identifier.

Address

::= addressType:AddressType identifier:0xnn×20

(identifier is big-endian)

An AddressType can either be an account address, a system address, public address, zk address or a government address.

AddressType

::=

0x00 => Account

| 0x01 => System

| 0x02 => Public

| 0x03 => Zk

| 0x04 => Gov

Boolean Type

A Boolean is encoded as a single byte, which is either 0 (false) or non-0 (true).

Boolean

::= b:0xnn

(false if b==0, true otherwise)

Byte Type

A Byte is encoded as a byte corresponding to its value.

Byte

::= 0xnn

Dynamic Bytes

DynamicBytes are encoded as a length, len, of 4 bytes, and a payload of len bytes. Both len and payload are encoded in big-endian order.

DynamicBytes

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

(big-endian)

Hash Type

A Hash is encoded as 32 bytes in big-endian order.

Hash

::= 0xnn×32

(big-endian)

List Type

A List<T> of len elements of type T are encoded as the len (4 bytes, big-endian order), and the len elements are encoded according to their type T.

List<T>

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

(len is big-endian)

Long Type

A Long is encoded as 8 bytes in big-endian order.

Long

::= 0xnn×8

(big-endian)

Option Type

An Option<T> is encoded as either one 0-byte if T is None, or as a non-zero byte and the encoding of T according to its type.

Option<T>

::=

0x00 => None

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

(b != 0)

Return Envelope

A ReturnEnvelope is encoded as an Address.

String Type

A String is encoded as its length, len (4 bytes), and the UTF-8 of len bytes. Both are encoded in big-endian order.

String

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

(big-endian)