Zeno, a distributed cross chain notariser

How does it work?

Ok so each member runs the chains?

Right, such that we get a reliable view of the network (unless everyone is using infura.io :eyes:). This does mean that all nodes need a beefy server with 1tb SSD.

How does it figure out what to do?

Depends on mode of notarisation, eg: However, in general, Zeno will inspect the chains to discover parameters for the next notarisation. Given these parameters, it will generate a round seed which is the hash of a few bits of information: Zeno will then try to agree on this information with other online nodes to get a threshold agreement. If this is successful, a transaction is written. If not, state is wiped and the process starts over (Top level loop). Screenshot

How do nodes co-operate?

Once a node has examined the chain state and figured out the round inputs, it enters a cooperative mode where each step is taken in concert with other nodes that are listening on the same round ID. In the event that not enough nodes are active on the same round ID, a timeout will occur when trying to collect a threshold number of items for a step. If a packet is received for a round ID that a node is not currently active on, it is cached in a fixed size rotating cache in case it is just about to catch up. This speeds up replication greatly. Many rounds may be active at the same time; rounds that have been completed need not be dropped immediately, as they run in their own threads, they can be left open to facilitate other nodes in catching up, and killed at some later point. Here is a function that ends in a transaction being written, if enough nodes agree. The runConsensus function runs code in the Consensus context, this provides functions to synchronise data between nodes.

Consensus in Zeno

Consensus frontend

Guts of data synchronisation; i.e. building an inventory of data from different nodes for a step

Concurrency in Zeno

Zeno talks with Ethereum

List shuffle algorithm

I implemented a deterministic list shuffle, to support proposer selection. This seems like a strange idea, given that it is a common problem, however it was quite fun. Tests.

Secp256k1

Zeno uses Secp256k1 extensively, and exchanges compact recoverable signatures to authenticate all messages. The Haskell wrapper for Secp256k1 used to support recovery, however, under heavy workloads it exhibited a bug, which I could not track down. The author of the library fixed the bug, however in the process, removed support for recoverable mode. It seems the issue comments may have been editorialized. Anyhow, I made the decision to remove the dependency, and implemented my own higher level functions to more closely match my use cases. This was for the same reason that Zeno has it's own Ethereum data structures, rather than using the Haskell web3 library; if you can easily implement or copy the bits you need, it has a smaller surface area and it is easier to fix things, especially if the library you are depending on is bloated or not well maintained.

Reflections on development with Haskell

Haskell has some properties that make it amazing to work with: However, I would not use it for a big project in 2020 because: And unfortunately there is not yet any new serious compiler to compete with Haskell's feature set. I think part of the problem is that GC-less functional programming is impossible.

Screenshots

monkeytop
normalop
scale-htop
scaletest