This document describes the block and transaction structure of the Cronos PoS Chain and explains different ways to extract and parse the details of them.
This API returns the events of the block. These events include the outcomes from transactions, and block changes such as block rewards minted ("mint") and distributed as well as consensus state updates such as validator missing block counts ("liveness")
The API supports pagination, make sure you have iterate all the pages pagination.offset=[offset starting from 0]&pagination.limit=[record per page]
The performance will degrade if you are searching for a result set that will grow over time. For example, if we search for events that grow with the block height, such as validator's reward distrubtion.
Multiple events in a single search are queried by AND condition. i.e If you do tx.height and message.sender. It will search for transactions that happened on that particular block height AND signed by the sender.
Most of the block events can be accessed using the Tendermint Block Results API. One caveat of using this API is that all the events key-value attributes are base64 encoded. Therefore it is non-human readable.
A simple Node.js tool has been written to help parse and decode all key-value attributes in the block results API response. It can be downloaded at https://github.com/calvinaco/cosmos-api-tools.
Note that when you integrate with the API you should still base64 decode the attributes programmatically.
1. Mint
In every block, CRO is minted and offered to the active validators and their delegators as block rewards. The actual minted token is subject to inflation and is adjusted every block. Further details on the minting parameters and configuration can be found here.
Minted tokens are distributed as blocks and proposer rewards in the same block. However, since Cosmos SDK does the lazy rewards calculation and collection, the minted tokens are first sent to the "Distribution" module account and are later transferred to an account when a delegator withdraws the rewards or commissions by sending a MsgWithdrawDelegatorReward or MsgWithdrawValidatorCommission.
In every block, mint tokens and transaction fees are distributed to every active validator in the network. As a result, there will be multiple events, each corresponding to a validator and the rewards it receives.
Block rewards are not credited to the delegator account directly. This event serves as a record-keeping purpose only. Each delegator account must explicitly send a MsgWithdrawDelegatorReward message transaction to collect the rewards.
To get the reward per validator:
Detail
Accessor
Type
Validator Address
Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].value)
where
Base64Decode(result.begin_block_events[event_index].type) === "rewards" && Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].key) === "validator"
Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].value)
where
Base64Decode(result.begin_block_events[event_index].type) === "rewards" && Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].key) === "amount"
String
3. Proposer Rewards
Block proposers can get extra transaction fees bonus for the block they have successfully proposed. More details can be found here for reference.
Similar to block rewards, proposer rewards are not credited to the account directly. This event serves as a record-keeping purpose only. Each validator creator account must explicitly send a MsgWithdrawDelegatorReward message transaction to collect the rewards.
Detail
Accessor
Type
Validator Address
Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].value)
where
Base64Decode(result.begin_block_events[event_index].type) === "proposer_reward" && Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].key) === "validator"
Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].value)
where
Base64Decode(result.begin_block_events[event_index].type) === "proposer_reward" && Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].key) === "amount"
String
4. Commissions
Validator can charge a commission to the block rewards received by delegators. Commissions is already included in Block Rewards and Proposer Rewards
Similar to block rewards, commission rewards are not credited to the account directly. This event serves as a record-keeping purpose only. Each validator creator account must explicitly send a MsgWithdrawValidatorCommission message transaction to collect the rewards.
To get the commission received by each validator:
Detail
Accessor
Type
Validator Address
Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].value)
where
Base64Decode(result.begin_block_events[event_index].type) === "rewards" && Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].key) === "validator"
Transaction fee is an Asset Array, meaning that a transaction can pay fee in more than one token types.
4. Assets and Amount
There are mainly two types of assets and amount representation:
1. Single object
This is commonly seen in staking module but may appear in other modules as well. It represents a single token type.
Example
{"denom":"basecro","amount":"10000"}
where denom is the asset type and amount is the amount and basecro is the basic unit of CRO token (where 10^8 basecro = 1 cro)
Note that the amount is always in string for precision accuracy. Please make sure your language is capable of handling big integer numbers. It is highly recommended to use library similar to bignumber.js in your language to handle the amount.
2. Array
This is commonly seen in most message types. It represents a list of tokens.
At the time of writing, there will only be a single entry in this array because basecro (or basetcro in Croeseid Testnet) is the only supported asset on Cronos PoS Chain. However, after IBC transfer and other coins issuance methods are enabled, there will be more asset types, the coin source tracing and their denomination can be found here
This transaction will trigger an internal transfer from the "Distribution" module account to the withdraw to address. Note that the "Distribution" module account is an internal account in Cronos PoS Chain to hold the rewards, commissions and community pool funds before they are being distributed.
This transaction will initiate a transfer from an account to the "Distribution" module account. Note that the "Distribution" module account is an internal account in Cronos PoS Chain to hold the rewards, commissions and community pool funds before they are being distributed.
typeMsgEditValidatorstruct { Description Description`protobuf:"bytes,1,opt,name=description,proto3" json:"description"` ValidatorAddress string `protobuf:"bytes,2,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty" yaml:"address"`
// We pass a reference to the new commission rate and min self delegation as// it's not mandatory to update. If not updated, the deserialized rate will be// zero with no way to distinguish if an update was intended.// REF: #2373 CommissionRate *github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=commission_rate,json=commissionRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"commission_rate,omitempty" yaml:"commission_rate"`
MinSelfDelegation *github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,4,opt,name=min_self_delegation,json=minSelfDelegation,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"min_self_delegation,omitempty" yaml:"min_self_delegation"`
}typeDescriptionstruct {// moniker defines a human-readable name for the validator. Moniker string`protobuf:"bytes,1,opt,name=moniker,proto3" json:"moniker,omitempty"`// identity defines an optional identity signature (ex. UPort or Keybase). Identity string`protobuf:"bytes,2,opt,name=identity,proto3" json:"identity,omitempty"`// website defines an optional website link. Website string`protobuf:"bytes,3,opt,name=website,proto3" json:"website,omitempty"`// security_contact defines an optional email for security contact. SecurityContact string `protobuf:"bytes,4,opt,name=security_contact,json=securityContact,proto3" json:"security_contact,omitempty" yaml:"security_contact"`
// details define other optional details. Details string`protobuf:"bytes,5,opt,name=details,proto3" json:"details,omitempty"`}
Descriptions: Perform a redelegation of coins from a delegator and source validator to a destination validator.
Note that the redelegation is just a record update of the internal state of a delegator's staked funds. The delegator account won't have any funds movement based on the redelegation except.
There is a side effect of MsgBeginRedelegate, upon successful execution of this message, all the rewards of the delegator from the previous (source) validator will be withdrawn automatically to the delegator account.
tx_response.logs[message_index].events[event_index].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "recipient".
String
Auto Withdraw Rewards From Address (Always the "distribution" module account) #
tx_response.logs[message_index].events[event_index].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "sender".
String
Auto Withdraw Rewards Amount #
tx_response.logs[message_index].events[event_index].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "amount".
String
Note: There may be multiple auto reward withdrawals that happen. In such a case, the transfer event will have multiple {"recipient":"","sender":"","amount":""}. An example is
Descriptions: Perform an undelegation from a delegate and a validator.
Note that the funds are moved between module accounts upon a MsgUndelegate message execution. The funds movement to the user account happens only when the unbond completes. For details, you can refer to the next section.
tx_response.logs[message_index].events[event_index].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "recipient".
String
Auto Withdraw Rewards From Address (Always the "distribution" module account) #
tx_response.logs[message_index].events[event_index].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "sender".
String
Auto Withdraw Rewards Amount #
tx_response.logs[message_index].events[event_index].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "amount".
String
Note: Similar to MsgBeginRedelegate, there may be multiple auto reward withdrawals happen. In such a case the transfer event will have the multiple {"recipient":"","sender":"","amount":""}
Descriptions: The undelegation is completed on the first block after the "Unbond Completion Time", in which there will be a special event in the Tendermint Block Results API.
Liveness issue occurs when the validator fails to sign 50%* of the blocks in a 5000# blocks sliding window.
Upon a validator committing a liveness issue, the validator is jailed for 24 hours (85400 seconds#).
# The liveness metrics and the penalty are subject to the network parameters to be explained in the details section
Double Sign
Double sign occurs when a validator attempts to provide multiple signatures of the same block height.
This is considered as a serious fault and upon committing the validator will get jailed forever and get slashed for 5% of the total staking#.
This slashing is applied to all the delegations (both self delegation and delegation from other accounts).
# The slashing rate is subject to the network parameters to be explained in the details section
Limitations
There is a limitation in the protocol that the slashing amount cannot be easily extracted right now. Theoretically one could calculate the slashed amount of each delegator by applying the slash rate and delegation proportion but in practice small precision issues may be introduced in the calculation process and introduce discrepancies with the chain, so it is not recommended to do so.
On the other hand, the slashed amount, similar to the block rewards and commission, is not deducted from delegator account directly. There are events to signal the jail and slashing occurs but it serve more of the purpose of describing such as event occurs only.
2a. Burn Proposal's Deposit if Proposal does not Get Enough Deposit
If a proposal does not meet the depsoit requirement after the deposit period, the deposit will NOT be returned to the depositors. Those deposits will be burnt from the "gov" module account as well.
The latest deposit requirement ("min_deposit") and deposit period ("max_deposit_period") can be checked on https://rpc.mainnet.crypto.org/cosmos/gov/v1beta1/params/deposit. Note that they are network parameters and may change over time after governance proposals.
To monitor a proposal becomes inactive, it can be detected by monitoring the end_block_events in Tendermint Block Results API. However, for the amount of deposit burnt, you have to keep track of the deposits made to the proposal before. Note that this operation does not involve any user account as the deposits are burnt.
There are a few cases where proposal deposits will be burnt. For details, please refer to Proposal Result for more details.
If a proposal does not get enough votes that exceed the "quorum" or has the "No with Veto" votes exceed the "veto_threshold", the deposit will NOT be returned to the depositors. Those deposits will be burnt from the "gov" module account as well.
To monitor a proposal that got rejected and deposits got burned, it can be detected by monitoring the end_block_events Tendermint Block Results API. There will be a "proposal_result" event marking the proposal as rejected, and different from Return Proposal's Deposit, there will be NO transfer event in the end_block_results, which means the deposit is NOT returned and is burnt.
However, for the amount of deposit burnt, you have to keep track of the deposits made to the proposal before. Note that this operation does not involve any user account as the deposits are burnt.