BlockKeeperContractRoot.sol
Overview
BlockKeeperContractRoot.sol implements the root contract for managing Block Keeper nodes and their lifecycle within a blockchain network. This contract handles configuration parameters, deployment of node wallets, staking operations, reward and slash calculations, and coordination among related contracts representing different stages of Block Keeper nodes (PreEpoch, Epoch, Cooler). The contract maintains the network state, controls staking thresholds, and facilitates secure interactions using cryptographic keys and indexes.
Contract: BlockKeeperContractRoot
Purpose
Acts as the central controller for Block Keeper node management. It:
Manages staking and reward distribution logic
Controls deployment and configuration of Block Keeper node wallets and related epoch contracts
Maintains the network state and enforces minimum staking and active node requirements
Handles slashing events and rewards through precise accounting
Coordinates cryptographic key acceptance (BLS keys and signer indexes) for node validation
State Variables
Variable | Type | Description |
|---|---|---|
|
| Version string of the contract |
|
| Inspirational quote string, unrelated to functionality |
|
| Stores code cells for different contract components (wallet, epoch, keys, etc.) |
|
| Duration of a single epoch in seconds (default 259200) |
|
| Epoch cliff time calculated from epoch duration |
|
| Wait step time derived from epoch duration |
|
| Minimum required number of active Block Keeper nodes |
|
| Total stake amount across all active Block Keeper nodes |
|
| Address of the license root contract |
|
| Wallet touch parameter for controlling interaction |
|
| Timestamp marking the start of the network |
|
| Current count of active Block Keeper nodes |
|
| Last processed block sequence number |
|
| Number of active Block Keepers at the start of the current block |
|
| Required number of active Block Keepers if enforced |
|
| Flag indicating if minimum active Block Keepers requirement is enforced |
|
| Accumulated reward sum |
|
| Accumulated slashed stake amount |
|
| Initialization parameter affecting stake calculations |
|
| Cached parameter used in reward calculations |
|
| Flag indicating if the contract is closed by the owner |
|
| Global parameter used in reward calculations |
|
| Remainder parameter used in reward calculations |
|
| Parameter reserved for future use |
Constructor
constructor(address licenseRoot)
Initializes
_networkStartto current block timestampSets
_licenseRootto provided address
Key Functions and Methods
ensureBalance()
Private function that:
Updates block sequence number and active Block Keeper count at block start
Ensures contract balance is above a defined ROOT_BALANCE threshold by minting tokens if necessary
Usage: Called internally before state-changing operations to maintain contract solvency.
calcParams()
Private function to update reward calculation parameters based on elapsed time and total stake.
Computes
mbkfrom elapsed time using externalgosh.calcmbk()Updates
_REMparamand_GparamaccordinglyUses division and modulus operations to handle reward remainders
Usage: Called before adjusting stakes or distributing rewards.
Configuration Functions
setConfig(): Allows owner to set epoch duration, minimum block keepers, staking parameters, walletTouch, and initialization values. Requires contract to be open.setConfigNode(): Allows the contract itself to update configuration parameters.
Both functions recalculate dependent parameters like _epochCliff and _waitStep.
Deployment Functions
deployAckiNackiBlockKeeperNodeWallet(pubkey, whiteListLicense): Deploys a new Block Keeper node wallet contract with specified public key and license whitelist. Enforces maximum licenses limit.
Stake Management Functions
coolerSlash(seqNoStart, pubkey): Records slashed amounts originating from Cooler contracts.decreaseStakes(pubkey, seqNoStart, slash_stake, rep_coef): Decreases total stake on slashing events, updates slash sum.increaseActiveBlockKeeperNumber(pubkey, seqNoStart, stake, rep_coef, virtualStake): Increments active Block Keeper count and total stake. CallssetStake()on the epoch contract.decreaseActiveBlockKeeper(...): Decreases active Block Keeper count and stakes, handles reward payout and slash updates.
Block Keeper Request Handling
receiveBlockKeeperRequestWithStakeFromWallet(pubkey, bls_pubkey, signerIndex, rep_coef, is_min, ProxyList, myIp, nodeVersion): Handles initial requests from node wallets to join as Block Keepers, validates stake against min/max thresholds, deploys BLSKeyIndex contract, and forwards acceptance.receiveBlockKeeperRequestWithStakeFromWalletContinue(...): Handles continuation of staking requests with updated parameters, similar to the initial function but for ongoing participation.
BLS Key and Signer Index Acceptance Callbacks
isBLSAccepted(...): Callback from BLSKeyIndex contract confirming key acceptance, deploys SignerIndex contract.isSignerIndexAccepted(...): Callback from SignerIndex contract confirming signer acceptance, triggers deployment of PreEpoch contract.isBLSAcceptedContinue(...)andisSignerIndexContinue(...): Continuation versions of the above callbacks, handling ongoing participation and updating contracts accordingly.
Utility and Calculation Functions
calculateMaxStake(diff): Calculates maximum allowable stake based on the difference between rewards and slashes.calcBKReward(reward_sum, rep_coef, stake, gparam): Calculates Block Keeper reward based on stake, reputation coefficient, and global parameters.
Getter Functions
Provide external read access to contract parameters, addresses, and codes related to Block Keeper components:
Addresses of Cooler, Wallet, Epoch, PreEpoch contracts
Code cells for Wallet, Epoch, ProxyList
Current configuration parameters
Current reward and stake thresholds
Version information
Fallback Function
receive() external: Accepts incoming token transfers and adds the amount to_slash_sum.
Important Implementation Details
Uses cryptographic public keys (BLS and signer indexes) to validate Block Keeper nodes.
Stake and reputation coefficients influence reward distribution and active node counting.
Dynamic calculation of minimum and maximum stakes ensures network stability and fairness.
The contract maintains a precise accounting system for slashes and rewards, with remainder tracking to avoid rounding errors.
Deployments of child contracts (wallet, epoch, pre-epoch, cooler) use code cells stored in
_codemapping, enabling upgradeability and modularity.Access control enforced via sender checks (
senderIs) and modifiers (onlyOwner,accept).Uses custom minting and token transfer functions (
gosh.mintshellq,gosh.mintecc) for token economics.
Interactions with Other Contracts and Libraries
Imports and uses multiple contracts for node wallet (
AckiNackiBlockKeeperNodeWallet), epoch management (BlockKeeperEpochContract), cooler (BlockKeeperCoolerContract), and pre-epoch (BlockKeeperPreEpochContract).Uses utility libraries such as
BlockKeeperLibfor address calculations and state initialization cell composition.Coordinates with cryptographic key contracts
BLSKeyIndexandSignerIndexfor node identity verification.Calls external functions from the
goshnamespace for token minting and stake calculations.Relies on internal utilities and constants (e.g.,
CONFIG_CLIFF_DENOMINATOR,ERR_SENDER_NO_ALLOWED) defined elsewhere in the project.
Usage Examples
Deploying a Block Keeper Node Wallet
blockKeeperRoot.deployAckiNackiBlockKeeperNodeWallet(pubkey, whiteListLicense);
Deploys a new node wallet for the given public key and license whitelist, ensuring the whitelist does not exceed the maximum allowed licenses.
Handling a Stake Request from a Node Wallet
blockKeeperRoot.receiveBlockKeeperRequestWithStakeFromWallet(pubkey, bls_pubkey, signerIndex, rep_coef, is_min, ProxyList, myIp, nodeVersion);
Processes a staking request, validates stake against minimum and maximum thresholds, and initiates the creation of BLS and Signer index contracts for the node.
Adjusting Configuration Parameters (Owner Only)
blockKeeperRoot.setConfig(epochDuration, minBlockKeepers, isNeedNumberOfActiveBlockKeepers, needNumberOfActiveBlockKeepers, walletTouch, nlinit);
Updates the contract configuration parameters related to epochs, staking requirements, and wallet behavior.
Mermaid Class Diagram
classDiagram
class BlockKeeperContractRoot {
-string version
-string _notion
-mapping(uint8 => TvmCell) _code
-uint64 _epochDuration
-uint64 _epochCliff
-uint64 _waitStep
-uint128 _minBlockKeepers
-uint256 _totalStake
-address _licenseRoot
-uint8 _walletTouch
-uint32 _networkStart
-uint128 _numberOfActiveBlockKeepers
-uint32 _block_seqno
-uint128 _numberOfActiveBlockKeepersAtBlockStart
-uint128 _needNumberOfActiveBlockKeepers
-bool _isNeedNumberOfActiveBlockKeepers
-uint128 _reward_sum
-uint128 _slash_sum
-uint128 _nlinit
-uint128 _mbkOld
-bool _is_close_owner
-uint256 _Gparam
-uint256 _REMparam
-uint32 _Bparam
+constructor(address)
-ensureBalance()
-calcParams()
+closeRoot()
+setConfig(uint64,uint128,bool,uint128,uint8,uint128)
+setConfigNode(uint64,uint128,bool,uint128,uint8,uint128)
+deployAckiNackiBlockKeeperNodeWallet(uint256,mapping)
+coolerSlash(uint64,uint256)
+decreaseStakes(uint256,uint64,uint128,uint128)
+increaseActiveBlockKeeperNumber(uint256,uint64,uint128,uint128,optional)
+receiveBlockKeeperRequestWithStakeFromWallet(uint256,bytes,uint16,uint128,bool,mapping,string,optional)
+isBLSAccepted(address,uint256,bytes,uint128,bool,uint16,uint128,optional,mapping,string,optional)
+isSignerIndexAccepted(address,uint256,bytes,uint128,bool,uint16,uint128,optional,mapping,string,optional)
+calculateMaxStake(uint128)
+receiveBlockKeeperRequestWithStakeFromWalletContinue(uint256,bytes,uint64,uint16,bool,mapping,uint64,uint128,optional)
+isBLSAcceptedContinue(address,uint256,bytes,uint128,bool,uint64,uint16,optional,mapping,uint128,optional)
+isSignerIndexContinue(address,uint256,bytes,uint128,bool,uint64,uint16,optional,mapping,uint128,optional)
+setNewCode(uint8,TvmCell)
+decreaseActiveBlockKeeper(uint256,uint128,uint64,uint128,optional,uint128,uint256,bool)
-calcBKReward(uint128,uint128,uint128,uint256)
+getBlockKeeperCoolerAddress(uint256,uint64)
+getAckiNackiBlockKeeperNodeWalletAddress(uint256)
+getAckiNackiBlockKeeperNodeWalletCode()
+getBlockKeeperEpochCode()
+getBlockKeeperEpochAddress(uint256,uint64)
+getBlockKeeperPreEpochAddress(uint256,uint64)
+getDetails()
+getEpochCodeHash()
+getPreEpochCodeHash()
+getRewardOut(uint128,uint128,uint256,uint128)
+getProxyListCode()
+getProxyListAddress(uint256)
+getRewardNow(uint128,uint128)
+getMinStakeNow()
+getMaxStakeNow()
+getConfig()
+getSignerIndexAddress(uint16)
+getMinStakeOut(uint128,uint128,uint128,uint128)
+getBLSIndexAddress(bytes)
+getCodes()
+getVersion()
}
This diagram shows the BlockKeeperContractRoot contract with its state variables and public/private methods, highlighting the comprehensive functionality encapsulated in this root contract.