Types Subprotocol

ParallelChain F Protocol Types (pchain-types) defines data structures prescribed by the ParallelChain F Blockchain Protocol. These definitions help Web Applications, clients, and differing implementations of 'Node' software developed by different groups communicate with each other and exhibit correct, protocol-specified semantics and behavior.

Table of Contents - Characteristics - Specification of Encoding Formats - Block Header - Block - Transaction - Transaction Command - Transaction Log - Transaction Receipt - Exit Status - Merkle Proof - State Proof - Unpadded Base64URL

Characteristics

ParallelChain F Protocol Types is designed with three desired properties in mind: 1. Obvious determinism. 2. Compact encoding. 3. Fast

Determinism refers to the uniqueness of resulting bytes serialized from a data structure. Same data should be able to be serialized to one-and-only-one series of bytes. Determinism is essential for Blockchain systems, since a single off-place byte totally changes cryptographic hashes and signatures produced over the data, making them much more difficult to verify. Additionally, this 'predictability' in the encoding allows serializer implementations to make more assumptions about the data, and possibly use memory allocation or parallel-processing tricks to speed up serialization and deserialization.

Message format (e.g. definition of a block) is well-known, consistent and unchanged all over the time.

Given the above design considerations, we achieve the characteristics by adopting Borsh as underlying implementation.

A few features shared by all data types defined by ParallelChain F Protocol Types are: 1. Data type consists of only unsigned integers and vector of bytes 2. Little endian integer 3. Is interoperable with the Hotstuff-rs consensus crate.

Specification of Encoding Formats

Block Header

| Name | Type | Description | |:--- |:--- |:--- | |hash | sha256 hash | Block hash of this block | |height | u64 | The number of Justify-links between this Block and the Genesis Block. 0 for the Genesis Block | |justify | hotstuffrs::types::QuorumCertificate | A QuorumCertificate that points to the Block’s parent | |data hash | hotstuffrs::types::CryptoHash | The SHA256 Hash over content inside the block header | |chain id | hotstuffrs::types::AppID | A number unique to a particular ParallelChain Mainnet-based blockchain. This prevents, for example, Blocks from one chain from being published in another chain as evidence of malfeasance. | |proposer | public address (32 bytes) | The Public Address of the Validator that is the Leader of the View this Block was proposed in | |timestamp | u32 | A Unix timestamp. Number of seconds since 1970-01-01 | |basefee | u64 | The (inclusive) minimum number of Grays that a Transaction included in this Block must pay for every Gas used. | |txs hash | sha256 hash | Transactions Hash, the Binary Merkle Tree root hash over the Block’s Transactions | |receipts hash | sha256 hash | Receipts Hash, the Binary Merkle Tree root hash over the Block’s Receipts | |state hash | sha256 hash | State Hash, the SHA256 root hash of the blockchain’s World State Merkle Patricia Trie (MPT) after executing all of this Block’s Transactions | |log bloom | bloom filter (256 bytes) | Log Bloom, the 256-byte Block-level Bloom Filter union of all the Bloom Filters of each Log topic from the Block’s Receipts |

Log Bloom

Log Bloom is a bloom filter (a fixed-size bit array) to minimize the number of block queries that clients need to make. Each event entity in Block's Receipts would undergo the Bloom Function to be included in the Log Bloom. When user wants to find transactions with specific event topics, he simply hash the topics of interest and figure out which bits to look at in the Log Bloom. If any of these bits are set to 0, it guarantees the interested event must not be generated in any transaction in this block. If all the bits are 1, then the transactions might be in this block, but further checking on the block data needs to be sure. The filer result might have false positives, but never have false negatives. Log Bloom Function is a function to reduce a event entry into a single SHA256 hash and set three bits out of 2048-bit in bloom filter. Steps to generate Log Bloom:

Block

Block describes and authorizes the execution of a batch of transactions (state transitions) on the blockchain.

| Name | Type | Description | |:--- |:--- |:--- | |header | BlockHeader | Block header| |transactions| Vec\<Transaction> |A dynamically sized list of Transactions| |receipts| Vec\<Receipt> |A dynamically sized list of Receipts. If a Block contains a Transaction, it must also contain its Receipt. Receipts appear in the order of their Transactions.|

Transaction

| Name | Type | Description | |:--- |:--- |:--- | |signer | public address (32 bytes) | The public address of the external account which signed this transaction | |nonce | u64 | The number of transactions signed by the signer that have been included on the blockchain before this transaction. This ensures that all of the signer’s transactions are included in the blockchain in an expected order, and prevents the same transaction from being included in multiple blocks. | |commands | Vec\<Command> | A list of execution commands that triggers a sequence of state transitions | |gas limit | u64 | The maximum number of gas units (ref.) that should be used in executing this transaction | |max base fee per gas | u64 | The maximum number of grays that the signer is willing to burn for a gas unit used in this transaction | |priority fee per gas | u64 | the number of grays that the signer is willing to pay the block proposer for including this transaction in a block | |signature | signature (64 bytes) | the signature formed by signing over content of this transaction by using the signer’s private key | |hash | sha256 hash | The cryptographic hash of signature |

Transaction Command

Command is the item type describing the item inside the field commands in a Transaction. It is defined as an enum which is represented by a byte followed by its content according to each command type.

Transfer (0x00)

Transfer Balance from transaction signer to recipient.

| Name | Type | Description | |:--- |:--- |:--- | |recipient | public address (32 bytes) | Recipient of the transfer |amount | u64 | The amount to transfer |

Deploy (0x01)

Deploy smart contract to the state of the blockchain.

| Name | Type | Description | |:--- |:--- |:--- | |contract | variable sized bytes | Smart contract in format of WASM bytecode | |cbi version | u32 | Version of Contract Binary Interface |

Call (0x02)

Trigger method call of a deployed smart contract.

| Name | Type | Description | |:--- |:--- |:--- | |target | public address (32 bytes) | The address of the target contract | |method | string | The method to be invoked | |arguments | Option\> | The arguments supplied to the invoked method. It is a list of serialized method arguments (see [Serializable]) | |amount | Option\amount() according to the CBI. |

Create Pool (0x03)

Instantiation of a Pool in state

| Name | Type | Description | |:--- |:--- |:--- | |commission rate | u8 | Commission rate (in unit of percentage) is the portion that the owners of its delegated stakes should pay from the reward in an epoch transaction. |

Set Pool Settings (0x04)

Update settings of an existing Pool.

| Name | Type | Description | |:--- |:--- |:--- | |commission rate | u8 | Commission rate (in unit of percentage) is the portion that the owners of its delegated stakes should pay from the reward in an epoch transaction. |

Delete Pool (0x05)

Delete an existing Pool in state.

Create Deposit (0x06)

Instantiation of a Pool in state

| Name | Type | Description | |:--- |:--- |:--- | |operator | public address (32 bytes) | The address of operator of the target pool | |balance | u64 | The deposit amount | |auto-stake-rewards | bool | Flag to indicate whether the received reward in epoch transaction should be automatically staked to the pool|

Set Deposit Settings (0x07)

Update settings of an existing Deposit.

| Name | Type | Description | |:--- |:--- |:--- | |operator | public address (32 bytes) | The address of operator of the target pool | |auto-stake-rewards | bool | Flag to indicate whether the received reward in epoch transaction should be automatically staked to the pool|

Topup Deposit (0x08)

Increase balance of an existing Deposit.

| Name | Type | Description | |:--- |:--- |:--- | |operator | public address (32 bytes) | The address of operator of the target pool | |amount | u64 | The amount added to Deposit's Balance |

Withdraw Deposit (0x09)

Withdraw balance from an existing Deposit.

| Name | Type | Description | |:--- |:--- |:--- | |operator | public address (32 bytes) | The address of operator of the target pool | |max. amount | u64 | The amount of deposits that the stake owner wants to withdraw. The prefix 'max' is denoted here because the actual withdrawal amount can be less than the wanted amount |

Stake Deposit (0x0A)

Increase stakes to an existing Pool.

| Name | Type | Description | |:--- |:--- |:--- | |operator | public address (32 bytes) | The address of operator of the target pool | |max. amount | u64 | The amount of stakes that the stake owner wants to stake to the target pool. The prefix 'max' is denoted here because the actual amount to be staked can be less than the wanted amount. |

Unstake Deposit (0x0B)

| Name | Type | Description | |:--- |:--- |:--- | |operator | public address (32 bytes) | The address of operator of the target pool | |max. amount | u64 | The amount of stakes that the stake owner wants to remove from the target pool. The prefix 'max' is denoted here because the actual amount to be removed can be less than the wanted amount. |

Next Epoch (0x0C)

Administration Command: proceed to next epoch.

Transaction Log

Log is used to describe an event within a smart contract. Users can emit logs as they like. Each log record consists of two parts, topic and data. Each Event has one Topic that used to describe the event. It can be seen as indexed key of the event which is searchable. Data can include large and complicated data. Both are unlimited in length but charge differently.

| Name | Type | Description | |:--- |:--- |:--- | |Topic |bytes |Key of this event. It is created from contract execution| |Value |bytes |Value of this event. It is created from contract execution|

Transaction Receipt

Transaction Receipt is a list of CommandReceipt which summarizes the result of execution of a [Command].

Command Receipt

| Name | Type | Description | |:--- |:--- |:--- | |exit status | exit status (1 byte) | Exit status tells whether the corresponding command in the sequence succeeded in doing its operation, and, if it failed, whether the failure is because of gas exhaustion or some other reason. | |gas used | u64 | How much gas was used in the execution of the transaction. This will at most be the transaction’s gas limit. | |return values | variable sized bytes | The return value of the corresponding command. | |logs | Vec\

Exit Status

Exit Status defines the success and error types of a command receipt.

| Name | Value | Description | |:--- |:--- |:--- | |Success | 0x00 | The Transaction successfully accomplished everything that it could have been expected to do. | |Failed | 0x01 | The Transaction failed to accomplish the primary operation that Transactions of its kinds are expected to accomplish. | |Gas Exhausted | 0x02 | The Gas Limit was exceeded by a dynamically costed activity in a dynamic-cost Transaction. |

Merkle Proof

In each block, transactions and receipts form a Merkle tree seperately. The Merkle tree, also known as a hash tree, has a binary tree structure, with the hashes of the transactional data on the bottom row being referred to as "Leaf Nodes," the intermediate hashes being referred to as "Non-Leaf Nodes," and the hash at the top being referred to as the "Merkle Root" or the "Root Hash". To build the Merkle tree, all transactions are first grouped in pairs. Each pair has a computed hash that's stored directly in the parent node. These nodes are also grouped into pairs, after which their hash is stored on the next level up. This process continues until reaching the root of the Merkle tree. In blockchain, it typically consists of hundreds of thousands of blocks, each of which can contain up to several thousand transactions. Merkle tree provides an efficient way to verify the inclusion of transactional data in blockchain, without storing the entire block data. Merkle proof is the fragment of Merkle tree. It consists of the neighbor nodes in the path from the leaf node, the transactional data that you want to proof, to the merkle root. The verifier can then use these neighbor nodes to compute the hash of all nodes in the path to the root and verify that the last node is indeed the existing root hash stored in block header.

| Name | Type | Description | |:--- |:--- |:--- | |Root Hash|sha256 hash|Merkle root hash required in the proof| |Total Leaves Count|u64|Number of Leaves in the Merkle Tree| |Leaf Indices (li) |bytes|Vector of u32 integers. Integer li[i] represents the i-th leave to prove in the Trie| |Leaf Hashes (lh) |bytes|Vector of sha256 hashes| |Proof (prf)|bytes|Bytes used for verification|

Note: MerkleProof message definition is compatible to crate rs_merkle. After deserializing to rust struct, fields can be passed to the function verify.

State Proof

Unlike transactional data, the state needs to be frequently updated: the nonce and balance of accounts is often changed, and keys in storage are inserted and deleted all the time. We need a data structure that can quickly calculate the new tree root after an insert, update or delete operation, without recomputing the entire tree. Thus Merkle-Patricia tree (MPT) is being used to store the state. MPT is a combination of Patricia Trie (radix tree) and Merkle tree. Patricia Trie is a base 16 radix tree in which each node is associated with a key, the actual path taken through the tree to get the corresponding value. Keys of all child nodes share the same sequence keys (prefix) from parent node. It provides two properties:

Bounded depth; Assuming the key is of size N bits and the encoding in M bits (e.g. base 16), a branch node can have at most M + 1 elements (e.g. 1 optional value + 16 hex nibbles), the maximum depth of N / M. Root hash only depends on data but not the order of insert/update.

MPT introduces crytographic secure inprovement on top of Patricia Trie. Each node is referenced by its computed hash, which is used for look-up in database. By taking advantage of Merkle tree, MPT put children node hashes to correspond sixteen slots on branch node. Thus, MPT can support proof for items in Account states.

| Name | Type | Description | |:--- |:--- |:--- | |Root Hash|sha256 hash|Merkle root hash required in the proof| |Items (pi) |bytes|Items are key-value pairs to verify with root hash and proof. Its data representation is Vec\<(Vec\)>| |Proof (pp) |bytes|Proof is sequence of some nodes in trie traversed in pre-order traversal order. Its data representation is Vec\|

Note: StateProofs message definition is compatible to crate trie-db.

Unpadded Base64URL

In some components of the ParallelChain F system, There is a need for a way to represent arbitrary byte sequences as UTF-8, url-safe strings. Two examples are: 1. The GET /account routes, where clients have to specify address of the account to GET from by including its address in the request URL, and 2. very-light, which stores keypairs in a JSON file (keypair.json).

The standard bytes-to-characters encoding that all ParallelChain F components use is Base64URL, as defined in IETF RFC 4648, without padding characters. protocol-types exports an alias of String, Base64URL, alongside two functions encode and decode to convert from bytes to Base64URL and the other way around.