Преглед изворни кода

Started revising the "paper".

Matthew Carr пре 2 година
родитељ
комит
5b09633229
2 измењених фајлова са 147 додато и 138 уклоњено
  1. 5 0
      .gitignore
  2. 142 138
      doc/Paper/Paper.tex

+ 5 - 0
.gitignore

@@ -6,3 +6,8 @@
 *.toc
 **target/
 crates/scratch/
+*.bbl
+*.fdb_latexmk
+*.fls
+*.xdv
+*.blg

+ 142 - 138
doc/Paper/Paper.tex

@@ -22,32 +22,33 @@ The online services that users currently have access to are incredible. They han
 the details of backing up user data and implementing access controls to facilitate
 safe sharing. However, because these are closed systems, users are forced to trust that
 the operators are benevolent, and they lack any real way of ensuring that the access
-control they prescribe will actually be enforced. There have been several systems proposed
+controls they prescribe will actually be enforced. There have been several systems proposed
 as an alternative to the conventional model, but these systems suffer from several shortcommings.
 They either assume the need for cloud storage providers (Blockstack) or implement all operations
-using a global blockchain, limiting performance (FileCoin). Blocktree takes a different approach.
+using a global blockchain, limiting performance (Filecoin). Blocktree takes a different approach.
 
 The idea behind blocktree is to organize a user's computers into a cooperative unit, called a
 blocktree. The user is said to own the blocktree, and they wield soveriegn authority over it.
 The artifact granting them this authority is the root private key for the blocktree. Measures for protecting
 this key and delegating its authority are important design considerations of the system.
-The owners of blocktrees are encouraged to collaborate with each to store data by
+The owners of blocktrees are encouraged to collaborate with each other to replicate data by
 means of a cryptocurrency known as blockcoin. The blockchain implementing this cryptocurrency
 is the source of global state for the system, and allows for the creation of global paths.
 
-All data stored in blocktree is contained in units called blocks. The blocks in a blocktree, of
-course, form a tree. Each block has a path corresponding to its location in the tree. The first
-component of a fully qualified block tree path is the fingerprint of the root public key of the
+All data stored in blocktree is contained in units called blocks. As the name would suggest, the blocks
+in a blocktree form a tree. Each block has a path corresponding to its location in the tree. The first
+component of a fully qualified blocktree path is the fingerprint of the root public key of the
 blocktree. Thus a blocktree path can globally specify a block. If a block is not a leaf,
-then it is called a directory, and the data it contains is managed by the system,
-including the list of blocks which are children of the block. In addition to its payload of data,
+then it is called a directory, and the data it contains is managed by the system.
+This information includes the list of blocks which are children of the directory. In addition
+to its payload of data,
 each block has a header containing cryptographic access control mechanisms. These mechanisms ensure
-that only authorized users can read or optionally write to the block.
+that only authorized users can read and optionally write to the block.
 
 Users and nodes in the blocktree system are identified by hashes of their public keys. These hashes
-are referred to as principals, as they are the units used for setting access control policy.
+are referred to as principals, and they are used for setting access control policy.
 
-This remainder of this paper is as follows:
+This remainder of this paper is organized as follows:
 \begin{itemize}
 \item A description of the operations of a single blocktree.
 \item The definition of a blockchain which provides global state and links individual blocktrees
@@ -61,12 +62,12 @@ together.
 The atomic unit of data storage, confidentiality and authenticity 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 the public key of the principal whose is being given access.
-The resulting cipher text is stored in the header of the block. Thus
+The block key can be encapsulated using the public key of a principal whose is to be given access.
+The resulting ciphertext is stored in the header of the block. Thus
 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
+header. This ensures that when a principal is given read access to a block, it automatically has
 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 read the block.
 
@@ -83,7 +84,7 @@ writecap is approximately an x509 certificate chain. A writecap contains the fol
 \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:
+of the following conditions are met:
 \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
@@ -91,50 +92,52 @@ 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,
+\item The principal corresponding to the public key used to sign the last writecap in the chain,
 is the owner of the blocktree.
 \end{itemize}
 The intuition 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
+that leads back to the owner of the blocktree. 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
+participating in a blocktree 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
+is recorded in the directory where the node is attached. A node is responsible for the storage of
+the directory where it is attached and all of the blocks that are recursively contained with in it.
+Of course if there is a child node attached to a subdirectory contained in the directory the node is
+responsible for, then the child node is responsible for the subdirectory.
+In this way data storage can be delegated, allowing the system to scale. When more than one
+node is attached to the same directory they form a cluster.
+Each node in the cluster contains a copy of the data that the cluster is responsible for. They
 maintain consistency of this data by running the Raft consensus protocol.
 
-Every blocktree requires at least one node attached to the root block to function. The nodes
-in the root block contain the user's private key. For security, it is highly recommended that
-this key be stored in a Trusted Platform Module (TPM), and that the TPM be configured to disallow
-unauthenticate key use. As it is envisioned for multiple nodes to run on a single computer,
-thus sharing a single TPM, this last point is particularly important. Even though these nodes
-contain the root key, they do not use it for most operations, and instead use the scheme described
-in the next paragraph to obtain their own credentials.
-
-When a new node is created, it generates a new public-private key pair. The public key of this
+When a new blocktree is created a node generates a key pair to serve use as the root keys.
+It is imperative for the security of the system that the root private key is protected, and it
+is highly recommended that it be stored in a Trusted Platform Module (TPM) and that the TPM
+be configured to disallow unauthenticated use of this key. The node then generates its own key pair
+and uses the root private key to issue itself a writecap for the root of the tree. Once it has
+this writecap, it creates the root block and generates a block key for it. A readcap is added to
+this block for the root public key and the node's public key. Additional
+cryptographic operations are performed using the node's key pair, and only when a new writecap
+needs to be created for an addition root node is the root private key used.
+
+When a new node comes online and wishes to join the blocktree, it generates its own key pair.
+The public key of this
 node then needs to be transmitted to another node that's already part of the user's blocktree. The
-mechanism used will depend on the nature of the device on which the node is running, and is
-outside the scope of this description. For example, a phone could scan a QR code which contains
+mechanism used will depend on the nature of the device on which the new node is running.
+For example, a phone could scan a QR code which contains
 the IP address of the user's root node, and then transmit its public key to that internet host.
 In order for the new node to be added to the user's blocktree, it needs to be issued a writecap
-and the block where it will attach needs to have a readcap added.
+and a readcap must be added to the directory where it will be attached.
 This could be accomplished
 by providing a user interface on the node which received the public key from the new node.
 This interface would show the user the requests that have been received from new nodes attempting
 to join their blocktree. The user can then choose to approve or deny the request, and can specify
-the path where the node will attach. If the user chooses to approve the request, they are
-prompted for the root password. This is used to send an authenticated signing request to the TPM on
-the node containing the user's root key. If the password is correct, the TPM will sign the requested
-data, producing a valid writecap, which the node can then send back to the new node.
+the path where the new node will attach. If the user chooses to approve the request, then the writecap
+is signed using the node's key and transmitted to then new node.
 
 The ability to cope with key compromise is an important design consideration in any real-world
 cryptosystem. In blocktree the compromise of a node key is handled by re-keying every block under
@@ -151,45 +154,45 @@ private key in multiple secure cryptographic co-processors is so important.
 A concept that has proven to be very useful in the world of filesystems is the symbolic link.
 This is a short file that contains the path to another file, and is interpreted by most programs
 as being a "link" to that file. Blocktree supports a similar system, where a block can be
-marked as a symbolic link when its body contains a blocktree path. This also provides us with
+marked as a symbolic link and its body contains a blocktree path. This also provides us with
 a convenient way of storing readcaps for data that a node would otherwise not have access to.
 For instance a symbolic link could be created which points to a block in another user's blocktree.
 The other user only knows the public key of the owner of our blocktree, so they issue
 a readcap to it. But the root nodes, when given the user's password, can open this readcap and extract
-the block key. This key can then be encapsulated using he public key of the node which
+the block key. This key can then be encapsulated using the public key of the node which
 requires access, and placed in the symbolic link. When the node needs to read the data
 in the block, it opens the readcap in the symbolic link, follows the link to the block (how
 that actually happens will be discussed below) and decrypts its contents.
 
-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
+While the consistency of individual blocks can be maintained using Raft, a distributed locking
+mechanism is employed to enable transactions which span multiple blocks.
+This is
+accomplished by exploiting the 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:
+for into a single logical block representing the node itself. Thus we can talk about a node having
+a parent, and by this we mean its parent in the nodetree. In terms of the blocktree, the parent
+of a node is the first node encountered when the path back to the root is traversed.
+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.
+\item A node sends a request to lock a block to the current consensus 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.
+  for when the lock expires.
 \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 indicating the result is then passed back up the tree ending at the original 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.
+  enforcing the lock, causing it to be removed.
 \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
+of the consensus cluster that is responsible for the block, this guarantees that
 writes from other nodes will not be accepted.
 
 \section{Connecting Blocktrees}
@@ -202,9 +205,10 @@ which is the sum of the fees for each event in the chain and a variable amount o
 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.
+the fact that blockcoin exists to provide an accounting mechanism for data.
 
-When a node writes data to a tree block, and it wishes this block to be globally accessible, then
+When a node writes data to a tree block, and it wishes this block to be globally accessible or
+replicated for redundancy,
 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
@@ -213,32 +217,32 @@ 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 it will pay and the frequency it will make these payments. 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 
+states the amount of blockcoin it will pay for each of the fragment's maintenance payments. When
+another nodes wishes to accept the offer, it directly contacts the first node, which then sends 
+it the fragment and publishes an 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
+Thus any other node in the network can use the information contained in this event to
 determine the set of nodes which contain the fragments of any given path.
 
 In order for the node which stored a fragment to receive its next payment, it has to pass
-a time-bound challenge-response protocol initiated by the node that ownes the fragment.
+a time-bound challenge-response protocol initiated by the node that owns the fragment.
 The owning node select a leaf in the Merkel tree of the fragment and sends the index of
 this leaf to the storing node. The storing node then walks the path from this leaf back to
 the root of the Merkle tree, and updates a hash value using the data in each node it traverses.
-It sends this result back to the owning node who then verifies that this value matches its
+It sends this result back to the owning node which verifies that this value matches its
 own computation. If it does then the owning node signs a message indicating that the challenge
-passed and that the storing node should be paid. The storing node recives this message and uses
+passed and that the storing node should be paid. The storing node receives this message and uses
 it to construct an event, which it signs and publishes to the blocktree. This event causes
-the blockcoin amount specified to be withdrawn from the owning node's account and deposited
-into storing nodes account.
+the blockcoin amount specified to be transferred from the owning node's to the storing
+node's blocktree.
 
 The fact that payments occur over time provides a simple incentive for nodes to be honest and
 store the data they agree to. In banking terms, the storing node views the fragment as an
 asset, it is a loan of its disk space which provides a series of payments over time.
 On the other hand the owning node views the fragment as a liability, it requires payments to
 be made over time. In order for a blocktree owner to remain solvent, it must balance its
-liabitlies with its assets, incentivizing it to store data for others so that its own data
+liabilities with its assets, incentivizing it to store data for others so that its own data
 will be stored.
 
 In order for nodes to be able to contact other nodes, a mechanism is required for associating
@@ -246,70 +250,74 @@ an internet protocol (IP) address with a principal. This is done by having nodes
 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.
+IP address to a principal in order to receive messages not meant for it.
 
 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
+events, and ensuring previous events
+cannot be changed, another data structure is required to enable efficient queries.
+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:
+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 semantics of local blocktrees.
+In functional programming terms, it can be thought of as a left fold over all of the events in the
+blockchain.
+The above queries are facilitated 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.
+\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 containing 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
+their local copy of each tree block appropriately. The experienced reader will recognize that this is an event 
+sourced architecture. Currently only these two tree blocks are known to be needed, but if new events are
 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.
+queries that we have yet to envision.
 
 \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
+and scalability). 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:
+system calls to interact with the particulars of the blocktree system.
+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}
+The standard WASI filesystem APIs are used
+to interact with the contents of blocktrees. For instance a file descriptor for a block can be obtained
+by calling path\_open. Writes and reads of blocks are performed using the privileges of the node on which
+the app is running. 
 
-When an app is installed it is given a block under which it can store data that is shared between all nodes
+When an app is installed it is given a directory 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". 
+with the string ``/apps". When an app is runs on a node, it is confined to a block contained
+in the node's directory. It is only allowed read and write blocks in this block, but to allow it to
+access shared data, a symbolic link is created to the app's shared directory 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.
+Apps are published by writing them into a blocktree. The path of the directory used to publish an app is used to
+identify it. Only one app per directory is allowed. This directory contains the WebAssembly module itself as
+well as a JSON manifest. This manifest defines the app's user-friendly name as well as the list
+of permissions it requires. This list of permissions is used to determine which APIs the app has access to.
 
 % Privacy Safe vs Unsafe
-Apps are broken into two large categories: those that are privacy safe and those that are not.
+Apps are broken into two 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
+outside of the blocktree it's part of. Thus requesting 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
@@ -323,66 +331,62 @@ supply a protocol contract to. This contract is then compiled into a state machi
 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.
+would be compiled to a particularly simply state machine, with only one state: the listening state.
+This state would expose a hook that where a callback can be registered to handle a 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
+More complicated (stateful) protocols would have 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.
+the callbacks only use an approved set of APIs, but could enable much higher performance.
 
 % 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
+running on dies (which is detected by other nodes), 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
+deaths are recorded. More interestingly, this can be used to integrate with a control
+plane. For instance, if a blocktree were running in AWS, when a message is received indicating
+that a node has died, a new EC2 instance could be started to replace it. 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
+In order to explore how blocktree can be used, the design of several hypothetical systems
+is discussed. It's important to note that blocktree does not try to force all computation
+to be local to a user's device, it merely tries to enable this for applications where it
 is possible.
 
 \subsection{Contacts and Mail}
 The first application we'll consider is one which manages a user's contacts. This would expose
-the usual CRUD operations, allowing a user to input the name of a person they know and associate
+the usual create, read, update and delete operations, allowing a user to input the name
+of a person they know and associate
 that name with their public key. Once the principal of a person is known, then their public
 key can be looked up in the global blocktree. This principal needs to be communicated to the
 user via some out-of-band method. They could receive it in an email, a text message, or embedded
-in a QR code. Of course this out-of-band communications needs to be authenticated, otherwise
+in a QR code. Of course this out-of-band communication needs to be authenticated, otherwise
 it would be easy to fool the user into associating an attacker's key for the person.
 
 The user now has a way of associating a blocktree with the name of this person. However, the
-root public key of this block tree is not enough to establish secure communications, because
-the root private key is not avialable to every node in the person's blocktree. In particular
-it would be inadvisable for the root private key to be stored on a user's mobile device,
-so a message encrypted using the root public key would not be readable on this device. To
-address this mailbox blocks are created.
-
-For each contact two blocks are created: the inbox and the outbox. The user creates a readcap
-for the person and adds it to the outbox. The inbox is a symbolic link to the user's outbox in
-the blocktree of the person. Thus each person can read messages sent to them using their readcap,
-and they can write messages into their own blocktree where the other party knows how to find them.
-Now to solve the problem outlined above, the person needs to give permission to a node in their
-blocktree in order for it to read messages from the user. It does this by creating a new readcap
-for the node, containing the block key in the readcap it was issued. It then stores that
-readcap in the symbolic link in its blocktree (the inbox for the user). When the person uses
-their mobile to read messages from the user, it looks at the union of the readcaps in the
-symbolic link and the inbox. Once it finds the one for its principal, it decryptes the block key
-and uses it to decypher the contents of the inbox.
-
-In addition to being able to check its inbox for messages, the person also receives a blocktree
-message from the user when a new message is sent. This means that the person doesn't need to
-constantly poll the inbox to see if it has new messages, it can be assured it will be
-notified.
+root public key of this blocktree is not enough to establish secure communications, because
+the root private key is not available to every node in the person's blocktree. In particular
+it would be inadvisable for the root private key to be stored on a user's mobile device. To
+address this mailbox directories are created.
+
+For each contact two directories are created: the inbox and the outbox. The user creates a readcap
+for another user's root key and adds it to the outbox. The inbox is a symbolic link to the user's
+outbox in the blocktree of the other user. Thus each user
+can write messages into their own blocktree at a location where the other party knows how
+to find them. But, in order for a node to read these messages it requires a its own readcap. Only the root
+nodes can issue this readcap as only they have access to the root key. Once permission has been
+granted to a node, a root node can use the root key to decrypt the readcap issued to it, and then
+encrypt it using the public key of the node. The resulting readcap is then stored in the header
+of the inbox.
+
+In addition to being able to check the inbox for mail, a blocktree message is sent to the receiving
+blocktree when mail is sent. This message may contain the entire contents of the mail, if the
+contents are short enough. But if the mail contains a lot of data, for instance a video, then
+the message just serves as a notification that new mail is available.
 
 \subsection{Social Network}
 Building a social network on top of the contacts app is fairly straight-forward. Once
@@ -443,7 +447,7 @@ I hope this example shows that having a standard format for data and the federat
 can provide designers with much greater flexibility, even if they do not care about decentralization
 or their user's privacy.
 
-\subsection{The Open Metaverse}
+\subsection{The Metaverse}
 As a final example I'd like to consider a platform for recording spacial information. The key insight
 that enables this is very general: blocktree enables the creation of distributed tree-like data structures.
 For instance, its straight forward to imagine creating a distributed hashtable implemented as a red-black tree.