Serialization Standard
We provide a custom implementation to serialize data structures used by the Casper node to their byte representation. This document details how this custom serialization is implemented, allowing developers to build a library that implements the custom serialization.
In your smart contracts, you can implement serialization using cltype-any.
Account
An Account is a structure that represents a user on a Casper network. The account structure consists of the following fields:
-
main_purseThe account's main purse
URef. You may find information onURefserialization here.
Account Hash
A blake2b hash of the public key, representing the address of a user's account. The account hash serializes as a 32-byte buffer containing the bytes of the account hash.
Action Thresholds
The minimum weight thresholds that have to be met when executing an action of a certain type. It serializes as two consecutive u8 values as follows.
-
deploymentThe minimum weight threshold required to perform deployment actions as au8value. -
key_managementThe minimum weight threshold required to perform key management actions as au8value.
Activation Point
The first era to which the associated protocol version applies. It serializes as a single u8 tag indicating if the era in question is genesis. If it is the genesis era, the following bytes will be a timestamp. If not, the bytes represent an era_id.
-
era_idAn Era ID newtype identifying the era when the protocol version will activate. -
timestampA timestamp if the activation point is of the Genesis variant.
Approval
A struct containing a signature and the public key of the signer.
-
signatureThe approval signature, which serializes as the byte representation of theSignature. The first byte within the signature is 1 in the case of anEd25519signature or 2 in the case ofSecp256k1. -
signerThe public key of the approvals signer. It serializes to the byte representation of thePublicKey. If thePublicKeyis anEd25519key, then the first byte within the serialized buffer is 1 followed by the bytes of the key itself; else, in the case ofSecp256k1, the first byte is 2.
AssociatedKey
A key granted limited permissions to an Account, for purposes such as multisig. It is serialized as a BTreeMap where the first 4 bytes represent a u32 value describing the number of keys and weights held within. The remainder consists of a repeating pattern of serialized named keys and then weights of the length dictated by the first four bytes.
-
account_hashThe account hash of the associated key. -
weightThe weight of an associated key. The weight serializes as au8value.
AvailableBlockRange
An unbroken, inclusive range of blocks. It serializes as two consecutive u64 values containing the following two fields:
-
lowThe inclusive lower bound of the range. -
high- The inclusive upper bound of the range.
Bid
An entry in the validator map. The structure consists of the following fields:
-
validator_public_keyThe validator's public key. It serializes as aPublicKey. -
bonding_purseThe purse used for bonding. It serializes as aUref. -
staked_amountThe amount of tokens staked by a validator (not including delegators). It serializes as aU512value. -
delegation_rateThe delegation rate of the bid. It serializes as ani32signed 32-bit integer primitive. -
vesting_scheduleThe vesting schedule for a genesis validator.Noneif it is a non-genesis validator. It serializes as anOption. -
delegatorsThe validator's delegators, indexed by their public keys. They are serialized as aBTreeMapwhere the first 4 bytes represent au32value describing the number ofPublicKeys and delegators held within. The remainder consists of a repeating pattern of serializedPublicKeys and then delegators of the length dictated by the first four bytes. -
inactiveIf the validator has been evicted. A boolean value that serializes as a single byte;truemaps to1, whilefalsemaps to0.
Block
A block is the core component of the Casper linear blockchain, used in two contexts:
- A data structure containing a collection of transactions. Blocks form the primary structure of the blockchain.
- A message that is exchanged between nodes containing the data structure as explained in (1).
Each block has a globally unique ID, achieved by hashing the contents of the block.
Each block points to its parent. An exception is the first block, which has no parent.
A block is structurally defined as follows:
hash: A hash over the header of the block.header: The header of the block that contains information about the contents of the block with additional metadata.body: The block's body contains the proposer of the block and hashes of deploys and transfers contained within it.
Block hash
The block hash is a Digest over the contents of the block Header. The BlockHash serializes as the byte representation of the hash itself.
Block header
The header portion of a block, structurally, is defined as follows:
parent_hash: is the hash of the parent block. It serializes to the byte representation of the parent hash. The serialized buffer of theparent_hashis 32 bytes long.state_root_hash: is the global state root hash produced by executing this block's body. It serializes to the byte representation of thestate root hash. The serialized buffer of thestate_root_hashis 32 bytes long.body_hash: the hash of the block body. It serializes to the byte representation of the body hash. The serialized buffer of thebody_hashis 32 bytes long.random_bit: is a boolean needed for initializing a future era. It is serialized as a single byte; true maps to 1, while false maps to 0.accumulated_seed: A seed needed for initializing a future era. It serializes to the byte representation of the parent Hash. The serialized buffer of theaccumulated_hashis 32 bytes long.era_end: contains equivocation and reward information to be included in the terminal finalized block. It is an optional field. Thus if the field is set asNone, it serializes to 0. The serialization of the other case is described in the EraEnd.timestamp: The timestamp from when the block was proposed. It serializes as a singleu64value. The serialization of au64value is described in the CLValues section.era_id: Era ID in which this block was created. It serializes as a singleu64value.height: The height of this block, i.e., the number of ancestors. It serializes as a singleu64value.protocol_version: The version of the Casper network when this block was proposed. It is 3-element tuple containingu32values. It serializes as a buffer containing the threeu32serialized values. Refer to the CLValues section on howu32values are serialized.
EraEnd
EraEnd as represented within the block header, is a struct containing two fields.
era_report: The first field is termed asEraReportand contains information about equivocators and rewards for an era.next_era_validator_weights: The second field is map for the validators and their weights for the era to follow.
EraReport itself contains two fields:
equivocators: A vector ofPublicKey.rewards: A Binary Tree Map ofPublicKeyandu64.
When serializing an EraReport, the buffer is first filled with the individual serialization of the PublicKey contained within the vector.
- If the
PublicKeyis anEd25519key, the first byte within the buffer is a1followed by the individual bytes of the serialized key. - If the
PublicKeyis anSecp256k1key, the first byte within the buffer is a2followed by the individual bytes of the serialized key.
When serializing the overarching struct of EraEnd, we first allocate a buffer, which contains the serialized representation of the EraReport as described above, followed by the serialized BTreeMap.
Note that EraEnd is an optional field. Thus the above scheme only applies if there is an EraEnd; if there is no era end, the field simply serializes to 0.
Body
The body portion of the block is structurally defined as:
proposer: The PublicKey which proposed this block.deploy_hashes: Is a vector of hex-encoded hashes identifying Deploys included in this block.transfer_hashes: Is a vector of hex-encoded hashes identifying Transfers included in this block.
When we serialize the BlockBody, we create a buffer that contains the serialized representations of the individual fields present within the block.
proposer: serializes to the byte representation of thePublicKey. If thePublicKeyis anEd25519key, then the first byte within the serialized buffer is 1 followed by the bytes of the key itself; else, in the case ofSecp256k1, the first byte is 2.deploy_hashes: serializes to the byte representation of all the deploy_hashes within the block header. Its length is32 * n, where n denotes the number of deploy hashes present within the body.transfer_hashes: serializes to the byte representation of all the deploy_hashes within the block header. Its length is32 * n, where n denotes the number of transfers present within the body.
BlockIdentifier
Identifier for possible ways to retrieve a Block. It can consist of any of the following in most situations:
-
hashIdentify and retrieve a Block with its hash. TheBlockHashserializes as the byte representation of the hash itself. -
heightIdentify and retrieve the Block with its height. Height serializes as a singleu64value. -
state_root_hashIdentify and retrieve the Block with its state root hash. It serializes to the byte representation of thestate root hash. The serialized buffer of thestate_root_hashis 32 bytes long.
ChainspecRegistry
ChainspecRegistry is a unique key variant which contains a mapping of file names to the hash of the file itself. This map includes Chainspec.toml and may include Accounts.toml and GlobalState.toml. It is serialized as a BTreeMap where the first 4 bytes represent a u32 value describing the number of names as strings and digests held within. The remainder consists of a repeating pattern of serialized strings and then digests of the length dictated by the first four bytes. Digests and their inclusion criteria are as follows:
-
chainspec_raw_hashwill always be included. -
genesis_accounts_raw_hashmay be included in specific circumstances. -
global_state_raw_hashmay be included in specific circumstances.
Contract
A contract struct containing the following fields:
ContractHash
A blake2b hash of a contract. The contract hash serializes as a 32-byte buffer containing the bytes of the contract hash.
ContractPackageHash
A blake2b hash of a contract package. The contract package hash serializes as a 32-byte buffer containing the bytes of the contract package hash.
ContractVersion
The version of the contract.
-
contract_hashThe contract hash of the contract. -
contract_versionThe version of the contract within the protocol major version. It serializes as au32value. -
protocol_version_majorThe major element of the protocol version this contract is compatible with. It serializes as au32value.
ContractWasmHash
A blake2b hash of a contract's Wasm. The contract's Wasm hash serializes as a 32-byte buffer containing the bytes of the contract's Wasm hash.
Delegator
Represents a party delegating their stake to a validator (or "delegatee"). The structure consists of the following fields:
-
delegator_public_keyThe public key of the delegator, serialized as aPublicKey. -
staked_amountThe amount staked by the delegator, serialized as aU512value. -
bonding_purseThe bonding purse associated with the delegation. It serializes as aURefvalue. -
validator_public_keyThe public key of the validator that the delegator will be delegating to, serialized as aPublicKey. -
vesting_scheduleThe vesting schedule for the provided delegator bid.Noneif it is a non-genesis validator. It serializes as anOption.
Deploy
A deploy is a data structure containing a smart contract and the requester's signature(s). Additionally, the deploy header contains additional metadata about the deploy itself. A deploy is structurally defined as follows:
hash: The hash of the deploy header.header: Contains metadata about the deploy. The structure of the header is detailed further in this document.payment: The payment code for contained smart contract.session: The stored contract itself.approvals: A list of signatures:
Deploy-Hash
The deploy hash is a digest over the contents of the deploy header. The deploy hash serializes as the byte representation of the hash itself.
Deploy-Header
account: A supported public key variant (currently eitherEd25519orSecp256k1). AnEd25519key is serialized as a buffer of bytes, with the leading byte being1forEd25519, with remainder of the buffer containing the byte representation of the signature. Correspondingly, aSecp256k1key is serialized as a buffer of bytes, with the leading byte being2.timestamp: A timestamp is a struct that is a unary tuple containing au64value. This value is a count of the milliseconds since the UNIX epoch. Thus the value1603994401469serializes as0xbd3a847575010000ttl: The Time to live is defined as the amount of time for which deploy is considered valid. Thettlserializes in the same manner as the timestamp.gas_price: The gas isu64value which is serialized asu64CLValue discussed below.body_hash: Body hash is a hash over the contents of the deploy body, which includes the payment, session, and approval fields. Its serialization is the byte representation of the hash itself.dependencies: Dependencies is a vector of deploy hashes referencing deploys that must execute before the current deploy can be executed. It serializes as a buffer containing the individual serialization of each DeployHash within the Vector.chain_name: Chain name is a human-readable string describing the name of the chain as detailed in the chainspec. It is serialized as a String CLValue described below.
Payment & Session
Payment and Session are both defined as ExecutableDeployItems. More information on ExecutableDeployItems can be found here
-
Module Bytes are serialized such that the first byte within the serialized buffer is
0with the rest of the buffer containing the bytes present.ModuleBytes { module_bytes: "[72 bytes]", args: 434705a38470ec2b008bb693426f47f330802f3bd63588ee275e943407649d3bab1898897ab0400d7fa09fe02ab7b7e8ea443d28069ca557e206916515a7e21d15e5be5eb46235f5 }will serialize to0x0048000000420481b0d5a665c8a7678398103d4333c684461a71e9ee2a13f6e859fb6cd419ed5f8876fc6c3e12dce4385acc777edf42dcf8d8d844bf6a704e5b2446750559911a4a328d649ddd48000000434705a38470ec2b008bb693426f47f330802f3bd63588ee275e943407649d3bab1898897ab0400d7fa09fe02ab7b7e8ea443d28069ca557e206916515a7e21d15e5be5eb46235f5
-
StoredContractByHash serializes such that the first byte within the serialized buffer is 1u8. This is followed by the byte representation of the remaining fields.
StoredContractByHash { hash: c4c411864f7b717c27839e56f6f1ebe5da3f35ec0043f437324325d65a22afa4, entry_point: "pclphXwfYmCmdITj8hnh", args: d8b59728274edd2334ea328b3292ed15eaf9134f9a00dce31a87d9050570fb0267a4002c85f3a8384d2502733b2e46f44981df85fed5e4854200bbca313e3bca8d888a84a76a1c5b1b3d236a12401a2999d3cad003c9b9d98c92ab1850 }0x01c4c411864f7b717c27839e56f6f1ebe5da3f35ec0043f437324325d65a22afa41400000070636c7068587766596d436d6449546a38686e685d000000d8b59728274edd2334ea328b3292ed15eaf9134f9a00dce31a87d9050570fb0267a4002c85f3a8384d2502733b2e46f44981df85fed5e4854200bbca313e3bca8d888a84a76a1c5b1b3d236a12401a2999d3cad003c9b9d98c92ab1850
-
StoredContractByName serializes such that the first byte within the serialized buffer is 2u8. This is followed by the individual byte representation of the remaining fields.
StoredContractByName { name: "U5A74bSZH8abT8HqVaK9", entry_point: "gIetSxltnRDvMhWdxTqQ", args: 07beadc3da884faa17454a }0x0214000000553541373462535a483861625438487156614b39140000006749657453786c746e5244764d685764785471510b00000007beadc3da884faa17454a
-
StoredVersionedContractByHash serializes such that the first byte within the serialized buffer is 3u8. However, the field version within the enum serializes as an Option CLValue.
StoredVersionedContractByHash { hash: b348fdd0d0b3f66468687df93141b5924f6bb957d5893c08b60d5a78d0b9a423, version: None, entry_point: "PsLz5c7JsqT8BK8ll0kF", args: 3d0d7f193f70740386cb78b383e2e30c4f976cf3fa834bafbda4ed9dbfeb52ce1777817e8ed8868cfac6462b7cd31028aa5a7a60066db35371a2f8 }0x03b348fdd0d0b3f66468687df93141b5924f6bb957d5893c08b60d5a78d0b9a423001400000050734c7a3563374a73715438424b386c6c306b463b0000003d0d7f193f70740386cb78b383e2e30c4f976cf3fa834bafbda4ed9dbfeb52ce1777817e8ed8868cfac6462b7cd31028aa5a7a60066db35371a2f8
-
StoredVersionedContractByName serializes such that the first byte within the serialized buffer is 4u8. The name and entry_point are serialized as a String CLValue, with the version field serializing as an Option.
StoredVersionedContractByName { name: "lWJWKdZUEudSakJzw1tn", version: Some(1632552656), entry_point: "S1cXRT3E1jyFlWBAIVQ8", args: 9975e6957ea6b07176c7d8471478fb28df9f02a61689ef58234b1a3cffaebf9f303e3ef60ae0d8 }0x04140000006c574a574b645a5545756453616b4a7a7731746e01d0c64e61140000005331635852543345316a79466c57424149565138270000009975e6957ea6b07176c7d8471478fb28df9f02a61689ef58234b1a3cffaebf9f303e3ef60ae0d8
-
Transfer serializes such that the first byte within the serialized buffer contains is 5u8, with the remaining bytes of the buffer containing the bytes contained within the args field of Transfer.
Approval
Approval contains two fields:
signer: The public key of the approvals signer. It serializes to the byte representation of thePublicKey. If thePublicKeyis anEd25519key, then the first byte within the serialized buffer is 1 followed by the bytes of the key itself; else, in the case ofSecp256k1, the first byte is 2.signature: The approval signature, which serializes as the byte representation of theSignature. The first byte within the signature is 1 in the case of anEd25519signature or 2 in the case ofSecp256k1.
DeployInfo
Information relating to a given deploy. The structure consists of the following fields:
-
deploy_hashThe hash of the relevant deploy, serialized as a byte representation of the hash itself. -
transfersTransfers performed by the deploy, serialized as aList. -
fromThe account identifier of the creator of the deploy, serialized as anaccount_hash. -
sourceThe source purse used for payment of the deploy, serialized as aURef. -
gasThe gas cost of executing the deploy, serialized as aU512.
Digest
A blake2b hash digest. The digest serializes as a byte representation of the hash itself.
DisabledVersions
Disabled contract versions, containing the following:
-
contract_versionThe version of the contract within the protocol major version. It serializes as au32value. -
protocol_version_majorThe major element of the protocol version this contract is compatible with. It serializes as au32value.
EntryPoint
A type of signature method. Order of arguments matters, since this can be referenced by index as well as name.
-
nameThe name of the entry point, serialized as aString. -
argsArguments for this method. They serialize as a list of theParameters, where each parameter represents an argument passed to the entrypoint. -
retThe return type of the method, serialized as aUnit. -
accessAn enum describing the possible access control options for a contract entry point. It serializes as a 1 for public or a 1 followed by aListof authorized users. -
entry_point_typeIdentifies the type of entry point. It serializes as a0for Session and a1for Contract.
EraID
An Era ID newtype. It serializes as a single u64 value.
EraInfo
Auction metadata, intended to be recorded each era. It serializes as a List of seigniorage allocations.
ExecutionEffect
The journal of execution transforms from a single deploy.
-
operationsThe resulting operations, serialized as aListof operations. -
transformsThe actual transformation performed while executing a deploy.
ExecutionResult
The result of a single deploy. It serializes as a u8 tag indicating either Failure as a 0 or Success as a 1. This is followed by the appropriate structure below:
Failure
The result of a failed execution.
-
effectThe effect of executing the deploy. -
transfersA record of transfers performed while executing the deploy, serialized as aList. -
costThe cost of executing the deploy, serializes as aU512value. -
error_messageThe error message associated with executing the deploy, serialized as aString.
Success
The result of a successful execution.
-
effectThe effect of executing the deploy. -
transfersA record of transfers performed while executing the deploy, serialized as aList. -
costThe cost of executing the deploy, serializes as aU512value.
Group
A (labeled) "user group". Each method of a versioned contract may be associated with one or more user groups which are allowed to call it. User groups are serialized as a String.
Groups
They are serialized as a BTreeMap where the first 4 bytes represent a u32 value describing the number of user groups and BTreeSets of URefs held within. The remainder consists of a repeating pattern of serialized user groups and BTreeSets of the length dictated by the first four bytes.
Keys
In this chapter, we describe what constitutes a "key", the permissions model for the keys, and how they are serialized.
A key in Global State is one of the following data types:
- 32-byte account identifier (called an "account identity key")
- 32-byte immutable contract identifier (called a "hash key")
- 32-byte reference identifier (called an "unforgeable reference")
- 32-byte transfer identifier
- 32-byte deploy information identifier
- 32-byte purse balance identifier
- 32-byte Auction bid identifier
- 32-byte Auction withdrawal identifier
- 32-byte Dictionary identifier
- 32-byte System Contract Registry
- 32-byte Auction unbond identifier
- 32-byte Chainspec Registry
The one exception to note here is the identifier for EraInfo, which actually serializes as a u64 value with an additional byte for the tag.
Account identity key
This key type is used specifically for accounts in the global state. All accounts in the system must be stored under an account identity key, and no other types. The 32-byte identifier which represents this key is derived from the blake2b256 hash of the public key used to create the associated account (see Accounts for more information).
Hash key
This key type is used for storing contracts immutably. Once a contract is written under a hash key, that contract can never change. The 32-byte identifier representing this key is derived from the blake2b256 hash of the deploy hash (see block-structure-head for more information) concatenated with a 4-byte sequential ID. The ID begins at zero for each deploy and increments by one each time a contract is stored. The purpose of this ID is to allow each contract stored in the same deploy to have a unique key.
Unforgeable Reference (URef)
URef broadly speaking can be used to store values and manage permissions to interact with the value stored under the URef. URef is a tuple which contains the address under which the values are stored and the Access rights to the URef. Refer to the Unforgeable Reference section for details on how URefs are managed.
Transfer Key
This key type is used specifically for transfers in the global state. All transfers in the system must be stored under a transfer key and no other type. The 32-byte identifier which represents this key is derived from the blake2b256 hash of the transfer address associated with the given transfer
DeployInfo Key
This key type is used specifically for storing information related to deploys in the global state. Information for a given deploy is stored under this key only. The 32-byte identifier which represents this key is derived from the blake2b256 hash of the deploy itself.
EraInfo Key
This key type is used specifically for storing information related to the Auction metadata for a particular era. The underlying data type stored under this is a vector of the allocation of seigniorage for that given era. The identifier for this key is a new type that wraps around the primitive u64 data type and co-relates to the era number when the auction information was stored.
This key type is used specifically for storing information related to auction bids in the global state. Information for the bids is stored under this key only. The 32-byte identifier which represents this key is derived from the blake2b256 hash of the public key used to create the associated account (see Accounts for more information).
This key type is used specifically for storing information related to auction withdraws in the global state. Information for the withdrawals is stored under this key only. The 32-byte identifier which represents this key is derived from the blake2b256 hash of the public key used to create the associated account (see Accounts for more information).
Serialization for Key
Given the different variants for the over-arching Key data-type, each of the different variants is serialized differently. This section of this chapter details how the individual variants are serialized. The leading byte of the serialized buffer acts as a tag indicating the serialized variant.
Key | Serialization Tag |
|---|---|
Account | 0 |
Hash | 1 |
URef | 2 |
Transfer | 3 |
DeployInfo | 4 |
EraInfo | 5 |
Balance | 6 |
Bid | 7 |
Withdraw | 8 |
Dictionary | 9 |
SystemContractRegistry | 10 |
Unbond | 11 |
ChainspecRegistry | 12 |
Accountserializes as a 32 byte long buffer containing the byte representation of the underlyingAccountHashHashserializes as a 32 byte long buffer containing the byte representation of the underlyingHashitself.URefis a tuple that contains the address of the URef and the access rights to thatURef. The serialized representation of theURefis 33 bytes long. The first 32 bytes are the byte representation of theURefaddress, and the last byte contains the bits corresponding to the access rights of theURef. Refer to the CLValue section of this chapter for details on howAccessRightsare serialized.Transferserializes as a 32 byte long buffer containing the byte representation of the hash of the transfer.DeployInfoserializes as 32 byte long buffer containing the byte representation of the Deploy hash. See the Deploy section above for how Deploy hashes are serialized.EraInfoserializes au64primitive type containing the little-endian byte representation ofu64.Balanceserializes as 32 byte long buffer containing the byte representation of the URef address.BidandWithdrawboth contain theAccountHashas their identifier; therefore, they serialize in the same manner as theAccountvariant.Dictionaryas the 32 byte long buffer containing the byte representation of the seed URef hashed with the identifying name of the dictionary item.SystemContractRegistryas a 32 byte long buffer of zeros.Unbondcontains theAccountHashas its identifier; therefore, it serialize in the same manner as theAccountvariant.ChainspecRegistryas a 32 byte long buffer of ones.
Permissions
There are three types of actions that can be done on a value: read, write, add. The reason for add to be called out separately from write is to allow for commutativity checking. The available actions depend on the key type and the context. Some key types only allow controlled access by smart contracts via the contract API, and other key types refer to values produced and used by the system itself and are not accessible to smart contracts at all but can be read via off-chain queries. This is summarized in the table below:
| Key | Type Available Actions |
|---|---|
| Account | Read + Add (via API) |
| Hash | Read |
| URef | Read + Write and/or Add |
| Transfer | System |
| Deploy | System |
| EraInfo | System |
| Balance | Read (via API) |
| Bid | System |
| Withdraw | System |
| Dictionary | Read (via API) |
| SystemContractRegistry | Read (via API) |
| Unbond | System |
| ChainspecRegistry | Read (via API) |
Refer to URef permissions on how permissions are handled in the case of URefs.
NamedArg
Named arguments to a contract. It is serialized by the combination of a String followed by the associated CLValue.
NamedKey
A mapping of string identifiers to a Casper Key type. It is serialized as a BTreeMap where the first 4 bytes represent a u32 value describing the number of named keys and values held within. The remainder consists of a repeating pattern of serialized named keys and then values of the length dictated by the first four bytes.
-
nameThe name of the entry. It serializes as astring. -
keyThe value of the entry, which is a CasperKeytype.
The named keys portion of the account structure serializes as a mapping of a string to Casper Key values as described here.
Operation
An operation performed while executing a deploy. It contains:
-
keyThe formatted string of the key, serialized as aString. -
kindOpKind, The type of operation performed. It serializes as a single byte based on the following table:
| OpKind | Serialization |
|---|---|
| Read | 0 |
| Write | 1 |
| Add | 2 |
| NoOp | 3 |
Parameter
Parameter to a method, structured as a name followed by a CLType. It is serialized as a String followed by a CLType.
ProtocolVersion
A newtype indicating the Casper Platform protocol version. It is serialized as three u32 values indicating major, minor and patch versions in that order.
PublicKey
Hex-encoded cryptographic public key, including the algorithm tag prefix. Serialization can be found under PublicKey.
RuntimeArgs
Represents a collection of arguments passed to a smart contract. They serialize as a List comprised of Tuples.
SeigniorageAllocation
Information about seigniorage allocation.
If the seigniorage allocation in question is for a validator, it serializes as the validator's PublicKey followed by the U512 amount.
If it is a delegator, it serializes as the delegator's PublicKey, followed by the validator's PublicKey and finally the U512 amount.
Signature
The signature serializes the byte representation of the underlying cryptographic primitive signature. The first byte within the signature is 1 in the case of an Ed25519 signature or 2 in the case of Secp256k1.
SystemContractRegistry
SystemContractRegistry is a unique Key under which a mapping of the names and ContractHashes for system contracts. This includes Mint, Auction, HandlePayment and StandardPayment. It is serialized as a BTreeMap where the first 4 bytes represent a u32 value describing the number of names as strings and ContractHashes held within. The remainder consists of a repeating pattern of serialized strings and then ContractHashes of the length dictated by the first four bytes.
TimeDiff
A human-readable duration between two timestamps. It serializes as a single u64 value.
Timestamp
A timestamp formatted as per RFC 3339 and serialized as a single u64 value.
TransferAddr
Hex-encoded transfer address, which serializes as a byte representation of itself.
Transform
The actual transformation performed while executing a deploy. It serializes as a single u8 value indicating the type of transform performed as per the following table. The remaining bytes represent the information and serialization as listed.
| Transform Type | Serialization | Description |
|---|---|---|
| Identity | 0 | A transform having no effect. |
| Write_CLValue | 1 | Writes the given CLValue to global state. |
| Write_Account | 2 | Write the given Account to global state. |
| Write_Contract_WASM | 3 | Writes a smart contract as Wasm to global state. |
| Write_Contract | 4 | Writes a smart contract to global state. |
| Write_Contract_Package | 5 | Writes a smart contract package to global state. |
| Write_Deploy_Info | 6 | Writes the given DeployInfo to global state. |
| Write_Transfer | 7 | Writes the given Transfer to global state. |
| Write_Era_Info | 8 | Writes the given EraInfo to global state. |
| Write_Bid | 9 | Writes the given Bid to global state. |
| Write_Withdraw | 10 | Writes the given Withdraw to global state. |
| Add_INT32 | 11 | Adds the given i32. |
| Add_UINT64 | 12 | Adds the given u64. |
| Add_UINT128 | 13 | Adds the given U128. |
| Add_UINT256 | 14 | Adds the given U256. |
| Add_UINT512 | 15 | Adds the given U512. |
| Add_Keys | 16 | Adds the given collection of named keys. |
| Failure | 17 | A failed transformation, containing an error message. |
TransformEntry
A transformation performed while executing a deploy.
UnbondingPurse
A purse used for unbonding. The structure consists of the following:
-
bonding_purseThe bonding purse, serialized as aURef. -
validator_public_keyThe public key of the validator, serialized as aPublicKey. -
unbonder_public_keyThe public key of the unbonder, serialized as aPublicKey. -
era_of_creationEra in which this unbonding request was created, as anEraIdnewtype, which serializes as au64value. -
amountThe unbonding amount, serialized as aU512value. -
new_validatorThe validator public key to redelegate to, serialized as anOptioncontaining the public key.
Values
A value stored in the global state is a StoredValue. A StoredValue is one of three possible variants:
- A
CLValue - A contract
- An account
We discuss CLValue and contract in more detail below. Details about accounts can be found in accounts-head.
Each StoredValue is serialized when written to the global state. The serialization format consists of a single byte tag, indicating which variant of StoredValue it is, followed by the serialization of that variant. The tag for each variant is as follows:
CLValueis0Accountis1Contractis2
The details of CLType serialization are in the following section. Using the serialization format for CLValue as a basis, we can succinctly write the serialization rules for contracts and accounts:
- contracts serialize in the same way as data with
CLTypeequal toTuple3(List(U8), Map(String, Key), Tuple3(U32, U32, U32)); - accounts serialize in the same way as data with
CLTypeequal toTuple5(ByteArray(U8, 32), Map(String, Key), URef, Map(ByteArray(U8, 32), U8), Tuple2(U8, U8)).
Note: Tuple5 is not a presently supported CLType. However, it is clear how to generalize the rules for Tuple1, Tuple2, Tuple3 to any size tuple.
CLValue
CLValue is used to describe data that is used by smart contracts. This could be as a local state variable, input argument, or return value. A CLValue consists of two parts: a CLType describing the type of the value and an array of bytes representing the data in our serialization format.
CLType is described by the following recursive data type:
enum CLType {
Bool, // boolean primitive
I32, // signed 32-bit integer primitive
I64, // signed 64-bit integer primitive
U8, // unsigned 8-bit integer primitive
U32, // unsigned 32-bit integer primitive
U64, // unsigned 64-bit integer primitive
U128, // unsigned 128-bit integer primitive
U256, // unsigned 256-bit integer primitive
U512, // unsigned 512-bit integer primitive
Unit, // singleton value without additional semantics
String, // e.g. "Hello, World!"
URef, // unforgeable reference (see above)
Key, // global state key (see above)
PublicKey // A Casper system PublicKey type
Option(CLType), // optional value of the given type
List(CLType), // list of values of the given type (e.g. Vec in rust)
ByteArray(CLType, u32), // same as `List` above, but number of elements
// is statically known (e.g. arrays in rust)
Result(CLType, CLType), // co-product of the given types;
// one variant meaning success, the other failure
Map(CLType, CLType), // key-value association where keys and values have the given types
Tuple1(CLType), // single value of the given type
Tuple2(CLType, CLType), // pair consisting of elements of the given types
Tuple3(CLType, CLType, CLType), // triple consisting of elements of the given types
Any // Indicates the type is not known
}
All data which can be assigned a (non-Any) CLType can be serialized according to the following rules (this defines the Casper serialization format):
Boolean
Boolean values serialize as a single byte; true maps to 1, while false maps to 0.
Numeric
Numeric values consisting of 64 bits or less serialize in the two's complement representation with little-endian byte order, and the appropriate number of bytes for the bit-width.
-
E.g.
7u8serializes as0x07 -
E.g.
7u32serializes as0x07000000 -
E.g.
1024u32serializes as0x00040000 -
Wider numeric values (i.e.
U128,U256,U512) serialize as one byte given the length of the next number (in bytes), followed by the two's complement representation with little-endian byte order. The number of bytes should be chosen as small as possible to represent the given number. This is done to reduce the serialization size when small numbers are represented within a wide data type. -
E.g.
U512::from(7)serializes as0x0107 -
E.g.
U512::from(1024)serializes as0x020004 -
E.g.
U512::from("123456789101112131415")serializes as0x0957ff1ada959f4eb106
Unit
Unit serializes to an empty byte array.
String
Strings serialize as a 32-bit integer representing the length in bytes (note: this might be different than the number of characters since special characters, such as emojis, take more than one byte), followed by the UTF-8 encoding of the characters in the string.
- E.g.
"Hello, World!"serializes as0x0d00000048656c6c6f2c20576f726c6421
Option
Optional values serialize with a single byte tag, followed by the serialization of the value itself. The tag is equal to 0 if the value is missing, and 1 if it is present.
- E.g.
Noneserializes as0x00 - E.g.
Some(10u32)serializes as0x010a000000
List
A list of values serializes as a 32-bit integer representing the number of elements in the list (note this differs from strings where it gives the number of bytes), followed by the concatenation of each serialized element.
- E.g.
List()serializes as0x00000000 - E.g.
List(1u32, 2u32, 3u32)serializes as0x03000000010000000200000003000000
ByteArray
A fixed-length list of values serializes as the concatenation of the serialized elements. Unlike a variable-length list, the length is not included in the serialization because it is statically known by the type of the value.
- E.g.
[1u32, 2u32, 3u32]serializes as0x010000000200000003000000
Result
A Result serializes as a single byte tag followed by the serialization of the contained value. The tag is equal to 1 for the success variant and 0 for the error variant.
- E.g. `Ok(314u64)` serializes as `0x013a01000000000000`
- E.g. `Err("Uh oh")` serializes as `0x00050000005568206f68`
Tuple
Tuples serialize as the concatenation of their serialized elements. Similar to ByteArray the number of elements is not included in the serialization because it is statically known in the type.
- E.g. `(1u32, "Hello, World!", true)` serializes as `0x010000000d00000048656c6c6f2c20576f726c642101`
Map
A Map serializes as a list of key-value tuples. There must be a well-defined ordering on the keys, and in the serialization, the pairs are listed in ascending order. This is done to ensure determinism in the serialization, as Map data structures can be unordered.
URef
URef values serialize as the concatenation of its address (which is a fixed-length list of u8) and a single byte tag representing the access rights. Access rights are converted as follows:
| Access Rights | Serialization |
|---|---|
NONE | 0 |
READ | 1 |
WRITE | 2 |
READ_WRITE | 3 |
ADD | 4 |
READ_ADD | 5 |
ADD_WRITE | 6 |
READ_ADD_WRITE | 7 |
- E.g. `uref-974019c976b5f26412ce486158d2431967af35d91387dae8cbcd43c20fce6452-007` shows a `URef` with full `READ_ADD_WRITE` rights.
When passing a URef to another entity on chain, you must ensure that the AccessRights are set correctly. If the URef represents a purse, AccessRights impact who can deposit and withdraw CSPR.
If a passed URef contains ADD permissions, the entity receiving the URef will then be able to deposit CSPR into the associated purse. WRITE permissions allow for withdrawing CSPR. As of 1.4.5, passing a main purse URef as a runtime argument will cause the host to automatically remove WRITE permissions. In this event, READ and ADD permissions will remain. Regardless, all due diligence should be performed to avoid passing a URef with WRITE permissions unintentionally.
PublicKey
PublicKey serializes as a single byte tag representing the algorithm followed by 32 bytes of the PublicKey itself:
- If the
PublicKeyis aSystemkey, the single tag byte is0. With this variant, the single byte of0is the entire key. - If the
PublicKeyis anEd25519key, the single tag byte is1followed by the individual bytes of the serialized key. - If the
PublicKeyis aSecp256k1key, the single tag byte is a2followed by the individual bytes of the serialized key.
Key
Key values serialize as a single byte tag representing the variant, followed by the serialization of the data that variant contains. For most variants, this is simply a fixed-length 32-byte array. The exception is Key::URef, which contains a URef; so its data serializes per the description above. The tags are as follows: Key::Account serializes as 0, Key::Hash as 1, Key::URef as 2.
CLType
CLType itself also has rules for serialization. A CLType serializes as a single-byte tag, followed by the concatenation of serialized inner types, if any (e.g., lists and tuples have inner types). ByteArray is a minor exception because it also includes the length in the type. However, the length is included in the serialization (as a 32-bit integer, per the serialization rules above), following the serialization of the inner type. The tags are as follows:
CLType | Serialization Tag |
|---|---|
Bool | 0 |
I32 | 1 |
I64 | 2 |
U8 | 3 |
U32 | 4 |
U64 | 5 |
U128 | 6 |
U256 | 7 |
U512 | 8 |
Unit | 9 |
String | 10 |
Key | 11 |
URef | 12 |
Option | 13 |
List | 14 |
ByteArray | 15 |
Result | 16 |
Map | 17 |
Tuple1 | 18 |
Tuple2 | 19 |
Tuple3 | 20 |
Any | 21 |
PublicKey | 22 |
CLValue
A complete CLValue, including both the data and the type, can also be serialized (to store it in the global state). This is done by concatenating: the serialization of the length (as a 32-bit integer) of the serialized data (in bytes), the serialized data itself, and the serialization of the type.
Contracts
Contracts are a special value type because they contain the on-chain logic of the applications running on a Casper network. A contract contains the following data:
- a wasm module
- a collection of named keys
- a protocol version
The wasm module must contain a function named call, which takes no arguments and returns no values. This is the main entry point into the contract. Moreover, the module may import any of the functions supported by the Casper runtime.
Note: though the call function signature has no arguments and no return value, within the call function body, the get_named_arg runtime function can be used to accept arguments (by ordinal), and the ret runtime function can be used to return a single CLValue to the caller.
The named keys are used to give human-readable names to keys in the global state, which are essential to the contract. For example, the hash key of another contract it frequently calls may be stored under a meaningful name. It is also used to store the URefs, which are known to the contract (see the section on Permissions for details).
Each contract specifies the Casper protocol version that was active when the contract was written to the global state.
WithdrawPurse
A purse used for unbonding, replaced in 1.5 by UnbondingPurse. WithdrawPurses prior to 1.5 were known as UnbondingPurses and now consist of historical data.
-
bonding_purseThe bonding purse, serialized as aURef. -
validator_public_keyThe public key of the validator, serialized as aPublicKey. -
unbonder_public_keyThe public key of the unbonder, serialized as aPublicKey. -
era_of_creationEra in which this unbonding request was created, as anEraIdnewtype, which serializes as au64value. -
amountThe unbonding amount, serialized as aU512value.