-
Notifications
You must be signed in to change notification settings - Fork 5
Network
All nodes communicate over TCP. Messages are encoded with XDR(RFC 4506). XDR uses the similar approach to Protocol Buffers or Thrift. All data declarations can be found in the reference stellar-core repo.
When started for the first time, programs don't know the IP addresses of any active nodes.
Initial trusted nodes(maintained by stellar.org
) should be added at first startup. Once a program has connected to the other nodes, its can begin to request GET_PEERS
messages and receive in response PEERS
message with the IP addresses and port numbers of other peers on the network, providing a fully decentralized method of peer discovery.
Each node must maintain a secret seed, public and private keys, derived from the seed, and the hashed network passphrase, which determines, in what network node operates.
Official Stellar networks passphrases are:
-
Test SDF Network ; September 2015
– the testnet -
Public Global Stellar Network ; September 2015
– the public network
Use any other string as the network passphrase to build private network.
Sha256 of network passphrase is called "network id".
All cryptographic operations are based on the Ed25519 (for signatures) and Curve25519 (for keypair generation).
Stellar-core node supports the next messages:
union StellarMessage switch (MessageType type)
{
case ERROR_MSG:
Error error;
case HELLO: // initiate handshake. Precedes `AUTH` message
Hello hello;
case AUTH: // authenticate the node. Used in the handshake, follows `HELLO` message
Auth auth;
case DONT_HAVE:
DontHave dontHave;
case GET_PEERS: // get a list of peers this node knows about
void;
case PEERS:
PeerAddress peers<100>;
case GET_TX_SET: // get a particular `txset` by its hash
uint256 txSetHash;
case TX_SET:
TransactionSet txSet;
case TRANSACTION: // pass on a tx you have heard about
TransactionEnvelope transaction;
// SCP
case GET_SCP_QUORUMSET:
uint256 qSetHash;
case SCP_QUORUMSET:
SCPQuorumSet qSet;
case SCP_MESSAGE:
SCPEnvelope envelope;
case GET_SCP_STATE:
uint32 getSCPLedgerSeq; // ledger seq requested ; if 0, requests the latest
};
The StellarMessage
union contains 3 logically distinct kinds of message:
- Messages directed to or from a specific peer, with or without a response:
HELLO
,GET_PEERS
,PEERS
,DONT_HAVE
,ERROR_MSG
- One-way broadcast messages informing other peers of an event:
TRANSACTION
andSCP_MESSAGE
- Two-way anycast messages requesting a value (by hash) or providing it:
GET_TX_SET
,TX_SET
,GET_SCP_QUORUMSET
,SCP_QUORUMSET
,GET_SCP_STATE
Every message, except for HELLO
and ERROR
, goes with HMAC and the sequence number. All these pieces form AuthenticatedMessage
structure:
union AuthenticatedMessage switch (uint32 v)
{
case 0:
struct
{
uint64 sequence; // incremental counter of all messages node sent
StellarMessage message; // one of the messages listed above
HmacSha256Mac mac; // calculated on the handshake
} v0;
};
Messages are minimally framed using the Record Marking (RM)
standard of RFC 5531 and the RM-framed messages are
transmitted over TCP/IP sockets, between peers.
| 4 bytes header | XDR message |
For every new connection, we need to build an AuthCert
and HELLO
XDR structs. (link).
Connection process:
- A wants to connect to B
- A starts a TCP connection to B
- connection is established
-
A builds
HELLO
message and sends it to B -
B now has IP and port of A, B builds
HELLO
message and sends it back to A -
A builds MAC key
- get a shared secret, using Elliptic-Curve Diffie-Hellman (ECDH) key agreement on A and B public keys
- feed this shared secret as a salt, and use concatenation of
0
, A nonce and B nonce as an input to HKDF (use Sha256 for hashing) - extract MAC key from the HKDF
-
A builds
AUTH
message, which is an empty message with the MAC, and sends it to B -
B verifies
AUTH
message from A -
B builds MAC key its
AUTH
message and sends it back to A- get a shared secret, using Elliptic-Curve Diffie-Hellman (ECDH) key agreement on A and B public keys
- feed this shared secret as a salt, and use concatenation of
1
, B nonce and A nonce as an input to HKDF (use Sha256 for hashing) - extract MAC key from the HKDF
-
B builds
AUTH
message, which is an empty message with the MAC, and sends it back to A -
A verifies the
AUTH
message from B
If any verification step fails, the peer disconnects immediately.
HELLO
message contains AuthCert
struct:
struct AuthCert
{
Curve25519Public pubkey; // the node's public key
uint64 expiration; // unix time
Signature sig;
};
sig
is built this way:
- concatenate network id,
ENVELOPE_TYPE_AUTH
XDR constant,expiration
andpubkey
to form a binary buffer - hash this buffer with sha256
- sign this hash with node's private key
- wrap the signature with
Signature
XDR data type
struct Hello
{
uint32 ledgerVersion; //current ledger protocol version. Used for know how upgrade frames to latest versions from legacy nodes. Related to stellar-core version.
uint32 overlayVersion; // max overlay version supported by the node
uint32 overlayMinVersion; // min overlay version understood by the node
Hash networkID; // sha256(network passphrase)
string versionStr<100>; // node version as a string (for information only)
int listeningPort; // the port node is listening to
NodeID peerID; // the node's public key
AuthCert cert; // see paragraph above for details
uint256 nonce; // some random number
};
Local node keeps track of which peers have sent us which broadcast messages, in order to ensure that for each broadcast message M and for each peer P, we either send M to P once (and only once), or receive M from P (thereby inhibit sending M to P at all).
The broadcast message types are TRANSACTION
and SCP_MESSAGE
.
All messages are marked with the ledger sequence number to which they relate, and all broadcast-management information for a given ledger number is purged when the ledger closes.