Documentation ¶
Index ¶
- Variables
- func EncodeBlock(protocolVersion int32, b Block) (blk *bstream.Block, err error)
- func ExamplePrefixed[B Block](chain *Chain[B], prefix, in string) string
- func GetCommonStoresURLs(dataDir string) (mergedBlocksStoreURL, oneBlocksStoreURL, forkedBlocksStoreURL string, ...)
- func GetIndexStore(dataDir string) (indexStore dstore.Store, possibleIndexSizes []uint64, err error)
- func LastMergedBlockNum(ctx context.Context, startBlockNum uint64, store dstore.Store, ...) uint64
- func Main[B Block](chain *Chain[B])
- func MustReplaceDataDir(dataDir, in string) string
- func NewToolsUpgradeMergedBlocksCmd[B Block](chain *Chain[B]) *cobra.Command
- func PrintOutputModeNames() []string
- type Block
- type BlockEncoder
- type BlockEncoderFunc
- type BlockIndexer
- type BlockIndexerFactory
- type BlockPrinterFunc
- type BlockTransformerFactory
- type Chain
- type CommandExecutor
- type PrintOutputMode
- type SubstreamsExtension
- type ToolsConfig
- type TransformFlag
- type TransformFlagParser
Constants ¶
This section is empty.
Variables ¶
var ( // Common ports MetricsListenAddr string = ":9102" // Firehose chain specific port IndexBuilderServiceAddr string = ":10009" ReaderNodeGRPCAddr string = ":10010" ReaderNodeManagerAPIAddr string = ":10011" MergerServingAddr string = ":10012" RelayerServingAddr string = ":10014" FirehoseGRPCServingAddr string = ":10015" SubstreamsTier1GRPCServingAddr string = ":10016" SubstreamsTier2GRPCServingAddr string = ":10017" // Data storage default locations BlocksCacheDirectory string = "file://{data-dir}/storage/blocks-cache" MergedBlocksStoreURL string = "file://{data-dir}/storage/merged-blocks" OneBlockStoreURL string = "file://{data-dir}/storage/one-blocks" ForkedBlocksStoreURL string = "file://{data-dir}/storage/forked-blocks" IndexStoreURL string = "file://{data-dir}/storage/index" )
Those are `var` and globally available so that some chains to keep backward-compatibility can change them. This is not advertised and should **not** be used by new chain.
var UnsafePayloadKind pbbstream.Protocol = pbbstream.Protocol_UNKNOWN
var UnsafeResolveReaderNodeStartBlock = func(ctx context.Context, command *cobra.Command, runtime *launcher.Runtime, rootLog *zap.Logger) (uint64, error) { return sflags.MustGetUint64(command, "reader-node-start-block-num"), nil }
UnsafeResolveReaderNodeStartBlock is a function that resolved the reader node start block num, by default it simply returns the value of the 'reader-node-start-block-num'. However, the function may be overwritten in certain chains to perform a more complex resolution logic.
Functions ¶
func EncodeBlock ¶ added in v0.1.0
func GetCommonStoresURLs ¶
func GetIndexStore ¶
func LastMergedBlockNum ¶ added in v0.1.7
func Main ¶
Main is the main entry point that configures everything and should be called from your Go 'main' entrypoint directly.
func MustReplaceDataDir ¶
MustReplaceDataDir replaces `{data-dir}` from within the `in` received argument by the `dataDir` argument
func NewToolsUpgradeMergedBlocksCmd ¶ added in v0.1.0
func PrintOutputModeNames ¶
func PrintOutputModeNames() []string
PrintOutputModeNames returns a list of possible string values of PrintOutputMode.
Types ¶
type Block ¶ added in v0.1.0
type Block interface { proto.Message // GetFirehoseBlockID returns the block ID as a string, usually in the representation // used by your chain (hex, base58, base64, etc.). The block ID must be unique across // all blocks that will ever exist on your chain. GetFirehoseBlockID() string // GetFirehoseBlockNumber returns the block number as an unsigned integer. The block // number could be shared by multiple blocks in which case one is the canonical one // and the others are forks (resolution of forks is handled by Firehose core later in the // block processing pipeline). // // The value should be sequentially ordered which means that a block with block number 10 // has come before block 11. Firehose core will deal with block skips without problem though // (e.g. block 1, is produced then block 3 where block 3's parent is block 1). GetFirehoseBlockNumber() uint64 // GetFirehoseBlockPreviousID returns the block ID of the parent block as a string. All blocks // ever produced must have a parent block ID except for the genesis block which is the first // one. The value must be the same as the one returned by GetFirehoseBlockID() of the parent. // // If it's the genesis block, return an empty string. GetFirehoseBlockParentID() string // GetFirehoseBlockTime returns the block timestamp as a time.Time of when the block was // produced. This should the consensus agreed time of the block. GetFirehoseBlockTime() time.Time // GetFirehoseBlockLIBNum returns the last irreversible block number as an unsigned integer // of this block. This is one of the most important piece of information for Firehose core. // as it determines when "forks" are now stalled and should be removed from memory and it // drives a bunch of important write processes that will write the block to disk only when the // block is now irreversible. // // The value returned should be the oldest block that should turned to be irreversible when this // block was produced. Assume for example the current block is 100. If finality rule of a chain // is that a block become irreversible after 12 blocks has been produced, then the value returned // in this case should be 88 (100 - 12) which means that when block 100 was produced, block 88 // can now be considered irreversible. // // Irreversibility is chain specific and how the value here is returned depends on the chain. On // probabilistic irreversible chains, like Bitcoin, the value returned here is usually the current // block number - <threshold> where <threshold> is choosen to be safe enough in all situations (ensure // that is block number < <threshold>, then you properly cap to 0). // // On deterministic irreversible chains, usually the last irreversible block number if part of the // consensus and as such should be part of the Protobuf block model somewhere. In those cases, this // value should be returned here. GetFirehoseBlockLIBNum() uint64 }
Block represents the chain-specific Protobuf block. Chain specific's block model must implement this interface so that Firehose core is able to properly marshal/unmarshal your block into/to the Firehose block envelope binary format.
All the methods are prefixed with `GetFirehoseBlock` to avoid any potential conflicts with the fields/getters of your chain's block model that would prevent you from implementing this interface.
Consumer of your chain's protobuf block model don't need to be aware of those details, they are internal Firehose core information that are required to function properly.
The value you return for each of those methods must be done respecting Firehose rules which are enumarated in the documentation of each method.
type BlockEncoder ¶ added in v0.1.0
BlockEncoder is the interface of an object that is going to a chain specific block implementing Block interface that will be encoded into bstream.Block type which is the type used by Firehose core to "envelope" the block.
func NewGenericBlockEncoder ¶ added in v0.1.0
func NewGenericBlockEncoder(protocolVersion int32) BlockEncoder
type BlockEncoderFunc ¶ added in v0.1.0
type BlockIndexer ¶ added in v0.1.0
type BlockIndexerFactory ¶ added in v0.1.0
type BlockPrinterFunc ¶
BlockPrinterFunc takes a chain agnostic [block] and prints it to a human readable form.
See [ToolsConfig#BlockPrinter] for extra details about expected printing.
type BlockTransformerFactory ¶ added in v0.1.0
type BlockTransformerFactory func(indexStore dstore.Store, indexPossibleSizes []uint64) (*transform.Factory, error)
BlockTransformerFactory is a bit convoluted, but yes it's a function acting as a factory that returns itself a factory. The reason for this is that the factory needs to be able to access the index store and the index size to be able to create the actual factory.
In the context of `firehose-core` transform registration, this function will be called exactly once for the overall process. The returns transform.Factory will be used multiple times (one per request requesting this transform).
type Chain ¶
type Chain[B Block] struct { // ShortName is the short name for your Firehose on <Chain> and is usually how // your chain's name is represented as a diminitutive. If your chain's name is already // short, we suggest to keep [ShortName] and [LongName] the same. // // As an example, Firehose on Ethereum [ShortName] is `eth` while Firehose on NEAR // short name is `near`. // // The [ShortName] **must** be non-empty, lower cased and must **not** contain any spaces. ShortName string // LongName is the full name of your chain and the case sensitivy of this value is respected. // It is used in description of command and some logging output. // // The [LongName] **must** be non-empty. LongName string // Protocol is exactly 3 characters long that is going to identify your chain when writing blocks // to file. The written file contains an header and a part of this header is the protocol value. // // The [Protocol] **must** be non-empty and exactly 3 characters long all upper case. Protocol string // ProtocolVersion is the version of the protocol that is used to write blocks to file. This value // is used in the header of the written file. It should be changed each time the Protobuf model change // to become backward incompatible. This usually should be accompagnied by a change in the Protobuf // block model of the chain. For example for Ethereum we would go from `sf.ethereum.v1.Block` to // `sf.ethereum.v2.Block` and the [ProtocolVersion] would be incremented from `1` to `2`. // // The [ProtocolVersion] **must** be positive and non-zero and should be incremented each time the Protobuf model change. ProtocolVersion int32 // ExecutableName is the name of the binary that is used to launch a syncing full node for this chain. For example, // on Ethereum, the binary by default is `geth`. This is used by the `reader-node` app to specify the // `reader-node-binary-name` flag. // // The [ExecutableName] **must** be non-empty. ExecutableName string // FullyQualifiedModule is the Go module of your actual `firehose-<chain>` repository and should // correspond to the `module` line of the `go.mod` file found at the root of your **own** `firehose-<chain>` // repository. The value can be seen using `head -1 go.mod | sed 's/module //'`. // // The [FullyQualifiedModule] **must** be non-empty. FullyQualifiedModule string // Version represents the actual version for your Firehose on <Chain>. It should be injected // via and `ldflags` through your `main` package. // // The [Version] **must** be non-empty. Version string // FirstStreamableBlock represents the block number of the first block that is streamable using Firehose, // for example on Ethereum it's set to `0`, the genesis block's number while on Antelope it's // set to 2 (genesis block is 1 there but our instrumentation on this chain instruments // only from block #2). // // This value is actually the default value of the `--common-first-streamable-block` flag and // all later usages are done using the flag's value and not this value. // // So this value is actually dynamic and can be changed at runtime using the // `--common-first-streamable-block`. // // The [FirstStreamableBlock] should be defined but the default 0 value is good enough // for most chains. FirstStreamableBlock uint64 // BlockFactory is a factory function that returns a new instance of your chain's Block. // This new instance is usually used within `firecore` to unmarshal some bytes into your // chain's specific block model and return a [proto.Message] fully instantiated. // // The [BlockFactory] **must** be non-nil and must return a non-nil [proto.Message]. BlockFactory func() Block // ConsoleReaderFactory is the function that should return the `ConsoleReader` that knowns // how to transform your your chain specific Firehose instrumentation logs into the proper // Block model of your chain. // // The [ConsoleReaderFactory] **must** be non-nil and must return a non-nil [mindreader.ConsolerReader] or an error. ConsoleReaderFactory func(lines chan string, blockEncoder BlockEncoder, logger *zap.Logger, tracer logging.Tracer) (mindreader.ConsolerReader, error) // BlockIndexerFactories defines the set of indexes built out of Firehose blocks to be served by Firehose // as custom filters. // // The [BlockIndexerFactories] is optional. If set, each key must be assigned to a non-nil [BlockIndexerFactory]. For now, // a single factory can be specified per chain. We use a map to allow for multiple factories in the future. // // If there is no indexer factories defined, the `index-builder` app will be disabled for this chain. // // The [BlockIndexerFactories] is optional. BlockIndexerFactories map[string]BlockIndexerFactory[B] // BlockTransformerFactories defines the set of transformer that will be enabled when the client request Firehose // blocks. // // The [BlockTransformerFactories] is optional. If set, each key must be assigned to a non-nil // [BlockTransformerFactory]. Multiple transformers can be defined. // // The [BlockTransformerFactories] is optional. BlockTransformerFactories map[protoreflect.FullName]BlockTransformerFactory // RegisterExtraStartFlags is a function that is called by the `reader-node` app to allow your chain // to register extra custom arguments. This function is called after the common flags are registered. // // The [RegisterExtraStartFlags] function is optional and not called if nil. RegisterExtraStartFlags func(flags *pflag.FlagSet) // ReaderNodeBootstrapperFactory enables the `reader-node` app to have a custom bootstrapper for your chain. // By default, no specialized bootstrapper is defined. // // If this is set, the `reader-node` app will use the one bootstrapper returned by this function. The function // will receive the `start` command where flags are defined as well as the node's absolute data directory as an // argument. ReaderNodeBootstrapperFactory func(cmd *cobra.Command, nodeDataDir string) (operator.Bootstrapper, error) // Tools aggregate together all configuration options required for the various `fire<chain> tools` // to work properly for example to print block using chain specific information. // // The [Tools] element is optional and if not provided, sane defaults will be used. Tools *ToolsConfig[B] // BlockEncoder is the cached block encoder object that should be used for this chain. Populate // when Init() is called will be `nil` prior to that. // // When you need to encode your chain specific block like `pbeth.Block` into a `bstream.Block` you // should use this encoder: // // bstreamBlock, err := chain.BlockEncoder.Encode(block) // BlockEncoder BlockEncoder // RegisterSubstreamsExtensions func(chain *Chain[B]) ([]SubstreamsExtension, error) }
Chain is the omni config object for configuring your chain specific information. It contains various fields that are used everywhere to properly configure the `firehose-<chain>` binary.
Each field is documented about where it's used. Throughtout the different Chain option, we will use `Acme` as the chain's name placeholder, replace it with your chain name.
func (*Chain[B]) BinaryName ¶
BinaryName represents the binary name for your Firehose on <Chain> is the [ShortName] lowered appended to 'fire' prefix to before for example `fireacme`.
func (*Chain[B]) BlockPrinter ¶
func (c *Chain[B]) BlockPrinter() BlockPrinterFunc
func (*Chain[B]) Init ¶ added in v0.1.0
func (c *Chain[B]) Init()
Init is called when the chain is first loaded to initialize the `bstream` library with the chain specific configuration.
This must called only once per chain per process.
**Caveats** Two chain in the same Go binary will not work today as `bstream` uses global variables to store configuration which presents multiple chain to exist in the same process.
func (*Chain[B]) LoggerPackageID ¶
LoggerPackageID computes a logger `packageID` value for a specific sub-package.
func (*Chain[B]) RootLoggerPackageID ¶
RootLoggerPackageID is the `packageID` value when instantiating the root logger on the chain that is used by CLI command and other
func (*Chain[B]) Validate ¶
func (c *Chain[B]) Validate()
Validate normalizes some aspect of the Chain values (spaces trimming essentially) and validates the chain by accumulating error an panic if all the error found along the way.
func (*Chain[B]) VersionString ¶
VersionString computes the version string that will be display when calling `firexxx --version` and extract build information from Git via Golang `debug.ReadBuildInfo`.
type PrintOutputMode ¶
type PrintOutputMode uint
ENUM(
Text JSON
)
const ( // PrintOutputModeText is a PrintOutputMode of type Text. PrintOutputModeText PrintOutputMode = iota // PrintOutputModeJSON is a PrintOutputMode of type JSON. PrintOutputModeJSON )
func ParsePrintOutputMode ¶
func ParsePrintOutputMode(name string) (PrintOutputMode, error)
ParsePrintOutputMode attempts to convert a string to a PrintOutputMode
func (PrintOutputMode) MarshalText ¶
func (x PrintOutputMode) MarshalText() ([]byte, error)
MarshalText implements the text marshaller method
func (PrintOutputMode) String ¶
func (x PrintOutputMode) String() string
String implements the Stringer interface.
func (*PrintOutputMode) UnmarshalText ¶
func (x *PrintOutputMode) UnmarshalText(text []byte) error
UnmarshalText implements the text unmarshaller method
type SubstreamsExtension ¶ added in v0.1.0
type SubstreamsExtension struct { PipelineOptioner pipeline.PipelineOptioner WASMExtensioner wasm.WASMExtensioner }
type ToolsConfig ¶
type ToolsConfig[B Block] struct { // BlockPrinter represents a printing function that render a chain specific human readable // form of the receive chain agnostic [bstream.Block]. This block is expected to be rendered as // a single line for example on Ethereum rendering of a single block looks like: // // “` // Block #24924194 (01d6d349fbd3fa419182a2f0cf0b00714e101286650c239de8923caef6134b6c) 62 transactions, 607 calls // “` // // If the [alsoPrintTransactions] argument is true, each transaction of the block should also be printed, following // directly the block line. Each transaction should also be on a single line, usually prefixed with a `- ` to make // the rendering more appealing. // // For example on Ethereum rendering with [alsoPrintTransactions] being `true` looks like: // // “` // Block #24924194 (01d6d349fbd3fa419182a2f0cf0b00714e101286650c239de8923caef6134b6c) 62 transactions, 607 calls // - Transaction 0xc7e04240d6f2cc5f382c478fd0a0b5c493463498c64b31477b95bded8cd12ab4 (10 calls) // - Transaction 0xc7d8a698351eb1ac64acb76c8bf898365bb639865271add95d2c81650b2bd98c (4 calls) // “` // // The `out` parameter is used to write to the correct location. You can use [fmt.Fprintf] and [fmt.Fprintln] // and use `out` as the output writer in your implementation. // // The [BlockPrinter] is optional, if nil, a default block printer will be used. It's important to note // that the default block printer error out if `alsoPrintTransactions` is true. BlockPrinter BlockPrinterFunc // RegisterExtraCmd enables you to register extra commands to the `fire<chain> tools` group. // The callback function is called with the `toolsCmd` command that is the root command of the `fire<chain> tools` // as well as the chain, the root logger and root tracer for tools. // // You are responsible of calling `toolsCmd.AddCommand` to register your extra commands. // // The [RegisterExtraCmd] function is optional and not called if nil. RegisterExtraCmd func(chain *Chain[B], toolsCmd *cobra.Command, zlog *zap.Logger, tracer logging.Tracer) error // TransformFlags specify chain specific transforms flags (and parsing of flag's value). The flags defined // in there are added to all Firehose-client like tools commannd (`tools firehose-client`, `tools firehose-prometheus-exporter`, etc.). // // The [TransformFlags] is optional. TransformFlags map[string]*TransformFlag // MergedBlockUpgrader when define enables for your chain to upgrade between different versions of "merged-blocks". // It happens from time to time that a data bug is found in the way merged blocks and it's possible to fix it by // applying a transformation to the block. This is what this function is for. // // When defined, a new tools `fire<chain> tools upgrade-merged-blocks` is added. This command will enable operators // to upgrade from one version to another of the merged blocks. // // The [MergedBlockUpgrader] is optional and not specifying it disables command `fire<chain> tools upgrade-merged-blocks`. MergedBlockUpgrader func(block *bstream.Block) (*bstream.Block, error) }
type TransformFlag ¶ added in v0.1.0
type TransformFlag struct { Description string Parser TransformFlagParser }
Source Files ¶
- chain.go
- common.go
- constants.go
- firehose.go
- flags.go
- index_builder.go
- main.go
- merger.go
- reader_node.go
- reader_node_stdin.go
- relayer.go
- setup.go
- start.go
- storage.go
- substreams_common.go
- substreams_tier1.go
- substreams_tier2.go
- tools.go
- tools_check.go
- tools_download_from_firehose.go
- tools_firehose_client.go
- tools_firehose_prometheus_exporter.go
- tools_firehose_single_block_client.go
- tools_print.go
- tools_print_enum.go
- tools_upgrade_merged_blocks.go
- types.go
- utils.go