Contractless/docs/DEV_CLIENTS.md

99 lines
3.1 KiB
Markdown

# Developer Client Notes
This file contains low-level notes for building external clients or debugging the Contractless RPC client flow. It is not required for normal node setup.
## RPC Clients
RPC clients are not treated the same as mining nodes. A client must follow the handshake format exactly, or the server may classify it as a node/miner instead of a client. When that happens, client tools can hang, be rejected or behave unexpectedly.
### Required Client Handshake Rules
1. Use a valid wallet address and signature in the handshake.
- The client must load a real wallet locally.
- The wallet encryption key is used only locally to open the wallet and sign the handshake.
- The wallet encryption key is not sent over the stream.
- The wallet address is sent as part of the handshake identity.
2. The opening handshake message must be `aced`.
- The client signs the hash of `aced`.
- The server verifies that signature against the wallet address supplied in the handshake.
3. A client must advertise its IP with port `0`.
- Example: `127.0.0.1:0`
- This is the rule that tells the server the connection is a client-style RPC connection rather than a mining node connection.
- The server checks whether the submitted `ip:port` is externally reachable.
- If the submitted port is open, the connection is treated as a miner/node.
- If the submitted port is `0` or not reachable, the connection is treated as a client.
4. The client timestamp must be within 1 second of the server timestamp.
- If the timestamp is too far off, the handshake is rejected.
5. The submitted IP must match the caller IP seen by the server.
- The server compares the claimed IP in the handshake against the actual remote peer IP.
### Handshake Byte Layout
The client sends:
- `2` bytes: message (`aced`)
- `65` bytes: recoverable signature
- `21` bytes: wallet address
- `4` bytes: timestamp
- `18` bytes: `ip:port`
Total client handshake size:
- `110` bytes
The server returns:
- `2` bytes: message
- `65` bytes: recoverable signature
- `21` bytes: wallet address
Total server handshake size:
- `88` bytes
### Server Return Messages
After the client handshake is accepted:
- miner/node connections receive `face`
- client connections receive `ecaf`
RPC clients should expect `ecaf`.
If you do not follow the client rules above, especially the `ip:0` rule, the server can classify your connection as a mining/node connection instead of a client connection. That will cause errors for standalone RPC tools.
### RPC Request Format After Handshake
After the handshake succeeds, the client sends:
- `1` byte: command
- `3` bytes: request uid
- command-specific payload bytes if required
Normal RPC replies are returned as:
- `1` byte: reply command (`111`)
- `3` bytes: request uid
- `2` bytes: payload length
- payload bytes
### Practical Note For Standalone Tools
Standalone tools in `src/bin` should behave like clients, not mining nodes. Their handshake should therefore:
- use a real wallet
- send `aced`
- sign it correctly
- advertise `your_ip:0`
If a standalone tool advertises a real RPC/mining port instead of `0`, the server may treat it as a node connection and the tool can fail in confusing ways.