Bor
Bor is the core execution layer of the Ramestta network, operating on the principles outlined in EIP-225 and following the Clique consensus protocol. It handles all transaction processing, smart contract execution, and state management with full EVM compatibility.
Validator Committee Selection
Ramestta relies on the Bor layer where a committee of Validators is selected from the validator pool based on their stake. This selection occurs at regular intervals and is shuffled periodically, determined by governance.
Selection Process
- Validators are assigned slots proportionally based on their stake
- Historical Polygon block data is used as a seed to shuffle the array
- Validators are selected based on producer count maintained by governance
- Tendermint's proposer selection algorithm chooses a producer for each sprint
// SelectNextProducers selects producers for the next span
// by converting validator power to slots
func SelectNextProducers(
blkHash common.Hash,
spanEligibleVals []Validator,
producerCount uint64,
) (selectedIDs []uint64, error) {
// If validators <= producerCount, select all
if len(spanEligibleVals) <= int(producerCount) {
for _, val := range spanEligibleVals {
selectedIDs = append(selectedIDs, uint64(val.ID))
}
return selectedIDs, nil
}
// Extract seed from block hash
seed := ToBytes32(blkHash.Bytes()[:32])
// Convert validator power to slots
validatorIndices := convertToSlots(spanEligibleVals)
// Shuffle using seed
selectedIDs, _ = ShuffleList(validatorIndices, seed)
return selectedIDs[:producerCount], nil
}Consensus Mechanics
In Ramestta's Proof-of-Stake system, participants stake RAMA tokens on a designated Polygon smart contract (the "staking contract") to become validators.
Spans and Sprints
Span
A defined set of blocks (1600 blocks) where a specific subset of validators is chosen. Each validator has voting power influencing their selection as block producer.
Sprint
A smaller subset within a span (16 blocks) where a single block producer is designated for block generation. Backup producers exist for failover.
heimdalldcli query bor params
# Output:
sprint_duration: 16
span_duration: 1600
producer_count: 4Block Authorization
Block producers (signers) authorize blocks by signing the block's hash. Bor designates backup producers in case the primary fails to generate a block.
- Wiggle Time: Predefined delay before backup producer starts generating a block
- In-turn Difficulty: Blocks signed in-turn have higher difficulty than out-of-turn
- Fork Resolution: Forks resolved by selecting chain with highest cumulative difficulty
Span Structure
interface Span {
ID: number; // Span ID
StartBlock: number; // First block in span
EndBlock: number; // Last block in span
ValidatorSet: ValidatorSet; // All validators for span
SelectedProducers: Validator[]; // Selected block producers
ChainID: string; // Bor chain ID (1370)
}View Change and Span Commitment
At the end of each span, Bor undergoes a view change, fetching new producers for the subsequent span. This involves:
- HTTP call to Heimdall node for new span data
- commitSpan call to BorValidatorSet genesis contract
- Validation of new producer set
- Switch to new validators for block production
State Synchronization
Bor features a mechanism to relay events from the Polygon chain. This ensures consistency between Polygon and Ramestta chains.
State Sync Process
- StateSynced event triggered on Polygon StateSender contract
- Heimdall validators monitor and validate these events
- Events passed to Bor layer at start of every sprint
- Bor executes system call to StateReceiver contract
- State updated via IStateReceiver.onStateReceive()
// IStateReceiver interface on Bor
interface IStateReceiver {
function onStateReceive(
uint256 stateId,
bytes calldata data
) external;
}
// Bor makes system calls internally with system address
// to change state without a transactionState-Sync Logs
State-sync logs are handled differently from normal logs in Bor:
- Bor produces a new transaction/receipt for state-sync after each sprint
- Includes all logs for state-sync operations
- TX hash derived from block number and block hash
- Does not alter consensus logic
CLI Commands
Frequently Used Commands
# Connect to Bor IPC
bor attach .bor/data/bor.ipc
# Inside IPC console:
# Get current block
eth.blockNumber
# Get sync status
eth.syncing
# Get node info
admin.nodeInfo
# Get peers
admin.peers
# Get signers for a block
bor.getSigners("0x98b3ea")
# Exit console
exitSpan Queries
# Query current span
heimdallcli query bor span latest-span --chain-id <heimdall-chain-id>
# Expected output:
{
"span_id": 2,
"start_block": 6656,
"end_block": 13055,
"validator_set": {
"validators": [...],
"proposer": {...}
},
"selected_producers": [...],
"bor_chain_id": "1370"
}
# Query span by ID
heimdallcli query bor span --span-id <span-id> --chain-id <heimdall-chain-id>
# Propose a new span
heimdallcli tx bor propose-span \
--start-block <start-block> \
--chain-id <heimdall-chain-id>Configuration Commands
# Check Heimdall sync status
curl http://localhost:26657/status
# Check latest block height on Heimdall
curl localhost:26657/status
# Check latest block height on Bor
curl http://<your-ip>:8545 \
-X POST \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0", "id":1, "method":"eth_blockNumber", "params":[]}'
# Get Bor signers
curl http://<your-ip>:8545 \
-X POST \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0", "id":1, "method":"bor_getSigners", "params":["0x98b3ea"]}'Node Management
# Stop Heimdall and Bor services (Linux packages)
sudo service heimdalld stop
sudo service bor stop
# Stop services (Binaries)
pkill heimdalld
pkill heimdalld-bridge
cd /path/to/bor && bash stop.sh
# Remove data directories (Linux packages)
sudo rm -rf /etc/heimdall/*
sudo rm -rf /etc/bor/*
# Remove data directories (Binaries)
sudo rm -rf /var/lib/heimdalld/
sudo rm -rf /var/lib/bor
# Terminate Bor process
ps -aux | grep bor
sudo kill -9 <PID>Peer Management
# Connect to Bor and list peers
bor attach bor.ipc
# Inside console:
admin.peers.forEach(function(value) {
console.log(value.enode + ',')
})
exitRPC Methods
| Method | Description | Example |
|---|---|---|
| eth_blockNumber | Get current block number | curl -X POST --data '{"jsonrpc":"2.0","method":"eth_blockNumber","id":1}' |
| eth_getBlockByNumber | Get block by number | params: ["0x1b4", true] |
| eth_getBalance | Get account balance | params: ["0x...", "latest"] |
| eth_sendRawTransaction | Send signed transaction | params: ["0x...signedTx"] |
| bor_getSigners | Get block signers | params: ["0x1b4"] |
| bor_getCurrentValidators | Get current validators | params: [] |
Genesis Contracts
Bor includes several genesis contracts deployed at initialization:
| Contract | Address | Purpose |
|---|---|---|
| BorValidatorSet | 0x0000...1000 | Manages validator set, receives span commits |
| StateReceiver | 0x0000...1001 | Receives state sync from Polygon |
| MRC20 (RAMA) | 0x0000...1010 | Native RAMA token - gas fees, staking |
Configuration
Key Bor configuration parameters:
| Parameter | Value | Description |
|---|---|---|
| NetworkId | 1370 | Ramestta mainnet chain ID |
| ChainId | 1370 | EIP-155 chain identifier |
| Block Time | ~2 seconds | Target block interval |
| Sprint | 16 blocks | Single producer period |
| Span | 1600 blocks | Producer set period |
| Gas Limit | 20,000,000 | Block gas limit |