From 6cf9cafcbab312271b6af71149a451bb6a55d35a Mon Sep 17 00:00:00 2001 From: gagliardetto Date: Wed, 15 Nov 2023 16:17:02 +0100 Subject: [PATCH] Handle genesis file --- config.go | 18 +++++++++++++++++ epoch.go | 20 +++++++++++++++++++ genesis.go | 12 ++++++++++++ multiepoch-getBlock.go | 44 +++++++++++++++++++++++------------------- 4 files changed, 74 insertions(+), 20 deletions(-) create mode 100644 genesis.go diff --git a/config.go b/config.go index a7699c4a..5451dcd9 100644 --- a/config.go +++ b/config.go @@ -125,6 +125,9 @@ type Config struct { URI URI `json:"uri" yaml:"uri"` } `json:"sig_exists" yaml:"sig_exists"` } `json:"indexes" yaml:"indexes"` + Genesis struct { + URI URI `json:"uri" yaml:"uri"` + } `json:"genesis" yaml:"genesis"` } func (c *Config) ConfigFilepath() string { @@ -296,5 +299,20 @@ func (c *Config) Validate() error { } } } + { + // if epoch is 0, then the genesis URI must be set: + if *c.Epoch == 0 { + if c.Genesis.URI.IsZero() { + return fmt.Errorf("epoch is 0, but genesis.uri is not set") + } + if !c.Genesis.URI.IsValid() { + return fmt.Errorf("genesis.uri is invalid") + } + // only support local genesis files for now: + if !c.Genesis.URI.IsLocal() { + return fmt.Errorf("genesis.uri must be a local file") + } + } + } return nil } diff --git a/epoch.go b/epoch.go index 73eed471..e921dbdd 100644 --- a/epoch.go +++ b/epoch.go @@ -22,6 +22,7 @@ import ( "github.com/rpcpool/yellowstone-faithful/gsfa" "github.com/rpcpool/yellowstone-faithful/ipld/ipldbindcode" "github.com/rpcpool/yellowstone-faithful/iplddecoders" + "github.com/rpcpool/yellowstone-faithful/radiance/genesis" "github.com/urfave/cli/v2" "k8s.io/klog/v2" ) @@ -30,6 +31,8 @@ type Epoch struct { epoch uint64 isFilecoinMode bool // true if the epoch is in Filecoin mode (i.e. Lassie mode) config *Config + // genesis: + genesis *GenesisContainer // contains indexes and block data for the epoch lassieFetcher *lassieWrapper localCarReader *carv2.Reader @@ -92,6 +95,10 @@ func (e *Epoch) Close() error { return errors.Join(multiErr...) } +func (e *Epoch) GetGenesis() *GenesisContainer { + return e.genesis +} + func NewEpochFromConfig(config *Config, c *cli.Context) (*Epoch, error) { if config == nil { return nil, fmt.Errorf("config must not be nil") @@ -105,6 +112,19 @@ func NewEpochFromConfig(config *Config, c *cli.Context) (*Epoch, error) { config: config, onClose: make([]func() error, 0), } + { + // if epoch is 0, then try loading the genesis from the config: + if *config.Epoch == 0 { + genesisConfig, ha, err := genesis.ReadGenesisFromFile(string(config.Genesis.URI)) + if err != nil { + return nil, fmt.Errorf("failed to read genesis: %w", err) + } + ep.genesis = &GenesisContainer{ + Hash: solana.HashFromBytes(ha[:]), + Config: genesisConfig, + } + } + } if isCarMode { // The CAR-mode requires a cid-to-offset index. diff --git a/genesis.go b/genesis.go new file mode 100644 index 00000000..ad91be58 --- /dev/null +++ b/genesis.go @@ -0,0 +1,12 @@ +package main + +import ( + "github.com/gagliardetto/solana-go" + "github.com/rpcpool/yellowstone-faithful/radiance/genesis" +) + +type GenesisContainer struct { + Hash solana.Hash + // The genesis config. + Config *genesis.Genesis +} diff --git a/multiepoch-getBlock.go b/multiepoch-getBlock.go index 14686c59..16d28411 100644 --- a/multiepoch-getBlock.go +++ b/multiepoch-getBlock.go @@ -249,26 +249,6 @@ func (multi *MultiEpoch) handleGetBlock(ctx context.Context, conn *requestContex } tim.time("get entries") - if slot == 0 { - // NOTE: we assume this is on mainnet. - blockZeroBlocktime := uint64(1584368940) - zeroBlockHeight := uint64(0) - blockZeroBlockHash := lastEntryHash.String() - var blockResp GetBlockResponse - blockResp.Transactions = make([]GetTransactionResponse, 0) - blockResp.BlockTime = &blockZeroBlocktime - blockResp.Blockhash = lastEntryHash.String() - blockResp.ParentSlot = uint64(0) - blockResp.Rewards = make([]any, 0) - blockResp.BlockHeight = &zeroBlockHeight - blockResp.PreviousBlockhash = &blockZeroBlockHash // NOTE: this is what solana RPC does. Should it be nil instead? Or should it be the genesis hash? - return nil, conn.ReplyRaw( - ctx, - req.ID, - blockResp, - ) - } - var allTransactions []GetTransactionResponse var rewards any hasRewards := !block.Rewards.(cidlink.Link).Cid.Equals(DummyCID) @@ -423,6 +403,21 @@ func (multi *MultiEpoch) handleGetBlock(ctx context.Context, conn *requestContex blockResp.ParentSlot = uint64(block.Meta.Parent_slot) blockResp.Rewards = rewards + if slot == 0 { + genesis := epochHandler.GetGenesis() + if genesis != nil { + blockZeroBlocktime := uint64(genesis.Config.CreationTime.Unix()) + blockResp.BlockTime = &blockZeroBlocktime + } + blockResp.ParentSlot = uint64(0) + + zeroBlockHeight := uint64(0) + blockResp.BlockHeight = &zeroBlockHeight + + blockZeroBlockHash := lastEntryHash.String() + blockResp.PreviousBlockhash = &blockZeroBlockHash // NOTE: this is what solana RPC does. Should it be nil instead? Or should it be the genesis hash? + } + { blockHeight, ok := block.GetBlockHeight() if ok { @@ -461,6 +456,15 @@ func (multi *MultiEpoch) handleGetBlock(ctx context.Context, conn *requestContex } tim.time("get parent block") + { + if len(blockResp.Transactions) == 0 { + blockResp.Transactions = make([]GetTransactionResponse, 0) + } + if blockResp.Rewards == nil || len(blockResp.Rewards.([]any)) == 0 { + blockResp.Rewards = make([]any, 0) + } + } + err = conn.Reply( ctx, req.ID,