github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/protocol/handler.go (about) 1 package protocol 2 3 import ( 4 "context" 5 6 "github.com/onflow/flow/protobuf/go/flow/access" 7 "github.com/onflow/flow/protobuf/go/flow/entities" 8 9 "github.com/onflow/flow-go/consensus/hotstuff" 10 "github.com/onflow/flow-go/consensus/hotstuff/signature" 11 "github.com/onflow/flow-go/engine/common/rpc/convert" 12 "github.com/onflow/flow-go/model/flow" 13 ) 14 15 type Handler struct { 16 api API 17 signerIndicesDecoder hotstuff.BlockSignerDecoder 18 } 19 20 // HandlerOption is used to hand over optional constructor parameters 21 type HandlerOption func(*Handler) 22 23 func NewHandler(api API, options ...HandlerOption) *Handler { 24 h := &Handler{ 25 api: api, 26 signerIndicesDecoder: &signature.NoopBlockSignerDecoder{}, 27 } 28 for _, opt := range options { 29 opt(h) 30 } 31 return h 32 } 33 34 func WithBlockSignerDecoder(signerIndicesDecoder hotstuff.BlockSignerDecoder) func(*Handler) { 35 return func(handler *Handler) { 36 handler.signerIndicesDecoder = signerIndicesDecoder 37 } 38 } 39 40 func (h *Handler) GetNetworkParameters( 41 ctx context.Context, 42 _ *access.GetNetworkParametersRequest, 43 ) (*access.GetNetworkParametersResponse, error) { 44 params := h.api.GetNetworkParameters(ctx) 45 46 return &access.GetNetworkParametersResponse{ 47 ChainId: string(params.ChainID), 48 }, nil 49 } 50 51 func (h *Handler) GetNodeVersionInfo( 52 ctx context.Context, 53 request *access.GetNodeVersionInfoRequest, 54 ) (*access.GetNodeVersionInfoResponse, error) { 55 nodeVersionInfo, err := h.api.GetNodeVersionInfo(ctx) 56 if err != nil { 57 return nil, err 58 } 59 60 return &access.GetNodeVersionInfoResponse{ 61 Info: &entities.NodeVersionInfo{ 62 Semver: nodeVersionInfo.Semver, 63 Commit: nodeVersionInfo.Commit, 64 SporkId: nodeVersionInfo.SporkId[:], 65 ProtocolVersion: nodeVersionInfo.ProtocolVersion, 66 }, 67 }, nil 68 } 69 70 // GetLatestProtocolStateSnapshot returns the latest serializable Snapshot 71 func (h *Handler) GetLatestProtocolStateSnapshot(ctx context.Context, req *access.GetLatestProtocolStateSnapshotRequest) (*access.ProtocolStateSnapshotResponse, error) { 72 snapshot, err := h.api.GetLatestProtocolStateSnapshot(ctx) 73 if err != nil { 74 return nil, err 75 } 76 77 return &access.ProtocolStateSnapshotResponse{ 78 SerializedSnapshot: snapshot, 79 }, nil 80 } 81 82 // GetProtocolStateSnapshotByBlockID returns serializable Snapshot by blockID 83 func (h *Handler) GetProtocolStateSnapshotByBlockID(ctx context.Context, req *access.GetProtocolStateSnapshotByBlockIDRequest) (*access.ProtocolStateSnapshotResponse, error) { 84 blockID := convert.MessageToIdentifier(req.GetBlockId()) 85 snapshot, err := h.api.GetProtocolStateSnapshotByBlockID(ctx, blockID) 86 if err != nil { 87 return nil, err 88 } 89 90 return &access.ProtocolStateSnapshotResponse{ 91 SerializedSnapshot: snapshot, 92 }, nil 93 } 94 95 // GetProtocolStateSnapshotByHeight returns serializable Snapshot by block height 96 func (h *Handler) GetProtocolStateSnapshotByHeight(ctx context.Context, req *access.GetProtocolStateSnapshotByHeightRequest) (*access.ProtocolStateSnapshotResponse, error) { 97 snapshot, err := h.api.GetProtocolStateSnapshotByHeight(ctx, req.GetBlockHeight()) 98 if err != nil { 99 return nil, err 100 } 101 102 return &access.ProtocolStateSnapshotResponse{ 103 SerializedSnapshot: snapshot, 104 }, nil 105 } 106 107 // GetLatestBlockHeader gets the latest sealed block header. 108 func (h *Handler) GetLatestBlockHeader( 109 ctx context.Context, 110 req *access.GetLatestBlockHeaderRequest, 111 ) (*access.BlockHeaderResponse, error) { 112 header, err := h.api.GetLatestBlockHeader(ctx, req.GetIsSealed()) 113 if err != nil { 114 return nil, err 115 } 116 return h.blockHeaderResponse(header) 117 } 118 119 // GetBlockHeaderByHeight gets a block header by height. 120 func (h *Handler) GetBlockHeaderByHeight( 121 ctx context.Context, 122 req *access.GetBlockHeaderByHeightRequest, 123 ) (*access.BlockHeaderResponse, error) { 124 header, err := h.api.GetBlockHeaderByHeight(ctx, req.GetHeight()) 125 if err != nil { 126 return nil, err 127 } 128 return h.blockHeaderResponse(header) 129 } 130 131 // GetBlockHeaderByID gets a block header by ID. 132 func (h *Handler) GetBlockHeaderByID( 133 ctx context.Context, 134 req *access.GetBlockHeaderByIDRequest, 135 ) (*access.BlockHeaderResponse, error) { 136 id, err := convert.BlockID(req.GetId()) 137 if err != nil { 138 return nil, err 139 } 140 header, err := h.api.GetBlockHeaderByID(ctx, id) 141 if err != nil { 142 return nil, err 143 } 144 return h.blockHeaderResponse(header) 145 } 146 147 // GetLatestBlock gets the latest sealed block. 148 func (h *Handler) GetLatestBlock( 149 ctx context.Context, 150 req *access.GetLatestBlockRequest, 151 ) (*access.BlockResponse, error) { 152 block, err := h.api.GetLatestBlock(ctx, req.GetIsSealed()) 153 if err != nil { 154 return nil, err 155 } 156 return h.blockResponse(block, req.GetFullBlockResponse()) 157 } 158 159 // GetBlockByHeight gets a block by height. 160 func (h *Handler) GetBlockByHeight( 161 ctx context.Context, 162 req *access.GetBlockByHeightRequest, 163 ) (*access.BlockResponse, error) { 164 block, err := h.api.GetBlockByHeight(ctx, req.GetHeight()) 165 if err != nil { 166 return nil, err 167 } 168 return h.blockResponse(block, req.GetFullBlockResponse()) 169 } 170 171 // GetBlockByID gets a block by ID. 172 func (h *Handler) GetBlockByID( 173 ctx context.Context, 174 req *access.GetBlockByIDRequest, 175 ) (*access.BlockResponse, error) { 176 id, err := convert.BlockID(req.GetId()) 177 if err != nil { 178 return nil, err 179 } 180 block, err := h.api.GetBlockByID(ctx, id) 181 if err != nil { 182 return nil, err 183 } 184 return h.blockResponse(block, req.GetFullBlockResponse()) 185 } 186 187 func (h *Handler) blockResponse(block *flow.Block, fullResponse bool) (*access.BlockResponse, error) { 188 signerIDs, err := h.signerIndicesDecoder.DecodeSignerIDs(block.Header) 189 if err != nil { 190 return nil, err // the block was retrieved from local storage - so no errors are expected 191 } 192 193 var msg *entities.Block 194 if fullResponse { 195 msg, err = convert.BlockToMessage(block, signerIDs) 196 if err != nil { 197 return nil, err 198 } 199 } else { 200 msg = convert.BlockToMessageLight(block) 201 } 202 return &access.BlockResponse{ 203 Block: msg, 204 }, nil 205 } 206 207 func (h *Handler) blockHeaderResponse(header *flow.Header) (*access.BlockHeaderResponse, error) { 208 signerIDs, err := h.signerIndicesDecoder.DecodeSignerIDs(header) 209 if err != nil { 210 return nil, err // the block was retrieved from local storage - so no errors are expected 211 } 212 213 msg, err := convert.BlockHeaderToMessage(header, signerIDs) 214 if err != nil { 215 return nil, err 216 } 217 218 return &access.BlockHeaderResponse{ 219 Block: msg, 220 }, nil 221 }