A decentralized social network is one where two users can find each other and communicate, even under adverse conditions. Users must be able to run a node and use it to communicate with each other. Each node must reach consensus about a user’s transactions and deliver them to all other nodes. If Alice follows Bob at one node, it must make sure that she wasn’t already following Bob and then update this relationship on every other node.
Users generate a lot of transactions and expect real-time delivery. Twitter, for example, has 200M daily users and sees 10k TPS and 100GB/day state growth. Existing decentralized networks can’t handle this kind of load with real-time delivery. It’s not because it’s impossible, but because they make tradeoffs to solve different user problems. Blockchains move money and are designed to prevent double spends, which makes sharding and pruning data difficult. Federated systems like email are shard-able but have weak decentralization and consistency, which makes apps harder to build. See Appendix D for more details.
Farcaster used a CRDT-based system called a deltagraph to decentralize its social network. By defining every transaction as a CRDT operation, consensus was reached quickly without coordination at the local node and gossiped to other nodes. Creating accounts and collecting fees were handled by an external blockchain, so the deltagraph could focus on social transactions. Farcaster was able to serve 100k users doing 500 TPS with 2GB/day state growth.
As the network grew to thousands of nodes, some transactions took days to reach all users. If a node experienced gossip failures, it could only recover by syncing manually with every other node. Since CRDT’s have no ordering there is no way to know if you missed a specific transaction without comparing all transactions since the beginning of time. Nodes also implement per-user rate limits to prevent flooding attacks, but these must be implemented locally since there is no globally consistent state. A transaction accepted by one node could be temporarily rejected by another. Some ordering of transactions was going to be necessary to meet the real-time guarantees that a social network needs. See Appendix C.
Snapchain is a replacement for Farcaster’s deltagraph that solves this problem. It uses the blockchain pattern to introduce ordering and achieve real-time delivery. Transactions are reduced to narrow operations like post and like, which must be independent across accounts to make sharding easy. The network prunes transactions often and only guarantees availability of recent state of the network. Pruning makes the network more efficient, reclaiming space when transactions conflict (e.g. like + unlike) or when a user stops paying rent to the network. Like the deltagraph before it, it delegates account creation and fee collection to an external blockchain.
Users create and manage accounts using a registry contract on an external blockchain. Calling the contract issues a unique account number called the farcaster id to the wallet. **Messages signed by the wallet are treated as authorized actions from the account. The account can be transferred to another wallet and may choose a recovery address in case the wallet is lost.
A blockchain has strong security and consistency guarantees, which make it easy to build features like account recovery. Users can also use smart contract wallets to share ownership of accounts. The downside is that there is a fee for each transaction, but this is tolerable since such actions are infrequent.
Accounts also need usernames for convenience and there exist many systems like ENS. If the user’s wallet can prove ownership of such a name via onchain or offchain proof, the account is said to own the name. While all references to the account in data structures are made to its farcaster id*,* apps can replace it with the friendly username in their user interface.
The registry also lets users generate “app keys” which can post messages on behalf of the account. App keys have limited permissions and cannot modify the account itself or other app keys. Users can use them like auth tokens to delegate permissions to third party applications without exposing their entire wallet.
A blockchain transaction is one that happens on the external blockchain. Alice makes a new account by making a transaction to the registry contract which associates a keypair with her account. A copy of every relevant blockchain transaction is held on Snapchain.
A snapchain transaction is a social action taken by a user like making a new post. Alice says “Hello World” by making an add-post transaction, signing it and broadcasting it. There are transaction types for common actions like deleting posts or following other users. Snapchain transactions are self-authenticating because any observer can verify that the chain of signatures back to the registry on the external blockchain.
< Diagram of transaction>
A user’s account state is the state derived after processing all of its blockchain and snapchain transactions. **In the example below, we see Alice’s account state changing as she creates an account, adds a post and then deletes it.
A user’s account state is a set of blockchain and snapchain transactions. A new transaction either adds itself to the account state or replaces or deletes a prior transaction. Transactions made by one account cannot affect the state of another account. Enforcing this restriction makes Snapchain more scalable since account-level sharding becomes trivial to implement.
An account’s state has a deterministic state root which is computed by putting all the unique transaction ids of the state into a merkle trie. The state root can be used to quickly compare the state of two accounts for sync or error correction.