github.com/MetalBlockchain/metalgo@v1.11.9/snow/engine/common/sender.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package common 5 6 import ( 7 "context" 8 9 "github.com/MetalBlockchain/metalgo/ids" 10 "github.com/MetalBlockchain/metalgo/utils/set" 11 ) 12 13 // SendConfig is used to specify who to send messages to over the p2p network. 14 type SendConfig struct { 15 NodeIDs set.Set[ids.NodeID] 16 Validators int 17 NonValidators int 18 Peers int 19 } 20 21 // Sender defines how a consensus engine sends messages and requests to other 22 // validators. 23 // 24 // Messages can be categorized as either: requests, responses, or gossip. Gossip 25 // messages do not include requestIDs, because no response is expected from the 26 // peer. However, both requests and responses include requestIDs. 27 // 28 // It is expected that each [nodeID + requestID + expected response type] that 29 // is outstanding at any given time is unique. 30 // 31 // As an example, it is valid to send `Get(nodeA, request0)` and 32 // `PullQuery(nodeA, request0)` because they have different expected response 33 // types, `Put` and `Chits`. 34 // 35 // Additionally, after having sent `Get(nodeA, request0)` and receiving either 36 // `Put(nodeA, request0)` or `GetFailed(nodeA, request0)`, it is valid to resend 37 // `Get(nodeA, request0)`. Because the initial `Get` request is no longer 38 // outstanding. 39 // 40 // This means that requestIDs can be reused. In practice, requests always have a 41 // reasonable maximum timeout, so it is generally safe to assume that by the 42 // time the requestID space has been exhausted, the beginning of the requestID 43 // space is free of conflicts. 44 type Sender interface { 45 StateSummarySender 46 AcceptedStateSummarySender 47 FrontierSender 48 AcceptedSender 49 FetchSender 50 QuerySender 51 AppSender 52 } 53 54 // StateSummarySender defines how a consensus engine sends state sync messages to 55 // other nodes. 56 type StateSummarySender interface { 57 // SendGetStateSummaryFrontier requests that every node in [nodeIDs] sends a 58 // StateSummaryFrontier message. 59 SendGetStateSummaryFrontier(ctx context.Context, nodeIDs set.Set[ids.NodeID], requestID uint32) 60 61 // SendStateSummaryFrontier responds to a StateSummaryFrontier message with this 62 // engine's current state summary frontier. 63 SendStateSummaryFrontier(ctx context.Context, nodeID ids.NodeID, requestID uint32, summary []byte) 64 } 65 66 type AcceptedStateSummarySender interface { 67 // SendGetAcceptedStateSummary requests that every node in [nodeIDs] sends an 68 // AcceptedStateSummary message with all the state summary IDs referenced by [heights] 69 // that the node thinks are accepted. 70 SendGetAcceptedStateSummary(ctx context.Context, nodeIDs set.Set[ids.NodeID], requestID uint32, heights []uint64) 71 72 // SendAcceptedStateSummary responds to a AcceptedStateSummary message with a 73 // set of summary ids that are accepted. 74 SendAcceptedStateSummary(ctx context.Context, nodeID ids.NodeID, requestID uint32, summaryIDs []ids.ID) 75 } 76 77 // FrontierSender defines how a consensus engine sends frontier messages to 78 // other nodes. 79 type FrontierSender interface { 80 // SendGetAcceptedFrontier requests that every node in [nodeIDs] sends an 81 // AcceptedFrontier message. 82 SendGetAcceptedFrontier(ctx context.Context, nodeIDs set.Set[ids.NodeID], requestID uint32) 83 84 // SendAcceptedFrontier responds to a AcceptedFrontier message with this 85 // engine's current accepted frontier. 86 SendAcceptedFrontier( 87 ctx context.Context, 88 nodeID ids.NodeID, 89 requestID uint32, 90 containerID ids.ID, 91 ) 92 } 93 94 // AcceptedSender defines how a consensus engine sends messages pertaining to 95 // accepted containers 96 type AcceptedSender interface { 97 // SendGetAccepted requests that every node in [nodeIDs] sends an Accepted 98 // message with all the IDs in [containerIDs] that the node thinks are 99 // accepted. 100 SendGetAccepted( 101 ctx context.Context, 102 nodeIDs set.Set[ids.NodeID], 103 requestID uint32, 104 containerIDs []ids.ID, 105 ) 106 107 // SendAccepted responds to a GetAccepted message with a set of IDs of 108 // containers that are accepted. 109 SendAccepted(ctx context.Context, nodeID ids.NodeID, requestID uint32, containerIDs []ids.ID) 110 } 111 112 // FetchSender defines how a consensus engine sends retrieval messages to other 113 // nodes. 114 type FetchSender interface { 115 // Request that the specified node send the specified container to this 116 // node. 117 SendGet(ctx context.Context, nodeID ids.NodeID, requestID uint32, containerID ids.ID) 118 119 // SendGetAncestors requests that node [nodeID] send container [containerID] 120 // and its ancestors. 121 SendGetAncestors(ctx context.Context, nodeID ids.NodeID, requestID uint32, containerID ids.ID) 122 123 // Tell the specified node about [container]. 124 SendPut(ctx context.Context, nodeID ids.NodeID, requestID uint32, container []byte) 125 126 // Give the specified node several containers at once. Should be in response 127 // to a GetAncestors message with request ID [requestID] from the node. 128 SendAncestors(ctx context.Context, nodeID ids.NodeID, requestID uint32, containers [][]byte) 129 } 130 131 // QuerySender defines how a consensus engine sends query messages to other 132 // nodes. 133 type QuerySender interface { 134 // Request from the specified nodes their preferred frontier, given the 135 // existence of the specified container. 136 // This is the same as PullQuery, except that this message includes the body 137 // of the container rather than its ID. 138 SendPushQuery( 139 ctx context.Context, 140 nodeIDs set.Set[ids.NodeID], 141 requestID uint32, 142 container []byte, 143 requestedHeight uint64, 144 ) 145 146 // Request from the specified nodes their preferred frontier, given the 147 // existence of the specified container. 148 SendPullQuery( 149 ctx context.Context, 150 nodeIDs set.Set[ids.NodeID], 151 requestID uint32, 152 containerID ids.ID, 153 requestedHeight uint64, 154 ) 155 156 // Send chits to the specified node 157 SendChits( 158 ctx context.Context, 159 nodeID ids.NodeID, 160 requestID uint32, 161 preferredID ids.ID, 162 preferredIDAtHeight ids.ID, 163 acceptedID ids.ID, 164 ) 165 } 166 167 // NetworkAppSender sends VM-level messages to nodes in the network. 168 type NetworkAppSender interface { 169 // Send an application-level request. 170 // 171 // The VM corresponding to this AppSender may receive either: 172 // * An AppResponse from nodeID with ID [requestID] 173 // * An AppRequestFailed from nodeID with ID [requestID] 174 // 175 // A nil return value guarantees that the VM corresponding to this AppSender 176 // will receive exactly one of the above messages. 177 // 178 // A non-nil return value guarantees that the VM corresponding to this 179 // AppSender will receive at most one of the above messages. 180 SendAppRequest(ctx context.Context, nodeIDs set.Set[ids.NodeID], requestID uint32, appRequestBytes []byte) error 181 // Send an application-level response to a request. 182 // This response must be in response to an AppRequest that the VM corresponding 183 // to this AppSender received from [nodeID] with ID [requestID]. 184 SendAppResponse(ctx context.Context, nodeID ids.NodeID, requestID uint32, appResponseBytes []byte) error 185 // SendAppError sends an application-level error to an AppRequest 186 SendAppError(ctx context.Context, nodeID ids.NodeID, requestID uint32, errorCode int32, errorMessage string) error 187 // Gossip an application-level message. 188 SendAppGossip( 189 ctx context.Context, 190 config SendConfig, 191 appGossipBytes []byte, 192 ) error 193 } 194 195 // CrossChainAppSender sends local VM-level messages to another VM. 196 type CrossChainAppSender interface { 197 // SendCrossChainAppRequest sends an application-level request to a 198 // specific chain. 199 // 200 // The VM corresponding to this CrossChainAppSender may receive either: 201 // * A CrossChainAppResponse from [chainID] with ID [requestID] 202 // * A CrossChainAppRequestFailed from [chainID] with ID [requestID] 203 // 204 // A nil return value guarantees that the VM corresponding to this 205 // CrossChainAppSender will eventually receive exactly one of the above 206 // messages. 207 // 208 // A non-nil return value guarantees that the VM corresponding to this 209 // CrossChainAppSender will receive at most one of the above messages. 210 SendCrossChainAppRequest(ctx context.Context, chainID ids.ID, requestID uint32, appRequestBytes []byte) error 211 // SendCrossChainAppResponse sends an application-level response to a 212 // specific chain 213 // 214 // This response must be in response to a CrossChainAppRequest that the VM 215 // corresponding to this CrossChainAppSender received from [chainID] with ID 216 // [requestID]. 217 SendCrossChainAppResponse(ctx context.Context, chainID ids.ID, requestID uint32, appResponseBytes []byte) error 218 // SendCrossChainAppError sends an application-level error to a CrossChainAppRequest 219 SendCrossChainAppError(ctx context.Context, chainID ids.ID, requestID uint32, errorCode int32, errorMessage string) error 220 } 221 222 // AppSender sends application (VM) level messages. 223 // See also common.AppHandler. 224 type AppSender interface { 225 NetworkAppSender 226 CrossChainAppSender 227 }