staking.sh
Overview
staking.sh is a Bash script designed to manage staking operations for a blockchain node wallet interacting with smart contracts in a staking system. It automates the processes of placing new stakes, continuing existing stakes, handling epoch transitions, and managing cooler epochs related to the staking lifecycle. It also supports graceful shutdown and staking continuation cancellation via UNIX signals.
The script interacts primarily with blockchain contracts via the tvm-cli command-line interface, querying contract details and submitting transactions. It manages wallet state, licenses, and stake statuses, ensuring the node participates properly in staking epochs. It also handles balance calculations and BLS key updates to maintain staking eligibility.
Key Constants and Variables
Contract ABI paths: Paths to ABI JSON files for various contracts (WALLET_ABI, ABI, PRE_EPOCH_ABI, COOLER_ABI, EPOCH_ABI).
ROOT: The root address of the BlockKeeper system contract.
Flags and state variables: IS_EPOCH_ACTIVE, IS_EPOCH_CONTINUE, SEQNO, WILL_EPOCH_CONTINUE,
DAEMON.Addresses and keys: Wallet address (WALLET_ADDR), node owner key file (NODE_OWNER_KEY), BLS keys file (
BLS_KEYS_FILE), and node IP address (NODE_IP).
Command-line Arguments and Options
The script accepts three positional arguments:
NODE_OWNER_KEY: Path to the node owner's key JSON file.
BLS_KEYS_FILE: Path to the BLS keys JSON file.NODE_IP: Node's IP address (validated as IPv4).
Optional flags:
-d <seconds>: Enables daemon mode with a sleep interval of<seconds>between staking checks.-l <logfile>: Specifies the log file to write output and errors.
Logging
The log() function timestamps and outputs messages to the log file specified by -l. Old logs are archived before starting.
Signal Handling
SIGINTandSIGTERM: Triggertrigger_stopping_staking(), which attempts to gracefully stop staking by waiting for the current epoch to finish and touching the epoch contract.SIGHUP: Triggerstrigger_stopping_continue_staking(), which disables continuation of staking and attempts to cancel continuation stakes.
Functions
trigger_stopping_staking()
Purpose: Gracefully stops staking by waiting for the current epoch to finish and then touching the epoch contract.
Process:
Retrieves wallet details and active stakes.
Gets epoch address based on wallet owner public key and sequence number.
Queries the current block sequence number and waits until the epoch finishing block is reached.
Calls the
touchmethod on the epoch contract to finalize.
Returns: Exits the script after completion.
trigger_stopping_continue_staking()
Purpose: Stops continuation of staking upon receiving SIGHUP.
Process:
Retrieves wallet details and active stakes.
Gets epoch address and epoch details.
Checks if continuation is active; if so, sends a cancel request.
Polls wallet balance to confirm cancellation.
Returns: None (logs outcome).
update_bls_keys(bKeysFile)
Purpose: Updates BLS keys using an external node-helper command.
Parameters:
bKeysFile: Path to the BLS keys file.
Process:
Checks for presence of node-helper.
Runs
node-helper blsto update keys.Sends
SIGHUP(kill -1) to the node process to reload keys.
Returns: Exits on failure.
place_stake()
Purpose: Places a new stake on the blockchain.
Process:
Retrieves wallet details and calculates available balance from licenses.
Ensures at least half of available tokens are staked.
Finds an unused signer index by checking blockchain accounts.
Sends a stake request transaction with BLS public key, stake amount, signer index, and node IP.
Waits for active stakes to appear confirming the stake placement.
Returns: None (logs success or failure).
place_continue_stake(seqNoStartOld)
Purpose: Places a continuation stake for an existing epoch.
Parameters:
seqNoStartOld: Sequence number of the old stake epoch to continue.
Process:
Similar to
place_stake()but for continuation stakes.Updates BLS keys before sending continuation stake request.
Returns: None (logs success or failure).
calculate_reward(coolerAddress, stakeHex)
Purpose: Calculates rewards from the cooler contract.
Parameters:
coolerAddress: Address of the cooler contract.stakeHex: Original stake amount in hex.
Process:
Retrieves cooler contract's ECC balance.
Converts stake from hex to decimal.
Calculates reward as difference between cooler balance and stake.
Returns: Sets global variable
REWARD.
process_cooler_epoch(coolerAddress, stakeHex)
Purpose: Handles reward calculation and potential touching of the cooler epoch contract.
Parameters:
coolerAddress: Cooler contract address.stakeHex: Stake amount in hex.
Process:
Checks if the cooler epoch has finished based on block sequence.
If finished, calculates rewards.
Returns: None (logs results).
process_epoch()
Purpose: Main function managing the epoch and staking lifecycle.
Process:
Retrieves wallet and active stakes details.
If no active stakes and continuation allowed, places a new stake.
Iterates over active stakes and handles them based on their status:
Status
0: Pre-epoch — waits for starting block and touches pre-epoch contract.Status
1: Active epoch — checks continuation status, potentially sends continuation stake, and touches epoch contract if finished.Status
2: Cooler epoch — processes cooler epoch rewards.
Returns: None (logs state and actions).
Main Execution Flow
Parses options and arguments.
Validates node owner key, BLS keys file, and node IP.
Waits for the blockchain network endpoint and wallet address availability.
Retrieves wallet address and initial wallet state.
If no active stakes, places a stake.
If daemon mode is enabled (
-d), loops continuously callingprocess_epoch()with sleep intervals.Otherwise, runs
process_epoch()once.
Interaction with Other System Components
Blockchain Contracts: Uses tvm-cli to interact with multiple smart contracts: BlockKeeper root, wallet, epoch, pre-epoch, and cooler contracts.
Node Software: Updates BLS keys and sends signals to the node process to reload keys.
External Tools: Requires
jqfor JSON processing, bc for arithmetic, and node-helper for BLS key management.Files: Reads node owner keys, BLS keys, and logs to specified files.
Important Implementation Details
Uses
jqextensively to parse and manipulate JSON data from contract calls.Balances and stake amounts are managed carefully, converting between hexadecimal and decimal.
The script uses randomized signer index selection within a range, checking for unused addresses.
Staking continuation is managed with attention to epoch progress and block sequence numbers.
Signal traps ensure proper resource cleanup and state updates on shutdown or configuration changes.
Implements retry loops for network calls to handle temporary unavailability.
Mermaid Flowchart of Main Functions and Interactions
flowchart TD
Start --> ParseArgs[Parse Args & Options]
ParseArgs --> ValidateFiles[Validate Keys & IP]
ValidateFiles --> WaitNetwork[Wait for Network Endpoint]
WaitNetwork --> GetWalletAddr[Get Wallet Address]
GetWalletAddr --> GetWalletDetails[Get Wallet Details]
GetWalletDetails --> CheckActiveStakes{Active Stakes?}
CheckActiveStakes -- No --> PlaceStake["place_stake()"]
PlaceStake --> DaemonCheck{Daemon Mode?}
CheckActiveStakes -- Yes --> DaemonCheck
DaemonCheck -- No --> ProcessEpoch["process_epoch()"]
DaemonCheck -- Yes --> Loop["Loop: process_epoch() + Sleep"]
Loop --> Loop
ProcessEpoch --> ActiveStakesLoop[For each active stake]
ActiveStakesLoop -->|status 0| HandlePreEpoch[Pre-epoch: wait & touch]
ActiveStakesLoop -->|status 1| HandleEpoch[Active epoch: continue stake, touch]
ActiveStakesLoop -->|status 2| HandleCooler[Cooler epoch: process rewards]
%% Signal handlers
Start -->|SIGINT/SIGTERM| TriggerStopStaking["trigger_stopping_staking()"]
Start -->|SIGHUP| TriggerStopContinue["trigger_stopping_continue_staking()"]
%% Other functions
PlaceStake --> UpdateBLSKeys["update_bls_keys()"]
HandleEpoch --> PlaceContinueStake["place_continue_stake()"]
Usage Examples
Run staking script with node owner key, BLS keys file, and node IP, logging to
staking.log:./staking.sh -l staking.log node_owner.json bls_keys.json 192.168.1.10Run staking script in daemon mode with 30-second intervals:
./staking.sh -d 30 -l staking.log node_owner.json bls_keys.json 192.168.1.10Send
SIGINTorSIGTERMto the script process to trigger graceful shutdown and epoch touching.Send
SIGHUPto disable staking continuation and cancel continuation stakes.
Parameters and Return Values Detail
Function | Parameters | Return Value | Description |
|---|---|---|---|
| None | Exits script | Gracefully stops staking by touching epoch contract. |
| None | None | Cancels staking continuation upon SIGHUP signal. |
|
| Exits on failure | Updates BLS keys and signals node process to reload keys. |
| None | None | Places a new stake using available licenses and balance. |
|
| None | Places continuation stake for an existing epoch. |
|
| None (sets | Calculates the reward based on cooler contract balance. |
| None | Checks cooler epoch finish and calculates rewards if needed. | |
| None | None | Main loop handling stake statuses and epoch transitions. |
Important Notes on Algorithms and Logic
Signer Index Selection: Randomly tries signer indices within [1..60000], checking blockchain account status for availability.
Stake Amount Calculation: Uses license balances minus locked amounts to compute available tokens; stakes half of available tokens.
Epoch Continuation Timing: Sends continuation stake after 30% of epoch blocks elapsed.
Epoch Touching: Touches pre-epoch, epoch, or cooler contracts after certain block sequence thresholds are met.
Balance Polling: After canceling continuation stake, polls wallet balance to verify stake return.
Error Handling: Uses retries and logs errors but continues operation unless critical failures occur.
Interaction with External Components
tvm-cli: The script uses tvm-cli extensively to query contract details and send calls or transactions.
jq: Utilized for JSON parsing of contract outputs and key files.
bc: For floating-point and base conversions in arithmetic operations.
node-helper: An external tool invoked to update BLS keys.
Node Process: The script signals the running node process to reload keys when updated.
Environment and Prerequisites
Requires installed and configured tvm-cli with proper network endpoint access.
Needs
jqand bc utilities available in the environment.External command node-helper must be present for BLS key updates.
Blockchain node must be accessible via IP address provided as argument.
Node owner key and BLS keys files must be valid JSON files with required fields.