Documentation
¶
Overview ¶
Package blockfetch implements the Ouroboros Block Fetch mini-protocol. It provides client and server implementations for requesting and serving blocks over the network according to the Cardano Ouroboros specification.
Package blockfetch implements the Ouroboros block-fetch mini-protocol.
AI Navigation Guide ¶
This package is a good reference for understanding the protocol package structure. All protocol packages follow similar patterns.
Key Files ¶
- blockfetch.go: Protocol definition with ProtocolName, ProtocolId, StateMap
- client.go: Client implementation for requesting blocks
- server.go: Server implementation for serving blocks
- messages.go: Message types with CBOR encoding
Protocol Structure Pattern ¶
All mini-protocol packages follow this structure:
{protocol}.go defines: - ProtocolName, ProtocolId constants - StateMap for state machine transitions - Protocol struct embedding protocol.Protocol
client.go provides: - Client struct with connection handling - NewClient() constructor - Request methods (e.g., RequestBlock, RequestRange)
server.go provides: - Server struct - Handler registration - Response methods
messages.go defines: - Message type constants - Message structs with CBOR tags - Constructor functions (NewMsg*)
State Machine ¶
BlockFetch states: Idle -> Busy -> Streaming -> Idle
Client requests a range of blocks, server streams them back.
Index ¶
- Constants
- Variables
- func NewMsgFromCbor(msgType uint, data []byte) (protocol.Message, error)
- type BatchDoneFunc
- type BlockFetch
- type BlockFetchOptionFunc
- func WithBatchDoneFunc(batchDoneFunc BatchDoneFunc) BlockFetchOptionFunc
- func WithBatchStartTimeout(timeout time.Duration) BlockFetchOptionFunc
- func WithBlockFunc(blockFunc BlockFunc) BlockFetchOptionFunc
- func WithBlockRawFunc(blockRawFunc BlockRawFunc) BlockFetchOptionFunc
- func WithBlockTimeout(timeout time.Duration) BlockFetchOptionFunc
- func WithMaxInFlightBytes(maxBytes uint64) BlockFetchOptionFunc
- func WithPipeline(p *pipeline.BlockPipeline) BlockFetchOptionFunc
- func WithRangeDoneFunc(rangeDoneFunc RangeDoneFunc) BlockFetchOptionFunc
- func WithRecvQueueSize(size int) BlockFetchOptionFunc
- func WithRequestPipelining(enabled bool) BlockFetchOptionFunc
- func WithRequestRangeFunc(requestRangeFunc RequestRangeFunc) BlockFetchOptionFunc
- type BlockFunc
- type BlockRawFunc
- type CallbackContext
- type Client
- func (c *Client) GetBlock(point pcommon.Point) (ledger.Block, error)
- func (c *Client) GetBlockRange(start pcommon.Point, end pcommon.Point) error
- func (c *Client) ProtocolInstance() *protocol.Protocol
- func (c *Client) RequestRange(ctx context.Context, req RangeRequest) (uint64, error)
- func (c *Client) Start()
- func (c *Client) Stop() error
- type Config
- type MsgBatchDone
- type MsgBlock
- type MsgClientDone
- type MsgNoBlocks
- type MsgRequestRange
- type MsgStartBatch
- type RangeDoneFunc
- type RangeRequest
- type RequestRangeFunc
- type Server
- type WrappedBlock
Constants ¶
const BusyMaxPendingMessageBytes = StreamingMaxPendingMessageBytes
BusyMaxPendingMessageBytes is the maximum allowed pending message bytes in the Busy state. This must match StreamingMaxPendingMessageBytes because MsgBlock can arrive while the protocol state machine is still in Busy (before recvLoop processes MsgStartBatch to transition to Streaming), creating a race between muxerRecvLoop limit checks and state transitions.
const BusyTimeout = 60 * time.Second
BusyTimeout is the timeout for the server to start a batch or respond no blocks.
const DefaultMaxInFlightBytes uint64 = 100 * DefaultRequestExpectedBytes
DefaultMaxInFlightBytes is the default bound on the total expected size of outstanding pipelined range requests. It matches the ingress allowance cardano-node sizes for block-fetch in blockFetchProtocolLimits: blockFetchPipeliningMax (100) times the maximum block body size (88 KiB).
const DefaultRecvQueueSize = 384
DefaultRecvQueueSize is the default receive queue size.
const DefaultRequestExpectedBytes uint64 = 88 * 1024
DefaultRequestExpectedBytes is the size assumed for a range request whose caller did not estimate one. It is one maximum-size mainnet block body (maxBlockBodySize = 88 KiB), which makes DefaultMaxInFlightBytes degrade to cardano-node's blockFetchPipeliningMax of 100 outstanding requests for callers that cannot estimate.
const IdleMaxPendingMessageBytes = 65535
IdleMaxPendingMessageBytes is the maximum allowed pending message bytes in the Idle state. Only control messages (MsgRequestRange, MsgClientDone) are sent in this state, so the limit can be small.
const MaxRecvQueueSize = 512
MaxRecvQueueSize is the maximum allowed receive queue size (messages).
const MessageTypeBatchDone = 5
MessageTypeBatchDone is the message type for indicating the end of a batch.
const MessageTypeBlock = 4
MessageTypeBlock is the message type for sending a block.
const MessageTypeClientDone = 1
MessageTypeClientDone is the message type for client completion.
const MessageTypeNoBlocks = 3
MessageTypeNoBlocks is the message type for indicating no blocks are available.
const MessageTypeRequestRange = 0
MessageTypeRequestRange is the message type for requesting a range of blocks.
const MessageTypeStartBatch = 2
MessageTypeStartBatch is the message type for starting a batch.
const PipelinedIdleMaxPendingMessageBytes = StreamingMaxPendingMessageBytes
PipelinedIdleMaxPendingMessageBytes is the pending message byte limit used for the Idle state by a client with RequestPipelining enabled. With more than one request outstanding, the peer's MsgBlock for the next request can arrive while the local state machine is momentarily back in Idle, between the previous MsgBatchDone and the deferred transition for the next MsgRequestRange. The Idle limit therefore has to admit a block, for the same reason BusyMaxPendingMessageBytes does.
const ProtocolId uint16 = 3
ProtocolId is the unique protocol identifier for Block Fetch.
const ProtocolName = "block-fetch"
ProtocolName is the name of the Block Fetch protocol.
const StreamingMaxPendingMessageBytes = 2500000
StreamingMaxPendingMessageBytes is the maximum allowed pending message bytes when in the Streaming state
const StreamingTimeout = 60 * time.Second
StreamingTimeout is the timeout for the server to send the next block in a batch.
Variables ¶
var ErrNoBlocks = errors.New("block(s) not found")
ErrNoBlocks is the error reported for a range the peer answered with MsgNoBlocks: through RangeDoneFunc for a request made with RequestRange, and as the return value of GetBlock. Consumers match on it with errors.Is. The message is unchanged because it was previously the only thing to match on.
var ErrRequestPipeliningDisabled = errors.New(
"block-fetch request pipelining is not enabled on this client",
)
ErrRequestPipeliningDisabled is returned by RequestRange when the client was not configured with RequestPipelining.
var StateBusy = protocol.NewState(2, "Busy")
StateBusy represents the Busy state in the Block Fetch protocol.
var StateDone = protocol.NewState(4, "Done")
StateDone represents the Done state in the Block Fetch protocol.
var StateIdle = protocol.NewState(1, "Idle")
StateIdle represents the Idle state in the Block Fetch protocol.
var StateMap = protocol.StateMap{ StateIdle: protocol.StateMapEntry{ Agency: protocol.AgencyClient, PendingMessageByteLimit: IdleMaxPendingMessageBytes, Transitions: []protocol.StateTransition{ { MsgType: MessageTypeRequestRange, NewState: StateBusy, }, { MsgType: MessageTypeClientDone, NewState: StateDone, }, }, }, StateBusy: protocol.StateMapEntry{ Agency: protocol.AgencyServer, PendingMessageByteLimit: BusyMaxPendingMessageBytes, Timeout: BusyTimeout, PipelinedMessageTypes: []uint8{MessageTypeRequestRange}, Transitions: []protocol.StateTransition{ { MsgType: MessageTypeStartBatch, NewState: StateStreaming, }, { MsgType: MessageTypeNoBlocks, NewState: StateIdle, }, }, }, StateStreaming: protocol.StateMapEntry{ Agency: protocol.AgencyServer, PendingMessageByteLimit: StreamingMaxPendingMessageBytes, Timeout: StreamingTimeout, PipelinedMessageTypes: []uint8{MessageTypeRequestRange}, Transitions: []protocol.StateTransition{ { MsgType: MessageTypeBlock, NewState: StateStreaming, }, { MsgType: MessageTypeBatchDone, NewState: StateIdle, }, }, }, StateDone: protocol.StateMapEntry{ Agency: protocol.AgencyNone, }, }
StateMap defines the state transitions and agency for the Block Fetch protocol.
var StateStreaming = protocol.NewState(3, "Streaming")
StateStreaming represents the Streaming state in the Block Fetch protocol.
Functions ¶
Types ¶
type BatchDoneFunc ¶ added in v0.104.0
type BatchDoneFunc func(CallbackContext) error
BatchDoneFunc is a callback invoked when a batch is complete. It is not used for requests made through Client.RequestRange, which report completion through RangeDoneFunc instead.
type BlockFetch ¶
type BlockFetch struct {
Client *Client // Block Fetch client
Server *Server // Block Fetch server
}
BlockFetch provides a combined client and server for the Block Fetch protocol.
func New ¶
func New(protoOptions protocol.ProtocolOptions, cfg *Config) *BlockFetch
New creates a new BlockFetch instance with the given protocol options and configuration.
type BlockFetchOptionFunc ¶
type BlockFetchOptionFunc func(*Config)
BlockFetchOptionFunc is a function that modifies a BlockFetch Config.
func WithBatchDoneFunc ¶ added in v0.104.0
func WithBatchDoneFunc(batchDoneFunc BatchDoneFunc) BlockFetchOptionFunc
WithBatchDoneFunc sets the BatchDoneFunc callback in the Config.
func WithBatchStartTimeout ¶
func WithBatchStartTimeout(timeout time.Duration) BlockFetchOptionFunc
WithBatchStartTimeout sets the batch start timeout in the Config.
func WithBlockFunc ¶
func WithBlockFunc(blockFunc BlockFunc) BlockFetchOptionFunc
WithBlockFunc sets the BlockFunc callback in the Config.
func WithBlockRawFunc ¶ added in v0.108.0
func WithBlockRawFunc(blockRawFunc BlockRawFunc) BlockFetchOptionFunc
WithBlockRawFunc sets the BlockRawFunc callback in the Config.
func WithBlockTimeout ¶
func WithBlockTimeout(timeout time.Duration) BlockFetchOptionFunc
WithBlockTimeout sets the block timeout in the Config.
func WithMaxInFlightBytes ¶ added in v0.195.0
func WithMaxInFlightBytes(maxBytes uint64) BlockFetchOptionFunc
WithMaxInFlightBytes sets the bound on the total expected size of outstanding pipelined range requests. Zero selects DefaultMaxInFlightBytes.
func WithPipeline ¶ added in v0.154.0
func WithPipeline(p *pipeline.BlockPipeline) BlockFetchOptionFunc
WithPipeline sets the block processing pipeline in the Config. When a pipeline is configured, received blocks are submitted to the pipeline for parallel decoding, validation, and ordered application instead of being processed synchronously through callbacks.
func WithRangeDoneFunc ¶ added in v0.195.0
func WithRangeDoneFunc(rangeDoneFunc RangeDoneFunc) BlockFetchOptionFunc
WithRangeDoneFunc sets the RangeDoneFunc callback in the Config.
func WithRecvQueueSize ¶ added in v0.114.0
func WithRecvQueueSize(size int) BlockFetchOptionFunc
WithRecvQueueSize specifies the size of the received messages queue in the Config. Validation is deferred to NewConfig; invalid values are caught there.
func WithRequestPipelining ¶ added in v0.195.0
func WithRequestPipelining(enabled bool) BlockFetchOptionFunc
WithRequestPipelining enables or disables client request pipelining, which allows Client.RequestRange to keep multiple MsgRequestRange outstanding.
func WithRequestRangeFunc ¶ added in v0.66.0
func WithRequestRangeFunc( requestRangeFunc RequestRangeFunc, ) BlockFetchOptionFunc
WithRequestRangeFunc sets the RequestRangeFunc callback in the Config.
type BlockFunc ¶
type BlockFunc func(CallbackContext, uint, ledger.Block) error
BlockFunc is a callback for handling decoded blocks.
type BlockRawFunc ¶ added in v0.108.0
type BlockRawFunc func(CallbackContext, uint, []byte) error
BlockRawFunc is a callback for handling raw block data.
type CallbackContext ¶ added in v0.78.0
type CallbackContext struct {
ConnectionId connection.ConnectionId // Connection ID
Client *Client // Client instance (if applicable)
Server *Server // Server instance (if applicable)
// RequestId identifies the client range request that produced this
// callback. Requests are numbered from 1 in the order they were sent,
// and block-fetch responses are ordered, so this attributes each block
// and completion to the MsgRequestRange that asked for it. It is zero
// for server-side callbacks.
RequestId uint64
}
CallbackContext provides context for Block Fetch callbacks.
type Client ¶
Client implements the Block Fetch protocol client, which requests blocks from a server.
func NewClient ¶
func NewClient(protoOptions protocol.ProtocolOptions, cfg *Config) *Client
NewClient creates a new Block Fetch protocol client with the given options and configuration.
func (*Client) GetBlock ¶
GetBlock requests and returns a single block specified by the provided point. This is a synchronous call that returns the block or an error.
func (*Client) GetBlockRange ¶
GetBlockRange starts an async process to fetch all blocks in the specified range (inclusive). The provided callbacks are used for each block and when the batch is done.
Only one GetBlockRange or GetBlock call is in progress at a time; a second call blocks until the first batch completes. Use RequestRange to keep multiple requests outstanding.
func (*Client) ProtocolInstance ¶ added in v0.160.2
func (*Client) RequestRange ¶ added in v0.195.0
RequestRange queues a request for the given block range without waiting for previously queued requests to complete, so the peer always has work in hand at a batch boundary. It returns the request ID, which the client reports in CallbackContext.RequestId for every block of the range and in the RangeDoneFunc call that completes it. Blocks are delivered through the same callbacks GetBlockRange uses.
It blocks while the expected size of the outstanding requests would exceed the configured MaxInFlightBytes, and returns the context's error if the caller gives up first. A request larger than the whole bound is admitted once the queue is empty, so an oversized range cannot stall forever.
The client must be configured with RequestPipelining and a RangeDoneFunc.
func (*Client) Start ¶ added in v0.73.3
func (c *Client) Start()
Start begins the Block Fetch client protocol. Safe to call multiple times.
func (*Client) Stop ¶
Stop stops the Block Fetch client protocol and sends a ClientDone message. It waits up to 250ms for message delivery before shutting down the protocol, returning delivery errors, including context.DeadlineExceeded. An already shutting-down protocol is treated as successfully stopped.
type Config ¶
type Config struct {
BlockFunc BlockFunc // Callback for decoded blocks
BlockRawFunc BlockRawFunc // Callback for raw block data
BatchDoneFunc BatchDoneFunc // Callback when a batch is done
RangeDoneFunc RangeDoneFunc // Callback when a pipelined range request completes
RequestRangeFunc RequestRangeFunc // Callback for range requests
BatchStartTimeout time.Duration // Timeout for starting a batch
BlockTimeout time.Duration // Timeout for receiving a block
RecvQueueSize int // Size of the receive queue
SkipBlockValidation bool // Skip block validation during parsing
Pipeline *pipeline.BlockPipeline // Pipeline enables the block processing pipeline for batch operations
// RequestPipelining allows the client to keep more than one
// MsgRequestRange outstanding through Client.RequestRange. This is
// protocol request pipelining and is unrelated to Pipeline above, which
// is a processing pipeline for blocks that have already been received.
RequestPipelining bool
// MaxInFlightBytes bounds the total expected size of the range requests
// a pipelining client keeps outstanding. Zero means
// DefaultMaxInFlightBytes.
MaxInFlightBytes uint64
}
Config holds configuration options for the Block Fetch protocol.
func NewConfig ¶
func NewConfig(options ...BlockFetchOptionFunc) (Config, error)
NewConfig creates a new Config for Block Fetch, applying any provided option functions. It returns an error if the resulting configuration is invalid.
type MsgBatchDone ¶
type MsgBatchDone struct {
protocol.MessageBase
}
MsgBatchDone indicates the end of a batch of blocks.
func NewMsgBatchDone ¶
func NewMsgBatchDone() *MsgBatchDone
NewMsgBatchDone creates a new MsgBatchDone message.
type MsgBlock ¶
type MsgBlock struct {
protocol.MessageBase
WrappedBlock []byte // CBOR-encoded wrapped block
}
MsgBlock contains a block sent from the server to the client.
func NewMsgBlock ¶
NewMsgBlock creates a new MsgBlock with the given wrapped block data.
func (MsgBlock) MarshalCBOR ¶ added in v0.66.0
MarshalCBOR encodes the MsgBlock as CBOR.
type MsgClientDone ¶
type MsgClientDone struct {
protocol.MessageBase
}
MsgClientDone indicates the client is done with block fetching.
func NewMsgClientDone ¶
func NewMsgClientDone() *MsgClientDone
NewMsgClientDone creates a new MsgClientDone message.
type MsgNoBlocks ¶
type MsgNoBlocks struct {
protocol.MessageBase
}
MsgNoBlocks indicates that no blocks are available for the requested range.
func NewMsgNoBlocks ¶
func NewMsgNoBlocks() *MsgNoBlocks
NewMsgNoBlocks creates a new MsgNoBlocks message.
type MsgRequestRange ¶
type MsgRequestRange struct {
protocol.MessageBase
Start pcommon.Point // Start point of the range
End pcommon.Point // End point of the range
}
MsgRequestRange represents a request for a range of blocks.
func NewMsgRequestRange ¶
func NewMsgRequestRange( start pcommon.Point, end pcommon.Point, ) *MsgRequestRange
NewMsgRequestRange creates a new MsgRequestRange with the given start and end points.
type MsgStartBatch ¶
type MsgStartBatch struct {
protocol.MessageBase
}
MsgStartBatch indicates the start of a batch of blocks.
func NewMsgStartBatch ¶
func NewMsgStartBatch() *MsgStartBatch
NewMsgStartBatch creates a new MsgStartBatch message.
type RangeDoneFunc ¶ added in v0.195.0
type RangeDoneFunc func(CallbackContext, error) error
RangeDoneFunc is a callback invoked exactly once for each request made through Client.RequestRange. The error is nil when the peer completed the batch, and otherwise reports why the request will not be completed: the range was unavailable, the peer violated the protocol, or the protocol shut down with the request still outstanding.
type RangeRequest ¶ added in v0.195.0
type RangeRequest struct {
Start pcommon.Point // Start point of the range (inclusive)
End pcommon.Point // End point of the range (inclusive)
// ExpectedBytes is the caller's estimate of the total serialized size of
// the blocks in this range, used for the client's in-flight byte bound.
// A caller driving block-fetch from chain-sync headers has this from the
// header block body sizes. Zero means DefaultRequestExpectedBytes.
ExpectedBytes uint64
}
RangeRequest describes a single block range request queued through Client.RequestRange.
type RequestRangeFunc ¶ added in v0.66.0
RequestRangeFunc is a callback for handling block range requests.
type Server ¶
Server implements the Block Fetch protocol server, which serves blocks to clients.
func NewServer ¶
func NewServer(protoOptions protocol.ProtocolOptions, cfg *Config) *Server
NewServer creates a new Block Fetch protocol server with the given options and configuration.
func (*Server) BatchDone ¶ added in v0.66.0
BatchDone sends a BatchDone message to the client, indicating the end of a batch.
func (*Server) Block ¶ added in v0.66.0
Block sends a Block message to the client with the given block type and data.
func (*Server) NoBlocks ¶ added in v0.66.0
NoBlocks sends a NoBlocks message to the client, indicating no blocks are available.
func (*Server) ProtocolInstance ¶ added in v0.160.2
func (*Server) StartBatch ¶ added in v0.66.0
StartBatch sends a StartBatch message to the client, indicating the start of a batch.
type WrappedBlock ¶
type WrappedBlock struct {
cbor.StructAsArray
Type uint // Block type identifier
RawBlock cbor.RawMessage // Raw block data
}
WrappedBlock is a CBOR structure containing a block type and raw block data.