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  }