Delight: A Factom Light Node Concept
At the time of writing, the database size of a Factom Protocol MainNet node is around 28GiB and takes several days to sync. Not everyone who runs a Factom node necessarily wants or needs to keep a copy of the entire blockchain, particularly PegNet users who only need to track three specific chains.
Introducing delight (from “factomd light”) with one simple goal: only have what is necessary to function and ignore the rest.
The motivation behind this proposal is two-fold. The first is the obvious one — having a light node would be extremely beneficial to many users. The second is a more lofty goal, namely rebuilding factomd.
It is no secret that the factomd codebase is a big bowl of unmaintainable spaghetti code. Untangling that is a borderline impossible task but what about going the other way? Start with something simple that is still useful and then continuously add components until it is functionally equivalent to factomd.
The Bare Necessities
It would be easy to say that an application that connects to the P2P Network and rebroadcasts messages is a node but factomd is coded to be very forgiving. That means if a peer doesn’t support some of the features, it is still tolerated.
The worst-case scenario would is an unintentional Sybil attack by too many light nodes in the network who are incapable of syncing new nodes and supply missing messages. For that reason, I am going to define the bare necessity as a node that won’t disrupt the regular network behavior.
So what exactly is necessary? By default, a node should propagate messages that are being broadcast around the network, which is most application messages, and also respond to requests for missing data, whether that’s DBlocks for the first pass sync, entries for the second pass sync, or process list messages for building the current block. That gives us our basic requirements: DBlocks, Entries, and Process Lists.
A. P2P Network
This is the cornerstone of any node. Data goes in and data comes back out. The P2P module can be adopted without modifications from factomd as a black box module.
B. Message Layer
This would be responsible for accepting messages from the network, making sure the payload can be decoded, and then making it available to the light node modules, either via listeners or callbacks. The message layer would automatically rebroadcast messages that are supposed to be rebroadcast, which is a change from factomd, where messages are first processed internally before being sent back out.
There is some security risk associated with it, such as flooding the network with invalid messages, so some basic validation should still happen. Full validation of the message as it happens in factomd may not be possible since the data to verify certain things does not exist.
C. Process Lists
The heart of the consensus logic involves these process lists (PL). Every federated server has exactly one PL for which they are responsible for the order. Every message that goes into a PL (transactions, entries, etc.) is only accepted once it has an Ack, a second message that contains the signature for the first message, the VM index it goes into, and a height, which is the position of the message in the list.
Neighboring nodes will repeatedly ask for updates to see if new messages arrived that they don’t know about, or ask for messages at specific indexes if they have any gaps. To reply to these, the light node will need to temporarily save all the messages in the PLs, though this data doesn’t have to be permanently retained.
Note: It is possible to just have a good faith approach and take signed messages as-is without checking if the identity is actually a federated server. An attack targeting this would be able to insert fake messages into the PL of the light node but this would not affect full nodes.
Since the light node only has this module to be able to reply to requests and all the data is transient, malicious data would also not hurt the light node.
However, if the goal is to turn the light node into a full node eventually, we should consider the additional step of including identities.
D. Identities (Optional)
The identities are fairly simple but require the data from the admin chain and the various identity chains. The factom protocol requires the identity chains to exist at the point in time the identities are added to the authority set, which only means we need to add the requirement to sync both the admin chain as well as any identity chain.
The light node doesn’t need to do any validation, since only valid identities make it into the chain in the first place. It just needs to grab the most recent block signing key.
E. Data Sync
This, of course, is the reason we want the light node. We want to be able to control what we save and what not to save. The factom protocol supports two different types of requests: a) a range of directory blocks, which returns the directory blocks, containing the Factoid Block, EC Block, Admin Block, and a variable amount of entry blocks, along with the entries for the FBlock, ECBlock, and ABlock, and b) a single hash corresponding to a single entry.
There is, unfortunately, no way to simply request a specific chain by chain id, or download DBlocks without the A/F/EC-Block data. This gives us the opportunity to save that data to have it on hand for modules like D and G, and more importantly, be able to add new chains to monitor retroactively without having to re-download the DBlocks.
It is possible to only save this data partially, such as an index of chains to EBlocks and Entry Hashes, which is the minimum data required to download all the information for a single chain.
Other than the index/DBlocks, this module would only download the entry data for chains that are configured by the light node operator. Tracking by Chain ID is very simple and useful for applications like PegNet. Tracking by Chain-ExtIDs would require that the first entry of every chain is downloaded, which, for example, would allow tracking all chains related to the forum post securing addon.
To track by Entry-ExtID would require downloading all entries (and save them to be able to retroactively add chains), so that is not a feature that is planned in the initial version.
This would be a simple key-value database (as is used in factomd) that stores the desired chains/entries, as well as the DBlocks/index, some metadata, and be available to other modules such as D.
Like the P2P module, this would be an independent black box module.
G. Data Requests
Anytime a new node joins the network and needs to sync, it will send out the two types of requests described in E. If the corresponding data is in the database, we can just reply with the desired data.
However, if we don’t have the data (because we chose not to retain it), we can’t answer those messages. The requesting node will just try again after 10 seconds without an answer. As alluded to, this is typically not an issue if it’s a small number of nodes but if a majority of the network runs light nodes, full nodes can run into problems getting the data they want.
For this reason, we can add a way to retrieve that information from the outside with a support node. If we don’t have the data ourselves, we can download it on-demand from the support node and put it in the message. This comes at a cost of increased bandwidth but will serve for a healthier network.
H. Support Node
The support node would be a separate node, either your own local full node or the Open Node. The data would be queried via the API, then packaged into a reply. There is no security concern here since all data can be verified by hashes.
The downside is, of course, that it’s fairly inefficient and could lead to an unintentional DDoS of the Open Node. If light nodes become very popular, the Open Node may need to scale upward.
An alternative would be expanding the factom protocol itself to allow light nodes to identify themselves and be excluded from data requests, though this is not without its own ramifications.
The API would allow interaction with the node, namely retrieving chains and entries. The exact details of this are very malleable, and different modules could be written to suit different needs (JSON-RPC, REST, GraphQL, etc).
The process lists contain a lot of useful information but in the description above, we are throwing them out. This is done for simplicity’s sake but is not strictly necessary. All entries for chains first appear in the PLs before showing up in a DBlock, so it makes sense to temporarily cache the entries and make them available to Data Sync to not have to download them twice.
Similarly, we could infer from the PLs when a new block is finished, rather than keep asking our neighbors if any new blocks have been built. Theoretically, the entire block could be inferred from the data in the PLs.
However, there is a limit to this optimization. It would require a significant developer time investment to make sure that blocks are being generated the same way in the light node than in factomd. For example, the grant and coinbase payouts do not appear in the PL itself but are generated from the admin chain, so we would need a coinbase module in addition to a block building module.
This kind of work will need to be done if this is turned into a full fledged node but accepting slightly worse performance in exchange for a much simpler codebase and fewer system resources makes sense for the light node.
The light node would be fairly simple to build and, if done right, have no discernible impact on the health of the network itself. It could also serve as a base for any rewrite efforts of factomd, which has become unmanageable.
At the time of writing, no coding work has been done on this and it is only a theoretical concept.