|
| 1 | +# Messages |
| 2 | + |
| 3 | +All message sent in the network are of type `PeerMessage`. They are encoded using [Borsh](https://borsh.io/) which allows a rich structure, small size and fast encoding/decoding. For details about data structures used as part of the message see the [reference code](https://github.com/nearprotocol/nearcore). |
| 4 | + |
| 5 | +## Encoding |
| 6 | + |
| 7 | +A `PeerMessage` is converted into an array of bytes (`Vec<u8>`) using borsh serialization. An encoded message is conformed by 4 bytes with the length of the serialized `PeerMessage` concatenated with the serialized `PeerMessage`. |
| 8 | + |
| 9 | +Check [Borsh specification](https://github.com/nearprotocol/borsh#specification) details to see how it handles each data structure. |
| 10 | + |
| 11 | +## Data structures |
| 12 | + |
| 13 | +### PeerID |
| 14 | + |
| 15 | +The id of a peer in the network is its [PublicKey](https://github.com/nearprotocol/nearcore/blob/master/core/crypto/src/signature.rs). |
| 16 | + |
| 17 | +```rust |
| 18 | +struct PeerId(PublicKey); |
| 19 | +``` |
| 20 | + |
| 21 | +### PeerInfo |
| 22 | + |
| 23 | + |
| 24 | +```rust |
| 25 | +struct PeerInfo { |
| 26 | + id: PeerId, |
| 27 | + addr: Option<SocketAddr>, |
| 28 | + account_id: Option<AccountId>, |
| 29 | +} |
| 30 | +``` |
| 31 | + |
| 32 | +`PeerInfo` contains relevant information to try to connect to other peer. [`SocketAddr`](https://doc.rust-lang.org/std/net/enum.SocketAddr.html) is a tuple of the form: `IP:port`. |
| 33 | + |
| 34 | +### AccountID |
| 35 | + |
| 36 | +```rust |
| 37 | +type AccountId = String; |
| 38 | +``` |
| 39 | + |
| 40 | +### PeerMessage |
| 41 | + |
| 42 | +```rust |
| 43 | +enum PeerMessage { |
| 44 | + Handshake(Handshake), |
| 45 | + HandshakeFailure(PeerInfo, HandshakeFailureReason), |
| 46 | + /// When a failed nonce is used by some peer, this message is sent back as evidence. |
| 47 | + LastEdge(Edge), |
| 48 | + /// Contains accounts and edge information. |
| 49 | + Sync(SyncData), |
| 50 | + RequestUpdateNonce(EdgeInfo), |
| 51 | + ResponseUpdateNonce(Edge), |
| 52 | + PeersRequest, |
| 53 | + PeersResponse(Vec<PeerInfo>), |
| 54 | + BlockHeadersRequest(Vec<CryptoHash>), |
| 55 | + BlockHeaders(Vec<BlockHeader>), |
| 56 | + BlockRequest(CryptoHash), |
| 57 | + Block(Block), |
| 58 | + Transaction(SignedTransaction), |
| 59 | + Routed(RoutedMessage), |
| 60 | + /// Gracefully disconnect from other peer. |
| 61 | + Disconnect, |
| 62 | + Challenge(Challenge), |
| 63 | +} |
| 64 | +``` |
| 65 | + |
| 66 | +### AnnounceAccount |
| 67 | + |
| 68 | +Each peer should announce its account |
| 69 | + |
| 70 | +```rust |
| 71 | +struct AnnounceAccount { |
| 72 | + /// AccountId to be announced. |
| 73 | + account_id: AccountId, |
| 74 | + /// PeerId from the owner of the account. |
| 75 | + peer_id: PeerId, |
| 76 | + /// This announcement is only valid for this `epoch`. |
| 77 | + epoch_id: EpochId, |
| 78 | + /// Signature using AccountId associated secret key. |
| 79 | + signature: Signature, |
| 80 | +} |
| 81 | +``` |
| 82 | + |
| 83 | +### Handshake |
| 84 | + |
| 85 | +```rust |
| 86 | +struct Handshake { |
| 87 | + /// Protocol version. |
| 88 | + pub version: u32, |
| 89 | + /// Oldest supported protocol version. |
| 90 | + pub oldest_supported_version: u32, |
| 91 | + /// Sender's peer id. |
| 92 | + pub peer_id: PeerId, |
| 93 | + /// Receiver's peer id. |
| 94 | + pub target_peer_id: PeerId, |
| 95 | + /// Sender's listening addr. |
| 96 | + pub listen_port: Option<u16>, |
| 97 | + /// Peer's chain information. |
| 98 | + pub chain_info: PeerChainInfoV2, |
| 99 | + /// Info for new edge. |
| 100 | + pub edge_info: EdgeInfo, |
| 101 | +} |
| 102 | +``` |
| 103 | + |
| 104 | +<!-- TODO: Make diagram about handshake process, since it is very complex --> |
| 105 | + |
| 106 | +### Edge |
| 107 | + |
| 108 | +```rust |
| 109 | +struct Edge { |
| 110 | + /// Since edges are not directed `peer0 < peer1` should hold. |
| 111 | + peer0: PeerId, |
| 112 | + peer1: PeerId, |
| 113 | + /// Nonce to keep tracking of the last update on this edge. |
| 114 | + nonce: u64, |
| 115 | + /// Signature from parties validating the edge. These are signature of the added edge. |
| 116 | + signature0: Signature, |
| 117 | + signature1: Signature, |
| 118 | + /// Info necessary to declare an edge as removed. |
| 119 | + /// The bool says which party is removing the edge: false for Peer0, true for Peer1 |
| 120 | + /// The signature from the party removing the edge. |
| 121 | + removal_info: Option<(bool, Signature)>, |
| 122 | +} |
| 123 | +``` |
| 124 | + |
| 125 | +### EdgeInfo |
| 126 | + |
| 127 | +```rust |
| 128 | +struct EdgeInfo { |
| 129 | + nonce: u64, |
| 130 | + signature: Signature, |
| 131 | +} |
| 132 | +``` |
| 133 | + |
| 134 | +### RoutedMessage |
| 135 | + |
| 136 | +```rust |
| 137 | +struct RoutedMessage { |
| 138 | + /// Peer id which is directed this message. |
| 139 | + /// If `target` is hash, this a message should be routed back. |
| 140 | + target: PeerIdOrHash, |
| 141 | + /// Original sender of this message |
| 142 | + author: PeerId, |
| 143 | + /// Signature from the author of the message. If this signature is invalid we should ban |
| 144 | + /// last sender of this message. If the message is invalid we should ben author of the message. |
| 145 | + signature: Signature, |
| 146 | + /// Time to live for this message. After passing through some hop this number should be |
| 147 | + /// decreased by 1. If this number is 0, drop this message. |
| 148 | + ttl: u8, |
| 149 | + /// Message |
| 150 | + body: RoutedMessageBody, |
| 151 | +} |
| 152 | +``` |
| 153 | + |
| 154 | +### RoutedMessageBody |
| 155 | + |
| 156 | +```rust |
| 157 | +enum RoutedMessageBody { |
| 158 | + BlockApproval(Approval), |
| 159 | + ForwardTx(SignedTransaction), |
| 160 | + |
| 161 | + TxStatusRequest(AccountId, CryptoHash), |
| 162 | + TxStatusResponse(FinalExecutionOutcomeView), |
| 163 | + QueryRequest { |
| 164 | + query_id: String, |
| 165 | + block_id_or_finality: BlockIdOrFinality, |
| 166 | + request: QueryRequest, |
| 167 | + }, |
| 168 | + QueryResponse { |
| 169 | + query_id: String, |
| 170 | + response: Result<QueryResponse, String>, |
| 171 | + }, |
| 172 | + ReceiptOutcomeRequest(CryptoHash), |
| 173 | + ReceiptOutComeResponse(ExecutionOutcomeWithIdAndProof), |
| 174 | + StateRequestHeader(ShardId, CryptoHash), |
| 175 | + StateRequestPart(ShardId, CryptoHash, u64), |
| 176 | + StateResponse(StateResponseInfo), |
| 177 | + PartialEncodedChunkRequest(PartialEncodedChunkRequestMsg), |
| 178 | + PartialEncodedChunkResponse(PartialEncodedChunkResponseMsg), |
| 179 | + PartialEncodedChunk(PartialEncodedChunk), |
| 180 | + Ping(Ping), |
| 181 | + Pong(Pong), |
| 182 | +} |
| 183 | +``` |
| 184 | + |
| 185 | +## CryptoHash |
| 186 | + |
| 187 | +`CryptoHash` are objects with 256 bits of information. |
| 188 | + |
| 189 | +```rust |
| 190 | +pub struct Digest(pub [u8; 32]); |
| 191 | + |
| 192 | +pub struct CryptoHash(pub Digest); |
| 193 | +``` |
0 commit comments