les

package
Version: v21.1.0+incompatible Latest Latest
Warning

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

Go to latest
Published: Feb 1, 2021 License: GPL-3.0 Imports: 62 Imported by: 0

Documentation

Overview

Package les implements the Light Ethereum Subprotocol.

Index

Constants

View Source
const (
	MsgBlockBodies = iota
	MsgCode
	MsgReceipts
	MsgProofsV2
	MsgHelperTrieProofs
	MsgTxStatus
)
View Source
const (
	NetworkId          = 1
	ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
)
View Source
const (
	// Protocol messages inherited from LPV1
	StatusMsg          = 0x00
	AnnounceMsg        = 0x01
	GetBlockHeadersMsg = 0x02
	BlockHeadersMsg    = 0x03
	GetBlockBodiesMsg  = 0x04
	BlockBodiesMsg     = 0x05
	GetReceiptsMsg     = 0x06
	ReceiptsMsg        = 0x07
	GetCodeMsg         = 0x0a
	CodeMsg            = 0x0b
	// Protocol messages introduced in LPV2
	GetProofsV2Msg         = 0x0f
	ProofsV2Msg            = 0x10
	GetHelperTrieProofsMsg = 0x11
	HelperTrieProofsMsg    = 0x12
	SendTxV2Msg            = 0x13
	GetTxStatusMsg         = 0x14
	TxStatusMsg            = 0x15
	// Protocol messages introduced in LPV3
	StopMsg   = 0x16
	ResumeMsg = 0x17
)

les protocol message codes

View Source
const (
	ErrMsgTooLarge = iota
	ErrDecode
	ErrInvalidMsgCode
	ErrProtocolVersionMismatch
	ErrNetworkIdMismatch
	ErrGenesisBlockMismatch
	ErrNoStatusMsg
	ErrExtraStatusMsg
	ErrSuspendedPeer
	ErrUselessPeer
	ErrRequestRejected
	ErrUnexpectedResponse
	ErrInvalidResponse
	ErrTooManyTimeouts
	ErrMissingKey
)
View Source
const (
	MaxHeaderFetch           = 192 // Amount of block headers to be fetched per retrieval request
	MaxBodyFetch             = 32  // Amount of block bodies to be fetched per retrieval request
	MaxReceiptFetch          = 128 // Amount of transaction receipts to allow fetching per request
	MaxCodeFetch             = 64  // Amount of contract codes to allow fetching per request
	MaxProofsFetch           = 64  // Amount of merkle proofs to be fetched per retrieval request
	MaxHelperTrieProofsFetch = 64  // Amount of helper tries to be fetched per retrieval request
	MaxTxSend                = 64  // Amount of transactions to be send per request
	MaxTxStatus              = 256 // Amount of transactions to queried per request
)

Variables

View Source
var (
	ClientProtocolVersions    = []uint{lpv2, lpv3}
	ServerProtocolVersions    = []uint{lpv2, lpv3}
	AdvertiseProtocolVersions = []uint{lpv2} // clients are searching for the first advertised protocol in the list
)

Supported versions of the les protocol (first is primary)

View Source
var ProtocolLengths = map[uint]uint64{/* contains filtered or unexported fields */}

Number of implemented message corresponding to different protocol versions.

Functions

This section is empty.

Types

type BlockRequest

type BlockRequest light.BlockRequest

BlockRequest is the ODR request type for block bodies

func (*BlockRequest) CanSend

func (r *BlockRequest) CanSend(peer *peer) bool

CanSend tells if a certain peer is suitable for serving the given request

func (*BlockRequest) GetCost

func (r *BlockRequest) GetCost(peer *peer) uint64

GetCost returns the cost of the given ODR request according to the serving peer's cost table (implementation of LesOdrRequest)

func (*BlockRequest) Request

func (r *BlockRequest) Request(reqID uint64, peer *peer) error

Request sends an ODR request to the LES network (implementation of LesOdrRequest)

func (*BlockRequest) Validate

func (r *BlockRequest) Validate(db ethdb.Database, msg *Msg) error

Valid processes an ODR request reply message from the LES network returns true and stores results in memory if the message was a valid reply to the request (implementation of LesOdrRequest)

type BloomReq

type BloomReq struct {
	BloomTrieNum, BitIdx, SectionIndex, FromLevel uint64
}

type BloomRequest

type BloomRequest light.BloomRequest

ODR request type for requesting headers by Canonical Hash Trie, see LesOdrRequest interface

func (*BloomRequest) CanSend

func (r *BloomRequest) CanSend(peer *peer) bool

CanSend tells if a certain peer is suitable for serving the given request

func (*BloomRequest) GetCost

func (r *BloomRequest) GetCost(peer *peer) uint64

GetCost returns the cost of the given ODR request according to the serving peer's cost table (implementation of LesOdrRequest)

func (*BloomRequest) Request

func (r *BloomRequest) Request(reqID uint64, peer *peer) error

Request sends an ODR request to the LES network (implementation of LesOdrRequest)

func (*BloomRequest) Validate

func (r *BloomRequest) Validate(db ethdb.Database, msg *Msg) error

Valid processes an ODR request reply message from the LES network returns true and stores results in memory if the message was a valid reply to the request (implementation of LesOdrRequest)

type ChtRequest

type ChtRequest light.ChtRequest

ODR request type for requesting headers by Canonical Hash Trie, see LesOdrRequest interface

func (*ChtRequest) CanSend

func (r *ChtRequest) CanSend(peer *peer) bool

CanSend tells if a certain peer is suitable for serving the given request

func (*ChtRequest) GetCost

func (r *ChtRequest) GetCost(peer *peer) uint64

GetCost returns the cost of the given ODR request according to the serving peer's cost table (implementation of LesOdrRequest)

func (*ChtRequest) Request

func (r *ChtRequest) Request(reqID uint64, peer *peer) error

Request sends an ODR request to the LES network (implementation of LesOdrRequest)

func (*ChtRequest) Validate

func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error

Valid processes an ODR request reply message from the LES network returns true and stores results in memory if the message was a valid reply to the request (implementation of LesOdrRequest)

type CodeData

type CodeData []struct {
	Value []byte
}

CodeData is the network response packet for a node data retrieval.

type CodeReq

type CodeReq struct {
	BHash  common.Hash
	AccKey []byte
}

type CodeRequest

type CodeRequest light.CodeRequest

ODR request type for node data (used for retrieving contract code), see LesOdrRequest interface

func (*CodeRequest) CanSend

func (r *CodeRequest) CanSend(peer *peer) bool

CanSend tells if a certain peer is suitable for serving the given request

func (*CodeRequest) GetCost

func (r *CodeRequest) GetCost(peer *peer) uint64

GetCost returns the cost of the given ODR request according to the serving peer's cost table (implementation of LesOdrRequest)

func (*CodeRequest) Request

func (r *CodeRequest) Request(reqID uint64, peer *peer) error

Request sends an ODR request to the LES network (implementation of LesOdrRequest)

func (*CodeRequest) Validate

func (r *CodeRequest) Validate(db ethdb.Database, msg *Msg) error

Valid processes an ODR request reply message from the LES network returns true and stores results in memory if the message was a valid reply to the request (implementation of LesOdrRequest)

type HelperTrieReq

type HelperTrieReq struct {
	Type              uint
	TrieIdx           uint64
	Key               []byte
	FromLevel, AuxReq uint
}

type HelperTrieResps

type HelperTrieResps struct {
	Proofs  light.NodeList
	AuxData [][]byte
}

type LesApiBackend

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

func (*LesApiBackend) AccountExtraDataStateGetterByNumber

func (b *LesApiBackend) AccountExtraDataStateGetterByNumber(ctx context.Context, number rpc.BlockNumber) (vm.AccountExtraDataStateGetter, error)

func (*LesApiBackend) AccountManager

func (b *LesApiBackend) AccountManager() *accounts.Manager

func (*LesApiBackend) BlockByHash

func (b *LesApiBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)

func (*LesApiBackend) BlockByNumber

func (b *LesApiBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)

func (*LesApiBackend) BlockByNumberOrHash

func (b *LesApiBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error)

func (*LesApiBackend) BloomStatus

func (b *LesApiBackend) BloomStatus() (uint64, uint64)

func (*LesApiBackend) CallTimeOut

func (b *LesApiBackend) CallTimeOut() time.Duration

func (*LesApiBackend) ChainConfig

func (b *LesApiBackend) ChainConfig() *params.ChainConfig

func (*LesApiBackend) ChainDb

func (b *LesApiBackend) ChainDb() ethdb.Database

func (*LesApiBackend) CurrentBlock

func (b *LesApiBackend) CurrentBlock() *types.Block

func (*LesApiBackend) Downloader

func (b *LesApiBackend) Downloader() *downloader.Downloader

func (*LesApiBackend) EventMux

func (b *LesApiBackend) EventMux() *event.TypeMux

func (*LesApiBackend) ExtRPCEnabled

func (b *LesApiBackend) ExtRPCEnabled() bool

func (*LesApiBackend) GetEVM

func (b *LesApiBackend) GetEVM(ctx context.Context, msg core.Message, apiState vm.MinimalApiState, header *types.Header) (*vm.EVM, func() error, error)

func (*LesApiBackend) GetLogs

func (b *LesApiBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error)

func (*LesApiBackend) GetPoolNonce

func (b *LesApiBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error)

func (*LesApiBackend) GetPoolTransaction

func (b *LesApiBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction

func (*LesApiBackend) GetPoolTransactions

func (b *LesApiBackend) GetPoolTransactions() (types.Transactions, error)

func (*LesApiBackend) GetReceipts

func (b *LesApiBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)

func (*LesApiBackend) GetTd

func (b *LesApiBackend) GetTd(hash common.Hash) *big.Int

func (*LesApiBackend) GetTransaction

func (b *LesApiBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)

func (*LesApiBackend) HeaderByHash

func (b *LesApiBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error)

func (*LesApiBackend) HeaderByNumber

func (b *LesApiBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)

func (*LesApiBackend) HeaderByNumberOrHash

func (b *LesApiBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error)

func (*LesApiBackend) IsAuthorized

func (*LesApiBackend) ProtocolVersion

func (b *LesApiBackend) ProtocolVersion() int

func (*LesApiBackend) RPCGasCap

func (b *LesApiBackend) RPCGasCap() *big.Int

func (*LesApiBackend) RemoveTx

func (b *LesApiBackend) RemoveTx(txHash common.Hash)

func (*LesApiBackend) SendTx

func (b *LesApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error

func (*LesApiBackend) ServiceFilter

func (b *LesApiBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession)

func (*LesApiBackend) SetHead

func (b *LesApiBackend) SetHead(number uint64)

func (*LesApiBackend) StateAndHeaderByNumber

func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (vm.MinimalApiState, *types.Header, error)

func (*LesApiBackend) StateAndHeaderByNumberOrHash

func (b *LesApiBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (vm.MinimalApiState, *types.Header, error)

func (*LesApiBackend) Stats

func (b *LesApiBackend) Stats() (pending int, queued int)

func (*LesApiBackend) SubscribeChainEvent

func (b *LesApiBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription

func (*LesApiBackend) SubscribeChainHeadEvent

func (b *LesApiBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription

func (*LesApiBackend) SubscribeChainSideEvent

func (b *LesApiBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription

func (*LesApiBackend) SubscribeLogsEvent

func (b *LesApiBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription

func (*LesApiBackend) SubscribeNewTxsEvent

func (b *LesApiBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription

func (*LesApiBackend) SubscribeRemovedLogsEvent

func (b *LesApiBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription

func (*LesApiBackend) SuggestPrice

func (b *LesApiBackend) SuggestPrice(ctx context.Context) (*big.Int, error)

func (*LesApiBackend) SupportsMultitenancy

func (b *LesApiBackend) SupportsMultitenancy(rpcCtx context.Context) (*proto.PreAuthenticatedAuthenticationToken, bool)

func (*LesApiBackend) TxPoolContent

type LesOdr

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

LesOdr implements light.OdrBackend

func NewLesOdr

func NewLesOdr(db ethdb.Database, config *light.IndexerConfig, retriever *retrieveManager) *LesOdr

func (*LesOdr) BloomIndexer

func (odr *LesOdr) BloomIndexer() *core.ChainIndexer

BloomIndexer returns the bloombits chain indexer

func (*LesOdr) BloomTrieIndexer

func (odr *LesOdr) BloomTrieIndexer() *core.ChainIndexer

BloomTrieIndexer returns the bloom trie chain indexer

func (*LesOdr) ChtIndexer

func (odr *LesOdr) ChtIndexer() *core.ChainIndexer

ChtIndexer returns the CHT chain indexer

func (*LesOdr) Database

func (odr *LesOdr) Database() ethdb.Database

Database returns the backing database

func (*LesOdr) IndexerConfig

func (odr *LesOdr) IndexerConfig() *light.IndexerConfig

IndexerConfig returns the indexer config.

func (*LesOdr) Retrieve

func (odr *LesOdr) Retrieve(ctx context.Context, req light.OdrRequest) (err error)

Retrieve tries to fetch an object from the LES network. If the network retrieval was successful, it stores the object in local db.

func (*LesOdr) SetIndexers

func (odr *LesOdr) SetIndexers(chtIndexer, bloomTrieIndexer, bloomIndexer *core.ChainIndexer)

SetIndexers adds the necessary chain indexers to the ODR backend

func (*LesOdr) Stop

func (odr *LesOdr) Stop()

Stop cancels all pending retrievals

type LesOdrRequest

type LesOdrRequest interface {
	GetCost(*peer) uint64
	CanSend(*peer) bool
	Request(uint64, *peer) error
	Validate(ethdb.Database, *Msg) error
}

func LesRequest

func LesRequest(req light.OdrRequest) LesOdrRequest

type LesServer

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

func NewLesServer

func NewLesServer(e *eth.Ethereum, config *eth.Config) (*LesServer, error)

func (*LesServer) APIs

func (s *LesServer) APIs() []rpc.API

func (*LesServer) Protocols

func (s *LesServer) Protocols() []p2p.Protocol

func (*LesServer) SetBloomBitsIndexer

func (s *LesServer) SetBloomBitsIndexer(bloomIndexer *core.ChainIndexer)

func (*LesServer) SetContractBackend

func (s *LesServer) SetContractBackend(backend bind.ContractBackend)

SetClient sets the rpc client and starts running checkpoint contract if it is not yet watched.

func (*LesServer) Start

func (s *LesServer) Start(srvr *p2p.Server)

Start starts the LES server

func (*LesServer) Stop

func (s *LesServer) Stop()

Stop stops the LES service

type LightDummyAPI

type LightDummyAPI struct{}

func (*LightDummyAPI) Coinbase

func (s *LightDummyAPI) Coinbase() (common.Address, error)

Coinbase is the address that mining rewards will be send to (alias for Etherbase)

func (*LightDummyAPI) Etherbase

func (s *LightDummyAPI) Etherbase() (common.Address, error)

Etherbase is the address that mining rewards will be send to

func (*LightDummyAPI) Hashrate

func (s *LightDummyAPI) Hashrate() hexutil.Uint

Hashrate returns the POW hashrate

func (*LightDummyAPI) Mining

func (s *LightDummyAPI) Mining() bool

Mining returns an indication if this node is currently mining.

type LightEthereum

type LightEthereum struct {
	ApiBackend *LesApiBackend
	// contains filtered or unexported fields
}

func New

func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error)

func (*LightEthereum) APIs

func (s *LightEthereum) APIs() []rpc.API

APIs returns the collection of RPC services the ethereum package offers. NOTE, some of these services probably need to be moved to somewhere else.

func (*LightEthereum) BlockChain

func (s *LightEthereum) BlockChain() *light.LightChain

func (*LightEthereum) Downloader

func (s *LightEthereum) Downloader() *downloader.Downloader

func (*LightEthereum) Engine

func (s *LightEthereum) Engine() consensus.Engine

func (*LightEthereum) EventMux

func (s *LightEthereum) EventMux() *event.TypeMux

func (*LightEthereum) LesVersion

func (s *LightEthereum) LesVersion() int

func (*LightEthereum) Protocols

func (s *LightEthereum) Protocols() []p2p.Protocol

Protocols implements node.Service, returning all the currently configured network protocols to start.

func (*LightEthereum) ResetWithGenesisBlock

func (s *LightEthereum) ResetWithGenesisBlock(gb *types.Block)

func (*LightEthereum) SetContractAuthorizationManager

func (s *LightEthereum) SetContractAuthorizationManager(dm multitenancy.ContractAuthorizationProvider)

Quorum

Set the decision manager for multitenancy support

func (*LightEthereum) SetContractBackend

func (s *LightEthereum) SetContractBackend(backend bind.ContractBackend)

SetClient sets the rpc client and binds the registrar contract.

func (*LightEthereum) Start

func (s *LightEthereum) Start(srvr *p2p.Server) error

Start implements node.Service, starting all internal goroutines needed by the light ethereum protocol implementation.

func (*LightEthereum) Stop

func (s *LightEthereum) Stop() error

Stop implements node.Service, terminating all internal goroutines used by the Ethereum protocol.

func (*LightEthereum) TxPool

func (s *LightEthereum) TxPool() *light.TxPool

type Msg

type Msg struct {
	MsgType int
	ReqID   uint64
	Obj     interface{}
}

Msg encodes a LES message that delivers reply data for a request

type NodeInfo

type NodeInfo struct {
	Network    uint64                   `json:"network"`    // Ethereum network ID (1=Frontier, 2=Morden, Ropsten=3, Rinkeby=4)
	Difficulty *big.Int                 `json:"difficulty"` // Total difficulty of the host's blockchain
	Genesis    common.Hash              `json:"genesis"`    // SHA3 hash of the host's genesis block
	Config     *params.ChainConfig      `json:"config"`     // Chain configuration for the fork rules
	Head       common.Hash              `json:"head"`       // SHA3 hash of the host's best owned block
	CHT        params.TrustedCheckpoint `json:"cht"`        // Trused CHT checkpoint for fast catchup
}

NodeInfo represents a short summary of the Ethereum sub-protocol metadata known about the host peer.

type PrivateLightAPI

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

PrivateLightAPI provides an API to access the LES light server or light client.

func NewPrivateLightAPI

func NewPrivateLightAPI(backend *lesCommons) *PrivateLightAPI

NewPrivateLightAPI creates a new LES service API.

func (*PrivateLightAPI) GetCheckpoint

func (api *PrivateLightAPI) GetCheckpoint(index uint64) ([3]string, error)

GetLocalCheckpoint returns the specific local checkpoint package.

The checkpoint package consists of 3 strings:

result[0], 32 bytes hex encoded latest section head hash
result[1], 32 bytes hex encoded latest section canonical hash trie root hash
result[2], 32 bytes hex encoded latest section bloom trie root hash

func (*PrivateLightAPI) GetCheckpointContractAddress

func (api *PrivateLightAPI) GetCheckpointContractAddress() (string, error)

GetCheckpointContractAddress returns the contract contract address in hex format.

func (*PrivateLightAPI) LatestCheckpoint

func (api *PrivateLightAPI) LatestCheckpoint() ([4]string, error)

LatestCheckpoint returns the latest local checkpoint package.

The checkpoint package consists of 4 strings:

result[0], hex encoded latest section index
result[1], 32 bytes hex encoded latest section head hash
result[2], 32 bytes hex encoded latest section canonical hash trie root hash
result[3], 32 bytes hex encoded latest section bloom trie root hash

type ProofReq

type ProofReq struct {
	BHash       common.Hash
	AccKey, Key []byte
	FromLevel   uint
}

type ReceiptsRequest

type ReceiptsRequest light.ReceiptsRequest

ReceiptsRequest is the ODR request type for block receipts by block hash

func (*ReceiptsRequest) CanSend

func (r *ReceiptsRequest) CanSend(peer *peer) bool

CanSend tells if a certain peer is suitable for serving the given request

func (*ReceiptsRequest) GetCost

func (r *ReceiptsRequest) GetCost(peer *peer) uint64

GetCost returns the cost of the given ODR request according to the serving peer's cost table (implementation of LesOdrRequest)

func (*ReceiptsRequest) Request

func (r *ReceiptsRequest) Request(reqID uint64, peer *peer) error

Request sends an ODR request to the LES network (implementation of LesOdrRequest)

func (*ReceiptsRequest) Validate

func (r *ReceiptsRequest) Validate(db ethdb.Database, msg *Msg) error

Valid processes an ODR request reply message from the LES network returns true and stores results in memory if the message was a valid reply to the request (implementation of LesOdrRequest)

type RequestCostList

type RequestCostList []requestCostListItem

RequestCostList is a list representation of request costs which is used for database storage and communication through the network

type TrieRequest

type TrieRequest light.TrieRequest

ODR request type for state/storage trie entries, see LesOdrRequest interface

func (*TrieRequest) CanSend

func (r *TrieRequest) CanSend(peer *peer) bool

CanSend tells if a certain peer is suitable for serving the given request

func (*TrieRequest) GetCost

func (r *TrieRequest) GetCost(peer *peer) uint64

GetCost returns the cost of the given ODR request according to the serving peer's cost table (implementation of LesOdrRequest)

func (*TrieRequest) Request

func (r *TrieRequest) Request(reqID uint64, peer *peer) error

Request sends an ODR request to the LES network (implementation of LesOdrRequest)

func (*TrieRequest) Validate

func (r *TrieRequest) Validate(db ethdb.Database, msg *Msg) error

Valid processes an ODR request reply message from the LES network returns true and stores results in memory if the message was a valid reply to the request (implementation of LesOdrRequest)

type TxStatusRequest

type TxStatusRequest light.TxStatusRequest

TxStatusRequest is the ODR request type for transaction status

func (*TxStatusRequest) CanSend

func (r *TxStatusRequest) CanSend(peer *peer) bool

CanSend tells if a certain peer is suitable for serving the given request

func (*TxStatusRequest) GetCost

func (r *TxStatusRequest) GetCost(peer *peer) uint64

GetCost returns the cost of the given ODR request according to the serving peer's cost table (implementation of LesOdrRequest)

func (*TxStatusRequest) Request

func (r *TxStatusRequest) Request(reqID uint64, peer *peer) error

Request sends an ODR request to the LES network (implementation of LesOdrRequest)

func (*TxStatusRequest) Validate

func (r *TxStatusRequest) Validate(db ethdb.Database, msg *Msg) error

Valid processes an ODR request reply message from the LES network returns true and stores results in memory if the message was a valid reply to the request (implementation of LesOdrRequest)

Directories

Path Synopsis
Package flowcontrol implements a client side flow control mechanism
Package flowcontrol implements a client side flow control mechanism

Jump to

Keyboard shortcuts

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