Guides
Architecture Guide
Firechain's distributed ledger is a public database containing the history of all accounts which is distributed across a network of participants called validator nodes. These nodes maintain a copy of the ledger, and all of the nodes are connected to each other (often indirectly) so that they can share any updates to the ledger with one another. This makes it possible for transactions to be verified and recorded across the entire network, and for the ledger to be kept in sync across all of the nodes. The global state is a reflection of the last publicly reported state of every account's ledger, which serves as the source of truth for the network.
Before we get into the specifics of Firechain's architecture, it's helpful to understand the basics of how typical blockchains work, the role distributed ledgers and DAGs play, and how Firechain's HotDAG design differs from popular blockchain models.
What is a blockchain?
A blockchain is a data structure that consists of a set of blocks. The blockchain is a useful data structure for modeling ledgers, and you're probably familiar with its use in modeling cryptocurrencies, where each block contains a set of transactions, and each transaction represents a set of state changes. Each participant in the network, often called a node, keeps a local copy of the ledger, and nodes are connected to one another (either directly or indirectly) so that they can share any updates to the ledger as they occur. This makes it possible for new entries to be verified and propagated across the entire network, and for the ledger to be kept in sync across all of the nodes, without every node necessarily having to process every single transaction. The ledger is the source of truth for the network, and it is maintained by consensus among the nodes. Blockchains can offer very strong security guarantees, but they're notoriously difficult to scale.
Ledgers
The blockchain's ledger is made up of blocks, each of which contains a set of transactions and a reference to a previous block in the chain. This reference is called a hash and is used to link the blocks together. The hash is a unique identifier for the block, and it's deterministically computed using a cryptographic hash function. The hash is used to verify that the block has not been tampered with, and to ensure that the blocks are linked together in the correct order.
Literally a chain of blocks
A blockchain is a specific type of distributed ledger technology that uses a data structure called a block to record transaction history. Blocks contain a collection of transactions that are grouped together because they are related in some way. For example, a block might contain all of the transactions that were made during a specific time period, or all of the transactions that were made by a specific user. Blocks are chained together in a linear sequence, and each block contains a cryptographic hash of the previous block in the chain.
The first block in the chain is called the genesis block, and it is created when the network is first set up. The genesis block is special because it does not have a previous block to reference. The genesis block is often used to store information about the network, such as the current version of the software that is being used and the initial state of the ledger.
Consensus
A blockchain's ledger is secured by its consensus mechanism. This mechanism ensures that a majority of nodes in the network agree on the current state of the ledger at any given time, and it provides a way for nodes to verify that newly added entries are legitimate. The consensus mechanism is what makes it possible for the ledger to be kept in sync across all of the nodes in the network. There are many types of consensus mechanisms in use today, and the two most common categories are proof-of-work and proof-of-stake. In some consensus models nodes may be rewarded for participating in the consensus process, penalized for failing to act in accordance with the rules, or both.
Proof-of-work
Proof-of-work (PoW) is a type of consensus that requires nodes to solve a computationally intensive problem in order to add a new entry to the ledger in a process called mining. The problem is designed to be difficult to solve, but easy to verify. The difficulty of the problem is adjusted over time to ensure that new blocks are added to the ledger at a relatively consistent rate. The first node to solve the problem is given a reward, which incentivizes nodes to participate in the consensus process. Once a new block is added to the ledger, all of the nodes in the network are notified and they verify that the block is valid. If the block is valid, the nodes add it to their local copies of the ledger, and they begin "working" on the next block in the chain. If the block is invalid, nodes will ignore it and not add it to the ledger. Because solving the problem is difficult but verifying the solution is easy, it's trivial to identify invalid blocks. This enables a "trustless" system wherein the participants don't need to trust each other because consensus is based on objective rules rather than trustworthiness.
Popular blockchains that use PoW consensus mechanisms include Bitcoin and Monero, and, until very recently, Ethereum used proof-of-work as well. Proof-of-work is generally a very energy intensive process by design, and it has been criticized for being wasteful and environmentally unfriendly.
Proof-of-stake
Proof-of-stake (PoS) is a type of consensus that requires nodes to stake a certain amount of value in order to participate in the consensus process. Nodes that stake may be chosen to verify new blocks. Verifying new blocks entitles nodes to a reward, which incentivizes nodes to participate in the consensus process. Unlike PoW, PoS does not require nodes to solve difficult problems in order to add a new entry to the ledger. Instead, nodes post a bond that they stand to forfeit if they are found to be out of integrity. Because the consensus mechanism is not based on solving a computationally intensive problem, PoS is generally much more energy efficient than PoW.
Popular blockchains that use proof-of-stake consensus mechanisms include Ethereum, Polygon, and Cosmos, and many other blockchains are experimenting with PoS as well.
Which is better?
There's no consensus (heh) on which type of mechanism is better, and there are many factors to consider when evaluating the relative merits of PoW and PoS. It's important to keep in mind that there is no one-size-fits-all solution. Different blockchains have different goals, and different consensus mechanisms are better suited to different use cases.
Some critics argue that PoS is not as secure or decentralized as PoW, though this is a topic of intense debate. Dishonest nodes can attempt to add invalid blocks to the ledger in both PoW and PoS-based networks, and, in both cases, they risk losing something valuable if they are caught. In PoW systems, they simply don't earn a block reward, whereas in PoS systems, they risk losing their stake. Both mechanisms are susceptible to censorship insofar as dishonest nodes can attempt to censor transactions by not including them in blocks, but PoS systems are potentially more resistant to censorship than PoW systems because dishonest nodes risk losing their stake if they are shown to have acted in a way that is inconsistent with the rules of the system.
Firechain's Approach
Firechain uses a directed acyclic graph (DAG)-based ledger model called HotDAG that shares traits with Nano's block-lattice and, to a lesser extent, with IOTA's Tangle. Each account effectively has its own blockchain that contains all of the messages that have been sent by that account. An entry in an account's chain is a child of one that came before it, except for the first entry, which references the global state at the time of its creation and establishes the initial state of the account. The parent of the second entry in the chain is the first one, and so on. Account chains are linked through the messages they contain, and these links are used to build a global state that is kept in sync across all of the nodes in the network. As a result, validating the global state is as simple as verifying that the links between the account chains are valid. This makes it possible to verify the global state without having to download the entire history of the network, which is a major advantage over blockchains that use a single global chain.
HotDAG Ledger
Every Firechain transaction is really just a one-way message, but it can be helpful to think of things similarly to the way web requests work. Requests are outbound messages from one entity to another, and responses are messages sent in reference to requests. In Firechain, the sender's account chain is updated when it sends a message, and the recipient's account chain is updated when it processes that message. The account chains are linked together through by these entries, and those links are used to build a global state that is kept in sync across all of the nodes in the network.
Requests and responses are just messages
A request is a message that is sent from one account to another through a node. A response is a message that is sent from the receiver to the sender in response to a request. They are both processed in the same way. This is because they are both just messages, and they both have the same structure. Responses are just messages that reference other messages.
In Nano's block-lattice model, transactions are considered to be unsettled until a response is received. In Firechain, a response is often not necessary, and it may be omitted entirely where appropriate. For instance, in a peer-to-peer messaging application, it's common to for users to send several messages before a reply is received. However, in many cases, a response is necessary for a request to be considered settled, and, in those cases, the response is required.
Account Abstraction
In Firechain, the concept of an account is somewhat abstract. That's because all accounts are technically represented as entities (i.e. smart contracts) on the network. There's a basic interface that all accounts support by default, but it's possible to arbitrarily add to that functionality by "installing" a custom implementation. For instance, an account can represent a person, a business, a group of people, a group of businesses, a group of groups, or anything else that can be codified into logic. This is a powerful feature that enables Firechain to be used for a wide variety of use cases, and it's one of the reasons why Firechain is so flexible.
Layered Consensus
Firechain uses a layered DPoS consensus mechanism that is based on Tendermint. In Firechain, bonded validators are assigned to consensus groups that are responsible for a set of account chains for a period of time. Validators in the group are tasked with processing messages sent from or destined for that set of accounts, which might include executing logic on their behalf.
Consensus groups are like shards
You can think of consensus groups as a sort of self-contained shard that is responsible for a subset of the network's activity. They can be managed independently of the rest of the network and commit more concise state updates to the global state. This makes it possible for Firechain to handle a much larger level of activity than would be practical with a single global chain that represents the entire network.
Tendermint's Byzantine fault tolerant consensus mechanism is fast and efficient, and that makes it an excellent fit for Firechain. It's a leader-based model that appoints a randomly selected leader for each round. The leader is responsible for proposing a new block, and the other validators in the group are responsible for validating the block and voting on it. If a block is validated by 2/3 of the validators in the group, it is added to the ledger and the next round begins. If the block is not validated, the leader is penalized and the next round begins.
Rather than validating messages for the entire network, consensus groups are responsible for validating messages for a given set of accounts. This means that validators are only responsible for validating messages that are relevant to a small portion of the network, which makes it possible to dynamically scale the capacity of any subset of the network. It also means that validators can take part in "selective" consensus groups that are responsible for validating messages for specific accounts. This makes it possible to support a wide range of specialized use cases, like private applications whose functionality and/or state are restricted to whitelisted accounts, or even centralized consensus groups that are responsible for validating messages for a single smart contract. Accounts must opt-in to isolate themselves to a selective consensus group, and they can opt-out at any time.
Validator performance
The validators in each consensus group are expected to perform their duties in an honest and timely manner, and they can be penalized for failing to meet these expectations.
For example, each time a message is received, a validator is selected from the group to propose a new ledger entry for the sender's account chain. If at least 2/3 of its peers agree with the addition, the account's ledger is updated. If too many validators disagree, the entry is not added to the ledger, and a failed proposal is logged against the proposer. Validators who frequently make invalid proposals or fail to propose as expected are penalized. Penalties vary but often include losing some portion of the bonds posted, thus validators who are penalized too many times are automatically removed from the validator pool.
Selective validators aren't eligible for the network's native validator rewards, but it's possible for the accounts they are responsible for to reward them for their performance. For example, a validator might be rewarded for handling deposits into a high-volume DeFi app's smart contracts. This makes it possible to reward validators for their performance in a way that is specific to the use case they are supporting.
After each round, a new leader is selected. Global consensus groups are disbanded and new groups are formed every 5 minutes. New groups are formed by randomly selecting validators from the pool, and the groups are chosen in such a way that no validator is placed in more than one group at a time or with the same peers as in the previous group. This ensures that even a group containing several malicious validators isn't able to disrupt the network.
Overwatch
Firechain uses a system called Overwatch to ensure that validators and accounts follow the rules of the network. Overwatch is a system of checks and balances that is designed to ensure that validators and accounts are behaving in a way that is consistent with the rules of the network. Because not every case can be anticipated, Overwatch is designed to be flexible and to allow for the addition of new rules as needed.
Anyone can submit a report to Overwatch, and doing so requires the reporter to post a bond to prevent misuse. The system will aggregate evidence cited by the reporter along with internally gathered metadata and assign a committee of Sentries to review the case. If the report is found to be valid by at least 2/3 of the committee, it is added to the offender's history, and the reporter gets a reward along with their returned bond. If the report is invalid, it is discarded and the reporter loses their bond.
Overwatch and Sentries
Sentries are just validators randomly selected from the pool and assigned to the Overwatch consensus group. The Overwatch group doesn't perform the normal duties of a consensus group, like validating messages. Instead, it's responsible for reviewing reports and identifying network participants who are in violation of the protocol's rules. The Overwatch group is otherwise subject to the same rules as other consensus groups, except Overwatch groups rotate less frequently.
It is possible that a case isn't able to be resolved by Sentries. In that situation, the case rolls forward to the next group. If it's still unresolved by that group, the case is escalated to the Council of Guardians, which is made up of validators who have been elected by the community. The Council of Guardians is responsible for reviewing these cases and making a final decision.
Messages
Messages are the fundamental units of Firechain's ledger. They are broadcast from one account and typically directed at a specific receiver, and they generally change the state of at least one account. Messages are signed with the private key of the account they are sent from, and they are verified by that account's current consensus group before being forwarded to the target account. Messages can references others, and these links are used to link accounts together.
Message structure
A message is composed of a header
and a body
. The header contains metadata about the message, and the body contains the actual data being sent. The header is signed with the private key of the account that sent the message, and that signature is verified by the validator that processes the message. The body is not signed and isn't required to be validated, but a hash of the body is included in the header. This allows the network to verify that the body has not been tampered with at any point in the message's journey from sender to receiver.
A message header contains the following fields:
version
: The version of the Firechain protocol that the message is compatible with. This is used to determine a node's capability of handling a given message.type
: The type of message. This is used to determine how to process the message.sender
: The account that sent the message. This is used to determine which consensus group is responsible for delivering the message, and it is also used to verify the message's signature.receiver
: The account intended to receive the message. Important: This is not always the same as the beneficiary of the message.links
: The hash of the message(s) that this message is in response to, if applicable. This is used to link messages together. Note that it is possible for a message to link to multiple other messages, but it is not possible for a message to reference others that would create a cyclical message references, as this would violate the acyclic nature of the HotDAG.bodyHash
: The hash of the message body. This is used to verify that the body has not been tampered with at any point in the message's journey from sender to receiver.timestamp
: The time at which the message was sent. This is used to determine the order in which messages are processed.signature
: The signature of the message header. This is used to verify that the message was sent by the account that it claims to be from.
The body of a message is loosely defined, and it can contain any data that is relevant to the message's purpose. For instance, a message that is sent to a public smart contract might contain a function signature and a set of arguments in plaintext, whereas one sent to a peer-to-peer messaging application's router might contain an encrypted message body. This design choice allows the Firechain protocol to be used in a wide variety of use cases, and it also allows the protocol to be extended in the future without breaking backwards compatibility or requiring all nodes to upgrade.
Receivers ≠ Beneficiaries
The account identified in the receiver
field of a message header is not necessarily the beneficiary or final target of the message. For instance, a message sent to a smart contract might be processed by a router that forwards it to a different account. The receiver
determines which consensus group is responsible for processing the message, and it's possible for specialized consensus groups to handle messages in a manner that is opaque to the network as a whole. This is useful for applications that want to keep their internal logic private or implement some form of off-chain processing.
Message types
Messages are categorized into three types: request
, response
, and notification
. The request
type is used to send messages from one account to another, the response
type is used to send messages in response to requests, and the notification
type is used to send messages that explicitly do not require a response.
Responses are optional...except when they're not
In the same way that not every question needs an answer, not every message needs a response. However, in some cases a response is necessary, and, in those cases, the response is required for the message to be settled.
Let's say that Alice wants to send Bob 10 tokens. Alice sends a request to Bob's account transferring the tokens, and they're debited from her ledger immediately. Bob doesn't necessarily need to acknowledge this transfer. Perhaps he will send a message back confirming receipt, but it's not necessary for the transfer to be considered settled. Therefore, the tokens are credited to Bob's ledger immediately, and the message is settled.
But what if Alice wants to trade 10 tokens of one type for 20 of another type? In this case, Bob needs to acknowledge the transfer in order to settle it. So Alice sends a request to Bob's account proposing to transfer 10 tokens of type A, and Bob sends a response to Alice's account that accepts the 10 incoming tokens in exchange for 20 tokens of type B. Now both transfers are settled, and the trade is complete. Note that Bob could also ignore or reject the trade, in which case the transfer from Alice to Bob would be nullified and no transfer from Bob to Alice would occur.
Firechain requests that require a response are considered to be settled once the response is received, but the request itself is considered finalized as soon as it is broadcast to the network. When a request is received by a node, it is added to the node's copy of the sender's ledger. The node then notifies all of its neighbors about the change. The neighbors then add it to their copies of the ledger and notify their neighbors, and so on. This continues until the transaction has been added to the ledger of every node in the group in a process called gossiping.
Gossiping
Gossiping is a process by which information is spread throughout a group of nodes. In Firechain, gossiping is used to spread information about new transactions throughout the network.
TLDR
Every account's ledger contains the log of its interactions with the network. An entry in an account's ledger represents exactly one message which contains a reference to the hash of a specific previous state (typically the most recent entry in the account's chain). Outgoing messages are validated by the sender's consensus group, and incoming messages are processed by the consensus group that secures the receiving account. Messages are signed with the private key of the account that sent them. Messages can reference other messages, and those references are used to link accounts together and build the global state.
Messages are categorized into three types: request
, response
, and notification
. The request
type is used to send messages from one account to another, the response
type is used to send messages in response to requests, and the notification
type is used to send messages that explicitly do not require a response. When a request is received by a node, it is added to the node's copy of the sender's ledger. The node then gossips the change to its neighbors, and the neighbors then add it to their copies of the ledger and gossip the change to their neighbors, and so on. This continues until the transaction has been added to the ledger of every node in the group. Requests are not fully settled until a response is received, but the request itself is "final" as soon as it is verified by the sender's consensus group.
Potential Pitfalls
While the benefits of managing each account's history independently massively increases the capacity of the network, it's not without some potential risks. For instance, if a node is compromised, it could potentially tamper with the history of a single account. This would not affect the rest of the network, but it would affect the account that was compromised. This is why it's important to use a secure node implementation.
State consistency
One of the challenges with parallel transaction processing is that it's possible for two mutations to be applied to the same account in parallel. This can lead to a situation where the two mutations are applied in a different order on different nodes, which could lead to a divergence in the global state. For instance, if Alice and Bob both attempt to purchase the same NFT at the same time, it's possible that one node will process Alice's transaction first while another processes Bob's transaction first. This could lead to a situation where Alice owns the NFT according to one node's ledger and Bob owns it on another. This is a problem because it's not trivial to determine which node's state is "correct" in this scenario.
Mitigation
Most blockchains solve this problem by using a single global state that is updated in a serial fashion. This ensures that the state is consistent across the entire network, but it also limits the network's throughput. Firechain it by using a distributed state model wherein each account's state is updated independently. Each account's state is managed synchronously, but the state of different accounts can be updated in parallel. Local state consistency is maintained by using a consensus group to verify that each mutation is valid before it is applied to the account's ledger. This ensures that the state of each account is consistent, which is acceptable because the state of individual accounts is generally of little to no importance to the network as a whole.
If Alice and Bob both attempt to purchase the same NFT at the same time, one of them will succeed and the other will fail because the NFT must be transferred from a remote account which can only handle their requests one by one. The NFT will be transferred to the account that successfully purchased it, and the other account will be refunded. The outcome may not necessarily be what Alice or Bob would have preferred, but it guarantees that the state of the network is consistent.
Unhandled messages
A potential vulnerability to this model is that it's possible for a node to receive a message that references a previous entry it hasn't seen yet. In this case, the node notifies its peers of the gap and returns the request to the consensus group's queue until it can be processed. This is not only inefficient, but it also creates a potential attack vector. A malicious node could send a request to a consensus group that references a previous entry which may never have been broadcast at all. The group must wait until the referenced entry has been processed before handling the malicious one. This could be used to create a denial-of-service attack against a consensus group.
Mitigation
To limit this risk, consensus groups have a configurable limit on the number of unprocessable messages they will accept on behalf of a sender. If the group receives message that references an unknown previous entry, and the number of unprocessable messages it has already received is equal to or greater than this limit, the message is simply rejected. This prevents the consensus group from being overwhelmed with requests that it cannot process.
Flooding
Another potential risk is that a malicious user could send a large number of messages to a consensus group, causing it to be overwhelmed and potentially creating a situation where the consensus group is unable to process legitimate requests. This could be done using a variety of techniques, including sending a large number of requests to a single account, or sending many requests to or from one or more accounts controlled by an attacker which reference a large number of previous entries. This is a type of Sybil attack could temporarily disrupt a consensus group's ability to perform its duties.
Mitigation
There are a few layers of protection against this type of attack. The first and most obvious is that accounts can only send as many messages as their heat tolerance allows. This prevents an attacker from sending a large number of messages to a single account, and it also prevents an attacker from sending messages that inclues an unreasonable number of references. Another layer of protection is that the consensus group that secures a given account is not necessarily the same group that secures the account's peers. This means that an attacker would either need to control many accounts that are all part of the same consensus group, or they would need to control many validators such that they run a sufficiently high probability of being grouped with accomplices. The former is unlikely because the accounts in a given group are shuffled frequently, and the latter would require significant resources to pull off.
In the event that an attacker is able to control a large number of accounts that are part of the same group, the network has mechanisms to detect the attack and isolate the attacker's accounts. This is done by monitoring the velocity and volume of messages targeting accounts. When an account appears to be diverging from expectations, the consensus group can notify the network, and the network will remove the account from the consensus group such that the queue can be processed without any new additions. The account will then be moved to a new consensus group, which will process newly received messages for the account but not until the queue has been cleared. This process is called isolation, and it's a last resort to prevent a consensus group from being overwhelmed by a malicious user.
Isolation
Isolation is a process by which an account is removed from its current consensus group and placed into a new one, typically due to abnormal activity.
Accounts that trigger isolation are not typically isolated for long. The network will attempt to reintegrate the account as soon as possible. However, if an account is isolated frequently, the network will identify that account as potentially malicious and raise a case for Overwatch. Escalating measures can be applied via Overwatch to prevent the account from disrupting the network. For example, the network may place the account into a more restrictive consensus group, require it to perform PoW to send messages, reduce the account's heat tolerance to zero for a period of time, or even restrict the account from using the network entirely.
It's important to note that isolation is not intended as a punishment, but rather a protective measure to prevent the network from being misused. We take a very critical view on censorship, and blocking any account at the network level is an absolute last resort that must be approved by several community-appointed guardians in a process similar to a trial by jury. This type of action is only taken when an account's actions are deemed to be malicious or intentionally disruptive, and it is never done without due process.