bor

package
v1.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 18, 2024 License: GPL-3.0 Imports: 33 Imported by: 0

README

Bor Module

Table of Contents

Preliminary terminology

  • A side-transaction is a normal heimdall transaction but the data with which the message is composed needs to be voted on by the validators since the data is obscure to the consensus protocol itself and it has no way of validating the data's correctness.
  • A sprint comprises of 16 bor blocks (configured in bor).
  • A span comprises of 400 sprints in bor (check heimdall's bor params endpoint ).

Overview

The validators on bor chain produce blocks in sprints and spans. Hence, it is imperative for the protocol to formalise the validators who will be producers in a range of blocks (span). The bor module in heimdall facilitates this by pseudo-randomly selecting validators who will producing blocks (producers) from the current validator set. The bor chain fetches and persists this information before the next span begins. bor module is a crucial component in heimdall since the PoS chain "liveness" depends on it.

How does it work

A Span is defined by the data structure:

type Span struct {
	ID                uint64       `json:"span_id" yaml:"span_id"`
	StartBlock        uint64       `json:"start_block" yaml:"start_block"`
	EndBlock          uint64       `json:"end_block" yaml:"end_block"`
	ValidatorSet      ValidatorSet `json:"validator_set" yaml:"validator_set"`
	SelectedProducers []Validator  `json:"selected_producers" yaml:"selected_producers"`
	ChainID           string       `json:"bor_chain_id" yaml:"bor_chain_id"`
}

where ,

  • ID means the id of the span, calculated by monotonically incrementing the ID of the previous span.
  • StartBlock corresponds to the block in bor from which the given span would commence.
  • EndBlock corresponds to the block in bor at which the given span would conclude.
  • ValidatorSet defines the set of active validators.
  • SelectedProducers are the validators selected to produce blocks in bor from the validator set.
  • ChainID corresponds to bor chain ID.

A validator on heimdall can construct a span proposal message:

type MsgProposeSpan struct {
    ID         uint64                  `json:"span_id"`
    Proposer   hmTypes.HeimdallAddress `json:"proposer"`
    StartBlock uint64                  `json:"start_block"`
    EndBlock   uint64                  `json:"end_block"`
    ChainID    string                  `json:"bor_chain_id"`
    Seed       common.Hash             `json:"seed"`
}

Upon broadcasting the message, it is initially checked by HandleMsgProposeSpan handler for basic sanity (verify whether the proposed span is in continuity, appropriate span duration, correct chain ID, etc.). Since this is a side-transaction, the validators then vote on the data present in MsgProposeSpan on the basis of its correctness. All these checks are done in SideHandleMsgSpan (verifying Seed, span continuity, etc) and if correct, the validator would vote YES. Finally, if there are 2/3+ YES votes, the PostHandleMsgEventSpan persists the proposed span in the state via the keeper :

err := k.FreezeSet(ctx, msg.ID, msg.StartBlock, msg.EndBlock, msg.ChainID, msg.Seed)
if err != nil {
	k.Logger(ctx).Error("Unable to freeze validator set for span", "Error", err)
	return common.ErrUnableToFreezeValSet(k.Codespace()).Result()
}

FreezeSet internally invokes SelectNextProducers, which pseudo-randomly picks producers from the validator set, leaning more towards validators with higher voting power based on stake:

// select next producers
newProducers, err := k.SelectNextProducers(ctx, seed)
if err != nil {
	return err
}

and then initialises and stores the span:

newSpan := hmTypes.NewSpan(
	id,
	startBlock,
	endBlock,
	k.sk.GetValidatorSet(ctx),
	newProducers,
	borChainID,
)

return k.AddNewSpan(ctx, newSpan)
How to propose a span

A validator can leverage the CLI to propose a span like so :

heimdallcli tx bor propose-span --proposer <VALIDATOR ADDRESS> --start-block <BOR_START_BLOCK> --span-id <SPAN_ID> --bor-chain-id <BOR_CHAIN_ID>

Or the REST server :

curl -X POST "localhost:1317/bor/propose-span?bor-chain-id=<BOR_CHAIN_ID>&start-block=<BOR_START_BLOCK>&span-id=<SPAN_ID>"

Query commands

One can run the following query commands from the bor module :

  • span - Query the span corresponding to the given span id.
  • latest span - Query the latest span.
  • params - Fetch the parameters associated to bor module.
  • spanlist - Fetch span list.
  • next-span-seed - Query the seed for the next span.
  • propose-span - Print the propose-span command.
CLI commands
heimdallcli query bor span --span-id=<SPAN_ID>
heimdallcli query bor latest-span
heimdallcli query bor params
heimdallcli query bor spanlist --page=<PAGE_NUM> --limit=<LIMIT>
heimdallcli query bor next-span-seed
heimdallcli query bor propose-span --proposer <VALIDATOR ADDRESS> --start-block <BOR_START_BLOCK> --span-id <SPAN_ID> --bor-chain-id <BOR_CHAIN_ID>
REST endpoints
curl localhost:1317/bor/span/<SPAN_ID>
curl localhost:1317/bor/latest-span
curl localhost:1317/bor/params
curl localhost:1317/bor/next-span-seed
curl "localhost:1317/bor/prepare-next-span?span_id=<SPAN_ID>&start_block=<BOR_START_BLOCK>&chain_id="<BOR_CHAIN_ID>""

Documentation

Index

Constants

View Source
const (
	ShuffleRoundCount = 90
)

Variables

View Source
var (
	LastSpanIDKey         = []byte{0x35} // Key to store last span start block
	SpanPrefixKey         = []byte{0x36} // prefix key to store span
	LastProcessedEthBlock = []byte{0x38} // key to store last processed eth block for seed
)

Functions

func BeginBlocker added in v0.2.8

func BeginBlocker(ctx sdk.Context, _ abci.RequestBeginBlock, k Keeper)

func ExportGenesis

func ExportGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState

ExportGenesis returns a GenesisState for a given context and keeper.

func FromBytes8 added in v0.3.2

func FromBytes8(x []byte) uint64

FromBytes8 returns an integer which is stored in the little-endian format(8, 'little') from a byte array.

func GetSpanKey

func GetSpanKey(id uint64) []byte

GetSpanKey appends prefix to start block

func HandleMsgProposeSpan

func HandleMsgProposeSpan(ctx sdk.Context, msg types.MsgProposeSpan, k Keeper) sdk.Result

HandleMsgProposeSpan handles proposeSpan msg

func InitGenesis

func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState)

InitGenesis sets distribution information for genesis.

func NewHandler

func NewHandler(k Keeper) sdk.Handler

NewHandler returns a handler for "bor" type messages.

func NewPostTxHandler added in v0.1.7

func NewPostTxHandler(k Keeper, contractCaller helper.IContractCaller) hmTypes.PostTxHandler

NewPostTxHandler returns a side handler for "span" type messages.

func NewQuerier

func NewQuerier(keeper Keeper) sdk.Querier

NewQuerier creates a querier for auth REST endpoints

func NewSideTxHandler added in v0.1.7

func NewSideTxHandler(k Keeper, contractCaller helper.IContractCaller) hmTypes.SideTxHandler

NewSideTxHandler returns a side handler for "span" type messages.

func PostHandleMsgEventSpan added in v0.1.7

func PostHandleMsgEventSpan(ctx sdk.Context, k Keeper, msg types.MsgProposeSpan, sideTxResult abci.SideTxResultType) sdk.Result

PostHandleMsgEventSpan handles state persisting span msg

func SelectNextProducers

func SelectNextProducers(blkHash common.Hash, spanEligibleValidators []hmTypes.Validator, producerCount uint64) ([]uint64, error)

SelectNextProducers selects producers for next span by converting power to tickets

func ShuffleList

func ShuffleList(input []uint64, seed [32]byte) ([]uint64, error)

ShuffleList returns list of shuffled indexes in a pseudorandom permutation `p` of `0...list_size - 1` with “seed“ as entropy. We utilize 'swap or not' shuffling in this implementation; we are allocating the memory with the seed that stays constant between iterations instead of reallocating it each iteration as in the spec. This implementation is based on the original implementation from protolambda, https://github.com/protolambda/eth2-shuffle

improvements:
 - seed is always the first 32 bytes of the hash input, we just copy it into the buffer one time.
 - add round byte to seed and hash that part of the buffer.
 - split up the for-loop in two:
  1. Handle the part from 0 (incl) to pivot (incl). This is mirrored around (pivot / 2).
  2. Handle the part from pivot (excl) to N (excl). This is mirrored around ((pivot / 2) + (size/2)).
 - hash source every 256 iterations.
 - change byteV every 8 iterations.
 - we start at the edges, and work back to the mirror point.
   this makes us process each pear exactly once (instead of unnecessarily twice, like in the spec).

func SideHandleMsgSpan added in v0.1.7

func SideHandleMsgSpan(ctx sdk.Context, k Keeper, msg types.MsgProposeSpan, contractCaller helper.IContractCaller) (result abci.ResponseDeliverSideTx)

SideHandleMsgSpan validates external calls required for processing proposed span

func XXXSelectNextProducers added in v0.1.9

func XXXSelectNextProducers(blkHash common.Hash, spanEligibleVals []hmTypes.Validator, producerCount uint64) (selectedIDs []uint64, err error)

XXXSelectNextProducers selects producers for next span by converting power to tickets

Types

type AppModule

type AppModule struct {
	AppModuleBasic
	// contains filtered or unexported fields
}

AppModule implements an application module for the supply module.

func NewAppModule

func NewAppModule(keeper Keeper, contractCaller helper.IContractCaller) AppModule

NewAppModule creates a new AppModule object

func (AppModule) BeginBlock

func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock)

BeginBlock returns the begin blocker for the auth module.

func (AppModule) EndBlock

EndBlock returns the end blocker for the auth module. It returns no validator updates.

func (AppModule) ExportGenesis

func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage

ExportGenesis returns the exported genesis state as raw bytes for the auth module.

func (AppModule) InitGenesis

func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate

InitGenesis performs genesis initialization for the auth module. It returns no validator updates.

func (AppModule) Name

func (AppModule) Name() string

Name returns the auth module's name.

func (AppModule) NewHandler

func (am AppModule) NewHandler() sdk.Handler

NewHandler returns an sdk.Handler for the module.

func (AppModule) NewPostTxHandler added in v0.1.7

func (am AppModule) NewPostTxHandler() hmTypes.PostTxHandler

NewPostTxHandler side tx handler

func (AppModule) NewQuerierHandler

func (am AppModule) NewQuerierHandler() sdk.Querier

NewQuerierHandler returns the auth module sdk.Querier.

func (AppModule) NewSideTxHandler added in v0.1.7

func (am AppModule) NewSideTxHandler() hmTypes.SideTxHandler

func (AppModule) QuerierRoute

func (AppModule) QuerierRoute() string

QuerierRoute returns the auth module's querier route name.

func (AppModule) RegisterInvariants

func (AppModule) RegisterInvariants(_ sdk.InvariantRegistry)

RegisterInvariants performs a no-op.

func (AppModule) Route

func (AppModule) Route() string

Route returns the message routing key for the auth module.

type AppModuleBasic

type AppModuleBasic struct{}

AppModuleBasic defines the basic application module used by the auth module.

func (AppModuleBasic) DefaultGenesis

func (AppModuleBasic) DefaultGenesis() json.RawMessage

DefaultGenesis returns default genesis state as raw bytes for the auth module.

func (AppModuleBasic) GetQueryCmd

func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command

GetQueryCmd returns the root query command for the auth module.

func (AppModuleBasic) GetTxCmd

func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command

GetTxCmd returns the root tx command for the auth module.

func (AppModuleBasic) Name

func (AppModuleBasic) Name() string

Name returns the auth module's name.

func (AppModuleBasic) RegisterCodec

func (AppModuleBasic) RegisterCodec(cdc *codec.Codec)

RegisterCodec registers the auth module's types for the given codec.

func (AppModuleBasic) RegisterRESTRoutes

func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router)

RegisterRESTRoutes registers the REST routes for the auth module.

func (AppModuleBasic) ValidateGenesis

func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error

ValidateGenesis performs genesis state validation for the auth module.

func (AppModuleBasic) VerifyGenesis

func (AppModuleBasic) VerifyGenesis(bz map[string]json.RawMessage) error

VerifyGenesis performs verification on auth module state.

type Keeper

type Keeper struct {
	// contains filtered or unexported fields
}

Keeper stores all related data

func NewKeeper

func NewKeeper(
	cdc *codec.Codec,
	storeKey sdk.StoreKey,
	paramSpace subspace.Subspace,
	codespace sdk.CodespaceType,
	chainKeeper chainmanager.Keeper,
	stakingKeeper staking.Keeper,
	caller helper.ContractCaller,
) Keeper

NewKeeper is the constructor of Keeper

func (*Keeper) AddNewRawSpan

func (k *Keeper) AddNewRawSpan(ctx sdk.Context, span hmTypes.Span) error

AddNewRawSpan adds new span for bor to store

func (*Keeper) AddNewSpan

func (k *Keeper) AddNewSpan(ctx sdk.Context, span hmTypes.Span) error

AddNewSpan adds new span for bor to store

func (Keeper) Codespace

func (k Keeper) Codespace() sdk.CodespaceType

Codespace returns the codespace

func (*Keeper) FreezeSet

func (k *Keeper) FreezeSet(ctx sdk.Context, id uint64, startBlock uint64, endBlock uint64, borChainID string, seed common.Hash) error

FreezeSet freezes validator set for next span

func (*Keeper) GetAllSpans

func (k *Keeper) GetAllSpans(ctx sdk.Context) (spans []*hmTypes.Span)

GetAllSpans fetches all indexed by id from store

func (*Keeper) GetLastEthBlock

func (k *Keeper) GetLastEthBlock(ctx sdk.Context) *big.Int

GetLastEthBlock get last processed Eth block for seed

func (*Keeper) GetLastSpan

func (k *Keeper) GetLastSpan(ctx sdk.Context) (*hmTypes.Span, error)

GetLastSpan fetches last span using lastStartBlock

func (Keeper) GetNextSpanSeed added in v0.1.7

func (k Keeper) GetNextSpanSeed(ctx sdk.Context) (common.Hash, error)

func (*Keeper) GetParams

func (k *Keeper) GetParams(ctx sdk.Context) (params types.Params)

GetParams gets the bor module's parameters.

func (*Keeper) GetSpan

func (k *Keeper) GetSpan(ctx sdk.Context, id uint64) (*hmTypes.Span, error)

GetSpan fetches span indexed by id from store

func (*Keeper) GetSpanList

func (k *Keeper) GetSpanList(ctx sdk.Context, page uint64, limit uint64) ([]hmTypes.Span, error)

GetSpanList returns all spans with params like page and limit

func (*Keeper) HasSpan added in v0.1.7

func (k *Keeper) HasSpan(ctx sdk.Context, id uint64) bool

func (*Keeper) IncrementLastEthBlock

func (k *Keeper) IncrementLastEthBlock(ctx sdk.Context)

IncrementLastEthBlock increment last eth block

func (*Keeper) IterateSpansAndApplyFn

func (k *Keeper) IterateSpansAndApplyFn(ctx sdk.Context, f func(span hmTypes.Span) error)

IterateSpansAndApplyFn iterates spans and apply the given function.

func (Keeper) Logger

func (k Keeper) Logger(ctx sdk.Context) log.Logger

Logger returns a module-specific logger

func (*Keeper) SelectNextProducers

func (k *Keeper) SelectNextProducers(ctx sdk.Context, seed common.Hash) (vals []hmTypes.Validator, err error)

SelectNextProducers selects producers for next span

func (*Keeper) SetLastEthBlock

func (k *Keeper) SetLastEthBlock(ctx sdk.Context, blockNumber *big.Int)

SetLastEthBlock sets last eth block number

func (*Keeper) SetParams

func (k *Keeper) SetParams(ctx sdk.Context, params types.Params)

SetParams sets the bor module's parameters.

func (*Keeper) UpdateLastSpan

func (k *Keeper) UpdateLastSpan(ctx sdk.Context, id uint64)

UpdateLastSpan updates the last span start block

type ResponseWithHeight added in v1.0.1

type ResponseWithHeight struct {
	Height string              `json:"height"`
	Result jsoniter.RawMessage `json:"result"`
}

ResponseWithHeight defines a response object type that wraps an original response with a height.

Directories

Path Synopsis
client
cli
rest
Package classification HiemdallRest API
Package classification HiemdallRest API

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL