github.com/MetalBlockchain/metalgo@v1.11.9/message/ops.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package message
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  
    10  	"github.com/MetalBlockchain/metalgo/proto/pb/p2p"
    11  	"github.com/MetalBlockchain/metalgo/utils/set"
    12  )
    13  
    14  // Op is an opcode
    15  type Op byte
    16  
    17  // Types of messages that may be sent between nodes
    18  // Note: If you add a new parseable Op below, you must also add it to ops
    19  // (declared below)
    20  const (
    21  	// Handshake:
    22  	PingOp Op = iota
    23  	PongOp
    24  	HandshakeOp
    25  	GetPeerListOp
    26  	PeerListOp
    27  	// State sync:
    28  	GetStateSummaryFrontierOp
    29  	GetStateSummaryFrontierFailedOp
    30  	StateSummaryFrontierOp
    31  	GetAcceptedStateSummaryOp
    32  	GetAcceptedStateSummaryFailedOp
    33  	AcceptedStateSummaryOp
    34  	// Bootstrapping:
    35  	GetAcceptedFrontierOp
    36  	GetAcceptedFrontierFailedOp
    37  	AcceptedFrontierOp
    38  	GetAcceptedOp
    39  	GetAcceptedFailedOp
    40  	AcceptedOp
    41  	GetAncestorsOp
    42  	GetAncestorsFailedOp
    43  	AncestorsOp
    44  	// Consensus:
    45  	GetOp
    46  	GetFailedOp
    47  	PutOp
    48  	PushQueryOp
    49  	PullQueryOp
    50  	QueryFailedOp
    51  	ChitsOp
    52  	// Application:
    53  	AppRequestOp
    54  	AppErrorOp
    55  	AppResponseOp
    56  	AppGossipOp
    57  	// Cross chain:
    58  	CrossChainAppRequestOp
    59  	CrossChainAppErrorOp
    60  	CrossChainAppResponseOp
    61  	// Internal:
    62  	ConnectedOp
    63  	ConnectedSubnetOp
    64  	DisconnectedOp
    65  	NotifyOp
    66  	GossipRequestOp
    67  	TimeoutOp
    68  )
    69  
    70  var (
    71  	HandshakeOps = []Op{
    72  		PingOp,
    73  		PongOp,
    74  		HandshakeOp,
    75  		GetPeerListOp,
    76  		PeerListOp,
    77  	}
    78  
    79  	// List of all consensus request message types
    80  	ConsensusRequestOps = []Op{
    81  		GetStateSummaryFrontierOp,
    82  		GetAcceptedStateSummaryOp,
    83  		GetAcceptedFrontierOp,
    84  		GetAcceptedOp,
    85  		GetAncestorsOp,
    86  		GetOp,
    87  		PushQueryOp,
    88  		PullQueryOp,
    89  		AppRequestOp,
    90  	}
    91  	ConsensusResponseOps = []Op{
    92  		StateSummaryFrontierOp,
    93  		AcceptedStateSummaryOp,
    94  		AcceptedFrontierOp,
    95  		AcceptedOp,
    96  		AncestorsOp,
    97  		PutOp,
    98  		ChitsOp,
    99  		AppResponseOp,
   100  		AppErrorOp,
   101  	}
   102  	// AppGossip is the only message that is sent unrequested without the
   103  	// expectation of a response
   104  	ConsensusExternalOps = append(
   105  		ConsensusRequestOps,
   106  		append(
   107  			ConsensusResponseOps,
   108  			AppGossipOp,
   109  		)...,
   110  	)
   111  	ConsensusInternalOps = []Op{
   112  		GetStateSummaryFrontierFailedOp,
   113  		GetAcceptedStateSummaryFailedOp,
   114  		GetAcceptedFrontierFailedOp,
   115  		GetAcceptedFailedOp,
   116  		GetAncestorsFailedOp,
   117  		GetFailedOp,
   118  		QueryFailedOp,
   119  		CrossChainAppRequestOp,
   120  		CrossChainAppErrorOp,
   121  		CrossChainAppResponseOp,
   122  		ConnectedOp,
   123  		ConnectedSubnetOp,
   124  		DisconnectedOp,
   125  		NotifyOp,
   126  		GossipRequestOp,
   127  		TimeoutOp,
   128  	}
   129  	ConsensusOps = append(ConsensusExternalOps, ConsensusInternalOps...)
   130  
   131  	ExternalOps = append(ConsensusExternalOps, HandshakeOps...)
   132  
   133  	SynchronousOps = []Op{
   134  		// State sync
   135  		GetStateSummaryFrontierOp,
   136  		GetStateSummaryFrontierFailedOp,
   137  		StateSummaryFrontierOp,
   138  		GetAcceptedStateSummaryOp,
   139  		GetAcceptedStateSummaryFailedOp,
   140  		AcceptedStateSummaryOp,
   141  		// Bootstrapping
   142  		GetAcceptedFrontierOp,
   143  		GetAcceptedFrontierFailedOp,
   144  		AcceptedFrontierOp,
   145  		GetAcceptedOp,
   146  		GetAcceptedFailedOp,
   147  		AcceptedOp,
   148  		GetAncestorsOp,
   149  		GetAncestorsFailedOp,
   150  		AncestorsOp,
   151  		// Consensus
   152  		GetOp,
   153  		GetFailedOp,
   154  		PutOp,
   155  		PushQueryOp,
   156  		PullQueryOp,
   157  		QueryFailedOp,
   158  		ChitsOp,
   159  		// Internal
   160  		ConnectedOp,
   161  		ConnectedSubnetOp,
   162  		DisconnectedOp,
   163  	}
   164  
   165  	AsynchronousOps = []Op{
   166  		// Application
   167  		AppRequestOp,
   168  		AppErrorOp,
   169  		AppGossipOp,
   170  		AppResponseOp,
   171  		// Cross chain
   172  		CrossChainAppRequestOp,
   173  		CrossChainAppErrorOp,
   174  		CrossChainAppResponseOp,
   175  	}
   176  
   177  	FailedToResponseOps = map[Op]Op{
   178  		GetStateSummaryFrontierFailedOp: StateSummaryFrontierOp,
   179  		GetAcceptedStateSummaryFailedOp: AcceptedStateSummaryOp,
   180  		GetAcceptedFrontierFailedOp:     AcceptedFrontierOp,
   181  		GetAcceptedFailedOp:             AcceptedOp,
   182  		GetAncestorsFailedOp:            AncestorsOp,
   183  		GetFailedOp:                     PutOp,
   184  		QueryFailedOp:                   ChitsOp,
   185  		AppErrorOp:                      AppResponseOp,
   186  		CrossChainAppErrorOp:            CrossChainAppResponseOp,
   187  	}
   188  	UnrequestedOps = set.Of(
   189  		GetAcceptedFrontierOp,
   190  		GetAcceptedOp,
   191  		GetAncestorsOp,
   192  		GetOp,
   193  		PushQueryOp,
   194  		PullQueryOp,
   195  		AppRequestOp,
   196  		AppGossipOp,
   197  		CrossChainAppRequestOp,
   198  		GetStateSummaryFrontierOp,
   199  		GetAcceptedStateSummaryOp,
   200  	)
   201  
   202  	errUnknownMessageType = errors.New("unknown message type")
   203  )
   204  
   205  func (op Op) String() string {
   206  	switch op {
   207  	// Handshake
   208  	case PingOp:
   209  		return "ping"
   210  	case PongOp:
   211  		return "pong"
   212  	case HandshakeOp:
   213  		return "handshake"
   214  	case GetPeerListOp:
   215  		return "get_peerlist"
   216  	case PeerListOp:
   217  		return "peerlist"
   218  	// State sync
   219  	case GetStateSummaryFrontierOp:
   220  		return "get_state_summary_frontier"
   221  	case GetStateSummaryFrontierFailedOp:
   222  		return "get_state_summary_frontier_failed"
   223  	case StateSummaryFrontierOp:
   224  		return "state_summary_frontier"
   225  	case GetAcceptedStateSummaryOp:
   226  		return "get_accepted_state_summary"
   227  	case GetAcceptedStateSummaryFailedOp:
   228  		return "get_accepted_state_summary_failed"
   229  	case AcceptedStateSummaryOp:
   230  		return "accepted_state_summary"
   231  	// Bootstrapping
   232  	case GetAcceptedFrontierOp:
   233  		return "get_accepted_frontier"
   234  	case GetAcceptedFrontierFailedOp:
   235  		return "get_accepted_frontier_failed"
   236  	case AcceptedFrontierOp:
   237  		return "accepted_frontier"
   238  	case GetAcceptedOp:
   239  		return "get_accepted"
   240  	case GetAcceptedFailedOp:
   241  		return "get_accepted_failed"
   242  	case AcceptedOp:
   243  		return "accepted"
   244  	case GetAncestorsOp:
   245  		return "get_ancestors"
   246  	case GetAncestorsFailedOp:
   247  		return "get_ancestors_failed"
   248  	case AncestorsOp:
   249  		return "ancestors"
   250  	// Consensus
   251  	case GetOp:
   252  		return "get"
   253  	case GetFailedOp:
   254  		return "get_failed"
   255  	case PutOp:
   256  		return "put"
   257  	case PushQueryOp:
   258  		return "push_query"
   259  	case PullQueryOp:
   260  		return "pull_query"
   261  	case QueryFailedOp:
   262  		return "query_failed"
   263  	case ChitsOp:
   264  		return "chits"
   265  	// Application
   266  	case AppRequestOp:
   267  		return "app_request"
   268  	case AppErrorOp:
   269  		return "app_error"
   270  	case AppResponseOp:
   271  		return "app_response"
   272  	case AppGossipOp:
   273  		return "app_gossip"
   274  	// Cross chain
   275  	case CrossChainAppRequestOp:
   276  		return "cross_chain_app_request"
   277  	case CrossChainAppErrorOp:
   278  		return "cross_chain_app_error"
   279  	case CrossChainAppResponseOp:
   280  		return "cross_chain_app_response"
   281  		// Internal
   282  	case ConnectedOp:
   283  		return "connected"
   284  	case ConnectedSubnetOp:
   285  		return "connected_subnet"
   286  	case DisconnectedOp:
   287  		return "disconnected"
   288  	case NotifyOp:
   289  		return "notify"
   290  	case GossipRequestOp:
   291  		return "gossip_request"
   292  	case TimeoutOp:
   293  		return "timeout"
   294  	default:
   295  		return "unknown"
   296  	}
   297  }
   298  
   299  func Unwrap(m *p2p.Message) (fmt.Stringer, error) {
   300  	switch msg := m.GetMessage().(type) {
   301  	// Handshake:
   302  	case *p2p.Message_Ping:
   303  		return msg.Ping, nil
   304  	case *p2p.Message_Pong:
   305  		return msg.Pong, nil
   306  	case *p2p.Message_Handshake:
   307  		return msg.Handshake, nil
   308  	case *p2p.Message_GetPeerList:
   309  		return msg.GetPeerList, nil
   310  	case *p2p.Message_PeerList_:
   311  		return msg.PeerList_, nil
   312  	// State sync:
   313  	case *p2p.Message_GetStateSummaryFrontier:
   314  		return msg.GetStateSummaryFrontier, nil
   315  	case *p2p.Message_StateSummaryFrontier_:
   316  		return msg.StateSummaryFrontier_, nil
   317  	case *p2p.Message_GetAcceptedStateSummary:
   318  		return msg.GetAcceptedStateSummary, nil
   319  	case *p2p.Message_AcceptedStateSummary_:
   320  		return msg.AcceptedStateSummary_, nil
   321  	// Bootstrapping:
   322  	case *p2p.Message_GetAcceptedFrontier:
   323  		return msg.GetAcceptedFrontier, nil
   324  	case *p2p.Message_AcceptedFrontier_:
   325  		return msg.AcceptedFrontier_, nil
   326  	case *p2p.Message_GetAccepted:
   327  		return msg.GetAccepted, nil
   328  	case *p2p.Message_Accepted_:
   329  		return msg.Accepted_, nil
   330  	case *p2p.Message_GetAncestors:
   331  		return msg.GetAncestors, nil
   332  	case *p2p.Message_Ancestors_:
   333  		return msg.Ancestors_, nil
   334  	// Consensus:
   335  	case *p2p.Message_Get:
   336  		return msg.Get, nil
   337  	case *p2p.Message_Put:
   338  		return msg.Put, nil
   339  	case *p2p.Message_PushQuery:
   340  		return msg.PushQuery, nil
   341  	case *p2p.Message_PullQuery:
   342  		return msg.PullQuery, nil
   343  	case *p2p.Message_Chits:
   344  		return msg.Chits, nil
   345  	// Application:
   346  	case *p2p.Message_AppRequest:
   347  		return msg.AppRequest, nil
   348  	case *p2p.Message_AppResponse:
   349  		return msg.AppResponse, nil
   350  	case *p2p.Message_AppError:
   351  		return msg.AppError, nil
   352  	case *p2p.Message_AppGossip:
   353  		return msg.AppGossip, nil
   354  	default:
   355  		return nil, fmt.Errorf("%w: %T", errUnknownMessageType, msg)
   356  	}
   357  }
   358  
   359  func ToOp(m *p2p.Message) (Op, error) {
   360  	switch msg := m.GetMessage().(type) {
   361  	case *p2p.Message_Ping:
   362  		return PingOp, nil
   363  	case *p2p.Message_Pong:
   364  		return PongOp, nil
   365  	case *p2p.Message_Handshake:
   366  		return HandshakeOp, nil
   367  	case *p2p.Message_GetPeerList:
   368  		return GetPeerListOp, nil
   369  	case *p2p.Message_PeerList_:
   370  		return PeerListOp, nil
   371  	case *p2p.Message_GetStateSummaryFrontier:
   372  		return GetStateSummaryFrontierOp, nil
   373  	case *p2p.Message_StateSummaryFrontier_:
   374  		return StateSummaryFrontierOp, nil
   375  	case *p2p.Message_GetAcceptedStateSummary:
   376  		return GetAcceptedStateSummaryOp, nil
   377  	case *p2p.Message_AcceptedStateSummary_:
   378  		return AcceptedStateSummaryOp, nil
   379  	case *p2p.Message_GetAcceptedFrontier:
   380  		return GetAcceptedFrontierOp, nil
   381  	case *p2p.Message_AcceptedFrontier_:
   382  		return AcceptedFrontierOp, nil
   383  	case *p2p.Message_GetAccepted:
   384  		return GetAcceptedOp, nil
   385  	case *p2p.Message_Accepted_:
   386  		return AcceptedOp, nil
   387  	case *p2p.Message_GetAncestors:
   388  		return GetAncestorsOp, nil
   389  	case *p2p.Message_Ancestors_:
   390  		return AncestorsOp, nil
   391  	case *p2p.Message_Get:
   392  		return GetOp, nil
   393  	case *p2p.Message_Put:
   394  		return PutOp, nil
   395  	case *p2p.Message_PushQuery:
   396  		return PushQueryOp, nil
   397  	case *p2p.Message_PullQuery:
   398  		return PullQueryOp, nil
   399  	case *p2p.Message_Chits:
   400  		return ChitsOp, nil
   401  	case *p2p.Message_AppRequest:
   402  		return AppRequestOp, nil
   403  	case *p2p.Message_AppResponse:
   404  		return AppResponseOp, nil
   405  	case *p2p.Message_AppError:
   406  		return AppErrorOp, nil
   407  	case *p2p.Message_AppGossip:
   408  		return AppGossipOp, nil
   409  	default:
   410  		return 0, fmt.Errorf("%w: %T", errUnknownMessageType, msg)
   411  	}
   412  }