github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/state/cluster/badger/state_root.go (about) 1 package badger 2 3 import ( 4 "fmt" 5 6 "github.com/onflow/flow-go/model/cluster" 7 "github.com/onflow/flow-go/model/flow" 8 ) 9 10 // StateRoot is the root information required to bootstrap the cluster state. 11 type StateRoot struct { 12 block *cluster.Block // root block for the cluster chain 13 qc *flow.QuorumCertificate // root QC for the cluster chain 14 epoch uint64 // operating epoch for the cluster chain 15 } 16 17 func NewStateRoot(genesis *cluster.Block, qc *flow.QuorumCertificate, epoch uint64) (*StateRoot, error) { 18 err := validateClusterGenesis(genesis) 19 if err != nil { 20 return nil, fmt.Errorf("inconsistent state root: %w", err) 21 } 22 return &StateRoot{ 23 block: genesis, 24 qc: qc, 25 epoch: epoch, 26 }, nil 27 } 28 29 func validateClusterGenesis(genesis *cluster.Block) error { 30 // check height of genesis block 31 if genesis.Header.Height != 0 { 32 return fmt.Errorf("height of genesis cluster block should be 0 (got %d)", genesis.Header.Height) 33 } 34 // check header parent ID 35 if genesis.Header.ParentID != flow.ZeroID { 36 return fmt.Errorf("genesis parent ID must be zero hash (got %x)", genesis.Header.ParentID) 37 } 38 39 // check payload integrity 40 if genesis.Header.PayloadHash != genesis.Payload.Hash() { 41 return fmt.Errorf("computed payload hash does not match header") 42 } 43 44 // check payload 45 collSize := len(genesis.Payload.Collection.Transactions) 46 if collSize != 0 { 47 return fmt.Errorf("genesis collection should contain no transactions (got %d)", collSize) 48 } 49 50 return nil 51 } 52 53 func (s StateRoot) ClusterID() flow.ChainID { 54 return s.block.Header.ChainID 55 } 56 57 func (s StateRoot) Block() *cluster.Block { 58 return s.block 59 } 60 61 func (s StateRoot) QC() *flow.QuorumCertificate { 62 return s.qc 63 } 64 65 func (s StateRoot) EpochCounter() uint64 { 66 return s.epoch 67 }