[WIP] This project is a part of Era Swap Network.
Kami is a daemon (long running background process) that runs with a seperate EVM machine daemon, which completes an ESN Validator Node. Technical aspects related to Kami are specified here.
Since, Kami works with an ESN node daemon, it will utilise the peer discovery from the ESN nodes.
Peer-to-peer networking connections between Kami instances's are based on TCP/IP. The existing JSON RPC 2.0 standard is modified for representing authenticated asks, answers and tells in the P2P communication with ECC.
This is an experimental extension of the existing JSON RPC standard as it is. This modification is done for the purpose of identification and authentication between the nodes.
interface JsonRequest {
jsonrpc: '2.0';
method: string;
params: any[];
id: Bytes32 | null;
nonce?: number;
signature?: Signature;
}
interface JsonSuccessResponse {
jsonrpc: '2.0';
previousHash: Bytes32;
result: any;
id: Bytes32 | null;
nonce?: number;
signature?: Signature;
}
interface JsonErrorResponse {
jsonrpc: '2.0';
previousHash?: Bytes32;
error: JsonErrorObject;
id: Bytes32 | null;
nonce?: number;
signature?: Signature;
}
interface JsonErrorObject {
code: number;
message: string;
data?: string;
}
When doing non-authentic communication, the communication is much like normal JSON RPC 2.0.
- Requester makes a
JsonRequest
to the responder withid = null
(which means is an annomyous communication). - Responder responds with interface
JsonSuccessResponse
if the execution was successful orJsonErrorResponse
if there was any error.
TODO: To make this 100% compliant with JSON RPC 2.0, we can create a seperate key:
connection
and use for purpose of connectionId context (which is currently being used withid
).
This public key cryptosystem is based on the secp256k1
Eliptic Curve. Being modern and secure, it's been the choice in Ethereum and hence, it's implementation in Kami would be less complex for a developer to maintain it as well as end user to install and use it in context of Era Swap Smart Contracts.
ECDSA needs a 32 Byte digest for signing. ECDSA being used commonly in multiple blockchains, gives a security threat for reuse of the signed message in another dApp. The design choice for preparing the 32 Byte digest is explained here. The digest generation is inspired from EIP 191
. We have defined a rlpizeObject
method on a request object, which is used to serializeJson
it into a byte string. Finally, we add a domain seperator and hash it using keccak256
algorithm and further signing it with ECDSA to generate the signature point on the curve.
0x19 | 0x97 | <32-byte domain seperator> | <data to sign>
Here, 0x97
is the version byte (and from the version bytes registry looks like it's not taken). The domain seperator is defined as:
domainSeperator: Bytes32 = keccak256(
serializeJson({
name: 'Kami of Era Swap Network',
chainId: 5197,
})
)
TODO: Add explaination here
- Requester calls the
kami_peerInit
method with 16 random bytes withnull
id to the responder. - Responder generates random 16 bytes and concatenates it after requester's 16 bytes and sends the 32 bytes back, the requester has to use it as
id
in next communication. - Initiater uses this
id
received andnonce = 0
for signing the next request. The signature generation standard will be described in the next sections.
When doing a non-authentic communication using JSON RPC 2.0 for a method that requires authentic communication using Extended JSON RPC 2.0, the Kami node can throw an INVALID_REQUEST
error.
The misleading jsonrpc: '2.0'
might be updated to something else like 2.0-extended
or even 2.0-kami
, to signal the other node for using the extended version for communication, while there are no plans of doing this as of now.
A Kami can connect with other Kamis by knowing their IP addresses. Kami needs to know the wallet address of the peer nodes hence an authentication communication is needed here.
- A Kami needs initial seed nodes IP Addresses.
- A Kami starts authentication handshake with another Kami.
- If this Kami doesn't have stakes, another Kami might deny to connect.
- After finish of the handshake, the Kamis add each other to it's list of peers.
interface Peer {
connectionUrl: URL;
connectionId: Bytes32;
trusted: boolean;
reqNonce: number;
checkNonce: number;
connected: Date;
lastTalk: Date;
walletAddress: Address | null;
seats: number | null;
}
To limit traffic, a peer limit (of e.g. 100
) may be implemented. Also to minimize traffic, nodes can choose to connect to only those Kamis who have seats.
- Start Block Number (uint)
- Bunch Depth (uint)
- Transactions Mega Root (bytes32)
- Receipt Mega Root (bytes32)
- Signatures (bytes65[])
- A Kami will generate a bunch proposal locally.
- A Kami will request all nodes to sign to verify and provide a signature to be included in bunch proposal transaction.
- When a Kami receives a signature request, they compute the bunch proposal, checks if it matches, then signs on it. Else it returns an error.
- When a Kami receives response with signature, it adds it to a list of signatures along with respective seats.
- Every time, a new signature is received, it checks if 66% is acheived. If yes, then it arranges by decending order of seats up to 66% seats and drops any excess signatures.
- Prepares transaction and sends it to Ethereum.