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  }