Anatha System Architecture
Last updated
Last updated
Anatha System Architecture
The purpose of this document is to layout the architecture for the Anatha project. The scope of architecture is the core blockchain software, blockchain indexer and a JavaScript SDK through which various client-facing components will interface with the core blockchain and the blockchain indexer.
The core blockchain part for the Anatha Blockchain will be implemented with Tendermint and Cosmos SDK. The Tendermint Core handles executing the consensus engine and managing the P2P connectivity layer. As such, Tendermint doesn’t know anything about the transactions that are being executed. The transaction validity checks and transaction execution is conducted at the Cosmos SDK layer in separate functionality based state machines called modules.
Before the raw bytes that Tendermint works with get to the dedicated modules, they need to be processed by the Base Application. The Base Application is in charge for decoding the raw bytes to meaningful data and routing the transaction to the respective model for processing. The goal of the Base Application is to provide a secure interface between the store and the extensible state machine while defining as little about the state machine as possible.
The Core Blockchain will be called anathad and will be a compiled Golang binary executable.
The Anatha network will use the Bech32 address format wherever users must handle binary data. Bech32 encoding provides robust integrity checks on data and the human readable part (HRP) provides contextual hints that can assist UI developers with providing informative error messages. In the Anatha network, keys and addresses may refer to a number of different roles in the network like accounts, validators etc.
Address Bech 32 Prefix
Public Bech32 Prefix
Definition
anatha
anathapub
Account Address/Public Key
anathavalcons
anathavalconspub
Validator Consensus Address/Public Key
anathavaloper
anathavaloperpub
Validator Operator Address/Public Key
In this chapter, we will discuss the modules needed to execute the Anatha business logic defined by the Product document. We will also discuss efforts for reusing existing open-source modules and building them from scratch.
We will present all modules within a Module Definition Framework consisting of the following parts:
Abstract - defines high-level module purpose
Concepts - describe specialized concepts and definitions used throughout the spec
State - specification of which data is stored and in what kind of data structures
Messages - transactions that the module state machine can process
Begin Block - specify any begin-block operations
End Block - specify any end-block operations
Hooks - describe available hooks to be called by/from this module
Keepers - logical division for module functions. Keeper methods are invoked from handler functions only
Events - emitted for indexing. The events include a type and a key and value that are being emitted from the module
Parameters - configuration points for each module
The list is nonbinding and all parts are optional.
Abstract
The auth module is responsible for specifying the base transaction and account types for an application. It contains the ante handler, where all basic transaction validity checks (signatures, nonces, auxiliary fields) are performed, and exposes the account keeper, which allows other modules to read, write, and modify accounts.
State
Accounts contain authentication information for a uniquely identified external user of an SDK blockchain, including public key, address, and account number/sequence number for replay protection. For efficiency, since account balances must also be fetched to pay fees, account structs also store the balance of a user.
Messages
The auth module won’t have transaction handlers of its own but does expose a special handler called AnteHandler, used for performing basic validity checks on a transaction, such that it could be thrown out of the mempool. Note that the ante handler is called on CheckTx, but also on DeliverTx.
The AnteHandler is configurable and additional check middleware can be added to it. Initially, the AnteHandler would perform the following checks:
Transaction type - only allow known transaction types
Transaction signature checks
Fee amount checks
Keepers
The auth module only exposes one keeper, the AccountKeeper, which can be used to read and write accounts. It would also provide utility functions for reply attack protection. The keeper would expose the following methods:
Generate an account object with a specified address
Generate an account object with a consecutive account number
Retrieve account from the store
Persist an account to the store
Remove an account from the store
Iteration through all accounts
Retrieve accounts public key based on its address
Retrieve the sequence of an account based on its address
Get the next global account number
Parameters
The auth module will provide the following configurations:
The maximal amount of data that can be attached to a transaction as a memo. Memos can be used to invoke off-chain processing
The limit of signatures that can be included in a single transaction
Transaction fee mechanics that are determined by the size and the cost of signature verifications.
Abstract
The bank module is responsible for handling coin transfers between accounts and tracking special-case pseudo-transfers which must work differently with particular kinds of accounts (notably bonding/unbonding for savings accounts). It exposes several interfaces with varying capabilities for secure interaction with other modules which must alter user balances.
State
Presently, the bank module has no inherent state — it simply reads and writes accounts using the AccountKeeper from the auth module. This implementation choice is intended to minimize necessary state reads/writes since we expect most transactions to involve coin amounts (for fees), so storing coin data in the account saves reading it separately.
Keepers
The bank module provides three different exported keeper interfaces which can be passed to other modules which need to read or update account balances:
BaseKeeper - provides full-permission access: the ability to arbitrary modify any account's balance and mint or burn coins.
setCoins - fetches an account by address, sets the coins on the account, and saves the account
addCoins/subtractCoins - fetches the coins of an account, adds/subtracts the provided amount, and saves the account. This increases/decreases the total supply
SendKeeper - provides access to account balances and the ability to transfer coins between accounts, but not to alter the total supply:
sendCoins - transfers coins from one account to another
ViewKeeper - provides read-only access to account balances but no balance alteration functionality. All balance lookups are conducted in constant time and space complexity:
getCoins - returns the coins associated with an account
hasCoins - returns whether or not an account has at least the provided amount of coins
Messages
The bank module processes only one transaction of type MsgSend which supports transferring multiple sending balances to multiple receiving accounts. (US 2.2.1)
Events
The following events are emitted from the bank module:
Type: transfer, Key: recipient, Value: <address>
Type: transfer, Key: amount, Value: <amount>
Type: message, Key: module, Value: bank
Type: message, Key: action, Value: send
Type: message, Key: sender, Value: <address>
Parameters
The auth module will provide the following configurations:
Whether the token transfer function is enabled. This is used for the consensus protocol testing phase where all transfers would be locked
Abstract
This Distribution module implements a functional way to passively distribute rewards between network participants. For computation optimization, this mechanism does not distribute funds proactively, but rather allows the users to claim their rewards.
Concepts
The Distribution module consists of several pools that can either be modules or module accounts. The overall distribution mechanism is shown in a diagram below and consists of:
Inflation Distribution - 1% annual inflation that is generated every block is transferred from the Mint module and allocated to the Anatha Master Module and to the Network Validator Reward Pool
The Network Validation Reward Pool locks a calculated amount of rewards in the Savings Account module and distributes the rest in the following block for rewards gained in the previous block. The outbound distribution to the savings pool is calculated as follows:
The Savings Accounts Module activates distributions once every 24 hours to all savers that had collateral locked up for at least 24 hours
The Anatha Master Modules’ distribution function is triggered once daily and distributes the funds in the following way: (US 5.2.1)
50% of the distribution gets split between HRA holders that have been a HRA owner in the last 24h. Only one HRA per account is eligible for the reward (US 5.2.4)
25% of the distribution fees get transferred to the Anatha Development Fund Account // TODO: WHAT KIND OF ACCESS
25% of the distribution gets split between the Security Token Holders proportional to the amount of security tokens they are holding // TODO: Is this an account or do we need to store balances on chain
All mentioned coin distributions aren’t done proactively but are reserved until the point when the user decides to send a transaction that would invoke withdrawals for his/her account. (US 5.2.3)
The Anatha Master Module blocks award withdrawals for the first 365 days of the blockchain running. (US 5.2.2)
Messages
The Distribution module handles the following messages:
MsgWithdrawValidatorRewardsAll - when a validator wishes to withdraw their rewards it must send MsgWithdrawValidatorRewardsAll. This transaction withdraws the validators rewards, as well as any rewards earning on their self-stake. Note that parts of this transaction logic are also triggered each with any change in individual delegations, such as an unbond.
Abstract
The crisis module halts the blockchain under the circumstance that a blockchain invariant is broken.
Concepts
Invariants can be registered with the application during the application initialization process. Each module can expose invariants to the crisis module including their route. Invariants can be checked one at a time and require a transaction fee payment.
Due to the anticipated large gas cost required to verify an invariant (and potential to exceed the maximum allowable block gas limit) a constant fee is used instead of the standard gas consumption method. The constant fee is intended to be larger than the anticipated gas cost of running the invariant with the standard gas consumption method.
Messages
Blockchain invariants can be checked using the MsgVerifyInvariant message which specifies the exact invariant to be checked. This message is expected to fail if the sender does not have enough coins for the constant fee or the invariant route is not registered. This message checks the invariant provided, and if the invariant is broken it panics, halting the blockchain. If the invariant is broken, the constant fee is never deducted as the transaction is never committed to a block (equivalent to being refunded). However, if the invariant is not broken, the constant fee will not be refunded.
Events
The following events are emitted from the crisis module:
Type: invariant, Key: route, Value: <route>
Type: message, Key: module, Value: crisis
Type: message, Key: action, Value: verify_invariant
Type: message, Key: sender, Value: <address>
Parameters
The ConstantFee param is held in the global params store.
Abstract
The Governance module enables the blockchain to support an on-chain governance system. Before evolving to a decentralized governance system, this module will implement governance procedures based on a threshold on-chain multisignature model, meaning that only participants that are registered in the genesis block would be able to create governance proposals and vote. Utilizing the mechanism of the Upgrade module, the Governance module can be self-updated to decentralized governance.
Concepts
The governance process is divided in a few steps that are outlined below:
Proposal submission: Proposal is submitted to the blockchain by one of the predefined governance managers.
Vote: Once Proposal is submitted, the voting opens. Other predefined governance managers can then send TxGovVote transactions to vote on the proposal.
If the proposal involves a software upgrade:
Signal: Validators start signaling that they are ready to switch to the new version.
Switch: Once more than 75% of validators have signaled that they are ready to switch, their software automatically flips to the new version.
In the initial version of the governance module, there are two types of proposal:
PlainTextProposal - All the proposals that do not involve a modification of the source code go under this type. For example, an opinion poll would use a proposal of type PlainTextProposal.
SoftwareUpgradeProposal - Is accepted, validators are expected to update their software in accordance with the proposal. This mechanism is explained in the Upgrade module
Proposal handlers and types exposed in other modules
Other modules may expand upon the governance module by implementing their own proposal types and handlers. These types are registered and processed through the governance module (eg. ParamChangeProposal, TreasuryProposal, SofwareUpgradeProposal), which then execute the respective module's proposal handler when a proposal passes. This custom handler may perform arbitrary state changes.
The initial option set includes the following options: Yes, No, NoWithVeto, Abstain. NoWithVeto counts as No but also adds a Veto vote. Abstain option allows voters to signal that they do not intend to vote in favor or against the proposal but accept the result of the vote.
Quorum is defined as the minimum percentage of voting power that needs to be casted on a proposal for the result to be valid. Threshold is defined as the minimum proportion of Yes votes (excluding Abstain votes) for the proposal to be accepted.
Initially, the threshold is set at 50% with a possibility to veto if more than 1/3rd of votes (excluding Abstain votes) are NoWithVeto votes. This means that proposals are accepted if the proportion of Yes votes (excluding Abstain votes) at the end of the voting period is superior to 50% and if the proportion of NoWithVeto votes is inferior to 1/3 (excluding Abstain votes).
State
The main data structures that the Governance module uses are:
A mapping map[proposalID] -> Proposal. The Proposal type stores basic information about the proposal like: Content, ID, Status, Result and different timestamps
A mapping map[proposalID][address] to Vote. This mapping allows us to query all addresses that voted on the proposal along with their vote
Messages
The messages that the Governance module processes are:
TxGovSubmitProposal - submitting a proposal
TxGovVote - voting transaction
Abstract
The minting mechanism was designed to generate an inflation rate in the system. The inflation rate is initially set at 1% annually and calculated daily (or per block). The module supports having a dynamic inflation rate based on several parameters but starts off with a fixed 1% annual inflation rate which can be changed through governance proposals or network upgrade procedures.
State
The minting module state consists of two different stores:
Module-level store - keeps the current annual inflation rate and the current annual expected provisions. These values are updated on every block for the previous block that has been accepted by the network
Global parameter store - parameters that can be changed via governance proposals. Explained in the Parameters section
Begin Block
Minting parameters are recalculated and inflation paid at the beginning of each block for the previously processed block.
The target annual inflation rate is recalculated each block. If configured, the inflation is also subject to a rate change (positive or negative) depending on the distance from the desired staking/savings ratio. The maximum annual inflation rate change can be set independently, as well as the maximum and minimum values for annual inflation.
The annual provisions are calculated on each block based on current total supply and inflation rate with the formula:
Block provisions are generated for each block based on current annual provisions. The provisions are then minted by the mint module's ModuleMinterAccount and then transferred to the auth's FeeCollector module account. Block provisions are calculated by the following formula:
Parameters
The configurable parameters for the Minting module that are stored in the global parameter store:
MintDenom - the type of coin to mint
InflationRateChange - maximum annual change in the inflation rate
InflationMax - maximum inflation rate
InflationMin - minimum inflation rate
GoalBonded - the goal of the percentage of bonded assets
BlocksPerYear - an estimate of blocks per year. Not used for time-based calculations on the blockchain but only to calculate estimated block provisions
Note: To achieve a constant 1% annual inflation rate the parameters InflationMax and InflationMin both need to be set at 1%.
Events
The following events are emitted from the crisis module:
Type: mint, Key: bonded_ratio, Value: <bonded_ratio>
Type: mint, Key: inflation, Value: <inflation>
Type: mint, Key: annual_provisions, Value: <annual_provisions>
Type: mint, Key: amount, Value: <amount>
Abstract
The params module provides a globally available parameter store which can be used to configure different modules. It can support permissioned parameter store access.
Concepts
There are two main types of parameter stores:
Keeper Parameter Store - has permission to access all existing spaces. For it to be used by a module, it needs to be injected during the initialization of that module
Subspace - isolated namespace for parameter storage, where keys are prefixed by preconfigured space names. Subspaces can be used by other modules which need a private parameter store that other keepers cannot modify.
Abstract
The module enables the blockchain to support a Proof-of-Stake system. In this system, holders of the native staking token of the chain can become validators and stake tokens to ultimately determine the effective validator set for the system. The specific difference between other PoS networks is that in this system all validators will have the same voting power that equals their stake. This mechanism is only available to HRA holders. (US 4)
Concepts
An Anatha validator can be in one of the following three states:
Unbonded - The validator is not in the active set. They cannot sign blocks and do not earn rewards
Bonded - Once the validator stakes sufficient bonded tokens they automatically join the active set during EndBlock and their status is updated to Bonded. They are signing blocks and receiving rewards. They can be slashed for misbehavior. If a Validator wants to stop Validating they will have to announce that and must wait the duration of the UnbondingTime, a chain-specific param. during which time they are still slashable for offences if those offences were committed during the period of time that the tokens were bonded
Unbonding - When a validator leaves the active set, either by choice or due to slashing or tombstoning, an unbonding of their stake begins and lasts the specified UnboundingTime before their tokens are transferred from the BondedPool
In the current implementation of staking, there are following important concepts:
Operator - a keypair representing entity who runs a validator and has tokens staked
Validator - a keypair that participates in the consensus. One operator can decide to change its validator keys. This is what Tendermint sees
The validator set will be formed from top MaxValidators that will be sorted by the amount of time they have been in the validating set. Since this set wouldn’t change often, to provide an incentive for waiting validators, TODO SOLUTION? (US 4.4)
Messages
The staking module processes the following messages:
MsgCreateValidator - Notifying the blockchain of a new potential validator, the message must contain a predefined amount of MinSelfDelegation coins that are going to be staked (US 4.2)
MsgEditValidator - Enables changing validator information as: address, description
MsgBeginUnbonding - Notifies the network that the validator no longer wants to participate in the consensus algorithm. The validator needs to wait UnbondingTime before can claim their stake back (US 4.3)
End Block
On an End Block event several important changes happen:
The staking validator set is updated during this process. As a part of this process any updated validators are also returned back to Tendermint for inclusion in the Tendermint validator set which is responsible for validating Tendermint messages at the consensus layer. The new validator set consists of the top MaxValidators sorted by power. That validator set is compared with the previous one and all the missing validators begin unbounding their tokens, while the new validators are instantly bonded. All the token transfers are conducted between the NotBondedPool and BondedPool
When a validator is leaving the bonded validator set (either through being jailed, or not having sufficient bonded tokens) it begins the unbonding process. At this point the validator is said to be an unbonding validator, whereby it will mature to become an "unbonded validator" after the UnbondingTime period has passed. Each block the validator queue is to be checked for mature unbonding validators. At this point any mature validators are deleted from state.
Parameters
The staking module provides the following parameters:
MinSelfDelegation - the amount of stake all validators have to put in, it has to be the exact number
UnbondingTime - amount of time needed to unlock validators’ collateral after deciding to stop validating
MaxValidators - maximum number of validators allowed in a single consensus round
BondDenom - Denomination of the global staking currency
Abstract
The slashing module disincentivizes any attributable action by a protocol-recognized actor with value at stake by penalizing them ("slashing"). Penalties include:
Burning some amount of their stake
Removing their ability to vote on future blocks for a period of time
Concepts
At any given time, there are any number of validators registered in the state machine. Each block, the top MaxValidators validators who are not jailed become bonded, meaning that they may propose and vote on blocks. Validators who are bonded are at stake, meaning that part or all of their stake is at risk if they commit a protocol fault.
The protocol faults that are handled by the slashing module are:
Double block signs (Equivocation)
Liveness faults - Validators are penalized for failing to be included in the list of precommits for some number of blocks by being automatically jailed, potentially slashed, and unbonded
The slashing module keeps a global store of all slashing offense punishments but handles only Liveness faults as they are lighter offenses, while the more serious consensus offenses are handled in the Evidence module.
Liveness slashing is detected immediately as soon as the infraction occurs, and therefore no slashing period is needed to receive further offense proofs. A validator is immediately put into jail period, and they cannot commit another liveness fault until they send an unjailing transaction.
State
Every block includes a set of precommits by the validators for the previous block, known as the LastCommitInfo provided by Tendermint. A LastCommitInfo is valid so long as it contains precommits from +2/3 of total voting power.
Information about validator's liveness activity is tracked through ValidatorSigningInfo. It is indexed in the store as follows:
ValidatorSigningInfo is stored in a map with the key being the consensus address
MissedBlocksBitArray is stored in a map with the key being the consensus address and the value representing a bit array where each bit represents if the validator missed the block for a given index in the bit-array
The ValidatorSigningInfo structure keeps track of:
Address - The validator's consensus address.
StartHeight - The height that the candidate became an active validator (with non-zero voting power).
IndexOffset - Index which is incremented each time the validator was bonded in a block and may have signed a precommit or not
JailedUntil - Time for which the validator is jailed until due to liveness downtime
Tombstoned: Describes if the validator is tombstoned or not. It is set once the validator commits an equivocation or for any other configured misbehavior.
MissedBlocksCounter: A counter kept to avoid unnecessary array reads. Note that Sum(MissedBlocksBitArray) equals MissedBlocksCounter always.
Messages
The Slashing module handles the following messages:
Unjail - If a validator was automatically unbonded due to downtime and wishes to come back online & possibly rejoin the bonded set. If the validator has enough stake to be in the top MaximumBondedValidators, they will be automatically rebonded and begin to again collect rewards
Begin Block
At the beginning of each block, we update the ValidatorSigningInfo for each validator and check if they've crossed below the liveness threshold over a sliding window. This sliding window is defined by SignedBlocksWindow and the index in this window is determined by IndexOffset found in the validator's ValidatorSigningInfo. For each block processed, the IndexOffset is incremented regardless if the validator signed or not. Once the index is determined, the MissedBlocksBitArray and MissedBlocksCounter are updated accordingly.
Finally, in order to determine if a validator crosses below the liveness threshold, we fetch the maximum number of blocks missed:
and the minimum height at which we can determine liveness, minHeight. If the current block is greater than minHeight and the validator's MissedBlocksCounter is greater than MaxMissed, they will be slashed by SlashFractionDowntime, will be jailed for DowntimeJailDuration, and have the following values reset: MissedBlocksBitArray, MissedBlocksCounter, and IndexOffset.
Parameters
The Slashing module provides the following configurable parameters:
SignedBlocksWindow
MinSignedPerWindow
DowntimeJailDuration
SlashFractionDoubleSign
SlashFractionDowntime
Note: Parameters without explanation have been documented in the Begin Block chapter
Abstract
The Evidence module allows the submission and handling of arbitrary evidence of misbehavior such as equivocation and counterfactual signing.
Concepts
The module provides an API for other modules to register their evidence checking logic similar to the Crisis module. Submitted Evidence is first routed through the evidence module's Router in which it attempts to find a corresponding registered Handler for that specific Evidence type. Each Evidence type must have a Handler registered with the evidence module's keeper in order for it to be successfully routed and executed. The Handler for a given Evidence type can perform any arbitrary state transitions such as slashing, jailing, and tombstoning.
State
Currently the Evidence module only stores a list of valid submitted Evidence in the state.
Messages
Evidence is submitted through a MsgSubmitEvidence message. The supplied Evidence in the message must have a corresponding Handler registered with the Evidence module's Router in order to be processed and routed correctly.
Begin Block
Apart from the generalized framework for application-level evidence handling, the Evidence module provides a built in evidence handler for the underlying consensus engine which is automatically submitted if found. The relevant information is forwarded to the application as ABCI Evidence in abci.RequestBeginBlock so that the validator can be accordingly punished.
Currently, the evidence module only handles evidence of type Equivocation (double signing) which is derived from Tendermint's ABCIEvidenceTypeDuplicateVote during BeginBlock.
If valid Equivocation evidence is included in a block, the validator's stake is slashed by SlashFractionDoubleSign, which is defined by the slashing module, of what their stake was when the infraction occurred (rather than when the evidence was discovered).IIn addition, the validator is permanently jailed and tombstoned making it impossible for that validator to ever re-enter the validator set. Only Evidence that is not older than the specified MaxEvidenceAge will be considered.
Parameters
The Evidence module contains the following parameters:
MaxEvidenceAge - evidence older than the parameter is not considered
Abstract
The supply module passively tracks the total supply of coins within a chain, provides a pattern for other modules to hold/interact with coins and introduces a security invariant check to verify a chain's total supply.
Concepts
The total supply of the network is equal to the sum of all coins from all accounts. The total supply is updated every time a coin is minted or burned.
The supply module introduces a new type of account (ModuleAccount) which can be used by modules to allocate tokens and in special cases mint or burn tokens. At a base level, these module accounts are capable of sending/receiving tokens to and from accounts and other module accounts.
Each ModuleAccount has a different set of permissions that provide different object capabilities to perform certain actions. Permissions need to be registered upon the creation of the SupplyKeeper so that every time a ModuleAccount calls the allowed functions, the keeper can lookup the permissions to that specific account and perform or not the action.
State
The supply module store only keeps track of the total supply of the chain.
Keepers
The supply keeper provides wrapper functions for the AuthKeeper and the BankKeeper that are related to ModuleAccounts in order to be able to:
Get and set ModuleAccounts by providing its name
Send coins from and to other ModuleAccounts or standard accounts by passing its name
Mint or burn coins from ModuleAccounts
Abstract
The Upgrade module facilitates smoothly upgrading a live chain to a new (breaking) software version. It accomplishes this by providing a BeginBlocker hook that prevents the blockchain state machine from proceeding once a pre-defined upgrade block time or height has been reached The module does not assume anything regarding how governance decides to do an upgrade, but just the mechanism for coordinating the upgrade safely. Without software support for upgrades, upgrading a live chain is risky because all of the validators need to pause their state machines at exactly the same point in the process. If this is not done correctly, there can be state inconsistencies which are hard to recover from.
Concepts
The Upgrade module defines a Plan type in which a live upgrade is scheduled to occur. A Plan can be scheduled at a specific block height or time, but not both. A Plan is created once a (frozen) release candidate along with an appropriate upgrade Handler is agreed upon, where the Name of a Plan corresponds to a specific Handler. Typically, a Plan is created through a SoftwareUpgradeProposal governance proposal process, where if voted upon and passed, will be scheduled. The Info of a Plan may contain various metadata about the upgrade, typically application specific upgrade info to be included on-chain such as a git commit that validators could automatically upgrade to. The upgrade process can be fully automated for node operators. By populating the Info field with the necessary information, binaries can automatically be downloaded.
State
The internal state of the Upgrade module is relatively minimal and simple. The state only contains the currently active upgrade Plan (if one exists) by key 0x0 and if a Plan is marked as "done" by key 0x1.
Messages
Routes that relay messages to this module would only be passed to the Governance module which is the only way to initiate an Upgrade plan.
The following messages are available to the Governance module:
SoftwareUpgradeProposal
CancelSoftwareUpgradeProposal
Abstract
The Savings module allows users to lock up their collateral and receive interest on it in 24 hour periods.
State
The Savings module will save a list of accounts that have deposited their funds. It will store data structures to execute the on-chain fee distribution module proposed by Dev Ojha in https://drops.dagstuhl.de/opus/volltexte/2019/11400/. The savings funds will be transferred from the Network Validator Reward Pool explained in the Distribution module.
Messages
The Savings module will handle the following messages:
MsgDeposit - allows the user to deposit no more than 25% of funds available on their account
MsgWithdraw - allows the user to withdraw a specified amount from the savings account. This action resets the savings block time and interest accumulation will start in the interest payment period where the given savings account hasn’t been touched for 24 or more hours
MsgWithdrawInterest - allows the user to withdraw interest to their account
Parameters
The savings module will contain a configurable interest rate which can be changed by governance.
Abstract
This module covers User Story 1.
This module contains all of the logic linking an Anatha address to one or more human-readable addresses (HRAs) and their metadata, which could include multi-currency wallets and other crypto addresses.
Concepts
Every user can have multiple HRAs. Every one of those HRAs point to their native Anatha Address. Every Anatha Address holds a mapping of addresses for multiple cryptocurrencies grouped by the cryptocurrency and the order of the addresses within the same cryptocurrency. User have the ability to add multiple addresses from multiple cryptocurrencies. The first registered address of known cryptocurrencies within the Anatha Platform have a decreased registration fee. Every following registered address has an increased fee. The fee mechanism is set in place to reduce malicious transactions overloading the network.
State
For the internal HRA storage following structures will be allocated:
map[AnathaAddress] -> HRA[] - mapping from an Anatha address to the list of HRA-s owned by the address holder (prerequisite for US 1.2)
map[HRA] -> AnathaAddress - mapping from the hashed value of the HRA to the address of the owner
map[HRA] -> HraInfo - mapping from the hashed value of the HRA to the structure describing specifics of given HRA
map[AnathaAddress][CryptocurrencyId][Index] -> Address - mapping that maps an Anatha address to multiple addresses of multiple cryptocurrencies
Each HraInfo structure consists of the following fields:
ExpiryTime - the expiry timestamp of the HRA
Price - the price at which the HRA can be sold in uANATHA. 0 if not for sale
Messages
The HRA module would support handling the following messages:
RegisterHRA - message that has a parametrized cost that will tie the signers address to the registered HRA. As additional data to this transaction the user can pass the initial cryptocurrency wallet addresses that they want to be tied to their Anatha. If this is the first registration of an HRA, addresses generated in the Anatha Wallet would be automatically connected to the owners address (US 1.4, 5.1)
RenewHRA - message that would increase the ownership over an HRA for 1 year costing a parametrized fee (US 1.3.2)
SetSellingPrice - message that sets the price for the given HRA (US 3.1)
BuyHRA - message when sent with the supplied price that matches with the selling price of the HRA transfers the HRA to the buyer
DeleteHRA - message that removes the AnathaAddress -> HRA association. If this is the last of the users’ HRA all his cryptocurrency address mappings would be deleted (US 3.2, 5.1.2)
TransferHRA - message that transfers the HRA to another user
RegisterAddress - allows the user to tie an external cryptocurrency address to their Anatha Address that can be accessed through the HRA (US 5.1.3)
DeregisterAddress - allows the user to remove the previously registered external cryptocurrency address (US 1.5)
Keepers
The HRA module would expose the main keeper which would be accessible by other modules that require translating addresses. The rough list of functions provided by the keeper would be:
GetHRAInfo - returns HRA basic information
GetHRAByAddress - returns all HRAs owned by supplied address
GetAddressByHRA - returns the Anatha address (US 2)
PersistHRAInfo - stores modified HRA related data (US 5.1.1)
Begin Block
At the beginning of every block maintenance procedures which include pruning expired HRA information and mappings would be executed (US 5.1.4).
Parameters
HRADenomination - default uANATHA
HRAAnnualPrice - in combination with the previous parameter the total price of an annual registration is calculated. Default 100000000 = 1 ANATHA
Abstract
The Treasury module is in charge of holding the initial supply of Anatha, generating the treasury public sale price based on the amount of Anatha transferred out of the treasury and receive Anatha that had been bought back by the external Treasury System. The Treasury module will be controlled by an on-chain multi signature wallet with its threshold requirements specified in the genesis file. To fulfill the objectives from the Product document, this on-chain module requires a complementing off-chain module which is described in the Backend Services section.
Concepts
The Treasury module will expose routes to the Governance module through which this modules methods can be invoked through.
The Treasury module will have a BuyBack queue, where ANATHA holders would send their ANATHA as Orders and specify the cryptocurrency they want to get in exchange. If the liquidity of the Treasury Backend allows, it will execute the transfer and claim the ANATHA.
State
The Treasury module keeps a queryable current price in USD based on in-flow and out-flow of the initial supply of Anatha. Starting at $0.01, the ANATHA token price increases by $0.01 for every 10,000,000 (10 million) ANATHA sold.
0 - 10,000,000 tokens sold: $0.01
10,000,001 - 20,000,000 tokens sold: $0.02
20,000,001 - 30,000,000 tokens sold: $0.03
30,000,001 - 40,000,000 tokens sold: $0.04
...
7,690,000,001 - 7,700,000,000 tokens sold: $7.70
The Treasury will hold a queue of BuyBack Orders waiting to be executed:
Orders per user map[address] -> Order[]
Global list of orders -> Order[]
Keepers
The Treasury module keeper will provide the following functionalities:
Update sale price
Expose sale price
Manage Orders from the queue
Messages
TransferFunds - governance proposal based transfer funds from the Treasury to the specified address
DepositFunds - return of bought back Anatha and readjusting the sale price
SellBack - deposits attached ANATHA to the Treasury fund and the message metadata would include the cryptocurrency identifier the ANATHA holder would like to get
DeleteOrder - would allow the user to remove the order
FulfillOrder - message that can be sent only by the Treasury backend after fulfilling the SellBack order. This would release the locked funds back in to the Treasury fund
One of the main interfaces for an application is the command-line interface. This entrypoint adds commands from the application's modules to let end-users create messages and queries.
Transactions are created by users to wrap messages that trigger state changes when they get included in a valid block. Transaction commands are typically exposed in each module tx.go file.
Queries allow users to gather information about the application or network state; they are routed by the application and processed by the module in which they are defined. Query commands typically have their own query.go file.
The CLI Tool will be called anathacli and will be a compiled Golang binary executable.
Each Message from the listed modules can be crafted by the CLI.
The Anatha SDK is a JavaScript/Node.js library that can be installed from the npm registry. It includes methods for communicating with the Anatha blockchain. The Anatha SDK is intended to be used by developers to interact with the Anatha blockchain and build interfaces and applications on it.
The Anatha SDK will import all transaction types and provide an interface for creating payloads and signing each and every transaction specified in the Core. Apart from crafting, signing and relaying transactions, the Anatha SDK will have blockchain querying capabilities. It will also support basic wallet related functionalities. In that sense, the SDK would provide the same functionality as the CLI tool but tailored for a JavaScript environment.
Some of the functionalities that the SDK currently provides:
Initializing an Anatha wallet (keypair)
By generating a keypair
By importing a raw private key
Checking the balance of an address
Signing and transacting of Anatha coins
WebSocket event listeners that happen on each block and each transaction
Module Query and Transaction related functionality:
Query status of connected node
Query:
Block - Get verified data for a block at given height
Transactions - Search for all transactions that match the given tags (Events) or hash
Account balance
State exposed in every module (Governance, Distribution, Staking, Slashing, HRA, Savings, Treasury, …)
Transact:
Create and relay a signed transaction
Broadcast offline generated signatures
Messages exposed in every module (Governance, Distribution, Staking, Slashing, HRA, Savings, Treasury, …)
This chapter will include all the separate backend services that have been identified from the ratified Product Definition and User Stories documents. These services support the operation of the core blockchain by providing integrations for FE systems that a blockchain itself wouldn’t be able to provide.
The indexing service indexes transactions by wallet addresses and by transaction hashes which makes it easier to filter out transactions associated with a certain address and it makes it easy to query a single transactions by its unique hash (SHA256 hash of the whole transaction object).
The indexing service is constantly subscribed to new transactions from existing blockchain nodes and it stores indexed data in a Redis datastore. If, for whatever reason, the indexing service would stop working it would not lose existing data and it would continue the synchronization process from the last saved block.
As a part of the indexing process, invalid transactions are also saved, but they’re flagged with an invalid flag.
The Indexing service provides a highly available API which serves information that can’t be queried directly from the blockchain. These APIs would be used by various frontends like a blockchain explorer, wallet, etc.
To list a few items that the Indexer would index:
HRA by expiry date (US 1.3)
Transactions by address
The Treasury Backend is intended to work in parallel with the Treasury blockchain module and will be in charge of:
Managing ANATHA that have been transferred to the account controlled by the treasury backend
Handling various payment methods and disbursing ANATHA to buyers conveying to the USD selling price specified by the on-chain module
In an advanced implementation, the system would scan the market if it can fulfill the purchase order cheaper. If it can, the profits are kept by Anatha
Handling ANATHA buyback at 60% of on-chain price with provided liquidity from ANATHA purchases up to a set daily amount
Referring to user stories 1.3, 2.1.1 and 3.1.1 we see the need for a push notification microservice. The microservice will be implemented in Node.js.
The Notification Microservice will provide means for wallet users (desktop and mobile) to subscribe to push notifications that can be provided by Firebase or AWS.
To register for notifications, the user would need to sign a notification request using their Anatha private key. The Microservice would conclude which HRAs are owned by the signer and would send HRA expiry notifications when needed. The Microservice would interface with the Indexer to query expiring HRAs.
For the second Notification scenario where the receiver of funds who doesn’t have an address attached to their HRA needs to be notified about a pending transfer. If the sender doesn’t find an appropriate address he/she can send a request for this kind of notification to be dispatched. This endpoint needs to be rate limited by the address of the sender.
The notification system is used in a similar manner when buying/selling HRAs.