github.com/MetalBlockchain/metalgo@v1.11.9/snow/engine/common/engine.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 "time" 9 10 "github.com/MetalBlockchain/metalgo/api/health" 11 "github.com/MetalBlockchain/metalgo/ids" 12 "github.com/MetalBlockchain/metalgo/snow" 13 "github.com/MetalBlockchain/metalgo/snow/validators" 14 "github.com/MetalBlockchain/metalgo/utils/set" 15 ) 16 17 // Engine describes the standard interface of a consensus engine. 18 // 19 // All nodeIDs are assumed to be authenticated. 20 // 21 // A consensus engine may recover after returning an error, but it isn't 22 // required. 23 type Engine interface { 24 Handler 25 26 // Return the context of the chain this engine is working on 27 Context() *snow.ConsensusContext 28 29 // Start engine operations from given request ID 30 Start(ctx context.Context, startReqID uint32) error 31 32 // Returns nil if the engine is healthy. 33 // Periodically called and reported through the health API 34 health.Checker 35 } 36 37 type Handler interface { 38 AllGetsServer 39 StateSummaryFrontierHandler 40 AcceptedStateSummaryHandler 41 AcceptedFrontierHandler 42 AcceptedHandler 43 AncestorsHandler 44 PutHandler 45 QueryHandler 46 ChitsHandler 47 AppHandler 48 InternalHandler 49 } 50 51 type AllGetsServer interface { 52 GetStateSummaryFrontierHandler 53 GetAcceptedStateSummaryHandler 54 GetAcceptedFrontierHandler 55 GetAcceptedHandler 56 GetAncestorsHandler 57 GetHandler 58 } 59 60 type GetStateSummaryFrontierHandler interface { 61 // Notify this engine of a request for a StateSummaryFrontier message with 62 // the same requestID and the engine's most recently accepted state summary. 63 // 64 // This function can be called by any node at any time. 65 GetStateSummaryFrontier( 66 ctx context.Context, 67 nodeID ids.NodeID, 68 requestID uint32, 69 ) error 70 } 71 72 type StateSummaryFrontierHandler interface { 73 // Notify this engine of the response to a previously sent 74 // GetStateSummaryFrontier message with the same requestID. 75 // 76 // It is not guaranteed that the summary bytes are from a valid state 77 // summary. 78 StateSummaryFrontier( 79 ctx context.Context, 80 nodeID ids.NodeID, 81 requestID uint32, 82 summary []byte, 83 ) error 84 85 // Notify this engine that a GetStateSummaryFrontier request it issued has 86 // failed. 87 // 88 // This function will be called if a GetStateSummaryFrontier message with 89 // nodeID and requestID was previously sent by this engine and will not 90 // receive a response. 91 GetStateSummaryFrontierFailed( 92 ctx context.Context, 93 nodeID ids.NodeID, 94 requestID uint32, 95 ) error 96 } 97 98 type GetAcceptedStateSummaryHandler interface { 99 // Notify this engine of a request for an AcceptedStateSummary message with 100 // the same requestID and the state summary IDs at the requested heights. 101 // If this node doesn't have access to a state summary ID at a requested 102 // height, that height should be ignored. 103 // 104 // This function can be called by any node at any time. 105 GetAcceptedStateSummary( 106 ctx context.Context, 107 nodeID ids.NodeID, 108 requestID uint32, 109 heights set.Set[uint64], 110 ) error 111 } 112 113 type AcceptedStateSummaryHandler interface { 114 // Notify this engine of the response to a previously sent 115 // GetAcceptedStateSummary message with the same requestID. 116 // 117 // It is not guaranteed that the summaryIDs have heights corresponding to 118 // the heights in the request. 119 AcceptedStateSummary( 120 ctx context.Context, 121 nodeID ids.NodeID, 122 requestID uint32, 123 summaryIDs set.Set[ids.ID], 124 ) error 125 126 // Notify this engine that a GetAcceptedStateSummary request it issued has 127 // failed. 128 // 129 // This function will be called if a GetAcceptedStateSummary message with 130 // nodeID and requestID was previously sent by this engine and will not 131 // receive a response. 132 GetAcceptedStateSummaryFailed( 133 ctx context.Context, 134 nodeID ids.NodeID, 135 requestID uint32, 136 ) error 137 } 138 139 type GetAcceptedFrontierHandler interface { 140 // Notify this engine of a request for an AcceptedFrontier message with the 141 // same requestID and the ID of the most recently accepted container. 142 // 143 // This function can be called by any node at any time. 144 GetAcceptedFrontier( 145 ctx context.Context, 146 nodeID ids.NodeID, 147 requestID uint32, 148 ) error 149 } 150 151 type AcceptedFrontierHandler interface { 152 // Notify this engine of the response to a previously sent 153 // GetAcceptedFrontier message with the same requestID. 154 AcceptedFrontier( 155 ctx context.Context, 156 nodeID ids.NodeID, 157 requestID uint32, 158 containerID ids.ID, 159 ) error 160 161 // Notify this engine that a GetAcceptedFrontier request it issued has 162 // failed. 163 // 164 // This function will be called if a GetAcceptedFrontier message with 165 // nodeID and requestID was previously sent by this engine and will not 166 // receive a response. 167 GetAcceptedFrontierFailed( 168 ctx context.Context, 169 nodeID ids.NodeID, 170 requestID uint32, 171 ) error 172 } 173 174 type GetAcceptedHandler interface { 175 // Notify this engine of a request for an Accepted message with the same 176 // requestID and the subset of containerIDs that this node has accepted. 177 // 178 // This function can be called by any node at any time. 179 GetAccepted( 180 ctx context.Context, 181 nodeID ids.NodeID, 182 requestID uint32, 183 containerIDs set.Set[ids.ID], 184 ) error 185 } 186 187 type AcceptedHandler interface { 188 // Notify this engine of the response to a previously sent GetAccepted 189 // message with the same requestID. 190 // 191 // It is not guaranteed that the containerIDs are a subset of the 192 // containerIDs provided in the request. 193 Accepted( 194 ctx context.Context, 195 nodeID ids.NodeID, 196 requestID uint32, 197 containerIDs set.Set[ids.ID], 198 ) error 199 200 // Notify this engine that a GetAccepted request it issued has failed. 201 // 202 // This function will be called if a GetAccepted message with nodeID and 203 // requestID was previously sent by this engine and will not receive a 204 // response. 205 GetAcceptedFailed( 206 ctx context.Context, 207 nodeID ids.NodeID, 208 requestID uint32, 209 ) error 210 } 211 212 type GetAncestorsHandler interface { 213 // Notify this engine of a request for an Ancestors message with the same 214 // requestID, containerID, and some of its ancestors on a best effort basis. 215 // 216 // This function can be called by any node at any time. 217 GetAncestors( 218 ctx context.Context, 219 nodeID ids.NodeID, 220 requestID uint32, 221 containerID ids.ID, 222 ) error 223 } 224 225 type AncestorsHandler interface { 226 // Notify this engine of the response to a previously sent GetAncestors 227 // message with the same requestID. 228 // 229 // It is expected, but not guaranteed, that the first element in containers 230 // should be the container referenced in the request and that the rest of 231 // the containers should be referenced by a prior container in the list. 232 Ancestors( 233 ctx context.Context, 234 nodeID ids.NodeID, 235 requestID uint32, 236 containers [][]byte, 237 ) error 238 239 // Notify this engine that a GetAncestors request it issued has failed. 240 // 241 // This function will be called if a GetAncestors message with nodeID and 242 // requestID was previously sent by this engine and will not receive a 243 // response. 244 GetAncestorsFailed( 245 ctx context.Context, 246 nodeID ids.NodeID, 247 requestID uint32, 248 ) error 249 } 250 251 type GetHandler interface { 252 // Notify this engine of a request for a Put message with the same requestID 253 // and the container whose ID is containerID. 254 // 255 // This function can be called by any node at any time. 256 Get( 257 ctx context.Context, 258 nodeID ids.NodeID, 259 requestID uint32, 260 containerID ids.ID, 261 ) error 262 } 263 264 type PutHandler interface { 265 // Notify this engine of either the response to a previously sent Get 266 // message with the same requestID or an unsolicited container if the 267 // requestID is MaxUint32. 268 // 269 // It is not guaranteed that container can be parsed or issued. 270 Put( 271 ctx context.Context, 272 nodeID ids.NodeID, 273 requestID uint32, 274 container []byte, 275 ) error 276 277 // Notify this engine that a Get request it issued has failed. 278 // 279 // This function will be called if a Get message with nodeID and requestID 280 // was previously sent by this engine and will not receive a response. 281 GetFailed( 282 ctx context.Context, 283 nodeID ids.NodeID, 284 requestID uint32, 285 ) error 286 } 287 288 type QueryHandler interface { 289 // Notify this engine of a request for a Chits message with the same 290 // requestID. 291 // 292 // If the provided containerID is not processing, the engine is expected to 293 // respond with the node's current preferences before attempting to issue 294 // it. 295 // 296 // This function can be called by any node at any time. 297 PullQuery( 298 ctx context.Context, 299 nodeID ids.NodeID, 300 requestID uint32, 301 containerID ids.ID, 302 requestedHeight uint64, 303 ) error 304 305 // Notify this engine of a request for a Chits message with the same 306 // requestID. 307 // 308 // If the provided container is not processing, the engine is expected to 309 // respond with the node's current preferences before attempting to issue 310 // it. 311 // 312 // It is not guaranteed that container can be parsed or issued. 313 // 314 // This function can be called by any node at any time. 315 PushQuery( 316 ctx context.Context, 317 nodeID ids.NodeID, 318 requestID uint32, 319 container []byte, 320 requestedHeight uint64, 321 ) error 322 } 323 324 type ChitsHandler interface { 325 // Notify this engine of the response to a previously sent PullQuery or 326 // PushQuery message with the same requestID. 327 // 328 // It is expected, but not guaranteed, that preferredID transitively 329 // references preferredIDAtHeight and acceptedID. 330 Chits( 331 ctx context.Context, 332 nodeID ids.NodeID, 333 requestID uint32, 334 preferredID ids.ID, 335 preferredIDAtHeight ids.ID, 336 acceptedID ids.ID, 337 ) error 338 339 // Notify this engine that a Query request it issued has failed. 340 // 341 // This function will be called if a PullQuery or PushQuery message with 342 // nodeID and requestID was previously sent by this engine and will not 343 // receive a response. 344 QueryFailed( 345 ctx context.Context, 346 nodeID ids.NodeID, 347 requestID uint32, 348 ) error 349 } 350 351 type NetworkAppHandler interface { 352 AppRequestHandler 353 AppResponseHandler 354 AppGossipHandler 355 } 356 357 type AppRequestHandler interface { 358 // Notify this engine of a request for an AppResponse with the same 359 // requestID. 360 // 361 // The meaning of request, and what should be sent in response to it, is 362 // application (VM) specific. 363 // 364 // It is not guaranteed that request is well-formed or valid. 365 // 366 // This function can be called by any node at any time. 367 AppRequest( 368 ctx context.Context, 369 nodeID ids.NodeID, 370 requestID uint32, 371 deadline time.Time, 372 request []byte, 373 ) error 374 } 375 376 type AppResponseHandler interface { 377 // Notify this engine of the response to a previously sent AppRequest with 378 // the same requestID. 379 // 380 // The meaning of response is application (VM) specifc. 381 // 382 // It is not guaranteed that response is well-formed or valid. 383 AppResponse( 384 ctx context.Context, 385 nodeID ids.NodeID, 386 requestID uint32, 387 response []byte, 388 ) error 389 390 // Notify this engine that an AppRequest it issued has failed. 391 // 392 // This function will be called if an AppRequest message with nodeID and 393 // requestID was previously sent by this engine and will not receive a 394 // response. 395 AppRequestFailed( 396 ctx context.Context, 397 nodeID ids.NodeID, 398 requestID uint32, 399 appErr *AppError, 400 ) error 401 } 402 403 type AppGossipHandler interface { 404 // Notify this engine of a gossip message from nodeID. 405 // 406 // The meaning of msg is application (VM) specific, and the VM defines how 407 // to react to this message. 408 // 409 // This message is not expected in response to any event, and it does not 410 // need to be responded to. 411 AppGossip( 412 ctx context.Context, 413 nodeID ids.NodeID, 414 msg []byte, 415 ) error 416 } 417 418 type CrossChainAppHandler interface { 419 CrossChainAppRequestHandler 420 CrossChainAppResponseHandler 421 } 422 423 type CrossChainAppRequestHandler interface { 424 // Notify this engine of a request for a CrossChainAppResponse with the same 425 // requestID. 426 // 427 // The meaning of request, and what should be sent in response to it, is 428 // application (VM) specific. 429 // 430 // Guarantees surrounding the request are specific to the implementation of 431 // the requesting VM. For example, the request may or may not be guaranteed 432 // to be well-formed/valid depending on the implementation of the requesting 433 // VM. 434 CrossChainAppRequest( 435 ctx context.Context, 436 chainID ids.ID, 437 requestID uint32, 438 deadline time.Time, 439 request []byte, 440 ) error 441 } 442 443 type CrossChainAppResponseHandler interface { 444 // Notify this engine of the response to a previously sent 445 // CrossChainAppRequest with the same requestID. 446 // 447 // The meaning of response is application (VM) specifc. 448 // 449 // Guarantees surrounding the response are specific to the implementation of 450 // the responding VM. For example, the response may or may not be guaranteed 451 // to be well-formed/valid depending on the implementation of the requesting 452 // VM. 453 CrossChainAppResponse( 454 ctx context.Context, 455 chainID ids.ID, 456 requestID uint32, 457 response []byte, 458 ) error 459 460 // Notify this engine that a CrossChainAppRequest it issued has failed. 461 // 462 // This function will be called if a CrossChainAppRequest message with 463 // nodeID and requestID was previously sent by this engine and will not 464 // receive a response. 465 CrossChainAppRequestFailed( 466 ctx context.Context, 467 chainID ids.ID, 468 requestID uint32, 469 appErr *AppError, 470 ) error 471 } 472 473 type AppHandler interface { 474 NetworkAppHandler 475 CrossChainAppHandler 476 } 477 478 type InternalHandler interface { 479 // Notify this engine of peer changes. 480 validators.Connector 481 482 // Notify this engine that a registered timeout has fired. 483 Timeout(context.Context) error 484 485 // Gossip to the network a container on the accepted frontier 486 Gossip(context.Context) error 487 488 // Halt this engine. 489 // 490 // This function will be called before the environment starts exiting. This 491 // function is special, in that it does not expect the chain's context lock 492 // to be held before calling this function. This function also does not 493 // require the engine to have been started. 494 Halt(context.Context) 495 496 // Shutdown this engine. 497 // 498 // This function will be called when the environment is exiting. 499 Shutdown(context.Context) error 500 501 // Notify this engine of a message from the virtual machine. 502 Notify(context.Context, Message) error 503 }