99 lines
3.1 KiB
Markdown
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.
|