github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/module/validation/common.go (about) 1 package validation 2 3 import ( 4 "fmt" 5 6 "github.com/onflow/flow-go/engine" 7 "github.com/onflow/flow-go/model/flow" 8 "github.com/onflow/flow-go/model/flow/filter" 9 "github.com/onflow/flow-go/state/protocol" 10 ) 11 12 // identityForNode ensures that `nodeID` is an authorized member of the network 13 // at the given block and returns the corresponding node's full identity. 14 // Error returns: 15 // - sentinel engine.InvalidInputError is nodeID is NOT an authorized member of the network 16 // - generic error indicating a fatal internal problem 17 func identityForNode(state protocol.State, blockID flow.Identifier, nodeID flow.Identifier) (*flow.Identity, error) { 18 // get the identity of the origin node 19 identity, err := state.AtBlockID(blockID).Identity(nodeID) 20 if err != nil { 21 if protocol.IsIdentityNotFound(err) { 22 return nil, engine.NewInvalidInputErrorf("unknown node identity: %w", err) 23 } 24 // unexpected exception 25 return nil, fmt.Errorf("failed to retrieve node identity: %w", err) 26 } 27 28 return identity, nil 29 } 30 31 // ensureNodeHasWeightAndRole checks whether, at the given block, `nodeID` 32 // - has _positive_ weight 33 // - and has the expected role 34 // - is an active participant of the current epoch and not ejected (i.e. has `EpochParticipationStatusActive`) 35 // 36 // Returns the following errors: 37 // - sentinel engine.InvalidInputError if any of the above-listed conditions are violated. 38 // 39 // Note: the method receives the identity as proof of its existence. 40 // Therefore, we consider the case where the respective identity is unknown to the 41 // protocol state as a symptom of a fatal implementation bug. 42 func ensureNodeHasWeightAndRole(identity *flow.Identity, expectedRole flow.Role) error { 43 // check that the role is expected 44 if identity.Role != expectedRole { 45 return engine.NewInvalidInputErrorf("expected node %x to have role %s but got %s", identity.NodeID, expectedRole, identity.Role) 46 } 47 // check if the identity has non-zero weight 48 if identity.InitialWeight == 0 { 49 return engine.NewInvalidInputErrorf("node %x has zero weight", identity.NodeID) 50 } 51 // check if the identity is a valid epoch participant(is active in the current epoch + not ejected) 52 if !filter.IsValidCurrentEpochParticipant(identity) { 53 return engine.NewInvalidInputErrorf("node (%x) is not an active participant, instead has status: %s", identity.NodeID, 54 identity.EpochParticipationStatus.String()) 55 } 56 57 return nil 58 }