github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/p2p/rpc_topic_mappings.go (about) 1 package p2p 2 3 import ( 4 "reflect" 5 6 "github.com/pkg/errors" 7 types "github.com/prysmaticlabs/eth2-types" 8 p2ptypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types" 9 pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 10 ) 11 12 // SchemaVersionV1 specifies the schema version for our rpc protocol ID. 13 const SchemaVersionV1 = "/1" 14 15 // Specifies the protocol prefix for all our Req/Resp topics. 16 const protocolPrefix = "/eth2/beacon_chain/req" 17 18 // Specifies the name for the status message topic. 19 const statusMessageName = "/status" 20 21 // Specifies the name for the goodbye message topic. 22 const goodbyeMessageName = "/goodbye" 23 24 // Specifies the name for the beacon blocks by range message topic. 25 const beaconBlocksByRangeMessageName = "/beacon_blocks_by_range" 26 27 // Specifies the name for the beacon blocks by root message topic. 28 const beaconBlocksByRootsMessageName = "/beacon_blocks_by_root" 29 30 // Specifies the name for the ping message topic. 31 const pingMessageName = "/ping" 32 33 // Specifies the name for the metadata message topic. 34 const metadataMessageName = "/metadata" 35 36 const ( 37 // V1 RPC Topics 38 // RPCStatusTopicV1 defines the v1 topic for the status rpc method. 39 RPCStatusTopicV1 = protocolPrefix + statusMessageName + SchemaVersionV1 40 // RPCGoodByeTopicV1 defines the v1 topic for the goodbye rpc method. 41 RPCGoodByeTopicV1 = protocolPrefix + goodbyeMessageName + SchemaVersionV1 42 // RPCBlocksByRangeTopicV1 defines v1 the topic for the blocks by range rpc method. 43 RPCBlocksByRangeTopicV1 = protocolPrefix + beaconBlocksByRangeMessageName + SchemaVersionV1 44 // RPCBlocksByRootTopicV1 defines the v1 topic for the blocks by root rpc method. 45 RPCBlocksByRootTopicV1 = protocolPrefix + beaconBlocksByRootsMessageName + SchemaVersionV1 46 // RPCPingTopicV1 defines the v1 topic for the ping rpc method. 47 RPCPingTopicV1 = protocolPrefix + pingMessageName + SchemaVersionV1 48 // RPCMetaDataTopicV1 defines the v1 topic for the metadata rpc method. 49 RPCMetaDataTopicV1 = protocolPrefix + metadataMessageName + SchemaVersionV1 50 ) 51 52 // RPCTopicMappings map the base message type to the rpc request. 53 var RPCTopicMappings = map[string]interface{}{ 54 RPCStatusTopicV1: new(pb.Status), 55 RPCGoodByeTopicV1: new(types.SSZUint64), 56 RPCBlocksByRangeTopicV1: new(pb.BeaconBlocksByRangeRequest), 57 RPCBlocksByRootTopicV1: new(p2ptypes.BeaconBlockByRootsReq), 58 RPCPingTopicV1: new(types.SSZUint64), 59 RPCMetaDataTopicV1: new(interface{}), 60 } 61 62 // Maps all registered protocol prefixes. 63 var protocolMapping = map[string]bool{ 64 protocolPrefix: true, 65 } 66 67 // Maps all the protocol message names for the different rpc 68 // topics. 69 var messageMapping = map[string]bool{ 70 statusMessageName: true, 71 goodbyeMessageName: true, 72 beaconBlocksByRangeMessageName: true, 73 beaconBlocksByRootsMessageName: true, 74 pingMessageName: true, 75 metadataMessageName: true, 76 } 77 78 var versionMapping = map[string]bool{ 79 SchemaVersionV1: true, 80 } 81 82 // VerifyTopicMapping verifies that the topic and its accompanying 83 // message type is correct. 84 func VerifyTopicMapping(topic string, msg interface{}) error { 85 msgType, ok := RPCTopicMappings[topic] 86 if !ok { 87 return errors.New("rpc topic is not registered currently") 88 } 89 receivedType := reflect.TypeOf(msg) 90 registeredType := reflect.TypeOf(msgType) 91 typeMatches := registeredType.AssignableTo(receivedType) 92 93 if !typeMatches { 94 return errors.Errorf("accompanying message type is incorrect for topic: wanted %v but got %v", 95 registeredType.String(), receivedType.String()) 96 } 97 return nil 98 } 99 100 // TopicDeconstructor splits the provided topic to its logical sub-sections. 101 // It is assumed all input topics will follow the specific schema: 102 // /protocol-prefix/message-name/schema-version/... 103 // For the purposes of deconstruction, only the first 3 components are 104 // relevant. 105 func TopicDeconstructor(topic string) (string, string, string, error) { 106 origTopic := topic 107 protPrefix := "" 108 message := "" 109 version := "" 110 111 // Iterate through all the relevant mappings to find the relevant prefixes,messages 112 // and version for this topic. 113 for k := range protocolMapping { 114 keyLen := len(k) 115 if keyLen > len(topic) { 116 continue 117 } 118 if topic[:keyLen] == k { 119 protPrefix = k 120 topic = topic[keyLen:] 121 } 122 } 123 124 if protPrefix == "" { 125 return "", "", "", errors.Errorf("unable to find a valid protocol prefix for %s", origTopic) 126 } 127 128 for k := range messageMapping { 129 keyLen := len(k) 130 if keyLen > len(topic) { 131 continue 132 } 133 if topic[:keyLen] == k { 134 message = k 135 topic = topic[keyLen:] 136 } 137 } 138 139 if message == "" { 140 return "", "", "", errors.Errorf("unable to find a valid message for %s", origTopic) 141 } 142 143 for k := range versionMapping { 144 keyLen := len(k) 145 if keyLen > len(topic) { 146 continue 147 } 148 if topic[:keyLen] == k { 149 version = k 150 topic = topic[keyLen:] 151 } 152 } 153 154 if version == "" { 155 return "", "", "", errors.Errorf("unable to find a valid schema version for %s", origTopic) 156 } 157 158 return protPrefix, message, version, nil 159 } 160 161 // RPCTopic is a type used to denote and represent a req/resp topic. 162 type RPCTopic string 163 164 // ProtocolPrefix returns the protocol prefix of the rpc topic. 165 func (r RPCTopic) ProtocolPrefix() string { 166 prefix, _, _, err := TopicDeconstructor(string(r)) 167 if err != nil { 168 return "" 169 } 170 return prefix 171 } 172 173 // MessageType returns the message type of the rpc topic. 174 func (r RPCTopic) MessageType() string { 175 _, message, _, err := TopicDeconstructor(string(r)) 176 if err != nil { 177 return "" 178 } 179 return message 180 } 181 182 // Version returns the schema version of the rpc topic. 183 func (r RPCTopic) Version() string { 184 _, _, version, err := TopicDeconstructor(string(r)) 185 if err != nil { 186 return "" 187 } 188 return version 189 }