parazyd 1 год назад
Родитель
Сommit
87df23be1a

+ 13 - 9
doc/src/arch/anonymous_assets.md

@@ -3,7 +3,8 @@
 DarkFi network allows for the issuance and transfer of anonymous assets
 with an arbitrary number of parameters. These tokens are anonymous,
 relying on zero-knowledge proofs to ensure validity without revealing
-any other information. **All transactions over the network are managed by smart contracts.**
+any other information. **All transactions over the network are managed
+by smart contracts.**
 
 New tokens are created and destroyed every time you send an anonymous
 transaction. To send a transaction on DarkFi, you must first issue a
@@ -17,15 +18,17 @@ Through this process, the link between inputs and outputs is broken.
 
 ## Mint
 
-During the **Mint** phase we create a new coin commitment $C$, which is bound
-to the public key $P$. The coin commitment $C$ is publicly revealed on the
-blockchain and added to the merkle tree, which is stored locally on
-the DarkFi wallet.
+During the **Mint** phase we create a new coin commitment $C$, which is
+bound to the public key $P$. The coin commitment $C$ is publicly
+revealed on the blockchain and added to the Merkle tree, which is
+stored locally on the DarkFi wallet.
 
 We do this using the following process:
 
-Let $v$ be the coin's value. Generate random $r_C$, $r_V$ and a secret serial
-$\rho$. The random values ensure the uniqueness and security of the commitment; the serial $\rho$ will be later used to generate the nullifier $N$ of the burn phase and to tie $N$ to $C$.
+Let $v$ be the coin's value. Generate random $r_C$, $r_V$ and a secret
+serial $\rho$. The random values ensure the uniqueness and security of
+the commitment; the serial $\rho$ will be later used to generate the
+nullifier $N$ of the burn phase and to tie $N$ to $C$.
 
 Create a commitment to these parameters in zero-knowledge:
 
@@ -43,8 +46,9 @@ Reveal $C$ and $V$ commitments. Add $C$ to the Merkle tree.
 When we spend the coin, we must ensure that the value of the coin
 cannot be double spent. We call this the *Burn* phase. The process
 relies on a $N$ nullifier, which we create  using the secret key $x$
-for the public key $P$ and the coin itself $C$. Nullifiers are unique per coin and prevent
-double spending. $R$ is the Merkle root. $v$ is the coin's value.
+for the public key $P$ and the coin itself $C$. Nullifiers are unique
+per coin and prevent double spending. $R$ is the Merkle root. $v$ is
+the coin's value.
 
 Generate a random number $r_V$.
 

+ 26 - 20
doc/src/arch/arch.md

@@ -49,10 +49,12 @@ gantt
         <td>Research</td>
         <td></td>
         <td>
-Research new techniques, draft up architecture design documents and modify the specs.
+Research new techniques, draft up architecture design documents and
+modify the specs.
 
-During this phase the team looks into new experimental techniques and begins to envision
-how the product will evolve during the next phase of the cycle.
+During this phase the team looks into new experimental techniques and
+begins to envision how the product will evolve during the next phase of
+the cycle.
         </td>
         <td>pre-alpha</td>
     </tr>
@@ -64,11 +66,12 @@ how the product will evolve during the next phase of the cycle.
 Add big features and merge branches. Risky changes that are likely to
 cause bugs or additional work must be done before the end of this phase.
 
-The first 10 weeks overlap with the Dcon3  & Dcon4 phases of the previous
-release, and many developers will focus on bug fixing in those first weeks.
+The first 10 weeks overlap with the Dcon3  & Dcon4 phases of the
+previous release, and many developers will focus on bug fixing in those
+first weeks.
 
-Developers dedicate a steady 1-2 days/week to the bug tracker, focusing on
-triaging and newly introduced bugs.
+Developers dedicate a steady 1-2 days/week to the bug tracker, focusing
+on triaging and newly introduced bugs.
         </td>
         <td>alpha</td>
     </tr>
@@ -78,11 +81,13 @@ triaging and newly introduced bugs.
         <td></td>
         <td>
 Work to improve, optimize and fix bugs in new and existing features. 
-Only smaller and less risky changes, including small features, should be
-made in this phase.
+Only smaller and less risky changes, including small features, should
+be made in this phase.
 
-If a new feature is too unstable or incomplete, it will be reverted before the end of this phase.
-Developers spend 2-3 days/week in the bug tracker, triaging, fixing recently introduced or prioritized module bugs.
+If a new feature is too unstable or incomplete, it will be reverted
+before the end of this phase. Developers spend 2-3 days/week in the
+bug tracker, triaging, fixing recently introduced or prioritized module
+bugs.
         </td>
         <td>alpha</td>
     </tr>
@@ -93,10 +98,8 @@ Developers spend 2-3 days/week in the bug tracker, triaging, fixing recently int
         <td>
 Focus on bug fixing and getting the release ready.
 
-Development moves to the stable stabilizing branch. In 
-master Dcon1 for the next release starts. 
-stable is regularly merged into master.
-
+Development moves to the stable stabilizing branch. In master Dcon1
+for the next release starts. stable is regularly merged into master.
 
 High priority bugs dictate how much time developers will spend in the 
 tracker as oppose to work on the next release Dcon1 features.
@@ -108,10 +111,12 @@ tracker as oppose to work on the next release Dcon1 features.
         <td>Prepare release</td>
         <td>2 weeks</td>
         <td>
-Stable branch is frozen to prepare for the release. Only critical and carefully reviewed bug fixes allowed.
+Stable branch is frozen to prepare for the release. Only critical and
+carefully reviewed bug fixes allowed.
 
 Release candidate and release builds are made.
-Developers spend a short time 5 days/week with an eye in the tracker for any unexpected high priority regression.
+Developers spend a short time 5 days/week with an eye in the tracker
+for any unexpected high priority regression.
         </td>
         <td>release candidate</td>
     </tr>
@@ -120,8 +125,8 @@ Developers spend a short time 5 days/week with an eye in the tracker for any une
         <td>Release</td>
         <td>1 week</td>
         <td>
-Stage where the final builds are packaged for all platforms, last tweaks
- to the logs, memes, social media, video announcements.
+Stage where the final builds are packaged for all platforms, last
+tweaks to the logs, memes, social media, video announcements.
 
 The final switch is flicked on [dark.fi](https://dark.fi/) for the new
 release to show up on the Download page.
@@ -262,5 +267,6 @@ to properly price them for verification fees.
 
 ### Documentation
 
-* Create beginner level tutorial to introduce contract development and tools.
+* Create beginner level tutorial to introduce contract development and
+  tools.
 * Create a list of outstanding work before mainnet.

+ 47 - 46
doc/src/arch/chat.md

@@ -2,14 +2,15 @@
 
 ## Improve Sync Algo
 
-Right now the algo for syncing is very bad. It looks through every available
-channel sequentially and performs these steps:
+Right now the algo for syncing is very bad. It looks through every
+available channel sequentially and performs these steps:
 
-1. get the current tips
-2. request their parents
-3. repeat
+1. Get the current tips
+2. Request their parents
+3. Repeat
 
-The entire process is the slowest sync algo. Lets think of a better sync algo.
+The entire process is the slowest sync algo. Lets think of a better
+sync algo.
 
 ### Graph Locator
 
@@ -19,21 +20,21 @@ struct GraphLocator {
 }
 ```
 
-Each tip slot contains a *sparse* path from an active tip to the current root.
-Sparse here means the path is not complete.
+Each tip slot contains a *sparse* path from an active tip to the
+current root. Sparse here means the path is not complete.
 
-The slot is: current tip, a continuous path for the next 5 and then from there,
-gaps which double for every event.
+The slot is: current tip, a continuous path for the next 5 and then
+from there, gaps which double for every event.
 
-When a node receives the graph locator, it can them compare it with its own
-graph and immediately see where their graphs both diverge.
+When a node receives the graph locator, it can them compare it with
+its own graph and immediately see where their graphs both diverge.
 
 It then will sync from the divergence point.
 
 ### Phased Algo
 
-Events are increasingly carrying more data. Therefore the graph structure should
-be separated from the event data.
+Events are increasingly carrying more data. Therefore the graph
+structure should be separated from the event data.
 
 ```
 struct EventHeader {
@@ -44,30 +45,31 @@ struct EventHeader {
 
 The sync algo then becomes:
 
-1. **Locate phase:** Our node creates a GraphLocator and sends it to the remote.
-   The remote uses this to see which events we're missing.
+1. **Locate phase:** Our node creates a GraphLocator and sends it to
+   the remote. The remote uses this to see which events we're missing.
    The remote then sends a *capped* flood of Inventory objects.
-    1. Our node may need to repeat sending the GraphLocator requests since
-       the remote only sends a capped number of updates.
-2. **Header sync phase:** Our node sends GetData request containing lists of the
-   missing event header hashes. The remote responds with event header objects.
-   Our node then links these up to build the missing graph structure.
-3. **Data sync phase:** Lastly our node walks the graph and for every missing
-   blob, requests the data. It does this backwards.
+    1. Our node may need to repeat sending the GraphLocator requests
+       since the remote only sends a capped number of updates.
+2. **Header sync phase:** Our node sends GetData request containing
+   lists of the missing event header hashes. The remote responds with
+   event header objects. Our node then links these up to build the
+   missing graph structure.
+3. **Data sync phase:** Lastly our node walks the graph and for every
+   missing blob, requests the data. It does this backwards.
 
 ### Effect on DDoS
 
-While improved sync is desirable, it still does not mitigate DDoS since the
-attacker can easily double their resources. This merely makes nodes more
-performant.
+While improved sync is desirable, it still does not mitigate DDoS since
+the attacker can easily double their resources. This merely makes nodes
+more performant.
 
 ## Protocol Restriction
 
-Proposal: add a global rate limit for messages. This is the easiest and most
-direct fix we should apply right now.
+Proposal: add a global rate limit for messages. This is the easiest
+and most direct fix we should apply right now.
 
-There is a rolling window of 1 minute with a maximum of 100 events allowed.
-Violators get `channel.ban()`.
+There is a rolling window of 1 minute with a maximum of 100 events
+allowed. Violators get `channel.ban()`.
 
 Use a `VecDeque` of timestamps. `clean_bantimes()` will then do:
 
@@ -80,8 +82,8 @@ while let Some(ts) = bantimes.front() {
 }
 ```
 
-Now all events within the list should be within the last minute. Push any new
-events to the list, then check:
+Now all events within the list should be within the last minute.
+Push any new events to the list, then check:
 
 ```rust
 if bantimes.len() > N {
@@ -91,27 +93,26 @@ if bantimes.len() > N {
 
 This is the most immediate mitigation and overdue anyway.
 
-Later we will make the 1 minute and N configurable with the static event graph
-admin instance. For now, we can hardcode these values.
+Later we will make the 1 minute and N configurable with the static
+event graph admin instance. For now, we can hardcode these values.
 
 ## Resource Manager
 
-This will also be a big step towards alleviating DDoS. Check the p2p doc for a
-design.
+This will also be a big step towards alleviating DDoS. Check the p2p
+doc for a design.
 
 ## RLN
 
-The global limit is not ideal since it's... global. However RLN fixes this since
-it provides a way for people to not be affected by the rate-limit. Problem
-solved.
+The global limit is not ideal since it's... global. However RLN fixes
+this since it provides a way for people to not be affected by the
+rate-limit. Problem solved.
 
 ## Spam
 
-Just regular spam. Solved by admin/mod features and outside the scope of this
-doc. We need the static event graph though so we can lock channels down during
-times of high activity or modify the posting rate of certain keys (like public
-ones).
-
-We already had the first step now with the `/ban` feature and admin keys in the
-TOML.
+Just regular spam. Solved by admin/mod features and outside the scope
+of this doc. We need the static event graph though so we can lock
+channels down during times of high activity or modify the posting rate
+of certain keys (like public ones).
 
+We already had the first step now with the `/ban` feature and admin
+keys in the TOML.

+ 98 - 88
doc/src/arch/consensus.md

@@ -22,17 +22,17 @@ blockchain achieve consensus.
 DarkFi uses RandomX Proof of Work algorithm.
 Therefore, block production involves the following steps:
 
-* First, a miner grabs its current best ranking fork and extends it with a
-  block composed of unproposed transactions from the miner's mempool.
+* First, a miner grabs its current best ranking fork and extends it
+  with a block composed of unproposed transactions from the miner's
+  mempool.
 
-* Then the miner tries to find a nonce such that when the block header is
-  hashed its bytes produce a number that is less than the current difficulty
-  target of the network, using the [RandomX mining
-  algorithm](https://github.com/tevador/RandomX).
+* Then the miner tries to find a nonce such that when the block header
+  is hashed its bytes produce a number that is less than the current
+  difficulty target of the network, using the [RandomX mining algorithm](https://github.com/tevador/RandomX).
 
-* Once the miner finds such a nonce, it broadcasts its block proposal to the
-  P2P network. Finally the miner triggers a confirmation check to see if its
-  newly extended fork can be confirmed.
+* Once the miner finds such a nonce, it broadcasts its block proposal
+  to the P2P network. Finally the miner triggers a confirmation check
+  to see if its newly extended fork can be confirmed.
 
 Pseudocode:
 ```
@@ -53,53 +53,55 @@ loop {
 
 ## Listening for block proposals
 
-Each node listens for new block proposals on the P2P network. Upon receiving
-block proposals, nodes try to extend the proposals onto a fork held in memory
-(this process is described in the next section). Then nodes trigger a
-confirmation check to see if their newly extended fork can be confirmed.
+Each node listens for new block proposals on the P2P network. Upon
+receiving block proposals, nodes try to extend the proposals onto a
+fork held in memory (this process is described in the next section).
+Then nodes trigger a confirmation check to see if their newly extended
+fork can be confirmed.
 
-Upon receiving a new block proposal, miners also check if the extended fork
-rank is better than the one they are currently trying to extend. If the fork
-rank is better, the miner will stop mining its proposal and start mining the
-new best fork.
+Upon receiving a new block proposal, miners also check if the extended
+fork rank is better than the one they are currently trying to extend.
+If the fork rank is better, the miner will stop mining its proposal and
+start mining the new best fork.
 
 ## Ranking
 
-Each block proposal is ranked based on how hard it is to produce. To measure
-that, we compute the squared distance of its height target from `MAX_INT`.
-For two honest nodes that mine the next block height of the highest ranking
-fork, their block will have the same rank. To mitigate this tie scenario,
-we also compute the squared distance of the blocks `RandomX` hash from
-`MAX_INT`, allowing us to always choose the actual higher ranking block for
-that height, in case of ties. The complete block rank is a tuple containing
-both squared distances.
+Each block proposal is ranked based on how hard it is to produce. To
+measure that, we compute the squared distance of its height target from
+`MAX_INT`. For two honest nodes that mine the next block height of the
+highest ranking fork, their block will have the same rank. To mitigate
+this tie scenario, we also compute the squared distance of the blocks
+`RandomX` hash from `MAX_INT`, allowing us to always choose the actual
+higher ranking block for that height, in case of ties. The complete
+block rank is a tuple containing both squared distances.
 
 Proof of Work algorithm lowers the difficulty target as hashpower grows.
-This means that blocks will have to be mined for a lower target, therefore
-rank higher, as they go further away from `MAX_INT`.
-
-Similar to blocks, blockchain/forks rank is a tuple, with the first part being the
-sum of its block's squared target distances, and the second being the sum of
-their squared hash distances. Squared distances are used to disproportionately
-favors smaller targets, with the idea being that it will be harder to trigger
-a longer reorg between forks. When we compare forks, we first check the first
-sum, and if it's tied, we use the second as the tie breaker, since we know it
-will be statistically unique for each sequence.
+This means that blocks will have to be mined for a lower target,
+therefore rank higher, as they go further away from `MAX_INT`.
+
+Similar to blocks, blockchain/forks rank is a tuple, with the first
+part being the sum of its block's squared target distances, and the
+second being the sum of their squared hash distances. Squared distances
+are used to disproportionately favors smaller targets, with the idea
+being that it will be harder to trigger a longer reorg between forks.
+When we compare forks, we first check the first sum, and if it's tied,
+we use the second as the tie breaker, since we know it will be
+statistically unique for each sequence.
 
 The ranking of a fork is always increasing as new blocks are appended.
-To see this, let $F = (M₁ ⋯  Mₙ)$ be a fork with a finite sequence of blocks $(Mᵢ)$
-of length $n$. The rank of a fork is calculated as
+To see this, let $F = (M₁ ⋯  Mₙ)$ be a fork with a finite sequence of
+blocks $(Mᵢ)$ of length $n$. The rank of a fork is calculated as
 $$ r_F = n ∑ᵢ₌₁ⁿ \t{rank}(Mᵢ) $$
-Let $F' = F ⊕  (Mₙ₊₁)$ of length $n + 1$ be the fork created by appending
-the block $Mₙ₊₁$ to $F$. Then we see that
+Let $F' = F ⊕  (Mₙ₊₁)$ of length $n + 1$ be the fork created by
+appending the block $Mₙ₊₁$ to $F$. Then we see that
 $$ r_{F'} > r_F $$
 since $\t{rank}(M) > 0$ for all $M$.
 
 ## Fork extension
 
-Since there can be more than one block producer, each node holds a set of known
-forks in memory. Nodes extend the best ranking fork in memory when producing a
-block.
+Since there can be more than one block producer, each node holds a set
+of known forks in memory. Nodes extend the best ranking fork in memory
+when producing a block.
 
 Upon receiving a block, one of the following cases may occur:
 
@@ -139,7 +141,8 @@ Extending F0 fork with a new block proposal:
 
 #### Case 2
 
-Extending F0 fork at [M0] block with a new block proposal, creating a new fork chain:
+Extending F0 fork at [M0] block with a new block proposal, creating a
+new fork chain:
 
                    |--[M0]--[M2]   <-- F0
     [C]--...--[C]--|
@@ -176,24 +179,26 @@ Reorg happened and we rebuild the chain:
 
 ## Confirmation
 
-Based on the rank properties, each node will diverge to the highest ranking
-fork, and new fork will emerge extending that at its tips.
-A security threshold is set, which refers to the height where the probability
-to produce a fork, able to reorg the current best ranking fork reaches zero,
-similar to the # of block confirmation used by other PoW based protocols.
+Based on the rank properties, each node will diverge to the highest
+ranking fork, and new fork will emerge extending that at its tips.
+A security threshold is set, which refers to the height where the
+probability to produce a fork, able to reorg the current best ranking
+fork reaches zero, similar to the # of block confirmation used by other
+PoW based protocols.
 
 When the confirmation check kicks in, each node will grab its best fork.
-If the fork's length exceeds the security threshold, the node will push (confirm)
-its first proposal to the canonical blockchain. The fork acts as a queue (buffer)
-for the to-be-confirmed proposals.
+If the fork's length exceeds the security threshold, the node will push
+(confirm) its first proposal to the canonical blockchain. The fork acts
+as a queue (buffer) for the to-be-confirmed proposals.
 
-Once a confirmation occurs, all the fork chains not starting with the confirmed
-block(s) are removed from the node's memory pool.
+Once a confirmation occurs, all the fork chains not starting with the
+confirmed block(s) are removed from the node's memory pool.
 
 We continue Case 3 from the previous section to visualize this logic.
 
-The confirmation threshold used in this example is 3 blocks. A node observes 2
-proposals. One extends the F0 fork and the other extends the F2 fork:
+The confirmation threshold used in this example is 3 blocks. A node
+observes 2 proposals. One extends the F0 fork and the other extends
+the F2 fork:
 
                    |--[M0]--[M2]+--[M5] <-- F0
     [C]--...--[C]--|
@@ -233,11 +238,11 @@ The canonical blockchain now contains blocks M0 and the current state is:
 
 # Appendix: Data Structures
 
-This section gives further details about the high level structures that will be
-used by the protocol.
+This section gives further details about the high level structures that
+will be used by the protocol.
 
-Note that for hashes, we define custom types like `TransactionHash`, but here
-we will just use the raw byte representation `[u8; 32]`.
+Note that for hashes, we define custom types like `TransactionHash`,
+but here we will just use the raw byte representation `[u8; 32]`.
 
 | Index         | Type  | Description                               |
 |---------------|-------|-------------------------------------------|
@@ -248,8 +253,8 @@ we will just use the raw byte representation `[u8; 32]`.
 `u32` can store 4.29 billion blocks, which with a 90 second blocktime
 corresponds to 12.2k years.
 
-`u16` max value 65535 which is far above the expected limits. By comparison
-the tx in Bitcoin with the most outputs has 2501.
+`u16` max value 65535 which is far above the expected limits. By
+comparison the tx in Bitcoin with the most outputs has 2501.
 
 ## Header
 
@@ -298,8 +303,8 @@ the tx in Bitcoin with the most outputs has 2501.
 
 ## Sequences
 
-Denote blocks by the symbols $bᵢ ∈ B$, then a sequence of blocks (alternatively
-a fork) is an ordered series $𝐛 = (b₁, …, bₘ)$.
+Denote blocks by the symbols $bᵢ ∈ B$, then a sequence of blocks
+(alternatively a fork) is an ordered series $𝐛 = (b₁, …, bₘ)$.
 
 Use $S$ for all sets of sequences for blocks in $B$.
 
@@ -307,9 +312,11 @@ Use $S$ for all sets of sequences for blocks in $B$.
 
 Each block is associated with a target $T : B → 𝕀$ where $𝕀 ⊂ ℕ$.
 
-1. Blocks with lower targets are harder to create and ranked higher in a sequence of blocks.
+1. Blocks with lower targets are harder to create and ranked higher in
+   a sequence of blocks.
 2. Given two competing forks $𝐚 = (a₁, …, aₘ)$ and $b = (b₁, …, bₙ)$,
-   we wish to select a winner. Assume $𝐚$ is the winner, then $∑ T(aᵢ) ≤ ∑ T(bᵢ)$.
+   we wish to select a winner. Assume $𝐚$ is the winner, then
+   $∑ T(aᵢ) ≤ ∑ T(bᵢ)$.
 3. There should only ever be a single winner.
    When $∑ T(aᵢ) = ∑ T(bᵢ)$, then we have logic to break the tie.
 
@@ -322,19 +329,20 @@ This function must *always* have unique values for distinct sequences.
 
 We also would like the property $W$ is additive on subsequences
 $$ W((b₁, …, bₘ)) = W((b₁)) + ⋯ + W((bₘ)) $$
-which allows comparing forks from any point within the blockchain. For example
-let $𝐬 = (s₁, …, sₖ)$ be the blockchain together with forks $𝐚, 𝐛$ extending $𝐬$
-into $𝐬 ⊕  𝐚 = (s₁, …, sₖ, a₁, …, aₘ)$ and $𝐬 ⊕  𝐛 = (s₁, …, sₖ, b₁, …, bₙ)$.
-Then we have that
+which allows comparing forks from any point within the blockchain. For
+example let $𝐬 = (s₁, …, sₖ)$ be the blockchain together with forks
+$𝐚, 𝐛$ extending $𝐬$ into $𝐬 ⊕  𝐚 = (s₁, …, sₖ, a₁, …, aₘ)$ and
+$𝐬 ⊕  𝐛 = (s₁, …, sₖ, b₁, …, bₙ)$. Then we have that
 $$ W(𝐬 ⊕  𝐚) < W(𝐬 ⊕  𝐛) ⟺  W(𝐚) < W(𝐛) $$
 which means it's sufficient to compare $𝐚$ and $𝐛$ directly.
 
 ## Proposed Rank
 
-With a PoW mining system, we are guaranteed to always have the block hash
-$h(b) ≤ T(b)$. Since the block hashes $( h(b₁), …, h(bₘ) )$ for a sequence
-$( b₁, …, bₘ )$ have the property that $∑ h(bᵢ) ≤ ∑ T(bᵢ)$, as well as being
-sufficiently random, we can use them to define our work function.
+With a PoW mining system, we are guaranteed to always have the block
+hash $h(b) ≤ T(b)$. Since the block hashes $( h(b₁), …, h(bₘ) )$ for a
+sequence $( b₁, …, bₘ )$ have the property that $∑ h(bᵢ) ≤ ∑ T(bᵢ)$,
+as well as being sufficiently random, we can use them to define our
+work function.
 
 Because $W$ is required to be additive, we define a block work function
 $w : B → ℕ$, and $W(𝐛) = ∑ w(bᵢ)$.
@@ -343,32 +351,34 @@ The block work function should have a statistically higher score for
 blocks with a smaller target, and always be distinct for unique blocks.
 We define $w$ as
 $$ w(b) = \max(𝕀) - h(b) $$
-since $h(b) < T(b) < \max(𝕀)$ this function is well defined on the codomain.
+since $h(b) < T(b) < \max(𝕀)$ this function is well defined on the
+codomain.
 
 ## Hash Function
 
-Let $𝕀$ be a fixed subset of $ℕ$ representing the output of a hash function
-$[0, \max(𝕀)]$.
+Let $𝕀$ be a fixed subset of $ℕ$ representing the output of a hash
+function $[0, \max(𝕀)]$.
 
 **Definition:** a *hash function* is a function $H : ℕ → 𝕀$ having the
 following properties:
 
 1. *Uniformity*, for any $y ∈ 𝕀$ and any $n ∈ ℕ$, there exists an $N > n$
    such that $H(N) = y$.
-2. *One-way*, for any $y ∈ 𝕀$, we are unable to construct an $x ∈ ℕ$ such
-   that $H(x) = y$.
+2. *One-way*, for any $y ∈ 𝕀$, we are unable to construct an $x ∈ ℕ$
+   such that $H(x) = y$.
 
-Note: the above notions rely on purely algebraic properties of $H$ without
-requiring the machinery of probability. The second property of being one-way
-is a stronger notion than $\ran(H)$ being statistically random. Indeed if the
-probability is non-zero then we could find such an $(x, y)$ which breaks the
-one-way property.
+Note: the above notions rely on purely algebraic properties of $H$
+without requiring the machinery of probability. The second property of
+being one-way is a stronger notion than $\ran(H)$ being statistically
+random. Indeed if the probability is non-zero then we could find such
+an $(x, y)$ which breaks the one-way property.
 
-**Theorem:** *given a hash function $H : ℕ → 𝕀$ as defined above, it's impossible to
-construct two distinct sequences $𝐚 = (a₁, …, aₘ)$ and $𝐛 = (b₁, …, bₙ)$
-such that $H(a₁) + ⋯ + H(aₘ) = H(b₁) + ⋯ + H(bₙ)$.*
+**Theorem:** *given a hash function $H : ℕ → 𝕀$ as defined above, it's
+impossible to construct two distinct sequences $𝐚 = (a₁, …, aₘ)$ and
+$𝐛 = (b₁, …, bₙ)$ such that $H(a₁) + ⋯ + H(aₘ) = H(b₁) + ⋯ + H(bₙ)$.*
 
 By property (2), we cannot find a $H(x) = 0$.
-Again by (2), we cannot construct an $x$ such that $H(x) + H(a) = H(b)$ for
-any $a, b ∈ ℕ$. Recursive application of (2) leads us to the stated theorem.
+Again by (2), we cannot construct an $x$ such that $H(x) + H(a) = H(b)$
+for any $a, b ∈ ℕ$. Recursive application of (2) leads us to the stated
+theorem.
 

+ 177 - 164
doc/src/arch/dao.md

@@ -41,25 +41,28 @@ From `darkfi/src/contract/dao/proof/mint.zk`:
 
 Brief description of the DAO bulla params:
 
-* **proposer_limit**: the minimum amount of governance tokens needed to open a proposal.
-* **quorum**: minimal threshold of participating total tokens needed for a proposal to pass.
-  Normally this is implemented as min % of voting power, but we do this in
-  absolute value
-* **early_exec_quorum**: minimal threshold of participating total tokens needed for a proposal
-  to be considered as strongly supported, enabling early execution. Must be greater or equal
-  to normal quorum.
-* **approval_ratio**: the ratio of winning/total votes needed for a proposal to pass.
+* **proposer_limit**: the minimum amount of governance tokens needed to
+  open a proposal.
+* **quorum**: minimal threshold of participating total tokens needed for
+  a proposal to pass. Normally this is implemented as min % of voting
+  power, but we do this in absolute value
+* **early_exec_quorum**: minimal threshold of participating total
+  tokens needed for a proposal to be considered as strongly supported,
+  enabling early execution. Must be greater or equal to normal quorum.
+* **approval_ratio**: the ratio of winning/total votes needed for a
+  proposal to pass.
 * **gov_token_id**: DAO's governance token ID.
 * **notes_public_key**: notes(coins) decryption public key
 * **proposer_public_key**: proposals creator public key
 * **proposals_public_key**: proposals viewer public key
 * **votes_public_key**: votes viewer public key
 * **exec_public_key**: proposals executor public key
-* **early_exec_public_key**: strongly supported proposals executor public key
+* **early_exec_public_key**: strongly supported proposals executor
+  public key
 * **bulla_blind**: bulla blind
 
-DAO creators/founders have full control on how they want to configure and share
-the actions keys, giving them the ability to veto if needed.
+DAO creators/founders have full control on how they want to configure
+and share the actions keys, giving them the ability to veto if needed.
 
 ## `DAO::propose()`: Propose the Vote
 
@@ -75,28 +78,29 @@ From `darkfi/src/contract/dao/proof/propose-main.zk`:
 	);
 ```
 
-Proposals are committed to a specific calls set, therefore they
-are generic and we can attach various calls to it. We will use a
-money transfer as the example for rest sections.
+Proposals are committed to a specific calls set, therefore they generic
+and we can attach various calls to it. We will use a money transfer as
+the example for rest sections.
 
 ## `DAO::vote()`: Vote on a Proposal
 
-Governance token holders each make an encrypted homomorphic commitment to
-their vote. The homomorphism is additive so $f(u) + f(v) = f(u + v)$.
+Governance token holders each make an encrypted homomorphic commitment
+to their vote. The homomorphism is additive so $f(u) + f(v) = f(u + v)$.
 They also encrypt their vote to the DAO pubkey.
 
 Finally once voting is completed, the holders of the DAO pubkey (which
-is up to DAO policy) can decrypt the votes $f(v₁), …, f(vₙ)$, sum the values
-$v₁ + ⋯ + vₙ$ and so have the value which can be used in ZK proofs alongside
-the publicly available commitment $f(v₁ + ⋯ + vₙ) = f(v₁) + ⋯ + f(vₙ)$.
+is up to DAO policy) can decrypt the votes $f(v₁), …, f(vₙ)$, sum the
+values $v₁ + ⋯ + vₙ$ and so have the value which can be used in ZK
+proofs alongside publicly available commitment
+$f(v₁ + ⋯ + vₙ) = f(v₁) + ⋯ + f(vₙ)$.
 
 ## `DAO::exec()`: Execute Passed Proposal
 
 This is the key part. We produce a tx which has two contract calls:
-`[money::transfer(), DAO::exec()]`. The coins spent in `money::transfer()`
-belong to the DAO and have the condition that they can only be spent
-when combined with `DAO::exec()`. Here is what coins in `money::transfer()`
-look like:
+`[money::transfer(), DAO::exec()]`. The coins spent in
+`money::transfer()` belong to the DAO and have the condition that they
+can only be spent when combined with `DAO::exec()`. Here is what coins
+in `money::transfer()` look like:
 
 ```zkas
 	C = poseidon_hash(
@@ -110,27 +114,28 @@ look like:
 	);
 ```
 
-When we send coins to the DAO treasury, we set `spend_hook` to the DAO contract,
-and `user_data` to the DAO bulla.
+When we send coins to the DAO treasury, we set `spend_hook` to the DAO
+contract, and `user_data` to the DAO bulla.
 
-When spending the coins, they reveal the `spend_hook` publicly and `user_data`
-(encrypted). `money::transfer()` enforces that the next contract call must be
-the same as the `spend_hook`.
+When spending the coins, they reveal the `spend_hook` publicly and
+`user_data` (encrypted). `money::transfer()` enforces that the next
+contract call must be the same as the `spend_hook`.
 
-The contract invoked by `spend_hook` can then use the `user_data`. We use this
-to store the DAO bulla. `DAO::exec()` will then use this as our DAO, and check
-the proposal we are executing belongs to this DAO through the reference to
-the DAO bulla in the proposal params.
+The contract invoked by `spend_hook` can then use the `user_data`. We
+use this to store the DAO bulla. `DAO::exec()` will then use this as
+our DAO, and check the proposal we are executing belongs to this DAO
+through the reference to the DAO bulla in the proposal params.
 
-`DAO::exec()` then encodes the rules that specify there has to be a valid
-proposal where voting passed the threshold and so on.
+`DAO::exec()` then encodes the rules that specify there has to be a
+valid proposal where voting passed the threshold and so on.
 
-Assuming both contracts validate successfully, the funds are transferred out
-of the DAO treasury.
+Assuming both contracts validate successfully, the funds are
+transferred out of the DAO treasury.
 
 # Formalism
 
-Let the $ℂ$ be the category for all sets of coins $C$ with one-way arrows
+Let the $ℂ$ be the category for all sets of coins $C$ with one-way
+arrows
 $C → C'$ such that $C ⊆ C'$ and an initial object $C₀ = ∅ $.
 We require that arrows with the same source and target commute.
 $$ \begin{CD}
@@ -139,21 +144,22 @@ $$ \begin{CD}
    Cₐ @>c_b'>> C_{ab}
 \end{CD} $$
 
-We define the nullifier functor $N : ℂ^{\t{op}} → ℕ$ which is an isomorphism
-of $ℂ$ that reverses arrows.
+We define the nullifier functor $N : ℂ^{\t{op}} → ℕ$ which is an
+isomorphism of $ℂ$ that reverses arrows.
 
 $$ \begin{CD}
    C @>>> NC \\
 @VcVV @AANcA \\
    C' @>>> NC'
 \end{CD} $$
-We can see the action of adding $c$ to $C$ (expressed as the left downwards
-arrow) gets lifted to the arrow going backwards in the nullifier category.
-The collection of arrows in $ℂ$ and $ℕ$ then describes the coins and nullifier
-sets which are represented in merkle trees.
+We can see the action of adding $c$ to $C$ (expressed as the left
+downwards arrow) gets lifted to the arrow going backwards in the
+nullifier category. The collection of arrows in $ℂ$ and $ℕ$ then
+describes the coins and nullifier sets which are represented in Merkle
+trees.
 
-From the diagram we see that $C → C' → NC' → NC → C$ so that $Nc$ cancels $c$.
-Pasting diagrams together, we get
+From the diagram we see that $C → C' → NC' → NC → C$ so that $Nc$
+cancels $c$. Pasting diagrams together, we get
 
 $$ \begin{CD}
    C₀ @>>> NC₀ \\
@@ -162,46 +168,48 @@ $$ \begin{CD}
 @Vc₂VV @AANc₂A \\
    C₂ @>>> NC₂ \\
 \end{CD} $$
-where all squares commute. Since all paths in $ℂ$ are one way, proving a
-coin $cₖ : Cₖ₋₁ → Cₖ$ exists is equivalent to being at any state $Cₖ, Cₖ₊₁, Cₖ₊₂, …$.
+
+where all squares commute. Since all paths in $ℂ$ are one way, proving
+a coin $cₖ : Cₖ₋₁ → Cₖ$ exists is equivalent to being at any state
+$Cₖ, Cₖ₊₁, Cₖ₊₂, …$.
 
 **Lemma:** If our state is $Cₖ$ then our set must contain the coins
 represented as arrows $c₁, …, cₖ$.
 
 # Anon Voting Mechanics
 
-When making a proposal, we need to prove ownership of a threshold of coins.
-Likewise for voting. Essentially they are similar problems of proving ownership
-of a coin $c$ that is still valid. As shown above this reduces to the following
-statements:
+When making a proposal, we need to prove ownership of a threshold of
+coins. Likewise for voting. Essentially they are similar problems of
+proving ownership of a coin $c$ that is still valid. As shown above
+this reduces to the following statements:
 
 * Is $c$ in the set of all coins $C$?
 * If yes, then is $n(c)$ *not* in the set of nullifiers $N$?
 
-Normally this logic is handled by transfers, but we need to additionally
-check it without leaking info about $c$. Since $n(c)$ is derived
-deterministically, leaking $n(c)$ also leaks info on $c$.
+Normally this logic is handled by transfers, but we need to
+additionally check it without leaking info about $c$. Since $n(c)$ is
+derived deterministically, leaking $n(c)$ also leaks info on $c$.
 
 Nullifiers must be checked otherwise expired coins can be used.
 
 ## Forking the Global State
 
-The first method involves copying the coins state $C$. Every proof makes use
-of $C$ while revealing $n(c)$ which is checked against the current nullifier
-state. To avoid anonymity leaks from revealing $n(c)$, we additionally move the coin
-using a `Money::transfer()` call.
+The first method involves copying the coins state $C$. Every proof
+makes use of $C$ while revealing $n(c)$ which is checked against the
+current nullifier state. To avoid anonymity leaks from revealing
+$n(c)$, we additionally move the coin using a `Money::transfer()` call.
 
 The downside is that wallets need to:
 
-* Keep track of the coins tree $C$. This will involve logic to periodically
-  checkpoint the incremental tree in a deterministic way.
+* Keep track of the coins tree $C$. This will involve logic to
+  periodically checkpoint the incremental tree in a deterministic way.
 * When doing any action, the wallet must move coins simultaneously.
-  Wallets must also keep track of the unspent coin since for example it might
-  be used in another vote (or the wallet makes a proposal and wants to vote
-  with the same coin).
+  Wallets must also keep track of the unspent coin since for example it
+  might be used in another vote (or the wallet makes a proposal and
+  wants to vote with the same coin).
 
-Additionally you cannot obtain a coin then vote. You must own the coin before
-the vote is proposed.
+Additionally you cannot obtain a coin then vote. You must own the coin
+before the vote is proposed.
 
 ## Forking the Global State (with SMT)
 
@@ -211,8 +219,8 @@ tree alongside $C$.
 The downsides are:
 
 * More expensive for voters since SMT is expensive in ZK.
-* We're taking an older snapshot of the coins state. Spent coins spent after
-  the vote are proposed will still be able to vote.
+* We're taking an older snapshot of the coins state. Spent coins spent
+  after the vote are proposed will still be able to vote.
 
 ## Tracking Coins with Local State
 
@@ -223,49 +231,49 @@ proposals when voting to the SMT field in the coin.
 
 The downside for wallets is that:
 
-* The SMT committed to is large and needs to be transferred to receivers
-  when sending the coin.
-    * Alternatively coins could contain a special key (also in the `user_data`
-      field), which when voting you must make a verifiable encryption.
-      That way wallets can later scan all proposals for a DAO to find where
-      their particular governance token voted.
-* It's very complex. For example, can DAOs own governance tokens? So far DAO
-  tokens must have the `spend_hook` set, but with this, we now require another
-  `spend_hook` which preserves the SMT when transferring coins. The mechanics
-  for two parents of a call aren't specified, so we'd maybe have to add some
-  concept of symlinks.
-
-However while complex, it is the most accurate of all 3 methods reflecting
-the current state.
+* The SMT committed to is large and needs to be transferred to
+  receivers when sending the coin.
+    * Alternatively coins could contain a special key (also in the
+      `user_data` field), which when voting you must make a verifiable
+      encryption. That way wallets can later scan all proposals for a
+      DAO to find where their particular governance token voted.
+* It's very complex. For example, can DAOs own governance tokens? So
+  far DAO tokens must have the `spend_hook` set, but with this, we now
+  require another `spend_hook` which preserves the SMT when
+  transferring coins. The mechanics for two parents of a call aren't
+  specified, so we'd maybe have to add some concept of symlinks.
+
+However while complex, it is the most accurate of all 3 methods
+reflecting the current state.
 
 # Tree States On Disk
 
-This section is not specific to DAO or Money, but describes a generic set
-abstraction which you can add or remove items from.
+This section is not specific to DAO or Money, but describes a generic
+set abstraction which you can add or remove items from.
 
 Requirements:
 
-* Add and remove items, which is represented by two G-sets denoted coins $Cₖ$
-  and nullifiers $Nₖ$. Let $Rₖ$ and $Sₖ$ be commitments to them both
-  respectively.
-* Given any snapshot $(Rₖ, Sₖ)$, it's possible to definitively say whether the
-  set it represents contains an item $x$ or not.
+* Add and remove items, which is represented by two G-sets denoted
+  coins $Cₖ$ and nullifiers $Nₖ$. Let $Rₖ$ and $Sₖ$ be commitments to
+  them both respectively.
+* Given any snapshot $(Rₖ, Sₖ)$, it's possible to definitively say
+  whether the set it represents contains an item $x$ or not.
     * Be able to do this fully ZK.
-* Wallets can easily take any snapshot, and using delta manipulation of the
-  state, be able to make inclusion and exclusion proofs easily.
+* Wallets can easily take any snapshot, and using delta manipulation of
+  the state, be able to make inclusion and exclusion proofs easily.
 * Verify in WASM that $Rₖ$ and $Sₖ$ correspond to the same $k$.
 
 The proposal is as follows and involves a merkle tree $𝐂$, and a SMT $𝐍$.
 
-For the sake of clarity, we will not detail the storing of the trees themselves.
-For $𝐂$, the tree is stored in `db_info`, while $𝐍$ has a full on-disk
-representation. Instead the info in this section concerns the auxiliary data
-required for using the trees with snapshotted states.
+For the sake of clarity, we will not detail the storing of the trees
+themselves. For $𝐂$, the tree is stored in `db_info`, while $𝐍$ has a
+full on-disk representation. Instead the info in this section concerns
+the auxiliary data required for using the trees with snapshotted states.
 
 ## DB Merkle Roots
 
-This is used to quickly lookup a state commitment for $𝐂$ and figure out when it
-occurred.
+This is used to quickly lookup a state commitment for $𝐂$ and figure
+out when it occurred.
 
 | Key or Value | Field Name   | Size | Desc                       |
 |--------------|--------------|------|----------------------------|
@@ -274,8 +282,8 @@ occurred.
 | v            | Call index   | 1    | Index of contract call     |
 
 We call `get_tx_location(tx_hash) -> (block_height, tx_index)`, and
-then use the `(block_height, tx_index)` tuple to figure out all info about
-this state change (such as when it occurred).
+then use the `(block_height, tx_index)` tuple to figure out all info
+about this state change (such as when it occurred).
 
 ## DB SMT Roots
 
@@ -292,17 +300,17 @@ If they match, then they both exist in the same `update()` call.
 
 ## DB Coins (Wallets)
 
-This DB is maintained by the user wallet, and periodic garbage collection will
-remove values older than a cutoff.
+This DB is maintained by the user wallet, and periodic garbage
+collection will remove values older than a cutoff.
 
 Keeps track of values added to $𝐂$ or $𝐍$.
 
-For $𝐂$ given an earlier tree checkpoint state, we can rewind, then fast forward
-to have a valid merkle tree for the given snapshot.
+For $𝐂$ given an earlier tree checkpoint state, we can rewind, then
+fast forward to have a valid Merkle tree for the given snapshot.
 Wallets should additionally periodically copy the merkle tree $𝐂$.
 
-In the case of $𝐍$, we construct an overlay for SMT, which allows rewinding the
-tree so exclusion proofs can be constructed.
+In the case of $𝐍$, we construct an overlay for SMT, which allows
+rewinding the tree so exclusion proofs can be constructed.
 
 | Key or Value | Field Name   | Size | Desc                                  |
 |--------------|--------------|------|---------------------------------------|
@@ -313,56 +321,61 @@ tree so exclusion proofs can be constructed.
 | v            | Value        | 32   | Coin or nullifier                     |
 | v            | Type         | 1    | Single byte indicating the type       |
 
-This structure for the keys in an ordered B-Tree, means it can be iterated
-from any point. We can start from any location from our last stored merkle
-tree checkpoint, and iterate forwards adding coins until we reach our
-desired snapshot $(Rₖ, Sₖ)$. We then have a valid merkle tree and SMT
-reconstructed and can create the desired inclusion or exclusion proofs.
+This structure for the keys in an ordered B-Tree, means it can be
+iterated from any point. We can start from any location from our last
+stored Merkle tree checkpoint, and iterate forwards adding coins until
+we reach our desired snapshot $(Rₖ, Sₖ)$. We then have a valid Merkle
+tree and SMT reconstructed and can create the desired inclusion or
+exclusion proofs.
 
-Q: should this be 2 databases or one? If we use 2 then we can remove the type
-byte. Maybe more conceptually clearer?
+Q: should this be 2 databases or one? If we use 2 then we can remove
+the type byte. Maybe more conceptually clearer?
 
 ## OpenZeppelin Governance
 
 https://docs.openzeppelin.com/contracts/4.x/governance
 
-It uses modules when the code is deployed to customize functionality. This
-includes:
+It uses modules when the code is deployed to customize functionality.
+This includes:
 
 * Timelock, users can exit if they disagree before decision is executed.
 * Votes module which changes how voting power is determined
-* Quorum module for how the quorum is defined. The options are GovernorVotes and
-  ERC721Votes.
-* What options people have when casting a vote, and how those votes are counted.
-    * GovernorCountingSimple offers For, Against and Abstain. Only For and
-      Abstain are counted towards quorum.
+* Quorum module for how the quorum is defined. The options are
+  GovernorVotes and ERC721Votes.
+* What options people have when casting a vote, and how those votes
+  are counted.
+    * GovernorCountingSimple offers For, Against and Abstain. Only For
+      and Abstain are counted towards quorum.
 * AccessControl
 * Clock management, whether to use block index or timestamps.
 
 The Governor (which in DarkFi is the DAO params) has these params:
 
-* Voting delay. How long after a proposal is created should voting power be
-  fixed. A large voting delay gives users time to unstake tokens if needed.
+* Voting delay. How long after a proposal is created should voting
+  power be fixed. A large voting delay gives users time to unstake
+  tokens if needed.
     * In DarkFi users will just pre-announce proposals.
 * Voting period, typically 1 week
 
 These params are specified in the unit defined in the token's clock.
-This is the blockwindow in DarkFi. So the 'unit' should be a public DAO param too.
+This is the blockwindow in DarkFi. So the 'unit' should be a public DAO
+param too.
 
 AccessControl has several roles:
 
 * Proposer, usually delegated to the Governor instance
-* Executor. Can be assigned to the special zero address so anyone can execute.
+* Executor. Can be assigned to the special zero address so anyone can
+  execute.
 * Admin role which can be renounced.
 
 OpenZeppelin is moving to timestamps instead of block index because:
 
-> It is sometimes difficult to deal with durations expressed in number of
-> blocks because of inconsistent or unpredictable time between blocks.
-> This is particularly true of some L2 networks where blocks are produced based
-> on blockchain usage. Using number of blocks can also lead to the governance
-> rules being affected by network upgrades that modify the expected time
-> between blocks.
+> It is sometimes difficult to deal with durations expressed in number
+> of blocks because of inconsistent or unpredictable time between
+> blocks. This is particularly true of some L2 networks where blocks
+> are produced based on blockchain usage. Using number of blocks can
+> also lead to the governance rules being affected by network upgrades
+> that modify the expected time between blocks.
 
 ## Aragon
 
@@ -371,8 +384,8 @@ https://aragon.org/how-to/governance-ii-setting-dao-governance-thresholds
 * Minimum participation, sometimes called quorum.
   With large whales, you want a higher threshold.
   Usual value is 5%.
-* Support threshold, sometimes called pass rate. In DarkFi this is called
-  the approval ratio. The most typical value is 50%.
+* Support threshold, sometimes called pass rate. In DarkFi this is
+  called the approval ratio. The most typical value is 50%.
 * Voting period. Most common is 7 days.
     * Speed. You want a short period if DAO needs to make fast decisions.
     * Participation. Longer period for higher participation.
@@ -382,35 +395,35 @@ Params can also be set then changed later to adjust.
 
 Delegation is a good feature to increase participation.
 
-Early execution means that if the proposal meets the requirements then it can
-be executed early. We should add this option to DarkFi DAO params.
+Early execution means that if the proposal meets the requirements then
+it can be executed early. We should add this option to DarkFi DAO params.
 
 ## Suggested Changes
 
 ~~DAO params:~~
 
-* ~~Voting period (currently called duration) should be moved from proposals to
-  DAO params.~~
-    * ~~upgrayedd: we should just have minimum allowed period in the DAO, but keep
-      this param in the proposal.~~
-* ~~Window (currently set at 4 hours of blocks) should be customizable. We need a
-  terminology for the unit of time. Maybe `time_units`.~~
+* ~~Voting period (currently called duration) should be moved from
+  proposals to DAO params.~~
+    * ~~upgrayedd: we should just have minimum allowed period in the
+      DAO, but keep this param in the proposal.~~
+* ~~Window (currently set at 4 hours of blocks) should be customizable.
+  We need a terminology for the unit of time. Maybe `time_units`.~~
     * ~~This should be switched from block index to using timestamps.
       See the quoted paragraph in the OpenZeppelin section above for the
       reasoning.~~
     * ~~upgrayedd: stick with block index.~~
-* ~~Early execution bool flag. If true, then passed proposals can be `exec()`uted
-  asap, otherwise the entire voting period must pass.~~
+* ~~Early execution bool flag. If true, then passed proposals can be
+  `exec()`uted asap, otherwise the entire voting period must pass.~~
 
 ~~No changes to proposals, except moving duration to DAO params.~~
 
 > Resolution:
-> The full voting period must pass in order to be able to execute a proposal.
-> A new configuration parameter was introduced, called early exec quorum,
-> where we can define the quorum for a proposal to be considered as strongly
-> supported/voted on, which should always be greater or equal to normal quorum.
-> With this addition, we can execute proposals before the voting period has
-> passed, if they were accepted.
+> The full voting period must pass in order to be able to execute a
+> proposal. A new configuration parameter was introduced, called early
+> exec quorum, where we can define the quorum for a proposal to be
+> considered as strongly supported/voted on, which should always be
+> greater or equal to normal quorum. With this addition, we can execute
+> proposals before the voting period has passed, if they were accepted.
 
 ~~Currently the DAO public key is used for:~~
 
@@ -419,23 +432,23 @@ be executed early. We should add this option to DarkFi DAO params.
 
 ~~We should introduce a new key:~~
 
-* ~~Proposer role, which is needed to make proposals. This can be shared openly
-  amongst DAO members if they wish to remove the restriction on who can make
-  proposals.~~
-    * ~~OZ does this with a canceller role that has the ability to cancel
-      proposals.~~
-    * ~~In the future allow multiple keys for this so you can see who makes
-      proposals.~~
+* ~~Proposer role, which is needed to make proposals. This can be
+  shared openly amongst DAO members if they wish to remove the
+  restriction on who can make proposals.~~
+    * ~~OZ does this with a canceller role that has the ability to
+      cancel proposals.~~
+    * ~~In the future allow multiple keys for this so you can see who
+      makes proposals.~~
 
 > Resolution:
-> DAO public key was split into six other keys, providing maximum control over
-> each DAO action. Now the DAO creator can define who can view the coin notes,
-> create proposals, view proposals, view votes, execute proposals and early
-> execute proposals. They can configure the keys however they like like reusing
-> keys if they want some actions to have same key.
-
-Optional: many DAOs these days implement Abstain, which increases the quorum
-without voting yes. This is for when you want to weak support a measure,
-allowing it to reach quorum faster. This could be implemented in DarkFi, by
-allowing the vote yes to optionally be 0.
-
+> DAO public key was split into six other keys, providing maximum
+> control over each DAO action. Now the DAO creator can define who can
+> view the coin notes, create proposals, view proposals, view votes,
+> execute proposals and early execute proposals. They can configure the
+> keys however they like like reusing keys if they want some actions to
+> have same key.
+
+Optional: many DAOs these days implement Abstain, which increases the
+quorum without voting yes. This is for when you want to weak support
+a measure, allowing it to reach quorum faster. This could be
+implemented in DarkFi, by allowing the vote yes to optionally be 0.

+ 16 - 15
doc/src/arch/dex.md

@@ -4,26 +4,27 @@ With cross-chain bridging and darkpool DEX then DarkFi would be a very
 attractive trading tool.
 
 We currently have OTC swaps which are an efficient way to settle trades
-on-chain. But there needs to be an orderbook for matching counterparties.
+on-chain. But there needs to be an orderbook for matching
+counterparties.
 
-We propose that this job can be performed by an order-matching bot which
-maintains an orderbook. Later this role can be split with MPC.
+We propose that this job can be performed by an order-matching bot
+which maintains an orderbook. Later this role can be split with MPC.
 
 The order-matching party needs to be able to construct the swap trade,
 even when the LP is offline.
 
-We propose to do this using the spend hook and a special `auth_otc` function.
-The `auth_otc` basically says:
+We propose to do this using the spend hook and a special `auth_otc`
+function. The `auth_otc` basically says:
 
-* The sender of the funds has the right at any time to withdraw liquidity and
-  cancel the LP.
-* The funds are delegated to the order-matching party but with restrictions:
+* The sender of the funds has the right at any time to withdraw
+  liquidity and cancel the LP.
+* The funds are delegated to the order-matching party but with
+  restrictions:
     * Can only make an OTC swap tx using the funds.
-    * The trade parameters are completely specified such as the price and
-      currencies.
-
-The funds are therefore delegated to the order-matching party, who finds
-counterparty offers and executes the trades settling them on-chain. Both parties
-receive their funds in a trustless anonymous manner. At any time the LP can be
-canceled and funds withdrawn.
+    * The trade parameters are completely specified such as the price
+      and currencies.
 
+The funds are therefore delegated to the order-matching party, who
+finds counterparty offers and executes the trades settling them
+on-chain. Both parties receive their funds in a trustless anonymous
+manner. At any time the LP can be canceled and funds withdrawn.

+ 179 - 130
doc/src/arch/net/p2p-network.md

@@ -1,40 +1,44 @@
 # P2P Network
 
-We instantiate a `p2p` network and call `start()`. This will begin running a single
-p2p network until `stop()` is called.
+We instantiate a `p2p` network and call `start()`. This will begin
+running a single p2p network until `stop()` is called.
 
 There are 3 session types:
 
 * `InboundSession`, concerned with incoming connections
 * `OutboundSession`, concerned with outgoing connections
-* `SeedSession` is a special session type which connects to seed nodes to populate
-  the hosts pool, then finishes once synced.
+* `SeedSession` is a special session type which connects to seed nodes
+  to populate the hosts pool, then finishes once synced.
 
-Connections are made by either `Acceptor` or `Connector` for incoming or outgoing
-respectively. They have multiple transport types; see `src/net/transport/` for the
-full list.
+Connections are made by either `Acceptor` or `Connector` for incoming
+or outgoing respectively. They have multiple transport types; see
+`src/net/transport/` for the full list.
 
 Connections are then wrapped in a `Channel` abstraction which allows
-protocols to be attached. See `src/net/protocol/` and run `fd protocol` for custom
-application specific network protocols. Also see the follow tutorial:
+protocols to be attached. See `src/net/protocol/` and run `fd protocol`
+for custom application specific network protocols. Also see the follow
+tutorial:
 
 * [Understanding Protocols](../../learn/dchat/creating-dchatd/protocols.md)
 
 ## Outbound Session
 
-The outbound session is responsible to ensure the hosts pool is populated, either
-through currently connected nodes or using the seed session.
-It performs this algorithm:
+The outbound session is responsible to ensure the hosts pool is
+populated, either through currently connected nodes or using the seed
+session. It performs this algorithm:
 
 1. Start $N$ slots, and a sleeping peer discovery process
 
 Then each slot performs this algorithm:
 
 1. If no addresses matching our filters are in the hosts pool then:
-    1. Wakeup the peer discovery process. This does nothing if peer discovery is already active.
-    2. Peer discovery tries first 2 times to poll the current network if there are connected nodes,
-       otherwise it will do a seed server sync.
-    3. Peer discovery then wakes any sleeping slots and goes back to sleep.
+    1. Wakeup the peer discovery process. This does nothing if peer
+       discovery is already active.
+    2. Peer discovery tries first 2 times to poll the current network
+       if there are connected nodes, otherwise it will do a seed server
+       sync.
+    3. Peer discovery then wakes any sleeping slots and goes back to
+       sleep.
 
 ## Hostlist filtering
 
@@ -83,109 +87,153 @@ algo](https://eprint.iacr.org/2019/411.pdf)
 
 ### Design Considerations
 
-* Mitigate attacks to a reasonable degree. Ensuring complete coverage against attacks is infeasible and likely
-  introduces significant latency into protocols.
-* Primarily target the p2p network running over anonymity networks like Tor, i2p or Nym.
-  This means we cannot rely on node addresses being reliable. Even on the clearnet, attackers can easily obtain
-  large numbers of proxy addresses.
+* Mitigate attacks to a reasonable degree. Ensuring complete coverage
+  against attacks is infeasible and likely introduces significant
+  latency into protocols.
+* Primarily target the p2p network running over anonymity networks like
+  Tor, i2p or Nym. This means we cannot rely on node addresses being
+  reliable. Even on the clearnet, attackers can easily obtain large
+  numbers of proxy addresses.
 
 The main attacks are:
 
-* **Sybil attack**. A malicious actor tries to subvert the network using sockpuppet nodes. For example
-  false signalling using version messages on the p2p network.
-* **Eclipse attack**. Targets a single node, through a p2p MitM attack where the malicious actor controls all
-  the traffic you see. For example they might send you a payment, then want to doublespend without you
-  knowing about it.
-* **Denial of Service**. Usually happens when a node is overloaded by too much data being sent.
+* **Sybil attack**. A malicious actor tries to subvert the network
+  using sockpuppet nodes. For example false signalling using version
+  messages on the p2p network.
+* **Eclipse attack**. Targets a single node, through a p2p MitM attack
+  where the malicious actor controls all the traffic you see. For
+  example they might send you a payment, then want to doublespend
+  without you knowing about it.
+* **Denial of Service**. Usually happens when a node is overloaded by
+  too much data being sent.
 
 From [libp2p2 DoS mitigation](
-https://docs.libp2p.io/concepts/security/dos-mitigation/): "An attack is
-considered viable if it takes fewer resources to execute than the damage
-it does. In other words, if the payoff is higher than the investment it
-is a viable attack and should be mitigated."
+https://docs.libp2p.io/concepts/security/dos-mitigation/): "An attack
+is considered viable if it takes fewer resources to execute than the
+damage it does. In other words, if the payoff is higher than the
+investment it is a viable attack and should be mitigated."
 
 ### Common Mitigations
 
-* **Backoff/falloff**. This is the strategy implemented in Bitcoin. This can be bad when arbitrary limits are implemented
-  since we slow down traffic for no reason.
-* **Choking controller**. BitTorrent no longer uses naive tit-for-tat, instead libtorrent implements an anti-leech seeding algo
-  from the paper [Improving BitTorrent: A Simple Approach](https://qed.usc.edu/papers/ChowGM08.pdf), which is focused on distributing
-  bandwidth to all peers. See also [libtorrent/src/choker.cpp](https://github.com/arvidn/libtorrent/blob/RC_2_0/src/choker.cpp).
-    * All p2p messages will have a score which represents workload for the node. There is a hard limit, and in general the choker
-      will try to balance the scores between all available channels.
-    * Opening the connection itself has a score with inbound connections assigned more cost than outgoing ones.
-* **Smart ban**. Malicious peers which violate protocols are hard banned. For example sending the wrong data for a chunk.
-    * See the method `channel.ban()` which immediately disconnects and blacklists the address.
-* **uTP congestion control**. BitTorrent implements a UDP protocol with its own congestion control. We could do such a similar strategy
-  with the addition of removing ordering. This reduces protocol latency mitigating attacks. See [libtorrent.org/utp.html](https://libtorrent.org/utp.html)
+* **Backoff/falloff**. This is the strategy implemented in Bitcoin.
+  This can be bad when arbitrary limits are implemented since we slow
+  down traffic for no reason.
+* **Choking controller**. BitTorrent no longer uses naive tit-for-tat,
+  instead libtorrent implements an anti-leech seeding algo from the
+  paper [Improving BitTorrent: A Simple Approach](https://qed.usc.edu/papers/ChowGM08.pdf),
+  which is focused on distributing bandwidth to all peers. See also
+  [libtorrent/src/choker.cpp](https://github.com/arvidn/libtorrent/blob/RC_2_0/src/choker.cpp).
+    * All p2p messages will have a score which represents workload for
+      the node. There is a hard limit, and in general the choker will
+      try to balance the scores between all available channels.
+    * Opening the connection itself has a score with inbound
+      connections assigned more cost than outgoing ones.
+* **Smart ban**. Malicious peers which violate protocols are hard
+  banned. For example sending the wrong data for a chunk.
+    * See the method `channel.ban()` which immediately disconnects and
+      blacklists the address.
+* **uTP congestion control**. BitTorrent implements a UDP protocol with
+  its own congestion control. We could do such a similar strategy
+  with the addition of removing ordering. This reduces protocol latency
+  mitigating attacks. See [libtorrent.org/utp.html](https://libtorrent.org/utp.html)
   for more info.
-    * Maybe less important if we use alternative networks like Tor or i2p.
-* **White, gray and black lists**. See section 2.2 of [Exploring the Monero P2P Network](https://eprint.iacr.org/2019/411.pdf) for
-  details of this algorithm. This aids with network connectivity, avoiding netsplits which could make the network more susceptible to
+    * Maybe less important if we use alternative networks like Tor or
+      i2p.
+* **White, gray and black lists**. See section 2.2 of [Exploring the Monero P2P Network](https://eprint.iacr.org/2019/411.pdf)
+  for details of this algorithm. This aids with network connectivity,
+  avoiding netsplits which could make the network more susceptible to
   eclipse/sybil attacks (large scale MiTM).
     * See: [Refine Session](https://codeberg.org/darkrenaissance/darkfi/src/branch/master/src/net/session/refine_session.rs)
-* **Protocol-level reputation system**. You have a keypair, which accrues more trust from the network. Nodes gossip trust metrics.
+* **Protocol-level reputation system**. You have a keypair, which
+  accrues more trust from the network. Nodes gossip trust metrics.
     * See [AnonRep: Towards Tracking-Resistant Anonymous Reputation](https://www.usenix.org/system/files/conference/nsdi16/nsdi16-paper-zhai.pdf)
     * Also the discussion in
       [Semaphore RLN, rate limiting nullifier for spam prevention in anonymous p2p setting](https://ethresear.ch/t/semaphore-rln-rate-limiting-nullifier-for-spam-prevention-in-anonymous-p2p-setting/5009)
-* **Reduce blast radius**. The p2p subsystem should run on its own dedicated executor, separate from database lookups or other
-  system operations.
+* **Reduce blast radius**. The p2p subsystem should run on its own
+  dedicated executor, separate from database lookups or other system
+  operations.
 * **fail2ban**
-* **Optimized blockchain database**. Most databases are written for interleaved reads and writes as well as deletion. Blockchains follow
-  a different pattern of infrequent writes being mostly append-only, and requiring weaker guarantees.
+* **Optimized blockchain database**. Most databases are written for
+ interleaved reads and writes as well as deletion. Blockchains follow a
+ different pattern of infrequent writes being mostly append-only, and
+ requiring weaker guarantees.
 
 ### Protocol Suggestions
 
-Core protocols should be modeled and analyzed with DoS protections added. Below are suggestions to start the investigation.
+Core protocols should be modeled and analyzed with DoS protections
+added. Below are suggestions to start the investigation.
 
 * Do not forward orphan txs or blocks.
 * Drop all double spend txs.
-    * Alternatively require a higher fee if we want to enable replace by fee.
+    * Alternatively require a higher fee if we want to enable replace
+      by fee.
     * Do not forward double spend txs.
-* Do not forward the same object (block, transaction .etc) to the same peer twice. Violation results in `channel.ban()`.
+* Do not forward the same object (block, transaction .etc) to the same
+  peer twice. Violation results in `channel.ban()`.
 * Very low fee txs are rate limited.
 * Limit orphan txs.
 * Drop large or unusual orphan transactions to limit damage.
-* Consider a verification cache to prevent attacks that try to trigger re-verification of stored orphan txs. Also limit the size of the cache.
+* Consider a verification cache to prevent attacks that try to trigger
+  re-verification of stored orphan txs. Also limit the size of the
+  cache.
   See [Fixed vulnerability explanation: Why the signature cache is a DoS protection.](https://bitcointalk.org/index.php?topic=136422.0)
 * Perform more expensive checks later in tx validation.
-* Nodes will only relay valid transactions with a certain fee amount. More expensive transactions require a higher fee.
-* Complex operations such as requesting data can be mitigated by tracking the number of requests from a peer.
-    * Attackers may attempt flooding invs for invalid data. The peer responds with get data but that object doesn't exist using
-      up precious bandwidth. Limit both the rate of invs to 2/s and size of items to 35.
-    * Also loops can cause an issue if triggered by the network. This should be carefully analyzed and flattened if possible,
-      otherwise they should be guarded against attack.
+* Nodes will only relay valid transactions with a certain fee amount.
+  More expensive transactions require a higher fee.
+* Complex operations such as requesting data can be mitigated by
+  tracking the number of requests from a peer.
+    * Attackers may attempt flooding invs for invalid data. The peer
+      responds with get data but that object doesn't exist using up
+      precious bandwidth. Limit both the rate of invs to 2/s and size
+      of items to 35.
+    * Also loops can cause an issue if triggered by the network. This
+      should be carefully analyzed and flattened if possible, otherwise
+      they should be guarded against attack.
 
 ### Customizable Policy
 
 Apps should be able to configure:
 
-* Reject hosts, for example based off current overall resource utilization or the host addr.
-    * Note: we have a configurable setting called `blacklist` which allows us to reject hosts by addr.
+* Reject hosts, for example based off current overall resource
+  utilization or the host addr.
+    * Note: we have a configurable setting called `blacklist` which
+      allows us to reject hosts by addr.
 * Accounting abstraction for scoring connections.
 
 ## Swarming
 
-TODO: research how this is handled on bittorrent. How do we lookup nodes in the swarm? Does the network maintain routing tables?
-Is this done through a DHT like Kademlia?
+TODO: research how this is handled on bittorrent. How do we lookup
+nodes in the swarm? Does the network maintain routing tables? Is this
+done through a DHT like Kademlia?
 
-Swarming means more efficient downloading of data specific to a certain subset. A new p2p instance is spawned with a
-clean hosts table. This subnetwork is self contained.
+Swarming means more efficient downloading of data specific to a certain
+subset. A new p2p instance is spawned with a clean hosts table. This
+subnetwork is self contained.
 
-An application is for example DarkIRC where everyday a new event graph is spawned. With swarming, you would connect to nodes
-maintaining this particular day's event graph.
+An application is for example DarkIRC where everyday a new event graph
+is spawned. With swarming, you would connect to nodes maintaining this
+particular day's event graph.
 
-The feature allows overlaying multiple different features in a single network such as tau, darkirc and so on. New networks require
-nodes to bootstrap, but with swarming, we reduce all these networks to a single bootstrap. The overlay network maintaining the
-routing tables is a kind of decentralized lilith which keeps track of all the swarms.
+The feature allows overlaying multiple different features in a single
+network such as tau, darkirc and so on. New networks require nodes to
+bootstrap, but with swarming, we reduce all these networks to a single
+bootstrap. The overlay network maintaining the routing tables is a kind
+of decentralized lilith which keeps track of all the swarms.
 
-Possibly a post-mainnet feature depending on the scale of architectural changes or new code required in the net submodule.
+Possibly a post-mainnet feature depending on the scale of architectural
+changes or new code required in the net submodule.
 
-To faciliate this future upgrade, we have made the peer discovery process a generic trait called `PeerDiscoveryBase`. Currently there is only one imeplementation, `PeerDiscovery`, which implements the peer discovery process in outbound sesssion. In the future `PeerDiscoveryBase` can be implemented to make new forms of peer discovery (i.e. subnets vs overlay peer discovery processes).
+To faciliate this future upgrade, we have made the peer discovery
+process a generic trait called `PeerDiscoveryBase`. Currently there is
+only one imeplementation, `PeerDiscovery`, which implements the peer
+discovery process in outbound sesssion. In the future
+`PeerDiscoveryBase` can be implemented to make new forms of peer
+discovery (i.e. subnets vs overlay peer discovery processes).
 
 ## Scoring Subsystem
 
-Connections should maintain a scoring system. Protocols can increment the score.
+Connections should maintain a scoring system. Protocols can increment
+the score.
 
 The score backs off exponentially. If the watermark is crossed then the
 connection is dropped.
@@ -210,12 +258,12 @@ Limits are calculated by measuring the following resources:
 connections)
 
 * Streams: an object of interaction between nodes (~analogous to
-`Channel`). Streams are not metered directly- rather they are constrained
-within the protocol and service scope (defined below). Inbound streams
-are more tightly controlled than outbound streams.
+`Channel`). Streams are not metered directly- rather they are
+constrained within the protocol and service scope (defined below).
+Inbound streams are more tightly controlled than outbound streams.
 
-Resource Management Scopes are hierarchial and downstream resource usage
-is aggregated at higher levels.
+Resource Management Scopes are hierarchial and downstream resource
+usage is aggregated at higher levels.
 
  ```
 System
@@ -232,23 +280,24 @@ System
 ```
 
 * System scope: top level scope. Nests all other scopes and defines
-global hard limits.
+  global hard limits.
 * Transcient scope: scope of resources still being established, e.g. a
-connection prior to a handshake.
+  connection prior to a handshake.
 * Service (analogous to `Session`) scopes. Logical groupings of streams
-that implement protocol flow and may additionally consume resources such
-as memory.
+  that implement protocol flow and may additionally consume resources
+  such memory.
 * Protocol scopes. Faciliates backwards compatiability since nodes can
-run multiple protocols (incl. old ones) with constrained resource usage.
+  run multiple protocols (incl. old ones) with constrained resource
+  usage.
 * Peer scopes. Sets a total limit on the resource usage of an individual
-peer.
-* Connection scopes. Constrains resource usage by a single
-connection. Starts monitoring when the connection begins and ends when
-the connection ends.
-* Stream (analogous to `Channel`) scopes. Begins when a stream is created
-and ends when the stream is closed.
+  peer.
+* Connection scopes. Constrains resource usage by a single connection.
+  Starts monitoring when the connection begins and ends when connection
+  ends.
+* Stream (analogous to `Channel`) scopes. Begins when a stream is
+  created and ends when the stream is closed.
 * User transaction scopes. A generic extension to the resource manager
-that can be implemented by a programmer.
+  that can be implemented by a programmer.
 
 There is also:
 
@@ -257,18 +306,18 @@ There is also:
 
 These are System and Transcient scopes for the `allowlist`, which is a
 list of honest peer anagolous to our `goldlist`. Allowlist scopes can
-continue to use (and meter) resources while the System scope has already
-reached its limit (to protect against ellipse attack).
+continue to use (and meter) resources while the System scope has
+already reached its limit (to protect against ellipse attack).
 
-Limits have a default setting that can be configured. It's also possible
-to scale limits with a particular config that allows for scaling to
-different machines.
+Limits have a default setting that can be configured. It's also
+possible to scale limits with a particular config that allows for
+scaling to different machines.
 
 ### DarkFi p2p resource manager
 
-The goal is to make something simple that we can extend later if necessary
-given how it behaves in the wild. We have simplified the libp2p `Resource
-management scopes` into a straightforward hierarchy:
+The goal is to make something simple that we can extend later if
+necessary given how it behaves in the wild. We have simplified the
+libp2p `Resource management scopes` into a straightforward hierarchy:
 
 ```
             node
@@ -281,8 +330,8 @@ management scopes` into a straightforward hierarchy:
 
 ```
 
-Resource usage is calculated from `Message` and `Protocol` and stored in
-`Channel`. We can sum the total resources by adding the total amount
+Resource usage is calculated from `Message` and `Protocol` and stored
+in `Channel`. We can sum the total resources by adding the total amount
 of resources used by each channel using the `p2p` method `channels()`,
 (this is easy since `Channel` has access to `p2p` via a weak ptr).
 
@@ -294,23 +343,24 @@ The `ScoringSubsystem` monitors scoring actions such as `send_message`
 or `recv_message` (and other actions that make use of resources defined
 by the `AbstractComputer`) and increments the resource usage.
 
-There is also a `Controller` that defines limits and decides on what action
-to take when a given limit has been breached (such as `channel.ban()`,
-`channel.throttle()` (TODO), or `choke()`, `snub()` etc (also TODO). It
-is important that the limits set by the `Controller` are configurable and
-can be injected in at runtime since `Message` and `Protocol` are dynamic,
-user-defined types.
+There is also a `Controller` that defines limits and decides on what
+action to take when a given limit has been breached (such as
+`channel.ban()`, `channel.throttle()` (TODO), or `choke()`, `snub()`
+etc (also TODO). It is important that the limits set by the
+`Controller` are configurable and can be injected in at runtime since
+`Message` and `Protocol` are dynamic, user-defined types.
 
 TODO:
 * implement `ScoringSubsystem`, `AbstractComputer`, and `Controller`.
 
 #### Channel Scoring
 
-We start with a score that keeps track of the resources used. Concretely the
-resources are: CPU, bandwidth, memory, disk space - any computing source.
-But to keep things simple, lets condense these measures into just two:
-work (representing CPU) and bytes (bandwidth/memory). These are primarily
-the main cause of resource starvation anyway (disk space is cheap).
+We start with a score that keeps track of the resources used.
+Concretely the resources are: CPU, bandwidth, memory, disk space - any
+computing source. But to keep things simple, lets condense these
+measures into just two: work (representing CPU) and bytes
+(bandwidth/memory). These are primarily the main cause of resource
+starvation anyway (disk space is cheap).
 
 ```
 struct ScoreTable {
@@ -321,8 +371,8 @@ struct ScoreTable {
 }
 ```
 
-There is an existing trait `Message`. We add a new trait method that takes
-a message and returns its score:
+There is an existing trait `Message`. We add a new trait method that
+takes a message and returns its score:
 
 ```
 impl Message for FooMessage {
@@ -353,33 +403,32 @@ message then:
 
 1. Call `scores.update()` which does:
     1. Apply an exponential decay to all the scores.
-    2. Call `scores.pop_front()` for any scores who are below the threshold (they
-       have expired).
+    2. Call `scores.pop_front()` for any scores who are below the
+      threshold (they have expired).
 2. Get the score of the received message.
 3. Store the score and timestamp in the vec.
 
 This logic is implemented in a `ScoringMetric` class.
 
-Now summing the vec will give you the cumulative score. Depending on how high
-this score is, we will:
+Now summing the vec will give you the cumulative score. Depending on
+how high this score is, we will:
 
 * Throttle the channel's incoming messages before processing them.
 * `channel.ban()`.
 
 #### Protocol Scoring
 
-The same mechanism can also be used by protocols, however mostly we can probably
-just use the channel scoring for most usecases as a good enough approximation.
-However there might be tight edge situations like the current dag sync which
-require more fine grained control.
+The same mechanism can also be used by protocols, however mostly we can
+probably just use the channel scoring for most usecases as a good
+enough approximation. However there might be tight edge situations like
+the current dag sync which require more fine grained control.
 
-In which case the protocol will instantiate its own `ScoringMetric` and keep
-track itself including calling ban on the channel.
+In which case the protocol will instantiate its own `ScoringMetric` and
+keep track itself including calling ban on the channel.
 
 #### Tracking the Remote
 
-The remote will ban us if we cross the limit. So our channel must also have a
-`scores_remote` which keeps track of *our* score (how the remote sees us).
-If we start getting too high then ease up on the messages to avoid getting
-blacklisted `channel.ban()` called on us.
-
+The remote will ban us if we cross the limit. So our channel must also
+have a `scores_remote` which keeps track of *our* score (how the remote
+sees us). If we start getting too high then ease up on the messages to
+avoid getting blacklisted `channel.ban()` called on us.

+ 10 - 9
doc/src/arch/overview.md

@@ -4,11 +4,11 @@ DarkFi is a layer one Proof-of-Work blockchain that supports anonymous
 applications. It is currently under development. This overview will
 outline a few key terms that help explain DarkFi.
 
-**Blockchain:** The DarkFi blockchain is based off Proof of Work RandomX
-algorithm. Consensus participating nodes, called miners, produce and propose
-new blocks to the network, extending some fork chain, which once it reaches
-a confirmation security threshold, can be appended to canonical by all nodes
-in the network.
+**Blockchain:** The DarkFi blockchain is based off Proof of Work
+RandomX algorithm. Consensus participating nodes, called miners,
+produce and propose new blocks to the network, extending some fork
+chain, which once it reaches a confirmation security threshold, can be
+appended to canonical by all nodes in the network.
 
 **Wallet:** A wallet is a portal to the DarkFi network. It provides
 the user with the ability to send and receive anonymous _darkened_
@@ -17,9 +17,9 @@ blockchain. All contract execution is done locally on the DarkFi wallet.
 
 **P2P Network:** The DarkFi ecosystem runs as a network of P2P nodes,
 where these nodes interact with each other over specific protocols (see
-[node overview](p2p-network.md)). Nodes communicate on a peer-to-peer network,
-which is also home to tools such as our P2P [irc](../misc/darkirc/darkirc.md)
-and P2P task manager [tau](../misc/tau.md).
+[node overview](p2p-network.md)). Nodes communicate on a peer-to-peer
+network, which is also home to tools such as our P2P
+[irc](../misc/darkirc/darkirc.md) and P2P task manager [tau](../misc/tau.md).
 
 **ZK smart contracts:** Anonymous applications on DarkFi run on proofs
 that enforce an order of operations. We call these zero-knowledge smart
@@ -37,4 +37,5 @@ compile and inspect contracts.
 **zkVM:** DarkFi's zkVM executes the binaries produced by zkas. The
 zkVM aims to be a general-purpose zkSNARK virtual machine that empowers
 developers to quickly prototype and debug zk contracts. It uses a
-trustless zero-knowledge proof system called Halo 2 with no trusted setup.
+trustless zero-knowledge proof system called Halo 2 with no trusted
+setup.

+ 71 - 68
doc/src/arch/sc/sc.md

@@ -91,14 +91,15 @@ conditions on the transaction's structure or other function calls
 {{#include ../../../../src/tx/mod.rs:transaction}}
 ```
 
-Function calls represent mutations of the current active state to a new state.
+Function calls represent mutations of the current active state to a new
+state.
 
 ```rust
 {{#include ../../../../src/sdk/src/tx.rs:contractcall}}
 ```
 
-The `contract_id` corresponds to the top level module for the contract which
-includes the global `State`.
+The `contract_id` corresponds to the top level module for the contract
+which includes the global `State`.
 
 The `func_id` of a function call corresponds to predefined objects
 in the submodules:
@@ -220,20 +221,20 @@ This section of the book documents smart contract development.
 
 ## Invoking Contracts
 
-In Solana and Ethereum, when invoking a contract, the call happens directly
-at the site of calling. That means the calling contract is responsible for
-constructing the params used to process the instruction.
+In Solana and Ethereum, when invoking a contract, the call happens
+directly at the site of calling. That means the calling contract is
+responsible for constructing the params used to process the instruction.
 
-In our case, it's more complicated since a smart contract function invocation
-involves ZK proofs with `get_metadata()` that can be verified in parallel.
-If we used the above model, we would first have to execute
-`process()` before verifying the proofs or signatures.
+In our case, it's more complicated since a smart contract function
+invocation involves ZK proofs with `get_metadata()` that can be
+verified in parallel. If we used the above model, we would first have
+to execute `process()` before verifying the proofs or signatures.
 
 Also arbitrary invocation allows arbitrary infinite recursion.
 
-The alternative method which is close to what we're doing already, is having
-the entire callgraph as a tree. Each `ContractCall`, now has a field called
-`children: Vec<ContractCall>`.
+The alternative method which is close to what we're doing already, is
+having the entire callgraph as a tree. Each `ContractCall`, now has a
+field called `children: Vec<ContractCall>`.
 
 ```rust
 pub struct ContractCall {
@@ -254,41 +255,42 @@ call `invoke()` exactly `n` times.
     let (params, retdat) = invoke(function_id);
 ```
 
-This doesn't actually invoke any function directly, but just iterates to the
-next child call in the current call. We should iterate through the entire list.
-If this doesn't happen, then there's a mismatch and the call fails with an
-error.
+This doesn't actually invoke any function directly, but just iterates
+to the next child call in the current call. We should iterate through
+the entire list. If this doesn't happen, then there's a mismatch and
+the call fails with an error.
 
-This logic is handled completely inside the contract without needing host
-functions.
+This logic is handled completely inside the contract without needing
+host functions.
 
-The downside is that the entire calldata for a smart contract is bundled
-in a tx, and isn't generated on the fly. This makes tx size bigger.
-However since we need ZK proofs, I expect the calldata would need to
-bundle the proofs for all invoked calls anyway.
+The downside is that the entire calldata for a smart contract is
+bundled in a tx, and isn't generated on the fly. This makes tx size
+bigger. However since we need ZK proofs, I expect the calldata would
+need to bundle the proofs for all invoked calls anyway.
 
-Essentially the entire program trace is created ahead of time by the "prover",
-and then the verifier simply checks the trace for correctness. This can be
-done in parallel since we have all the data ahead of time.
+Essentially the entire program trace is created ahead of time by the
+"prover", and then the verifier simply checks the trace for
+correctness. This can be done in parallel since we have all the data
+ahead of time.
 
 ### Depending on State Changes
 
-Another downside of this model is that state changes at the site of invocation
-are not immediate.
+Another downside of this model is that state changes at the site of
+invocation are not immediate.
 
-Currently in DarkFi, we separate contract calls into 2-phases: `process()`
-which verifies the calldata, and `update()` which takes a state update from
-`process()` and writes the changes.
+Currently in DarkFi, we separate contract calls into 2-phases:
+`process()` which verifies the calldata, and `update()` which takes a
+state update from `process()` and writes the changes.
 
 Host functions have permissions:
 
-* `process()` is READONLY, which means state can only be read. For example
-  it can use `db_get()` but *not* `db_set()`.
+* `process()` is READONLY, which means state can only be read. For
+  example it can use `db_get()` but *not* `db_set()`.
 * `update()` is WRITEONLY. It can only write to the state. For example
   it can use `db_set()` but *not* `db_get()`.
 
-Let `A`, `B` be smart contract functions. `A` calls `invoke(B)`. The normal
-flow in Ethereum would be:
+Let `A`, `B` be smart contract functions. `A` calls `invoke(B)`. The
+normal flow in Ethereum would be:
 
 ```
 process(A) ->
@@ -355,56 +357,57 @@ contract ChecksEffectsInteractions {
 }
 ```
 
-Interactions always occur last since they cause unknown effects. Performing
-logic based off state changes from an interacting outside contract (especially
-when user provided) is very risky.
+Interactions always occur last since they cause unknown effects.
+Performing logic based off state changes from an interacting outside
+contract (especially when user provided) is very risky.
 
-With the model of `invoke()` given above, we do not have any possibility of such
-an attack occurring.
+With the model of `invoke()` given above, we do not have any
+possibility of such an attack occurring.
 
 ## ABI
 
-We can do this in Rust through clever use of the serializer. Basically there
-is a special overlay provided for a Model which describes its layout.
-The layout saves the field names and types. Later this can be provided
-via a macro.
+We can do this in Rust through clever use of the serializer. Basically
+there is a special overlay provided for a Model which describes its
+layout. The layout saves the field names and types. Later this can be
+provided via a macro.
 
-Then dynamically in the program code, the params can be serialized/deserialized
-and inspected via this ABI overlay. This enables dynamic calls provided by
-users to be supported in an elegant and simple way.
+Then dynamically in the program code, the params can be (de)serialized
+and inspected via this ABI overlay. This enables dynamic calls provided
+by users to be supported in an elegant and simple way.
 
-The ABI also aids in debugging since when the overlay is loaded, then calldata
-can be inspected. Then we can inspect txs in Python, with exported ABIs saved
-as JSON files per contract documenting each function's params.
+The ABI also aids in debugging since when the overlay is loaded, then
+calldata can be inspected. Then we can inspect txs in Python, with
+exported ABIs saved as JSON files per contract documenting each
+function's params.
 
 ## Events
 
-Custom apps will need to subscribe to blockchain txs, and be able to respond
-to certain events. In Ethereum, there is a custom mechanism called
-[events](https://docs.soliditylang.org/en/latest/abi-spec.html#events).
+Custom apps will need to subscribe to blockchain txs, and be able to
+respond to certain events. In Ethereum, there is a custom mechanism
+called [events](https://docs.soliditylang.org/en/latest/abi-spec.html#events).
 This allows smart contracts to
 [return values to the UI](https://ethereum.stackexchange.com/questions/56879/can-anyone-explain-what-is-the-main-purpose-of-events-in-solidity-and-when-to-us).
 Events are indexed in the database.
 
-An equivalent mechanism in DarkFi, may be the ability to emit events which
-wallets can subscribe to. As for storing them an indexed DB, we already offer
-that functionality with `db_set()` during the update phase.
+An equivalent mechanism in DarkFi, may be the ability to emit events
+which wallets can subscribe to. As for storing them an indexed DB, we
+already offer that functionality with `db_set()` during the update
+phase.
 
-The emitted event could consist of the ContractId/FunctionId, an optional list
-of topics, and a binary blob.
+The emitted event could consist of the ContractId/FunctionId, an
+optional list of topics, and a binary blob.
 
 Alternatively, wallets would have to listen to all calls of a specific
-FunctionId. This allows wallets to only subscribe to some specific aspect of
-those calls.
+FunctionId. This allows wallets to only subscribe to some specific
+aspect of those calls.
 
-Solana by contrast allows the RPC to subscribe to accounts directly. The
-equivalent in our case, is subscribing to `db_set()` calls. Wallets can also
-receive these state changes and reflect them in their UI.
+Solana by contrast allows the RPC to subscribe to accounts directly.
+The equivalent in our case, is subscribing to `db_set()` calls. Wallets
+can also receive these state changes and reflect them in their UI.
 An [EventEmitter](https://github.com/solana-labs/solana/issues/14076)
 was recently added to Solana.
 
-Adding an explicit event emitter allows sending specific events used for
-wallets. This makes dev on the UI side much easier.
-Additionally the cost is low since any events emitted with no subscribers
-for that contract or not matching the filter will just be immediately dropped.
-
+Adding an explicit event emitter allows sending specific events used
+for wallets. This makes dev on the UI side much easier. Additionally
+the cost is low since any events emitted with no subscribers for that
+contract or not matching the filter will just be immediately dropped.

+ 19 - 14
doc/src/arch/services.md

@@ -1,7 +1,7 @@
 # Services
 
-Nodes and applications are composed out of services. These are long running
-components that may communicate with each other.
+Nodes and applications are composed out of services. These are long
+running components that may communicate with each other.
 
 The standard signature for a service is of the form:
 
@@ -26,12 +26,14 @@ impl Service {
 }
 ```
 
-Both `start()` and `stop()` should return immediately without blocking the caller.
-Any long running tasks they need to perform should be done using `StoppableTask` (see below).
+Both `start()` and `stop()` should return immediately without blocking
+the caller. Any long running tasks they need to perform should be done
+using `StoppableTask` (see below).
 
 ## `StoppableTask`
 
-Services will likely want to start any number of processes. For that you can use `StoppableTask`.
+Services will likely want to start any number of processes. For that
+you can use `StoppableTask`.
 
 For example `ManualSession` looks like this:
 
@@ -78,8 +80,9 @@ impl ManualSession {
 }
 ```
 
-The method in `start()` is a future that returns `Result<()>`. If you do not want
-to return a result (for example with long running processes), then simply use the future:
+The method in `start()` is a future that returns `Result<()>`. If you
+do not want to return a result (for example with long running
+processes), then simply use the future:
 
 ```rust
     async {
@@ -92,7 +95,8 @@ to return a result (for example with long running processes), then simply use th
 
 Another tool in our toolbox is the `subscribe()/notify()` paradigm.
 
-We can use `system::Subscriber`. Then inside our method we can define a method like so:
+We can use `system::Subscriber`. Then inside our method we can define
+a method like so:
 
 ```rust
     pub async fn subscribe_stop(&self) -> Result<Subscription<Error>> {
@@ -116,9 +120,10 @@ stop_sub.unsubscribe().await;
 
 ## Parent-Child Relationships
 
-In the async context we are forced to use `Arc<Self>`, but often times we want a parent-child
-relationship where if both parties contain an Arc reference to the other it creates a
-circular loop. For this case, we can use `std::sync::Weak` and `std::sync::Arc::new_cyclic()`.
+In the async context we are forced to use `Arc<Self>`, but often times
+we want a parent-child relationship where if both parties contain an
+Arc reference to the other it creates a circular loop. For this case,
+we can use `std::sync::Weak` and `std::sync::Arc::new_cyclic()`.
 
 ```rust
 pub struct Parent {
@@ -155,11 +160,11 @@ impl Child {
 }
 ```
 
-Otherwise if the relationship is just one way, use `Arc<Foo>`. For example if doing dependency
-injection where component B is dependent on component A, then we could do:
+Otherwise if the relationship is just one way, use `Arc<Foo>`. For
+example if doing dependency injection where component B is dependent
+on component A, then we could do:
 
 ```rust
 let comp_a = Foo::new();
 let comp_b = Bar::new(comp_a);
 ```
-

+ 14 - 14
doc/src/arch/tooling.md

@@ -2,33 +2,33 @@
 
 ## DarkFi Fullnode Daemon
 
-`darkfid` is the darkfi fullnode. It manages the blockchain, validates transactions
-and remains connected to the p2p network.
+`darkfid` is the darkfi fullnode. It manages the blockchain, validates
+transactions and remains connected to the p2p network.
 
-Clients can connect over localhost RPC or secure socket and perform these functions:
+Clients can connect over localhost RPC or secure socket and perform
+these functions:
 
 * Get the node status and modify settings realtime.
 * Query the blockchain.
 * Broadcast txs to the p2p network.
 * Get tx status, query the mempool and interact with components.
 
-`darkfid` does not have any concept of keys or wallet functionality. It does not
-manage keys.
+`darkfid` does not have any concept of keys or wallet functionality.
+It does not manage keys.
 
 ## Low Level Client
 
-Clients manage keys and objects. They make queries to `darkfid`, and receive notes
-encrypted to their public keys.
+Clients manage keys and objects. They make queries to `darkfid`, and
+receive notes encrypted to their public keys.
 
 Their design is usually specific to their application but modular.
 
-They also expose a high level simple to use API corresponding **exactly** to
-their commands so that product teams can easily build an application. They will
-use the command line tool as an interactive debugging application and
-point of reference.
+They also expose a high level simple to use API corresponding
+**exactly** to their commands so that product teams can easily build
+an application. They will use the command line tool as an interactive
+debugging application and point of reference.
 
-The API should be well documented with all arguments explained. Likewise for the
-commands help text.
+The API should be well documented with all arguments explained.
+Likewise for the commands help text.
 
 Command cheatsheets and example sessions are strongly encouraged.
-

+ 14 - 11
doc/src/arch/tx_lifetime.md

@@ -40,8 +40,8 @@ chain:
 ## Real-world simulation with non-instant confirmation
 
 The lifetime of a transaction $tx$ that passes verification and whose
-state transition is pending to be applied on top of the canonical (confirmed)
-chain:
+state transition is pending to be applied on top of the canonical
+(confirmed) chain:
 
 1. User creates a transaction $tx$
 2. User broadcasts $tx$ to `S`
@@ -64,8 +64,8 @@ in sequence
 ## Real-world simulation with non-instant confirmation, forks and multiple `CP` nodes
 
 The lifetime of a transaction $tx$ that passes verifications and whose
-state transition is pending to be applied on top of the canonical (confirmed)
-chain:
+state transition is pending to be applied on top of the canonical
+(confirmed) chain:
 
 1. User creates a transaction $tx$
 2. User broadcasts $tx$ to `S`
@@ -76,8 +76,8 @@ chain:
 7. $tx$ enters `M` `mempool`
 8. `M` broadcasts $tx$ to rest `M` nodes
 9. Block producer `SM` finds which fork to extend
-10. `SM` validates all unproposed transactions in its `mempool` in sequence,
-against extended fork state, discarding invalid
+10. `SM` validates all unproposed transactions in its `mempool` in
+  sequence, extended fork state, discarding invalid
 11. `SM` creates a block proposal containing $tx$ extending the fork
 12. `M` receives block proposal and validates its transactions against
 the extended fork state
@@ -92,12 +92,14 @@ transactions in sequence, against canonical state
 20. `S` writes the state updates to their chain
 21. `S` removes $tx$ from their `mempool`
 
-`M` will keep $tx$ in its `mempool` as long as it is a valid state transition
-for any fork(including canonical) or it get confirmed.
+`M` will keep $tx$ in its `mempool` as long as it is a valid state
+transition for any fork(including canonical) or it get confirmed.
 
-Unproposed transactions refers to all $tx$ not included in a proposal of any fork.
+Unproposed transactions refers to all $tx$ not included in a proposal
+of any fork.
 
-If a fork that can be confirmed fails to validate all its transactions(14), it should be dropped.
+If a fork that can be confirmed fails to validate all its
+transactions(14), it should be dropped.
 
 ## The `Transaction` object
 
@@ -134,7 +136,8 @@ For A -> B payments in DarkFi we use the Sapling scheme that originates
 from zcash. A payment transaction has a number of _inputs_ (which are
 coins being burned/spent), and a number of _outputs_ (which are coins
 being minted/created). An explanation for the ZK proofs for this scheme
-can be found [here](../zkas/examples/sapling.md) under the Zkas section of this book.
+can be found [here](../zkas/examples/sapling.md) under the Zkas section
+of this book.
 
 In code, the structs we use are the following:
 

+ 170 - 150
doc/src/arch/wallet.md

@@ -4,61 +4,66 @@
 
 See [DAGSync: Graph-aware Zcash wallets](https://words.str4d.xyz/dagsync-graph-aware-zcash-wallets/) by str4d.
 
-TLDR: as we're syncing the wallet, we normally scan forwards prioritizing both
-sends and receives the same. Instead we can optimize this for immediate
-spendability (despite not having full received balance). Assume we have the
-entire blockchain state but haven't yet trial decrypted all notes.
-
-* **Nullifier Tracking:** for every note, look for a nullifier. If it doesn't exist then the note has
-  not yet been spent.
-* **Targeted Decryption:** when the nullifier exists, then check the output notes of that transaction.
-  One of these is likely to be change we can spend.
+TLDR: as we're syncing the wallet, we normally scan forwards
+prioritizing both sends and receives the same. Instead we can optimize
+this for immediate spendability (despite not having full received
+balance). Assume we have the entire blockchain state but haven't yet
+trial decrypted all notes.
+
+* **Nullifier Tracking:** for every note, look for a nullifier. If it
+  doesn't exist then the note has not yet been spent.
+* **Targeted Decryption:** when the nullifier exists, then check the
+  output notes of that transaction. One of these is likely to be change
+   we can spend.
 
 Additionally:
 
-* **Source Discovery:** go backwards from the latest block and trial decrypt
-  outputs. Then for those decrypted outputs, check their nullifiers (as per
-  nullifier tracking above).
+* **Source Discovery:** go backwards from the latest block and trial
+  decrypt outputs. Then for those decrypted outputs, check their
+  nullifiers (as per nullifier tracking above).
 * **History Discovery:** simultaneously another scan goes forwards from
-  the last sync point until it meets the source discovery (going backwards).
+  the last sync point until it meets the source discovery (going
+  backwards).
 
-**Knitting** is where periodically wallets will gather all unspent coins and
-construct a new one. It will use the memo field to indicate to wallet sync
-that it doesn't need to go back any further than this point.
+**Knitting** is where periodically wallets will gather all unspent
+coins and construct a new one. It will use the memo field to indicate
+to wallet sync that it doesn't need to go back any further than this
+point.
 
-However since wallets keep track of their own coins (assuming a wallet isn't
-shared between 2 devices) which is the majority usecase, then this technique
-is less relevant since you know which coins you've spent.
+However since wallets keep track of their own coins (assuming a wallet
+isn't shared between 2 devices) which is the majority usecase, then
+this technique is less relevant since you know which coins you've spent.
 
 ## Modules and Addons
 
-The current standard model for smart contract cryptocurrencies is to abuse
-the web browser's plugin architecture. This has several undesirable effects:
+The current standard model for smart contract cryptocurrencies is to
+abuse the web browser's plugin architecture. This has several
+undesirable effects:
 
 * Dependency on js.
 * Poor security model.
-* Centralized frontends. The frontend can be loaded via IPFS (usually via a
-  gateway), but it still needs to access a hosted RPC. Users can deploy their
-  own and then configure the RPC URL but this is complicated so it rarely
-  happens. Then there are projects for "decentralized RPC" but this is lipstick
-  on a cow (the bloated browser).
+* Centralized frontends. The frontend can be loaded via IPFS (usually
+  via a gateway), but it still needs to access a hosted RPC. Users can
+  deploy their own and then configure the RPC URL but this is
+  complicated so it rarely happens. Then there are projects for
+  "decentralized RPC" but this is lipstick on a cow (the bloated browser).
   * Hosted frontends are a legal risk. See TornadoCash.
-* Limitations of the browser addon architecture. I cannot for example run a p2p
-  network and must go through some centralized "solution" (not a solution but
-  actually an anti-pattern).
-  * Firefox used to have a much stronger XUL framework which enabled cool things
-    like remote CLI control of the browser or interfacing with other tools,
-    but they deleted this and just put Chrome's addon architecture which made
-    a whole load of addons no longer possible.
+* Limitations of the browser addon architecture. I cannot for example
+  run a p2p network and must go through some centralized "solution"
+  (not a solution but actually an anti-pattern).
+  * Firefox used to have a much stronger XUL framework which enabled
+    cool things like remote CLI control of the browser or interfacing
+    with other tools, but they deleted this and just put Chrome's addon
+    architecture which made a whole load of addons no longer possible.
 * Non-portable. Running metamask ethereum apps on mobile is generally
-  non-trivial. Wallets should easily work across all platforms and devices
-  seamlessly.
-  * Metamask has a separate standalone Android app which is non-ideal since
-    now the big app has 2 separate impls. Ideally there is just one big app
-    since diverging impls lead to fragmentation.
-* The architecture is specific to browsers and non-portable to other software
-  unless they include a browser engine like WebKit which is a huge chunk of
-  code.
+  non-trivial. Wallets should easily work across all platforms and
+  devices seamlessly.
+  * Metamask has a separate standalone Android app which is non-ideal
+    since now the big app has 2 separate impls. Ideally there is just
+    one big app since diverging impls lead to fragmentation.
+* The architecture is specific to browsers and non-portable to other
+  software unless they include a browser engine like WebKit which is a
+  huge chunk of code.
 
 Benefits of [hackable software](https://www.geoffreylitt.com/2019/07/29/browser-extensions) are:
 
@@ -68,19 +73,22 @@ Benefits of [hackable software](https://www.geoffreylitt.com/2019/07/29/browser-
   use of the software.
   * Niche users can find a plugin for their edgecase which might not be
     supported in the big app.
-* Easy entry for devs that have an idea compared to making a new app or tool.
-  * Blender has a built in Python terminal, and the code is fully introspectable
-    which allows exploring the codebase and calling `help(foo)` on objects.
+* Easy entry for devs that have an idea compared to making a new app or
+  tool.
+  * Blender has a built in Python terminal, and the code is fully
+    introspectable which allows exploring the codebase and calling
+    `help(foo)` on objects.
 * Most major successful products are hackable. Important examples:
-  WinAmp, Blender3D, Firefox.
+  Winamp, Blender3D, Firefox.
 
 ### Addons
 
 Addons are sandboxed WASM code which has tightly controlled permissions.
 They are untrusted third party 'apps'.
 
-Most functionality are the client code for wallets. For example we want to use
-the DAO contract so we download an addon. An addon may provide this functionality:
+Most functionality are the client code for wallets. For example we want
+to use the DAO contract so we download an addon. An addon may provide
+this functionality:
 
 * An API that can be called by other addons.
 * A UI schema for building an interface.
@@ -88,25 +96,25 @@ the DAO contract so we download an addon. An addon may provide this functionalit
   maintaining any client specific state.
 
 Addons should be sandboxed. By default access to all host functions is
-blacklisted, and they must be explicitly whitelisted to call any function,
-including other addons.
+blacklisted, and they must be explicitly whitelisted to call any
+function other addons.
 
 We can run addons in separate threads so that if one of them crashes,
-the host application can simply kill the process. Addons can then run alongside
-each other without any effect on each other. However this leads to increased
-memory usage from the overhead of having every addon spawning a new thread,
-so we may wish to use WASM functionality to interpret addon functions that
-take too long.
+the host application can simply kill the process. Addons can then run
+alongside each other without any effect on each other. However this
+leads to increased memory usage from the overhead of having every addon
+spawning a new thread, so we may wish to use WASM functionality to
+interpret addon functions that take too long.
 
 There is a special function inside the WASM which is called on startup
-called `requested_permissions()`. This is used to request the permissions
-from the user who then adds it to the whitelist for this addon.
-While the requested permissions will be a list of namespaced functions,
-the UI will simply display these as something simple to the user like
-"manage a database" or "use event graph" (see below).
+called `requested_permissions()`. This is used to request the
+permissions from the user who then adds it to the whitelist for this
+addon. While the requested permissions will be a list of namespaced
+functions, the UI will simply display these as something simple to the
+user like "manage a database" or "use event graph" (see below).
 
-Addons are loaded dynamically and can be downloaded from a source such as
-the DHT network.
+Addons are loaded dynamically and can be downloaded from a source such
+as the DHT network.
 
 ![blender addons](../assets/blender-addons.png)
 
@@ -114,18 +122,20 @@ the DHT network.
 
 Blender's addon browser looks much better than Firefox's.
 
-When creating addon UIs, there should be a way to allow live reloading of the
-UI for convenient design, and possibly the impl too which makes live debugging
-possible.
+When creating addon UIs, there should be a way to allow live reloading
+of the UI for convenient design, and possibly the impl too which makes
+live debugging possible.
 
 #### Addon Maintenance
 
-Overtime there will be a tension between upgrading the core API and maintaining
-a large ecosystem of addons. Therefore there should be a centralized git repo
-for all addons listed in the wallet. Addon authors can tag releases and request
-their addon be updated downstream by the wallet maintainers.
+Overtime there will be a tension between upgrading the core API and
+maintaining a large ecosystem of addons. Therefore there should be a
+centralized git repo for all addons listed in the wallet. Addon authors
+can tag releases and request their addon be updated downstream by the
+wallet maintainers.
 
-This way when large breaking API changes are needed, we have the ability to:
+This way when large breaking API changes are needed, we have the
+ability to:
 
 * Simultaneously update all addons at once.
 * Communicate with addon authors to coordinate any changes needed such
@@ -134,40 +144,40 @@ This way when large breaking API changes are needed, we have the ability to:
 
 This is similar to how Linux distributions maintain packages.
 
-Addons must also have contact details so darkfi core and the wallet team are
-able to contact them.
+Addons must also have contact details so darkfi core and the wallet
+team are able to contact them.
 
 ### Modules
 
-These are dynamic objects which are trusted and provide full access to the
-host system.
+These are dynamic objects which are trusted and provide full access to
+the host system.
 
 An example of such a module could be an `event_graph` module.
-This enables addons to request a specific event graph instance. For example
-the users of a DAO may wish to coordinate through the p2p network.
-They would therefore use the `event_graph` module to create an event graph
-instance for that usecase, and the p2p network would create a swarm for this
-event graph. All of this would be handled by the module which simply provides
-a convenient interface to the addon.
+This enables addons to request a specific event graph instance. For
+example the users of a DAO may wish to coordinate through the p2p
+network. They would therefore use the `event_graph` module to create an
+event graph instance for that usecase, and the p2p network would create
+a swarm for this event graph. All of this would be handled by the
+module which simply provides a convenient interface to the addon.
 
-This enables using the full power of the system, but safely segregating this
-functionality from untrusted addons through a firewall.
-It solves the issue of relying on hosted/centralized gateways since user wallets
-will just spin up p2p nodes locally.
+This enables using the full power of the system, but safely segregating
+this functionality from untrusted addons through a firewall.
+It solves the issue of relying on hosted/centralized gateways since
+user wallets will just spin up p2p nodes locally.
 
-Modules can only be installed manually from file and require restarting the
-wallet.
+Modules can only be installed manually from file and require
+restarting the wallet.
 
 ### Scenegraph
 
-This is a popular gamedev design pattern where the entire program state is
-represented as an introspectable tree. It's similar to the UNIX pattern of
-"everything is a file", and maybe plan9's idea.
+This is a popular gamedev design pattern where the entire program state
+is represented as an introspectable tree. It's similar to the UNIX
+pattern of "everything is a file", and maybe plan9's idea.
 
 [The scenegraph](https://archive.gamedev.net/archive/reference/programming/features/scenegraph/index.html)
 is a world where the children are objects, and the objects have
-attributes that can be read and operated on. These can all be composed together
-through generic node interfaces.
+attributes that can be read and operated on. These can all be composed
+together through generic node interfaces.
 
 ![gamedev scenegraph](../assets/gamedev-scenegraph.jpg)
 
@@ -196,43 +206,45 @@ Application
     Module #1
 ```
 
-* Each object can emit events, and subscribe to events from other objects.
-  All objects have an `event()` method and `update()` method.
-  Update is called per frame, while event can be used for timer events such
-  as periodic updates or wakeups, as well as input events.
+* Each object can emit events, and subscribe to events from other
+  objects. All objects have an `event()` method and `update()` method.
+  Update is called per frame, while event can be used for timer events
+  such as periodic updates or wakeups, as well as input events.
 * Drawing related objects have a boundary where they can draw.
   They all implement a `draw()` method. Drawing outside the boundary is
   disallowed.
 * Everything has names, attributes and methods with docstrings.
   This is all introspectable and eventually scriptable.
-  Also the internal state can be accessed through inbuilt terminal, possibly
-  using Python.
+  Also the internal state can be accessed through inbuilt terminal,
+  possibly using Python.
 
 ## UI Specifics
 
 Laundry list of required features:
 
-* XUL/bpy inspired. There is a small wallet core, but the entire UI is created
-  using definitions and the DSL.
+* XUL/bpy inspired. There is a small wallet core, but the entire UI is
+  created using definitions and the DSL.
 * Dynamic fractional scaling.
 * Customizable scriptable interface, preferably using Python and/or Rust.
 * Calm UI with default darkmode. No animations.
 * Text oriented, clean and minimal design.
 * Avoid modal dialogs. Instead use mode toggling and expanding panels.
-  * The UI should enable you to view all relevant options and tools at a glance,
-    without the need for pushing or dragging windows around.
+  * The UI should enable you to view all relevant options and tools at a
+    glance, without the need for pushing or dragging windows around.
   * Tools and interface options designed to not block the user from
     using any other parts.
     * The UI should stay responsive by all means.
-        * This means the UI runs in its own thread, communicating with the
-          backend which runs on another thread.
-        * Non blocking and async. Remains responsive despite work happening.
+        * This means the UI runs in its own thread, communicating with
+          the backend which runs on another thread.
+        * Non blocking and async. Remains responsive despite work
+          happening.
   * User input should remain as consistent and predictable as possible.
 * Installation free: run out of the box for new installs, not requiring
   root system access.
-* Responsive design across desktop and mobile devices with minimal specific code
-  or changes required. Ideally none at all.
-* First class CLI support with access to all functionality existing in the UI.
+* Responsive design across desktop and mobile devices with minimal
+  specific code or changes required. Ideally none at all.
+* First class CLI support with access to all functionality existing in
+  the UI.
   * Possibly there is a way of transforming the UI schema specced by addons
     into a command line interface.
 
@@ -240,10 +252,10 @@ See also the [Blender Human Interface Guidelines: Paradigms](https://developer.b
 
 ## Roadmap
 
-1. Simple `drk` CLI tool with basic core apps working. We want to ship so
-   this is the only core prerequisite to start.
-2. We can add WASM addons with the basic framework after. Then migrate core apps
-   such as money or DAO to this.
+1. Simple `drk` CLI tool with basic core apps working. We want to ship
+   so this is the only core prerequisite to start.
+2. We can add WASM addons with the basic framework after. Then migrate
+   core apps such as money or DAO to this.
 3. Add modules subsystem.
 4. Construct the UI.
   1. Create the overall framework of resizable 'editors' and define the
@@ -270,19 +282,21 @@ Multi-platform main view with splitting and these editors:
 
 ### Story
 
-The story goes like this. There's a node running of some kind. This could be
-darkfid or darkirc.
+The story goes like this. There's a node running of some kind. This
+could be darkfid or darkirc.
 
-In the case of darkfid, there's additional per wallet processing that's done
-such as scanning transactions. Currently this is the role played by drk scan.
+In the case of darkfid, there's additional per wallet processing that's
+done such as scanning transactions. Currently this is the role played
+by drk scan.
 
-Regardless of whether there's one node with functionality existing as pluggable
-modules, we assume now there are nodes running which the wallet/UI must
-communicate with.
+Regardless of whether there's one node with functionality existing as
+pluggable modules, we assume now there are nodes running which the
+wallet/UI must communicate with.
 
-Inside the user wallet, there are multiple plugins. A plugin might need to
-query the blockchain, spawn a p2p network (to exchange data for OTC or
-coordinate DAO activity as examples). They do this by connecting to the nodes.
+Inside the user wallet, there are multiple plugins. A plugin might need
+to query the blockchain, spawn a p2p network (to exchange data for OTC
+or coordinate DAO activity as examples). They do this by connecting to
+the nodes.
 
 ### Key Concepts
 
@@ -290,8 +304,8 @@ We now give an overview of the current iteration of the scene graph:
 
 * Nodes have a type. Each node can have multiple children.
 * It is a graph not a tree. A node can have multiple parents.
-* Each node has several properties which have types such as f32, u32, str, enum.
-  Properties can also be an array or vec of these types.
+* Each node has several properties which have types such as f32, u32,
+  str, enum. Properties can also be an array or vec of these types.
   See `bin/darkwallet/pydrk/api.py:5` for the fields in a property.
 * Nodes have signals such as `mouse_clicked`. Multiple slots can be
   registered for a signal. Think of this like notifications.
@@ -299,18 +313,21 @@ We now give an overview of the current iteration of the scene graph:
 
 ### Plugins
 
-Each app has a separate plugin. Plugins have their own private internal data.
-Any data they wish to expose can be done by providing properties or methods in
-their node in the scene graph.
+Each app has a separate plugin. Plugins have their own private internal
+data. Any data they wish to expose can be done by providing properties
+or methods in their node in the scene graph.
 
-The scene graph then applies access restrictions depending on the ownership
-semantics of properties and methods (think like UNIX users and groups).
+The scene graph then applies access restrictions depending on the
+ownership semantics of properties and methods (think like UNIX users
+and groups).
 
-Plugins provide `init()` and `update(event)` functions. `init()` is called when
-a new *plugin instance* is created. Plugins can have multiple instances.
+Plugins provide `init()` and `update(event)` functions. `init()` is
+called when a new *plugin instance* is created. Plugins can have
+multiple instances.
 
-Using the scene graph, this is scriptable from any language, introspectable and
-with permissions - using a data structure inspised by UNIX and plan9.
+Using the scene graph, this is scriptable from any language,
+introspectable and with permissions - using a data structure inspised
+by UNIX and plan9.
 
 #### Example
 
@@ -325,42 +342,45 @@ and gives it a layer to draw in, which is simultaneously linked into both
     /plugin/dao/instance1/dao_instance1_layer
 ```
 
-The plugin can then speak with modules by calling methods or subscribing to
-signals on `/mod/darkfid`. Methods and signals are automatically proxied from
-the node.
+The plugin can then speak with modules by calling methods or
+subscribing to signals on `/mod/darkfid`. Methods and signals are
+automatically proxied from the node.
 
 ### Running a New Node per Function
 
-Lets say we wish to do OTC swaps and utilize the event graph. Are users then
-required to run a new node per app?
+Lets say we wish to do OTC swaps and utilize the event graph. Are users
+then required to run a new node per app?
 
 At least in this case, there should be a way to spin up an event graph.
 
-For scanning transactions, is this done at startup incurring an initialization
-cost when opening the wallet? I guess so to maintain independence of keys from
-the darkfid node.
+For scanning transactions, is this done at startup incurring an
+initialization cost when opening the wallet? I guess so to maintain
+independence of keys from the darkfid node.
 
-Another example is the task manager and darkirc chat. Do these remain separate
-daemons? When we add swarming support to p2p, it might be possible to merge all
-p2p functionality across apps into a unified subsystem, reducing complexity.
-In which case there should be a simple way to utilize this subsystem.
+Another example is the task manager and darkirc chat. Do these remain
+separate daemons? When we add swarming support to p2p, it might be
+possible to merge all p2p functionality across apps into a unified
+subsystem, reducing complexity. In which case there should be a simple
+way to utilize this subsystem.
 
-The more nodes users are required to run, the more difficult it will become to
-have a decentralized network, so we should find a way to reduce the burden for
-users to setup our infra.
+The more nodes users are required to run, the more difficult it will
+become to  have a decentralized network, so we should find a way to
+reduce the burden for users to setup our infra.
 
 ### Usage Patterns
 
 Wallets are clients talking to the node (remote).
 
-* There's persistent nodes running some process to sync data from the network (darkfid downloading/verifying blockchain, event graph, ...)
-* There's scanning done by wallets on startup (check for recv'd payments, decrypt DMs, .etc)
+* There's persistent nodes running some process to sync data from the
+  network (darkfid downloading/verifying blockchain, event graph, ...)
+* There's scanning done by wallets on startup (check for recv'd
+  payments, decrypt DMs, .etc)
   * Scanning downloads the updates from persistent nodes
-* Wallets can interact with nodes to push data to the network, or communicate with other nodes .etc
+* Wallets can interact with nodes to push data to the network, or
+  communicate with other nodes .etc
 * Wallet apps can talk with each other.
 
 ## References
 
 * [Veil: Private Browsing Semantics Without Browser-side Assistance](https://mickens.seas.harvard.edu/files/mickens/files/veil.pdf)
 * [Atlantis: Robust, Extensible Execution Environments for Web Applications](https://scholar.harvard.edu/files/mickens/files/atlantis.pdf)
-

+ 19 - 15
doc/src/crypto/key-recovery.md

@@ -1,27 +1,30 @@
 # Key Recovery Scheme
 
-The aim of this scheme is to enable 3 players to generate a single public key
-which can be recovered using any $t$ of $n$ players. It is trustless and anonymous.
-The scheme can be used for multisig payments which appear on chain as normal payments.
+The aim of this scheme is to enable 3 players to generate a single
+public key which can be recovered using any $t$ of $n$ players. It is
+trustless and anonymous. The scheme can be used for multisig payments
+which appear on chain as normal payments.
 
-The basic concept relies on the additivity of functions $(f∘g)(a) = f(a) + g(a)$,
-and additive homomorphism of EC points. That way we avoid heavy MPC multiplications
-and keep the scheme lightweight.
+The basic concept relies on the additivity of functions
+$(f∘g)(a) = f(a) + g(a)$, and additive homomorphism of EC points.
+That way we avoid heavy MPC multiplications and keep the scheme
+lightweight.
 
 The values $x₁, …, xₙ$ are fixed strings known by all players.
 
-Let $⟨x⟩ = \textrm{commit}(x)$ denote a hiding pedersen commitment to $x$.
+Let $⟨x⟩ = \textrm{commit}(x)$ denote a hiding pedersen commitment to
+$x$.
 
 ## Constructing the Curve
 
 Each player $i$ constructs their own curves, with the resulting curve
-being the sum of them all. Given any t points, we can recover the original curve and
-hence the secret.
+being the sum of them all. Given any t points, we can recover the
+original curve and hence the secret.
 
 ### Player $i$ creates curve $i$
 
-Player $i$ creates a random curve $Cᵢ = Y + a₀ + a₁X + ⋯ + aₜ₋₁Xᵗ⁻¹$, and broadcasts
-commits $A₀ = ⟨a₀⟩, …, Aₜ₋₁ = ⟨aₜ₋₁⟩$.
+Player $i$ creates a random curve $Cᵢ = Y + a₀ + a₁X + ⋯ + aₜ₋₁Xᵗ⁻¹$,
+and broadcasts commits $A₀ = ⟨a₀⟩, …, Aₜ₋₁ = ⟨aₜ₋₁⟩$.
 
 Then player $i$ lifts points
 $$ Rⱼ = (xⱼ, yⱼ) ∈ V(Cᵢ) $$
@@ -42,10 +45,11 @@ $$ P = A₀₁ + ⋯ + A₀ₙ = ⟨C₁(𝟎) + ⋯ + Cₙ(𝟎)⟩ = ⟨C(𝟎
 ## Key Recovery
 
 Let $T ⊆ N$ be the subset $|T| = t$ of players recovering the secret key.
-Reordering as needed, all players in $T$ send their points $Rⱼ$ for curves $C₁, …, Cₙ$ to player 1.
+Reordering as needed, all players in $T$ send their points $Rⱼ$ for
+curves $C₁, …, Cₙ$ to player 1.
 
-For each curve $Cᵢ$, player 1 now has $t$ points. Using either lagrange interpolation or row reduction, they
-can recover curves $C₁, …, Cₙ$ and compute $C = C₁ + ⋯ + Cₙ$.
+For each curve $Cᵢ$, player 1 now has $t$ points. Using either lagrange
+interpolation or row reduction, they can recover curves $C₁, …, Cₙ$ and
+compute $C = C₁ + ⋯ + Cₙ$.
 
 Then player 1 computes the shared secret $d = C(𝟎)$.
-

+ 64 - 53
doc/src/crypto/reading-maths-books.md

@@ -21,15 +21,15 @@ research texts to study from. Broadly speaking, they are:
 Usually you will follow one main text on a topic, but with a few other
 supplementary books as backup. Often you get stuck on a concept in the
 main text, and the supplement books will assist you to make sense by
-looking at things from a different explanation. Re-phrasing the same idea
-using different words can make a big difference in dicephering some
-theorem or object.
+looking at things from a different explanation. Re-phrasing the same
+idea using different words can make a big difference in dicephering
+some theorem or object.
 
 ## Video Courses
 
 There are many high quality online courses following important texts.
-They explain the main core forums, focusing your attention on the key ideas
-and explaining things in an intuitive non-formal manner.
+They explain the main core forums, focusing your attention on the key
+ideas and explaining things in an intuitive non-formal manner.
 
 Favourites:
 
@@ -41,73 +41,84 @@ Favourites:
 
 ## Getting Excited, Taking a High Level View
 
-Take a look at the contents. Familiarize yourself with the structure of the book.
-Make note of topics that you will learn and master. Get excited about the truths
-that you will unlock. You will come back here every periodically to remember why
-you are studying and where you are going.
+Take a look at the contents. Familiarize yourself with the structure of
+the book. Make note of topics that you will learn and master. Get
+excited about the truths that you will unlock. You will come back here
+every periodically to remember why you are studying and where you are
+going.
 
-Make a lesson plan. Often the first chapter of a new topic is important, but if
-you're already familiar then maybe you can jump to advanced material.
+Make a lesson plan. Often the first chapter of a new topic is
+important, but if you're already familiar then maybe you can jump to
+advanced material.
 
-Be aware if you struggle too much at the advanced level, and make no progress at
-all then it's a signal to swallow your pride, be humble and go down to a lower level
-before moving up again. We take shots, but sometimes we have to take a few steps
-back. The tortoise beats the hare.
+Be aware if you struggle too much at the advanced level, and make no
+progress at all then it's a signal to swallow your pride, be humble and
+go down to a lower level before moving up again. We take shots, but
+sometimes we have to take a few steps back. The tortoise beats the hare.
 
-However you must struggle. Don't be a weakling. Fight to rise up. Give it your
-focus, dedication and attention. Get into the zone, or [rausch](https://youtu.be/BTXj6ZEANFg?t=443).
-You evolve because it is hard.
+However you must struggle. Don't be a weakling. Fight to rise up. Give
+it your focus, dedication and attention. Get into the zone, or
+[rausch](https://youtu.be/BTXj6ZEANFg?t=443). You evolve because it is
+hard.
 
 ## Reading the Chapter
 
-Now you've chosen your chapter. Do a light first-pass read through it. Focus not
-on the details but the main theorems and structure of what you're learning.
-Try to understand from a conceptual level the main ideas and how they will fit
-together.
+Now you've chosen your chapter. Do a light first-pass read through it.
+Focus not on the details but the main theorems and structure of what
+you're learning. Try to understand from a conceptual level the main
+ideas and how they will fit together.
 
-It's normal for the end of the chapter to feel increasingly cryptic and unintelligible.
+It's normal for the end of the chapter to feel increasingly cryptic and
+unintelligible.
 
-Now return to the beginning of the chapter and begin seriously reading it.
-Make sure to follow the logic of ideas and understand what new objects are.
-You might get stuck on a difficult idea or long proof. Feel free to skip over
-these and return back to them after. Many of the concepts will be new, and
-you will be awkward in your dealing with them. Do not worry as the more familiar
-you become with this subject, your understanding will become solid.
+Now return to the beginning of the chapter and begin seriously reading
+it. Make sure to follow the logic of ideas and understand what new
+objects are. You might get stuck on a difficult idea or long proof.
+Feel free to skip over these and return back to them after. Many of the
+concepts will be new, and you will be awkward in your dealing with
+them. Do not worry as the more familiar you become with this subject,
+your understanding will become solid.
 
-As you work through the chapter towards the end, you are learning where all the theorems,
-definitions and proofs are. You will likely return back to these as you try to
-solve questions.
+As you work through the chapter towards the end, you are learning where
+all the theorems, definitions and proofs are. You will likely return
+back to these as you try to solve questions.
 
-While you're reading through, you will likely pass back over theorems you tried
-to understand earlier but skipped over. If they still don't make sense, then it's
-fine to again put them to the side and return back to them again after.
+While you're reading through, you will likely pass back over theorems
+you tried to understand earlier but skipped over. If they still don't
+make sense, then it's fine to again put them to the side and return
+back to them again after.
 
-In this way we are reading a chapter in several passes, going back through past
-material as we go forwards or try to solve questions. We also might sideline material
-in the beginning and decide to look more into them later.
+In this way we are reading a chapter in several passes, going back
+through past material as we go forwards or try to solve questions.
+We also might sideline material in the beginning and decide to look
+more into them later.
 
-Eventually our familiarity with the chapter is strong, and everything (more or less)
-makes sense.
+Eventually our familiarity with the chapter is strong, and everything
+(more or less) makes sense.
 
 ## Solving Questions
 
-When you are stuck, feel free to ask others in the team, or post questions on math
-stackexchange if nobody knows.
+When you are stuck, feel free to ask others in the team, or post
+questions on math stackexchange if nobody knows.
 
-You will need to research things, searching the web and studying the supplement books.
+You will need to research things, searching the web and studying the
+supplement books.
 
-I tend to slightly prefer books with solutions to questions for self study.
+I tend to slightly prefer books with solutions to questions for self
+study.
 
-You should always do questions. As many as possible. For core subjects, always attempt
-to do all or most of the questions, unless there are far too many.
+You should always do questions. As many as possible. For core subjects,
+always attempt to do all or most of the questions, unless there are far
+too many.
 
-When you are shorter on time or studying a subject on the side, you may choose to pick
-out a sample of questions with a mix of important looking topics and others which grab
-your attention or pique your curiosity.
+When you are shorter on time or studying a subject on the side, you may
+choose to pick out a sample of questions with a mix of important
+looking topics and others which grab your attention or pique your
+curiosity.
 
 ## Post-Chapter Review
 
-After reading the chapter, be sure to do a quick review and write down any theorems
-and proofs that caught your attention. You may wish to write them on flash cards or
-on a special notebook so later you can come back to them.
-
+After reading the chapter, be sure to do a quick review and write down
+any theorems and proofs that caught your attention. You may wish to
+write them on flash cards or on a special notebook so later you can
+come back to them.

+ 16 - 11
doc/src/dep/0001.md

@@ -6,13 +6,15 @@ status: accepted
 
 ## Motivation
 
-Currently `version` messages are empty, but before releasing in order to anticipate protocol
-upgrades, we should include the protocol version. This is for the moment inside `verack`,
-but should be moved to `version` since it allows immediately dropping the connection if the
-protocol version is incorrect (and indeed is the main purpose of the version message).
+Currently `version` messages are empty, but before releasing in order
+to anticipate protocol upgrades, we should include the protocol
+version. This is for the moment inside `verack`, but should be moved to
+`version` since it allows immediately dropping the connection if the
+protocol version is incorrect (and indeed is the main purpose of the
+version message).
 
-Additionally it should include further info which makes debugging connections and negotiation
-easier.
+Additionally it should include further info which makes debugging
+connections and negotiation easier.
 
 ## Proposal
 
@@ -26,11 +28,14 @@ easier.
 | `Vec<String>`        | ext_send_addr       | (Optional) External address of the node sending this message                                                           |
 | `Vec<(String, u32)>` | (services, version) | List of features to be enabled for this connection                                                                     |
 
-`resolv_recv_addr` is optional as inbound connections do not have such an address.
+`resolv_recv_addr` is optional as inbound connections do not have such
+an address.
 
 `ext_send_addr` is empty when no external address is set.
 
-The `(services, version)` field can be used to enable certain features in protocols, or even to upgrade protocols to new versions.
-When protocols are first attached, they can add their own data to this field which will be communicated in the subsequent version exchange.
-Any further negotiation needed can be done using protocol specific messages afterwards.
-
+The `(services, version)` field can be used to enable certain features
+in protocols, or even to upgrade protocols to new versions. When
+protocols are first attached, they can add their own data to this field
+which will be communicated in the subsequent version exchange. Any
+further negotiation needed can be done using protocol specific messages
+afterwards.

+ 68 - 57
doc/src/dep/0002.md

@@ -6,65 +6,75 @@ status: deprecated
 
 ## Current Situation
 
-When creating the DAO, we needed to invent the concept of protocol owned liquidity in DarkFi.
-Without this, in order to have on chain DAO treasuries, the DarkFi blockchain would have to
-recognize funds held by both the money and DAO contracts as valid. This introduces a security
+When creating the DAO, we needed to invent the concept of protocol
+owned liquidity in DarkFi. Without this, in order to have on chain DAO
+treasuries, the DarkFi blockchain would have to recognize funds held by
+both the money and DAO contracts as valid. This introduces a security
 risk if there is an error in the DAO contracts.
 
-Additionally it means that liquidity could only be held by the DAO contract, and any liquidity
-held by other contracts would have to be recognized by the consensus as valid. This would
-restrict the protocols that could work with on chain liquidity to a small hardcoded subset
+Additionally it means that liquidity could only be held by the DAO
+contract, and any liquidity held by other contracts would have to be
+recognized by the consensus as valid. This would restrict the protocols
+that could work with on chain liquidity to a small hardcoded subset
 due to security.
 
-Motivated by the desire to enable protocol owned liquidity, we created the concept in
-`money::transfer()` of the `spend_hook`.
+Motivated by the desire to enable protocol owned liquidity, we created
+the concept in `money::transfer()` of the `spend_hook`.
 
-Firstly a quick recap of how `money::transfer()` works. During the mint phase of creating
-coins, we construct a coin `C = hash(…, spend_hook, user_data)`. The `…` contains coin data such
-as value, token ID and other attributes. During the burn phase we produce a deterministic
-unlinkable nullifier.
+Firstly a quick recap of how `money::transfer()` works. During the
+mint phase of creating coins, we construct a coin
+`C = hash(…, spend_hook, user_data)`. The `…` contains coin data such
+as value, token ID and other attributes. During the burn phase we
+produce a deterministic unlinkable nullifier.
 
-This is a more general ZK concept of committing to several attributes, and then later either
-full on revealing them or more specifically applying constraints to the attributes.
-To enable protocol owned liquidity, we introduced the coin attributes `spend_hook` and
+This is a more general ZK concept of committing to several attributes,
+and then later either full on revealing them or more specifically
+applying constraints to the attributes. To enable protocol owned
+liquidity, we introduced the coin attributes `spend_hook` and
 `user_data`, motivated by these desires:
 
-* Generalize protocol-owned liquidity enabling any third party to write contracts that
-  own liquidity.
-* Stronger security model for on chain liquidity by only depending on the money contract
-  when composed with contracts like the DAO.
+* Generalize protocol-owned liquidity enabling any third party to write
+  contracts that own liquidity.
+* Stronger security model for on chain liquidity by only depending on
+  the money contract when composed with contracts like the DAO.
 
-When a coin is spent, the `spend_hook` is revealed publicly. The `money::transfer()` call
-enforces that the subsequent contract called in the tx matches the `spend_hook`.
-In our example, `spend_hook = DAO`, and then our tx will have two calls:
-`[money::transfer(), DAO::exec()]`. When spending a coin where the `spend_hook = DAO`,
-then `money::transfer()` will check the next contract in the tx will match the `spend_hook`.
+When a coin is spent, the `spend_hook` is revealed publicly. The
+`money::transfer()` call enforces that the subsequent contract called
+in the tx matches the `spend_hook`. In our example, `spend_hook = DAO`,
+and then our tx will have two calls: `[money::transfer(), DAO::exec()]`.
+When spending a coin where the `spend_hook = DAO`, then
+`money::transfer()` will check the next contract in the tx will match
+the `spend_hook`.
 
 Now you might ask some questions:
 
-* Here we are listing `DAO`, but actually we need a stricter check that the call is `DAO::exec()`
-  and not some other DAO method call.
+* Here we are listing `DAO`, but actually we need a stricter check that
+  the call is `DAO::exec()` and not some other DAO method call.
 * We need to enforce which DAO we are operating on.
 
-This is where the `user_data` is used. We can commit to several things including which function
-is called in the contract. Since in the DAO, only `DAO::exec()` can be composed, we just sidestep
-this and enforce that when a tx has two calls, then the DAO one must be `DAO::exec()`. We then
-use the `user_data` to store the DAO bulla.
+This is where the `user_data` is used. We can commit to several things
+including which function is called in the contract. Since in the DAO,
+only `DAO::exec()` can be composed, we just sidestep this and enforce
+that when a tx has two calls, then the DAO one must be `DAO::exec()`.
+We then use the `user_data` to store the DAO bulla.
 
 ## Motivation: Limitations of Current Approach
 
-The current approach enables contracts to own liquidity, which is how we can have DAO on chain
-treasuries. We have the ability for contracts to directly call other contracts. However this
-calling mechanism is static.
+The current approach enables contracts to own liquidity, which is how
+we can have DAO on chain treasuries. We have the ability for contracts
+to directly call other contracts. However this calling mechanism is
+static.
 
-We desire now to generalize the DAO calling mechanism, so any contract could be called.
-Currently `DAO::exec()` deserializes the `money::transfer()` calldata, and then enforces its
-checks on it inside wasm. These checks are hardcoded.
+We desire now to generalize the DAO calling mechanism, so any contract
+could be called. Currently `DAO::exec()` deserializes the
+`money::transfer()` calldata, and then enforces its checks on it inside
+wasm. These checks are hardcoded.
 
-It would be very useful if instead this data or code were to be dynamic. Therefore a DAO
-proposal could be called, not to call `money::transfer()` but instead to call another contract.
-This system would then be generic and usable with other contracts, such as an algorithmic
-streaming contract making calls on a ZK NFT.
+It would be very useful if instead this data or code were to be
+dynamic. Therefore a DAO proposal could be called, not to call
+`money::transfer()` but instead to call another contract. This system
+would then be generic and usable with other contracts, such as an
+algorithmic streaming contract making calls on a ZK NFT.
 
 ## Proposal: Introspective Params
 
@@ -90,26 +100,27 @@ pub struct ContractCall {
 }
 ```
 
-This way contracts can query each other's calldata in a dynamic compatible way.
-Some part of the params for a contract may be specific to that contract. Another part
-might be generic, which shares the same struct with multiple other contracts.
-This enables contracts to query an interface from another contract's calldata,
-deserialize that data and work with it, without having to hardcode a dependency,
-e.g `DAO::exec()` hardcoding a dependency on `money::transfer()` params.
+This way contracts can query each other's calldata in a dynamic
+compatible way. Some part of the params for a contract may be specific
+to that contract. Another part might be generic, which shares the same
+struct with multiple other contracts. This enables contracts to query
+an interface from another contract's calldata, deserialize that data
+and work with it, without having to hardcode a dependency, e.g.
+`DAO::exec()` hardcoding a dependency on `money::transfer()` params.
 
 ## Note on Auth Modules
 
-An alternative approach is introducing the concept of auth modules. So for example, with
-the DAO, a user could deploy their own contract on chain with specific logic, then
-make a proposal to execute that contract. We could also supply our own auth module with
-hardcoded branching support for several common contract types.
+An alternative approach is introducing the concept of auth modules. So
+for example, with the DAO, a user could deploy their own contract on
+chain with specific logic, then make a proposal to execute that
+contract. We could also supply our own auth module with hardcoded
+branching support for several common contract types.
 
-However while this may be desirable in some cases where complex logic in DAO proposals
-are required, it presents several downsides:
+However while this may be desirable in some cases where complex logic
+in DAO proposals are required, it presents several downsides:
 
-* The supplied auth module will hardcode support for a few contract types and not be
-  properly generic.
+* The supplied auth module will hardcode support for a few contract
+  types and not be properly generic.
 * User deployed contracts could be expensive and error prone.
-* For efficiency the DAO would probably end up hardcoding support for several contract
-  types directly, as well as other composable contracts.
-
+* For efficiency the DAO would probably end up hardcoding support for
+  several contract types directly, as well as other composable contracts.

+ 19 - 18
doc/src/dep/0003.md

@@ -10,20 +10,22 @@ status: accepted
 calculated as a commitment to the public key as
 $$ T = \t{PoseidonHash}(69 || \mathcal{X}(P) || \mathcal{Y}(P)) $$
 The ability to freeze minting tokens is offered. Let $Γ$ be the set of
-frozen token IDs. When attempting to call mint, if $T ∈ Γ$, then the contract
-will fail.
+frozen token IDs. When attempting to call mint, if $T ∈ Γ$, then the
+contract will fail.
 
 The amount being minted is publicly visible in the params.
 
 ## Motivation: Limitations of Current Approach
 
-The main issue is contracts are unable to issue tokens. The current design
-mandates the holder of a public key to issue the token.
+The main issue is contracts are unable to issue tokens. The current
+design mandates the holder of a public key to issue the token.
 
-Secondarily the token ID and amount being minted is visible breaking anonymity.
+Secondarily the token ID and amount being minted is visible breaking
+anonymity.
 
-To fix the first issue, a basic fix would be allow setting an auth parent
-contract for a specific token ID, but this does not fix the second issue.
+To fix the first issue, a basic fix would be allow setting an auth
+parent contract for a specific token ID, but this does not fix the
+second issue.
 
 ## Proposal: Introspective Params
 
@@ -48,29 +50,28 @@ For each coin $Cᵢ$, let there be corresponding proofs $πᵢ$ such that
 Additionally the contract checks that `auth_parent` is the function ID of
 the parent caller.
 
-The sole purpose of this call is to create a set of coins whose token ID
-is a valid commitment, containing the field `auth_parent` which is publicly
-revealed. Then it checks the parent caller matches this field.
+The sole purpose of this call is to create a set of coins whose token
+ID is a valid commitment, containing the field `auth_parent` which is
+publicly revealed. Then it checks the parent caller matches this field.
 
 ### `Money::auth_mint_v1()`
 
-In the interests of preserving the current functionality with minimal changes,
-we provide a default auth module for use with token minting.
+In the interests of preserving the current functionality with minimal
+changes, we provide a default auth module for use with token minting.
 
-This provides an upgrade path to a future design with stronger anonymity
-guarantees such as hiding the token ID from the network.
+This provides an upgrade path to a future design with stronger
+anonymity guarantees such as hiding the token ID from the network.
 
 The contract performs the following checks:
 
 * Reveals the token ID $T$ publicly.
 * Checks $T ∉ Γ$, the set of frozen token IDs.
-* Constructs a pedersen commit $V$ to the value in the coin, along with a proof.
-  This allows auditing the supply since all commitments are linked publicly with
-  the token ID.
+* Constructs a pedersen commit $V$ to the value in the coin, along
+  with a proof. This allows auditing the supply since all commitments
+  are linked publicly with the token ID.
 
 ### `Money::auth_mint_freeze_v1()`
 
 Adds the token ID $T$ to the set of frozen token IDs $Γ$.
 The caller must prove ownership of the public key which is set in the
 `user_data` field of the token ID.
-

+ 6 - 2
doc/src/glossary/glossary.md

@@ -1,6 +1,8 @@
 # Glossary
 
-* Pedersen commitment: a hiding and binding commitment scheme that takes a value and produces an elliptic curve point representing the commitment
+* Pedersen commitment: a hiding and binding commitment scheme that
+  takes a value and produces an elliptic curve point representing the
+  commitment
 	* [Explainer](https://medium.com/coinmonks/zero-knowledge-proofs-um-what-a092f0ee9f28)
 * zkas: the programming language in which you can write zk circuits
 	* [zkas compiler](https://codeberg.org/darkrenaissance/darkfi/src/branch/master/src/zkas)
@@ -9,5 +11,7 @@
 	* it runs during proof generation
 		* [Rust example](https://codeberg.org/darkrenaissance/darkfi/src/branch/master/tests/zkvm_opcodes.rs)
 		* [Python example](https://codeberg.org/darkrenaissance/darkfi/src/branch/master/bin/zkrunner/zkrunner.py#L141-L160)
-* zkrunner: a Python script which allows you, instead of providing circuit, witness, public inputs and code to generate/verify proof, you provide circuit, witness
+* zkrunner: a Python script which allows you, instead of providing
+  circuit, witness, public inputs and code to generate/verify proof,
+  you provide circuit, witness
 	* [Example](https://codeberg.org/darkrenaissance/darkfi/src/branch/master/bin/zkrunner/zkrunner.py#L180)

+ 95 - 45
doc/src/start-here.md

@@ -2,95 +2,145 @@
 
 ## Directory Structure
 
-DarkFi broadly follows the standardized unix directory structure.
+DarkFi loosely follows the standardized Unix directory structure.
 
 * All bundled applications are contained in `bin/` subdirectory.
 * Random scripts and helpers such as build artifacts, node deployment
   or syntax highlighting is in `contrib/`.
 * Documentation is in `doc/`.
 * Example codes are in `example/`.
-* Script utilities are in `script/`. See also the large `script/research/`
-  subdir.
-* All core code is contained in `src/`.
-  See [Architecture Overview](arch/overview.md) for a detailed description.
+* Script utilities are in `script/`.
+  See also the large `script/research/` subdir.
+* All core library code is contained in `src/`.
+  See [Architecture Overview](arch/overview.md) for a detailed
+  description.
     * The `src/sdk/` crate is used by WASM contracts and core code.
       It contains essential primitives and code shared between them.
-    * `src/serial/` is a crate containing the binary serialization code,
-      which is the same as used by Bitcoin.
+    * `src/serial/` is a crate containing the binary serialization code.
     * `src/contract/` contains our native bundled contracts. It's worth
-      looking at these to familiarize yourself with what contracts on DarkFi
-      are like.
+      looking at these to familiarize yourself with what contracts on
+      DarkFi are like.
 
 ## Using DarkFi
 
-Refer to the main [README](../index.html) file for instructions on how to
-install Rust and necessary deps.
+Refer to the main [README](../index.html) file for instructions on how
+to install Rust and necessary dependencies.
 
 Then proceed to the [Running a Node](testnet/node.md) guide.
 
 ## Join the Community
 
-Although we have a Telegram, we don't believe in centralized proprietary apps,
-and our core community organizes through our own fully anonymous p2p chat system
-which has support for Tor (and Nym waiting for 
-[this feature request](https://github.com/nymtech/nym/issues/3610)).
+Although we have a Telegram, we don't believe in centralized
+proprietary apps, and our core community organizes through our own
+fully anonymous p2p chat system which has support for Tor and i2p.
 
-Every Monday at 14:00 UTC (DST) or 15:00 UTC (ST) in #dev we have our main
-project meeting.
+Every Monday at 14:00 UTC (DST) or 15:00 UTC (ST) in #dev we have our
+main project meeting.
 
-See the guide on [darkirc](misc/darkirc/darkirc.md) for instructions on joining.
+See the guide on [darkirc](misc/darkirc/darkirc.md) for instructions
+on joining the chat.
 
 ## Contributing as a Dev
 
-Check out the [contributor's guide](dev/contrib/contrib.md) for where to find
-tasks and submitting patches to the project.
+Check out the [contributor's guide](dev/contrib/contrib.md) for where
+to find tasks and submitting patches to the project.
 
 If you're not a dev but wish to learn then take a look at the
 [agorism hackers study guide](dev/learn.md).
 
-Lastly familiarize yourself with the [project architecture](arch/arch.md).
-The book also contains a cryptography section with a helpful
+Lastly familiarize yourself with the
+[project architecture](arch/arch.md). The book also contains a
+cryptography section with a helpful
 [ZK explainer](crypto/zk_explainer.md).
 
 DarkFi also has a [project spec](spec/crypto-schemes.md) and
-a [DEP](dep/0001.md) (Drk Enhancement Proposals) system.
+a [DEP](dep/0001.md) (DarkFi Enhancement Proposals) system.
 
 ## Detailed Overview
 
 Source code is under `src/` subdirectory. Main interesting modules are:
 
-* `net/` is our own p2p network. There are sessions such as incoming or outgoing that have channels (connections). Protocols are attached to channels depending on the session. The p2p network is also multi-transport with support for TCP (+TLS), Tor and Nym. So you can access the p2p fully anonymously (network level privacy).
-* `event_graph/` which is a DAG sync protocol used for ensuring eventual consistency of data, such as with chat systems (you don't drop any messages).
-* `runtime/` is the WASM smart contract engine. We separate computation into several stages which is checks-effects-interactions paradigm in solidity but enforced in the smart contract explicitly. For example in the `exec()` phase, you can only read, whereas writes must occur in the `apply(update)` phase.
+* `net/` is our own p2p network. There are sessions such as incoming or
+  outgoing that have channels (connections). Protocols are attached to
+  channels depending on the session. The p2p network is also
+  multi-transport with support for TCP (+TLS), Tor and i2p. So you can
+  access the p2p fully anonymously (network level privacy).
+* `event_graph/` which is a DAG sync protocol used for ensuring
+  eventual consistency of data, such as with chat systems (you don't
+  drop any messages).
+* `runtime/` is the WASM smart contract engine. We separate computation
+  into several stages which is checks-effects-interactions paradigm in
+  solidity but enforced in the smart contract explicitly. For example
+  in the `exec()` phase, you can only read, whereas writes must occur
+  in the `apply(update)` phase.
 * `blockchain/` and `validator/` is the blockchain and consensus algos.
-* `zk/` is the ZK VM, which is simply loads bytecode which is used to build the circuits. It's a very simple model rather than the TinyRAM computation models. We opted for this because we prefer simplicity in systems design.
-* `sdk/` contains a crypto SDK usable in smart contracts and applications. There are also Python bindings here, useful for making utilities or small apps.
-* `serial/` contains our own serialization because we don't trust rust serialization libs like serde (recently confirmed when they start bundling binaries). We also have async serialization and deserialization which is good for network code.
-* `tx/` is the tx we use. Note signatures are not in the calldata as having this outside it allows more efficient verification (since you can do it in parallel and so on).
-    * All darkfi calls are precomputed ahead of time which is needed for ZK. Normally in eth or other smart contract chains, the calldata is calculated where the function is invoked. Whereas in darkfi the entire callgraph and calldata is bundled since ZK proofs must be computed ahead of time. This also improves things like static analysis and security (limiting call depth is easy to check before verification).
-    * Verifying sigs or call depth ahead of time helps make the chain more attack resistant.
+* `zk/` is the ZK VM, which is simply loads bytecode which is used to
+  build the circuits. It's a very simple model rather than the TinyRAM
+  computation models. We opted for this because we prefer simplicity in
+  systems design.
+* `sdk/` contains a crypto SDK usable in smart contracts and
+  applications. There are also Python bindings here, useful for making
+  utilities or small apps.
+* `serial/` contains our own serialization because we don't trust Rust
+  serialization libs like serde. We also have async serialization and
+  deserialization which is good for network code.
+* `tx/` is the tx we use. Note signatures are not in the calldata as
+  having this outside it allows more efficient verification (since you
+  can do it in parallel and so on).
+    * All DarkFi calls are precomputed ahead of time which is needed
+      for ZK. Normally in ETH or other smart contract chains, the
+      calldata is calculated where the function is invoked. Whereas in
+      DarkFi the entire callgraph and calldata is bundled since ZK
+      proofs must be computed ahead of time. This also improves things
+      like static analysis and security (limiting call depth is easy
+      to check before verification).
+    * Verifying sigs or call depth ahead of time helps make the chain
+      more attack resistant.
 * `contract/` contains our native smart contracts. Namely:
-    * `money`, which is multi-asset anonymous transfers, anonymous swaps and token issuance. The token issuance is programmatic. When creating a token, it commits to a smart contract which specifies how the token is allowed to be issued.
+    * `money`, which is multi-asset anonymous transfers, anonymous
+      swaps and token issuance. The token issuance is programmatic.
+      When creating a token, it commits to a smart contract which
+      specifies how the token is allowed to be issued.
     * `deploy` for deploying smart contracts.
-    * `dao`, which is a fully anonymous DAO. All the DAOs on chain are anonymous, including the amounts and activity of the treasury. All participants are anonymous, proposals are anonymous and votes are anonymous including the token weighted vote amount, and user identity. You cannot see who is in the DAO.
+    * `dao`, which is a fully anonymous DAO. All the DAOs on chain are
+      anonymous, including the amounts and activity of the treasury.
+      All participants are anonymous, proposals are anonymous and votes
+      are anonymous including the token weighted vote amount, and user
+      identity. You cannot see who is in the DAO.
 
-NOTE: we try to minimize external dependencies in our code as much as possible. We even try to limit dependencies within submodules.
+NOTE: We try to minimize external dependencies in our code as much as
+possible. We even try to limit dependencies within submodules.
 
 Inside `bin/` contains utilities and applications:
 
-* `darkfid/` is the daemon and `drk/` is the wallet. Currently being updated to the new testnet (if you see the commit log last few days).
-* `dnet/` is a viewer to see the p2p traffic of nodes, and `deg/` is a viewer for the event graph data. We use these as debugging and monitoring tools.
-* `dhtd/` is a distributed hash table, like IPFS, for transferring static data and large files around. Currently just a prototype but we'll use this later for images in the chat or other static content like seller pages on the marketplace.
-* `tau/` is an anon p2p task manager which we use. We don't use github issues, and seek to minimize our dependence on centralized services. Eventually we want to be fully p2p and attack resistant.
-* `darkirc/` is our main community chat. It uses [RLN](crypto/rln.md); you stake money and if you post twice in an epoch then you get slashed which prevents spam. There is a free tier. It uses the `event_graph` for synchronizing the history. You can attach any IRC frontend to use it rn. Later we'll make our own UI.
+* `darkfid/` is the main daemon and `drk/` is the wallet.
+* `dnet/` is a viewer to see the p2p traffic of nodes, and `deg/` is a
+  viewer for the event graph data. We use these as debugging and
+  monitoring tools.
+* `dhtd/` is a distributed hash table, like IPFS, for transferring
+  static data and large files around. Currently just a prototype but
+  we'll use this later for images in the chat or other static content
+  like seller pages on the marketplace.
+* `tau/` is an anon p2p task manager which we use. We don't use Github
+  issues, and seek to minimize our dependence on centralized services.
+  Eventually we want to be fully p2p and attack resistant.
+* `darkirc/` is our main community chat. It uses [RLN](crypto/rln.md);
+  you stake money and if you post twice in an epoch then you get
+  slashed which prevents spam. There is a free tier. It uses the
+  `event_graph` for synchronizing the history. You can attach any IRC
+  frontend to use it.
 * `zkas/` is our ZK compiler.
-* `zkrunner/` contains our ZK debugger (run `zkrunner` with `--trace`), and `zkrender` which renders a graphic of the circuit layout.
-* `lilith/` is a universal seed node. Eventually we will add swarming support to our p2p network which is an easy addon.
+* `zkrunner/` contains our ZK debugger (run `zkrunner` with `--trace`),
+  and `zkrender` which renders a graphic of the circuit layout.
+* `lilith/` is a universal seed node. Eventually we will add swarming
+  support to our p2p network which is an easy addon.
 
-Lastly worth taking a look is `script/research/` and `script/research/zk/` which contains impls of most major ZK algos. `bench/` contains benchmarks.
-`script/escrow.sage` is a utility for doing escrow. We'll integrate it in the wallet later, but it works for now.
+Lastly worth taking a look is `script/research/` and
+`script/research/zk/` which contains impls of most major ZK algos.
+`bench/` contains benchmarks. `script/escrow.sage` is a utility for
+doing escrow. We'll integrate it in the wallet later.
 
-We could say more on our design philosophy of simplicity oriented approach to systems dev, but I'll drop these links here for now:
+Our design philosophy and simplicity oriented approach to systemd dev:
 
 * [Suckless Philosophy: software that sucks less](https://suckless.org/philosophy/)
 * [How to Design Perfect (Software) Products  by Pieter Hintjens](http://hintjens.com/blog:19/noredirect/true)

+ 0 - 1
doc/src/testnet/node.md

@@ -468,4 +468,3 @@ We can now view the log, and grep through it.
 ```shell
 $ tail -n +0 -f /tmp/darkfid.log | grep -a --line-buffered -v DEBUG
 ```
-