/Docs/Architecture/Bor

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.

â„šī¸Geth Fork
Bor is a modified fork of Go-Ethereum (Geth), customized for Ramestta's PoS consensus and integration with Heimdall for validator management and block production.

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

  1. Validators are assigned slots proportionally based on their stake
  2. Historical Polygon block data is used as a seed to shuffle the array
  3. Validators are selected based on producer count maintained by governance
  4. Tendermint's proposer selection algorithm chooses a producer for each sprint
Producer Selection Algorithmgo
// 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.

Bor Parametersbash
heimdalldcli query bor params

# Output:
sprint_duration: 16
span_duration: 1600
producer_count: 4

Block 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

Span Typetypescript
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:

  1. HTTP call to Heimdall node for new span data
  2. commitSpan call to BorValidatorSet genesis contract
  3. Validation of new producer set
  4. 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

  1. StateSynced event triggered on Polygon StateSender contract
  2. Heimdall validators monitor and validate these events
  3. Events passed to Bor layer at start of every sprint
  4. Bor executes system call to StateReceiver contract
  5. State updated via IStateReceiver.onStateReceive()
State Receiver Interfacesolidity
// 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 transaction

State-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

Bor IPC Commandsbash
# 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
exit

Span Queries

Query Spansbash
# 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

Sync and Statusbash
# 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

Service Managementbash
# 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

Retrieve Peer Detailsbash
# Connect to Bor and list peers
bor attach bor.ipc

# Inside console:
admin.peers.forEach(function(value) {
    console.log(value.enode + ',')
})

exit

RPC Methods

MethodDescriptionExample
eth_blockNumberGet current block numbercurl -X POST --data '{"jsonrpc":"2.0","method":"eth_blockNumber","id":1}'
eth_getBlockByNumberGet block by numberparams: ["0x1b4", true]
eth_getBalanceGet account balanceparams: ["0x...", "latest"]
eth_sendRawTransactionSend signed transactionparams: ["0x...signedTx"]
bor_getSignersGet block signersparams: ["0x1b4"]
bor_getCurrentValidatorsGet current validatorsparams: []

Genesis Contracts

Bor includes several genesis contracts deployed at initialization:

ContractAddressPurpose
BorValidatorSet0x0000...1000Manages validator set, receives span commits
StateReceiver0x0000...1001Receives state sync from Polygon
MRC20 (RAMA)0x0000...1010Native RAMA token - gas fees, staking
âš ī¸System Addresses
Genesis contracts use special system addresses. The system call mechanism allows Bor to change contract state without creating a normal transaction.

Configuration

Key Bor configuration parameters:

ParameterValueDescription
NetworkId1370Ramestta mainnet chain ID
ChainId1370EIP-155 chain identifier
Block Time~2 secondsTarget block interval
Sprint16 blocksSingle producer period
Span1600 blocksProducer set period
Gas Limit20,000,000Block gas limit
✅Next Steps

Found an issue with this page? Report on GitHub