\documentclass{article}
\usepackage{amsfonts,amssymb,amsmath}
\usepackage[scale=0.75]{geometry}
\usepackage{hyperref}

\title{Blocktree \\
\large A platform for distributed computing.}
\author{Matthew Carr}
\date{May 28, 2022}
\begin{document}
\maketitle
\begin{abstract}
Blocktree is a platform which aims to make developing reliable distributed systems easy and safe. 
It does this by defining a format for data stored in the system, a mechanism for replicating
that data, and a programming interface for accessing it. It aims to solve the difficult problems
of cryptographic key management, consensus, and global addressing so that user code can focus on
solving problems germane to their application.
\end{abstract}

\section{Introduction}
(Do I need this?)

\section{An Individual Blocktree}
The atomic unit of data storage and privacy and authenticity guarantees is called a block. A
block contains a payload of data. Confidentiality of this data is achieved by encrypting it using 
a symmetric cipher using a random key. This random key is known as the block key.
The block key is encapsualated using
a public key cipher and the resulting cipher text is stored in the header of the block. Thus
only the person possessing the corresponding private key will be able to access the contents of
the block. Blocks are arranged into trees, and the parent of the block also has a block key.
The child's block key is always encapsulated using the parent's key and stored in the block
header. This ensures that if a principal is given access to a block, they automatically have
access to every child of that block. The encapsulated block key is known as a read capability,
or readcap, as it grants the holder the ability to the block.

Authenticity guarantees are provided using a digital signature scheme. In order to change the
contents of a block a data structure called a write capability, or writecap, is needed. A
writecap is approximately an x509 certificate chain. A writecap contains the following data:
\begin{itemize}
\item The path the writecap can be used under.
\item The principal that the writecap was issued to.
\item The timestamp when the writecap expires.
\item The public key of the principal who issued the writecap.
\item A digital signature produced by the private key corresponding to the above public key.
\item Optionally, the next writecap in the chain.
\end{itemize}
The last item is only excluded in the case of a self-signed writecap, i.e. one that was signed by
the same principal it was issued to. A writecap is considered valid for use on a block if all
of the following conditions are true:
\begin{itemize}
\item The signature on every writecap in the chain is valid.
\item The signing principal matches the principal the next writecap was issued to for every
write cap in the chain.
\item The path of the block is contained in the path of every writecap in the chain.
\item The current timestamp is strictly less than the expiration of all the writecaps in the
chain.
\item The principal corresponding to public key used to sign the last writecap in the chain,
is the owner of the blocktree.
\end{itemize}
The intiution behind these rules is that a writecap is only valid if there is a chain of trust
that leads back to the owner of the block tree. The owner may delegate their trust to any number
of intermediaries by issuing them writecaps. These writecaps are scoped based on the path
specified when they are issued. These intermediaries can then delegate this trust as well.
A block is considered valid if it contains a valid writecap, it was signed using the key
corresponding to the first writecap's public key, and this signature is valid.

Blocks are used for more than just orgnaizing data, they also organize computation. A program
participating in the blocktree network is referred to as a node. Multiple nodes may be run on
a single computer. Every node is attached to the blocktree at a specific path. This information
is recorded in the block where the node is attached. A node is responsible for the storage of
the block where it is attached and the blocks that are descended from this block, unless there
is another node attached to a descendent block.
In this way data storage can be delegated, allowing
the system to scale. When more than one node is attached to the same block they form a cluster.
Each node in the cluster contains a copy of the data that the cluster is reponsible for. They
maintain consistency of this data by running the Raft consensus protocol.

TODO: Nodes have keys. These keys are signed by the root key, creating a tree of trust.

TODO: Symbolic links and readonly models (views?).

While the consistency of an individual block can be maintained using Raft, in order to enable
transactions which span multiple blocks a distributed locking mechanism is employed. This is
accomplished by exploiting hierarchical arrangement of nodes in the tree. In order to describe
this, its first helpful to define a new term. The \emph{nodetree} of a blocktree is tree obtained
from the blocktree by collapsing all the blocks that a node (or cluster of nodes) is responsible
for into a single logical block representing the node itself. Thus we can talk about the node
which is the parent of another node, and by these we mean it is the parent of the node in the
nodetree. What this means in terms of the blocktree is that it is the first node encountered
when one traverses the path from the current block back to the root. Now, distributed locking
works as follows:
\begin{itemize}
\item A node sends a request to lock a block to the current concensus leader in its cluster.
  If the node is not part of a cluster, then it is the leader. This request contains a timestamp
  for when the lock expires, preventing the situation where a lock is never released.
\item If the leader is responsible for the block then it moves on to the next step. Otherwise
  it contacts its parent and forwards the lock request and this step is repeated for the parent.
\item The responsible node checks to see if there is already a lock for this block. If there is
  then the request fails. Otherwise the request succeeds and a lock is placed on the block. A
  message indicating the result is then pass back up the tree ending at the orignal node. This
  message includes the principal of the node enforcing the lock.
\item Once the locking node is done making its updates it sends a message directly to the node
  enforcing the lock, causing it to remove the lock.
\end{itemize}
Locking a block locks the subtree rooted at that block. Thus no writes to any path contained in
the path of the locked block will be allowed, unless they come from locking node. If the locking
node does not send the message
unlocking the block before the lock expires, then the modifications which had been performed by
it are dropped and the block reverts to its prior state. Since the locking node is the leader
of the consensus cluster that is responsible for the block's, this guarantees that
writes from other nodes will not be accepted.

\section{Connecting Blocktrees}
In order to allow nodes to access blocks in other blocktrees, a global ledger of events is used.
This ledger is implemented using a proof of work (PoW) blockchain and a corresponding 
cryptocurrency known as blockcoin. Nodes mine chain blocks (not to be confused with the tree 
blocks we've been discussing up till now) in the same way they do in other PoW blockchain
systems such as BitCoin. The node which manages to mine the next chain block receives a reward,
which is the sum of the fees for each event in the chain and a variable amount of newly minted
blockcoin. The amount of new blockcoin created by a chain block is directly proportional to the
amount of data storage events contained in the chain block. Thus the total amount of blockcoin
in circulation has a direct relationship to the amount of data stored in the system, reflecting
the fact that blockcoin exists to provide and accounting mechanism for data stored in the system.

When a node writes data to a tree block, and it wishes this block to be globally accessible, then
it produces what are called fragments. Fragments are the output symbols from an Erasure Coding
algorithm (such as the RaptorQ code). These algorithms are a class of fountain codes which have
the property that only $m$ out of $n$ (where $m < n$) symbols are needed to reconstruct the
original data. Such a code ensures that even if some of the fragments are lost, as long as $m$
remain, the original data can be recovered.

Once these fragments have been computed an event is created for each one and published to the
blockchain. This event indicates to other nodes that this node wishes to store a fragment and
states the amount of blockcoin the node will pay to the first node that accepts the offer. When
another nodes wishes to accept the offer, it directly contacts the first node, who then sends 
it the fragment an publishes and event stating that the fragment is stored with the second 
node. This event includes the path of the block the fragment was computed from, the fragment's 
ID (the sequence number from the erasure code), and the principal of the node which stored it.
Thus any other node in the network can use the information contained in these events to
determine the set of nodes which contain the fragments of any given path.

In order for nodes to be able to conntact other nodes, a mechanism is required for associating
an internet protocol (IP) address with a principal. This is done by having nodes publish events
to the blockchain when their IP address changes. This event includes their new IP address,
their public key, and a digital signature computed using their private key. Other nodes can
then verify this signature to ensure that an attacker cannot bind the wrong
IP address to a principal in order to receive messages it was not meant to have.

While this event ledger is useful for appending new events, and ensuring that previous events
cannot be changed, another data structure is required to ensure that queries on this data can
be performed efficiently. In particular, it's important to be able to quickly perform the
following queries:
\begin{itemize}
\item Find the set of nodes storing the fragments for a given path.
\item Find the IP address of a node or owner given a principal.
\item Find the public key associated with a principal.
\end{itemize}
To enable these queries a special blocktree is maintained by each node in the network: the global blocktree.
This tree does not support the usual writing and locking sematics of local blocktrees. It can be thought of as
a left fold of all of the events in the blockchain, where each event is processed by updating blocks in the
global tree appropriately. The above queries are facilitate by the following blocks:
\begin{itemize}
\item \emph{/global/fragments}: this block contains a hashtable where the key is a path and the value is the list
of nodes storing the fragments for the block at that path.
\item \emph{/global/principals}: contains a hashtable where the key is the a principal and the value is the tuple
contining the public key of that principal, its current IP address, and its current blockcoin balance.
\end{itemize}
To compute the entries in these tree blocks, the nodes in the network iterate over all the chain blocks, updating
their local copy of each tree block approriately. The experienced reader will recognize that this is an event 
sourced architecture. At this time only the two tree blocks are known to be needed, but if new events need to be
added to the system it's easy to see that this system can be used for creating other data structures enabling
queries that we have yet to envision. One such extension is the registration of globally unique names, which will
be the focus of future work.

\section{Programming Environment}
Enabling an excellent developer experience is one of the primary goals of this system (the others being security
and scaleability). Nodes execute user code that has been compiled into WebAssembly modules. Such code
running on a blocktree node is referred to as an "app". An app
executes in a sandbox that isolates it from other code, as well as the security critical operations of the node
itself. The sandbox provides the code with an extension of the WebAssembly System Interface (WASI), with extra 
system calls to interact with the particulars of the blocktree system. The stadard WASI filesystem APIs are used
to interact with the contents of blocktrees. For instance a file descriptor for a remote block can be obtained
by calling path\_open. Writes and reads of blocks are performed using the privledges of the node on which
the app is running. The extra system calls fall into three categories:
\begin{itemize}
\item Distributed Locking
\item Messaging
\item Supervision Trees
\item Protocol Contracts (Session Types)
\end{itemize}

When an app is installed it is given a block under which it can store data that is shared between all nodes
in the blocktree. The path of this block is formed by prefixing the path the app was published at
with the string "/apps". When an app is installed on a particular node, it is run in a block contained
in the node's block. It can read and write blocks in this block, and to allow it to access shared data,
a symbolic link is created to the app's block in "/apps". 

% App Publishing
These apps are, of course, distributed in a blocktree. The path of the block used to publish the app is used to
identify the app, and must be unique. The block containing the app contains the WebAssembly module itself as
well as JSON file containing the app's manifest. This manifest defines the app's name as well as the list
of permissions it requires. This list of persmissions is used to determine which APIs the app will have access to.

% Privacy Safe vs Unsafe
Apps are broken into two large categories: those that are privacy safe and those that are not.
An app is privacy unsafe if it requests any permissions which allow it to send data
to any node that is not part of the blocktree in which it's running. Thus request the ability to
open a TCP socket would cause an app to be privacy unsafe. Similarly the creation of a protocol handler for
HTTP would also be privacy unsafe. Privacy unsafe apps can limit the scope of their unsafety by
imposing limits on the unsafe APIs that they request. For instance an app which needs to send
blocktree message back to the blocktree it was published in can request the messaging permission
for a path in this tree. Similarly, an app which only wants to open a TCP socket listening on the
local network, can limit the scope of its requested permission.

% Protocol Contracts
In order to make it easy to write apps which interface with existing systems, most notably
those using HTTP, apps are able to define protocols using a contract language and then register
call backs for these protocols. This works by providing a system call which the app can
supply a protocol contract to. This contract is then compiled into a state machine by the node
and a handle is returned to the app. This handle is then used to register callbacks for different
parts of the protocol. This ensures that the protocol is handled by the node itself and that
protocols can be shared between many different apps as a library. For instance, the HTTP protocol
would be compiled to a particularly simply state maching, with only one state: the listening state.
This state would expose a hook that where a callback can be registered to handle the request.
This state also defines the record format used to pass the request information to the callback
and the record format of the return value that is expected in order to produce the response.
More complicated (stateful) protocols would more states, each defining their own request and
response records, as well as hooks. One nice thing about this setup is that it will enable
optimizations where the state machine and the user callbacks can be compiled into a program
which can be safely run in the node itself, or even in a SmartNIC. This would require that
the callbacks only use an approved set of APIs, but it can enable much higher performance
network services.

% Supervision Trees
Apps can also arrange themselves into supervision trees, in the same way that Erlang
processes are arranged. In this scheme, when a child app crashes, or the node its
running on dies (which is detected by the node), then the app receives a message. In the
simplest case this can be used to implement a logging system, where crashes and node
deaths are recorded. More interestingly, this could be used to integrate with a control
plan. For instance, if a blocktree were running in AWS, when a message is recevied indicating
that a node has died a new EC2 instance could be started to replace it. Of course these
are just two of the potential applications of this mechanism. The reliability of Erlang
and other system employing the Actor Model have shown the robustness of this approach.

\section{A Brave New Web}
In order to explore how this system can be used, the design of several hypothetical systems
is discussed. It's important to note that blocktree does not try to force all compuatation
to be local to a user's device, it merely trys to enable this for applications where it
is possible.

\subsection{A contacts application.}

\subsection{A distributed social network.}

\subsection{An ecomerce website.}

\subsection{The Open Metaverse}

\end{document}
