Просмотр исходного кода

doc/arch: removed pos related stuff and added a high level description of PoW logic

skoupidi 2 лет назад
Родитель
Сommit
47b0e2905f

+ 0 - 1
doc/src/SUMMARY.md

@@ -31,7 +31,6 @@
 - [Architecture](arch/arch.md)
   - [Overview](arch/overview.md)
   - [Anonymous assets](arch/anonymous_assets.md)
-  - [Blockchain](arch/blockchain.md)
   - [Consensus](arch/consensus.md)
   - [Transactions](arch/tx_lifetime.md)
   - [Smart Contracts](arch/smart_contracts.md)

+ 1 - 1
doc/src/arch/arch.md

@@ -201,7 +201,7 @@ We need to handle confirmed and unconfirmed transactions, make things
 prettier and better to use. When broadcasting transactions, if they
 pass locally, the wallet should be updated to represent the state
 change but things should stay unconfirmed. The DAO SQL schema gives a
-nice way to do this, where there's a `tx_hash`, `slot_id`, etc. which
+nice way to do this, where there's a `tx_hash`, etc. which
 can be used to evaluate whether the transaction/coins/whatever was
 finalized.
 

+ 0 - 365
doc/src/arch/blockchain.md

@@ -1,365 +0,0 @@
-# Dynamic Proof of Stake
-
-## Overview
-
-The DarkFi blockchain is based off proof of stake  privacy focused Ouroboros Crypsinous,
-tunned with a discrete controller to achieve a stable supply.
-
-## Blockchain
-
-Blockchain $\mathbb{C_{loc}}$ is a series of epochs: it's a tree of chains,
-$C^1$, $C^2$, $\dots$, $C^n$, the chain ending in a single leader per slot single finalization.
-
-Crypsinous Blockchain is built on top of Zerocash sapling scheme, and Ouroboros Genesis  blockchain.
-Each participant $U_p$ stores its own local view of the Blockchain $C_{loc}^{U_p}$.
-$C_{loc}$ is a sequence of blocks $B_i$ (i>0), where each $B \in C_{loc}$
-$$ B = (tx_{lead},st)$$
-$$tx_{lead} = (LEAD, header, txs, stx_{proof})$$
-LEAD is a magic word, header is a metadata, and txs is a vector of transaction hash (see appendix).
-$stx_{proof}=(cm_{\prime{c}},sn_c,ep,sl,\rho,h,\pi)$
-the Block's st is the block data, and h is the hash of that data.
-the commitment of the newly created coin is:
-$(cm_{c_2},r_{c_2})=COMM(pk^{COIN}||\tau||v_c||\rho_{c_2})$,
-$\tau$ is slot timestamp, or index. $sn_c$ is the coin's serial number revealed to spend the coin.
-$$sn_c=PRF_{root_{sk}^{COIN}}^{sn}(\rho_c)$$
-$$\rho=\eta^{sk_{sl}^{COIN}}$$
-$\eta$ is randomness from  random oracle implemented as hash of previous epoch, $\rho$ id derived randomness from $\eta$.  $\pi$ is the NIZK proof of the LEAD statement.
-
-
-### st transactions
-the blockchain view is a chain of blocks, each block $B_j=(tx_{lead},st)$, while $st$ being the merkle tree structure of the validated transactions received through the network, that include transfer, and public transactions.
-
-### LEAD statement
-for $x=(cm_{c_2},sn_{c_1},\eta,sl,\rho,h,ptr,\mu_{\rho},\mu_{y},root)$, and
-$w=(path,root_{sk^{COIN}},path_{sk^{COIN}},\tau_c,\rho_c,r_{c_1},v,r_{c_2})$
-for tuple $(x,w) \in L_{lead}$ iff:
-
- * $pk^{COIN} = PRF_{root_{sk}^{COIN}}^{pk}(\tau_c)$.
- * $\rho_{c_2}=PRF_{root_{sk_{c_1}}^{COIN}}^{evl}(\rho_{c_1})$.
- note here the nonce of the new coin is deterministically driven from the nonce of the old coin, this works as resistance mechanism to allow the same coin to be eligible for leadership more than once in the same epoch.
- * $\forall i \in \{1,2\} : DeComm(cm_{c_i},pk^{COIN}||v||\rho_{c_i},r_{c_i})=T$.
- * path is a valid Merkle tree path to $cm_{c_1}$ in the tree with the root root.
- * $path_{sk^{COIN}}$ is a valid path to a leaf at position $sl-\tau_c$ in a tree with a root $root_{sk}^{COIN}$.
- * $sn_{c_1}= PRF_{root_{sk}^{COIN}}^{sn}(\rho_{c_1})$
- * $y = \mu_{y}^{root_{sk_{c_1}}^{COIN}||\rho_c}$
- * $\rho = \mu_{\rho}^{root_{sk_{c_1}}^{COIN}||\rho_c}$
- * $y< T(v)$
-note that this process involves burning old coin $c_1$, minting new  $c_2$ of the same value + reward.
-
-#### validation rules
-
-validation of proposed lead proof as follows:
-
-* slot index is less than current slot index
-* proposal extend from valid fork chain
-* transactions doesn't exceed max limit
-* signature is valid based off producer public key
-* verify block hash
-* verify block header hash
-* public inputs $\mu_y$, $\mu_{rho}$ are hash of current consensus $\eta$, and current slot
-* public inputs of target 2-term approximations $\sigma_1$, $\sigma_2$ are valid given total network stake and controller parameters
-* the competing coin nullifier isn't published before to protect against double spending, before burning the coin.
-* verify block transactions
-
-<!--
-this is now replaced by tx as a contract in zkas
-### transfer transaction $tx_{xfer}$
-transfer transaction of the pouring mechanism of input: old coin, and public coin, with output: new return change coin, and further recipient coin.  such that input total value $v^{old}_1 + v_{pub} = v^{new}_3 + v^{new}_4$
-$$ tx_{xfer} = (TRANSFER,stx_{proof},c_r)$$
-$$stx_{proof} = (\{cm_{c_{3}}),cm_{c_{4}}\}),(\{sn_{c_2},{sn_{c_1}}\}),\tau,root,\pi)$$
-$c_r$ is forward secure encryption of $stx_{rcpt}=(\rho_{c_3},r_{c_3},v_{c_3})$ to $pk_r$.
-the commitment of the new coins $c_3$, $c_4$ is:
-$$(cm_{c_3},r_{c_3})=Comm(pk_{pk_s}^{COIN}||\tau||v_{c_3}||\rho_{c_3})$$
-$$(cm_{c_4},r_{c_4})=Comm(pk_{pk_r}^{COIN}||\tau||v_{c_4}||\rho_{c_4})$$
-also the spend proofs of the old coins $sn_{c_1},sn_{c_2}$ are revealed.
-
-
-### NIZK proof $\pi$
-for the circuit inputs, and witnesses
-
-$$x = (\{cm_{c_3},cm_{c_4}\},\{sn_{c_1},sn_{c_2}\},\tau,root)$$
-$$w = (root_{sk_{c_1}^{COIN}},path_{sk_{c_1}^{COIN}},root_{sk_{c_2}^{COIN}},path_{sk_{c_2}^{COIN}},pk_{c_3}^{COIN},pk_{c_4}^{COIN},(\rho_{c_1},r_{c_1},v_1,path_1),(\rho_{c_2},r_{c_2},v_2,path_2),(\rho_{c_1},r_{c_1},v_1,path_1))$$
-
-$\pi$ is a proof for the following transfer statement using zerocash pouring mechanism.
-
-$$\forall_i \in \{1,2\}: pk_{c_i}^{COIN} = PRF_{root_{sk_{c_i}}^{COIN}}^{pk}(1)$$
-$$\forall_i \in \{1,\dots,4\} : DeComm(cm_{c_i},pk_{c_i}^{COIN}||v_i||\rho_{c_i},r_{c_i})=T$$
-$$v_1+v_2=v_3+v_4$$
-
-$path_1$  is a valid path to  $cm_{c_1}$  in a tree with the root root
-
-$path_2$ is a valid path to  $cm_{c_2}$  in a tree with the root root, $sn_{c_2}=PRF_{root_{sk_{c_1}^{COIN}}}^{zdrv}(\rho_{c_1})$
-
-$$path_{sk_{c_i}^{COIN}} \text{ is a valid path to a leaf at position } \tau \text{ in }, root_{sk_{c_i}^{COIN}} i \in \{1,2\}$$
-
-$$sn_{c_i}=PRF_{root_{sk_{c_i}^{COIN}}}^{sn}(\rho_{c_i}), \forall_i \in \{1,2\}$$
-
--->
-
-
-
-## Epoch
-
-An epoch is a vector of blocks. Some of the  blocks might be empty if there is no winning leader. tokens in stake are constant during the epoch.
-
-## Leader selection
-
-At the onset of each slot each stakeholder needs to verify if it's
-the weighted random leader for this slot.
-
-$$y < T_{i}$$ <center><sup><strong> check if the random y output is less than some
-threshold </strong></sup></center>
-
-This statement might hold true for zero or more stakeholders, thus
-we might end up with multiple leaders for a slot, and other times no
-leader. Also note that no node would know the leader identity or how many
-leaders are there for the slot, until it receives a signed block with
-a proof claiming to be a leader.
-
-
-<center><sup><strong>$\eta$ is random nonce generated from the blockchain,
-$\textbf{sid}$ is block id</strong></sup></center>
-
-$$\phi_{f} = 1 - (1-f)^{\alpha_i}$$ $$T_{i} =
-L \phi_{f}(\alpha_i^j)$$
-
-Note that $\phi_f(1)=f$, $\textbf{f}$: the active slot coefficient is
-the probability that a party holding all the stake will be selected to be
-a leader. Stakeholder is selected as leader for slot j with probability
-$\phi_f(\alpha_i)$, $\alpha_i$ is $U_i$ relative stake.
-
-see the appendix for absolute stake aggregation dependent leader selection
-family of functions.
-
-### automating f tuning
-
-the stable consensus token supply is maintained by the help of discrete PID controller, that maintain stabilized occurrence of single leader per slot.
-
-#### control lottery f tunning parameter
-
-$$f[k] = f[k-1] + K_1e[k] + K_2e[k-1] + K_3e[k-2]$$
-
-with $k_1 = k_p + K_i + K_d$,  $k_2 = -K_p -2K_d$,  $k_3 = K_d$, and e is the error function.
-
-
-### target T n-term approximation
-target function is approximated to avoid use of power, and division in zk, since no function in the family of functions that have independent aggregation property achieve avoid it (see appendix).
-
-#### target function
-
- target fuction T: $$ T = L * \phi(\sigma) = L * (1- (1 - f)^{\sigma}) $$
- $\sigma$ is relative stake.
- f is tuning parameter, or the probability of winning have all the stake
- L is field length
-
-#### $\phi(\sigma)$ approximation
-
- $$\phi(\sigma) = 1 - (1-f)^{\sigma} $$
- $$ = 1 - e^{\sigma ln(1-f)} $$
- $$ = 1 - (1 + \sum_{n=1}^{\infty}\frac{(\sigma ln (1-f))^n}{n!}) $$
- $$ \sigma = \frac{s}{\Sigma} $$
- s is stake, and $\Sigma$ is total stake.
-
-#### target T n term approximation
-
- $$ k = L ln (1-f)^1 $$
- $$ k^{'n} =  L ln (1-f)^n $$
- $$ T = -[k\sigma + \frac{k^{''}}{2!} \sigma^2 + \dots +\frac{ k^{'n}}{n!}\sigma^n] $$
- $$  = -[\frac{k}{\Sigma}s + \frac{k^{''}}{\Sigma^2 2!} s^2 + \dots +\frac{k^{'n}}{\Sigma^n n!} s^n] $$
-
-#### comparison of original target to approximation
-
-![approximation comparison to the original](https://github.com/darkrenaissance/darkfi/blob/master/script/research/crypsinous/linearindependence/target.png?raw=true)
-
-
-# Appendix
-
-This section gives further details about the structures that will
-be used by the protocol.
-
-## Blockchain
-
-| Field    |     Type     |                Description                 |
-|----------|--------------|--------------------------------------------|
-| `blocks` | `Vec<Block>` | Series of blocks consisting the Blockchain |
-
-
-## Header
-
-|   Field     |        Type        |            Description                     |
-|-------------|--------------------|--------------------------------------------|
-| `version`   | `u8`               | Version                                    |
-| `previous`  | `blake3Hash`       | Previous block hash                        |
-| `epoch`     | `u64`              | Epoch                                      |
-| `slot`      | `u64`              | Slot UID                                   |
-| `timestamp` | `Timestamp`        | Block creation timestamp                   |
-| `root`      | `MerkleRoot`       | Root of the transaction hashes merkle tree |
-
-
-## Block
-
-|   Field     |        Type       |            Description             |
-|-------------|-------------------|------------------------------------|
-| `magic`     | `u8`              | Magic bytes                        |
-| `header`    | `blake3Hash`      | Header hash                        |
-| `txs`       | `Vec<blake3Hash>` | Transaction hashes                 |
-| `lead_info` | `LeadInfo`        | Block leader information           |
-
-## LeadInfo
-
-| Field           | Type                | Description                                         |
-|-----------------|---------------------|-----------------------------------------------------|
-| `signature`     | `Signature`         | Block owner signature                               |
-| `public_inputs` | `Vec<pallas::Base>` | Nizk proof public inputs                            |
-| `serial_number` | `pallas::Base`      | competing coin's nullifier                          |
-| `eta`           | `[u8; 32]`          | randomness from the previous epoch                  |
-| `proof`         | `Vec<u8>`           | Nizk $\pi$ Proof the stakeholder is the block owner |
-| `offset`        | `u64`               | Slot offset block producer used                     |
-| `leaders`       | `u64`               | Block producer leaders count                        |
-
-## Public Inputs
-| Field        | Type           | Description                                           |
-|--------------|----------------|-------------------------------------------------------|
-| `pk`         | `pallas::Base` | burnt coin public key                                 |
-| `c1_cm_x`    | `pallas::Base` | burnt coin commitment x coordinate                    |
-| `c1_cm_y`    | `pallas::Base` | burnt coin commitment y coordinate                    |
-| `c2_cm_x`    | `pallas::Base` | minted coin commitment x coordinate                   |
-| `c2_cm_y`    | `pallas::Base` | minted coin commitment y coordinate                   |
-| `cm1_root`   | `pallas::Base` | root of burnt coin commitment in burnt merkle tree    |
-| `c1_sk_root` | `pallas::Base` | burn coin secret key                                  |
-| `sn`         | `pallas::Base` | burnt coin spending nullifier                         |
-| `y_mu`       | `pallas::Base` | random seed base from blockchain                      |
-| `y`          | `pallas::Base` | hash of random seed, and `y_mu`, used in lottery      |
-| `rho_mu`     | `pallas::Base` | random seed base from blockchain                      |
-| `rho`        | `pallas::Base` | hash of random seed and `rho_mu` to constrain lottery |
-| `sigma1`     | `pallas::Base` | first term in 2-terms target approximation.           |
-| `sigma2`     | `pallas::Base` | second term in 2-terms target approximation.          |
-
-
-### Linear family functions
-
-In the previous leader selection function, it has the unique
-property of independent aggregation of the stakes, meaning the
-property of a leader winning leadership with stakes $\sigma$
-is independent of whether the stakeholder would act as a pool
-of stakes, or distributed stakes on competing coins.  "one minus
-the probability" of winning leadership with aggregated stakes is
-$1-\phi(\sum_{i}\sigma_i)=1-(1+(1-f)^{\sigma_i})=-(1-f)^{\sum_{i}\sigma_i}$,
-the joint "one minus probability" of all the stakes (each with
-probability $\phi(\sigma_i))$ winning aggregated winning the leadership
-$\prod_{i}^{n}(1-\phi(\sigma_i))=-(1-f)^{\sum_i(\sigma_i)}$ thus: $$
-1-\phi(\sum_{i}\sigma_i) =\prod_{i}^{n}(1-\phi(\sigma_i)) $$
-
-A non-exponential  linear leader selection can be:
-
-$$y < T $$ $$y = 2^lk \mid 0 \le k \le 1$$ $$T = 2^l\phi(v)$$ $$
-\phi(v)=\frac{1}{v_{max+}+c}v  \mid c \in \mathbb{Z}$$
-
-#### Dependent aggregation
-
-Linear leader selection has the dependent aggregation property, meaning
-it's favorable to compete in pools with sum of the stakes over aggregated
-stakes of distributed stakes:
-
-$$\phi(\sum_{i}{\sigma_i})>\prod_{i}^{n}{\sigma_i}$$
-$$\sum_{i}{\sigma_i}>(\frac{1}{v_{max}+c})^{n-1}v_1v_2 \dots
-v_n$$ let's assume the stakes are divided to stakes of value
-$\sigma_i=1$ for $\Sigma>1 \in \mathbb{Z}$, $\sum_{i}{\sigma_i}=V$
-$$V>(\frac{1}{v_{max}+c})^{n-1}$$ note that $(\frac{1}{v_{max}+c})^{n-1}
-< 1, V>1$, thus competing with single coin of the sum of stakes held by
-the stakeholder is favorable.
-
-#### Scalar linear aggregation dependent leader selection
-
-A target function T with scalar coefficients can be formalized as
-$$T=2^lk\phi(\Sigma)=2^l(\frac{1}{v_{max}+c})\Sigma$$ let's assume
-$v_{max}=2^v$, and $c=0$ then: $$T=2^lk\phi(\Sigma)=2^{l-v}\Sigma$$
-then the lead statement is $$y<2^{l-v}\Sigma$$ for example for a group
-order or l=    24 bits, and maximum value of $v_{max}=2^{10}$, then
-lead statement: $$y<2^{14}\Sigma$$
-
-#### Competing max value coins
-
-For a stakeholder with $nv_{max}$ absolute stake, $\mid n \in \mathbb{Z}$
-it's advantageous for the stakeholder to distribute stakes on $n$
-competing coins.
-
-#### Inverse functions
-
-Inverse lead selection functions doesn't require maximum stake, most
-suitable for absolute stake, it has the disadvantage that it's inflating
-with increasing rate as time goes on, but it can be function of the
-inverse of the slot to control the increasing frequency of winning
-leadership.
-
-#### Leader selection without maximum stake upper limit
-
-The inverse leader selection without maximum stake value can be
-$\phi(v)=\frac{v}{v+c} \mid c  > 1$ and inversely proportional
-with probability of winning leadership, let it be called leadership
-coefficient.
-
-
-#### Decaying linear leader selection
-
-As the time goes one, and stakes increase, this means the combined stakes
-of all stakeholders increases the probability of winning leadership
-in next slots leading to more leaders at a single slot, to maintain,
-or to be more general to control this frequency of leaders per slot, c
-(the leadership coefficient) need to be function of the slot $sl$, i.e
-$c(sl) = \frac{sl}{R}$ where $R$ is epoch size (number of slots in epoch).
-
-#### Pairing leader selection independent aggregation function
-
-The only family of functions $\phi(\alpha)$ that are isomorphic
-to summation on multiplication $\phi(\alpha_1+\alpha_2)
-= \phi(\alpha_1)\phi(\alpha_2)$(having the independent aggregation
-property) is the exponential function, and since it's impossible to
-implement in plonk,  a re-formalization of the lead statement using
-pairing that is isomorphic to summation on multiplication is an option.
-
-Let's assume $\phi$ is isomorphic function
-between multiplication and addition, $\phi(\alpha) =
-\phi(\frac{\alpha}{2})\phi(\frac{\alpha}{2})=\phi(\frac{\alpha}{2})^2$,
-thus:
-$$\phi(\alpha)=\underbrace{\phi(1)\dots\phi(1)}_\text{$\alpha$}=\phi(1)^\alpha$$
-then the only family of functions $\phi : \mathbb{R} \rightarrow
-\mathbb{R}$ satisfying this is the exponential function
-$$\phi(\alpha)=c^{\alpha} \mid c  \in \mathbb{R}$$
-
-#### no solution for the lead statement parameters, and constants $S,f, \alpha$ defined over group of integers.
-
-assume there is a solution for the lead statement parameters and constants $S, f, \alpha$ defined over group of integers.
-for the statement $y<T$, $$T=L\phi_{max}\phi(\alpha)=S\phi(\alpha)$$
-$$S=ord(G)\phi_{max}\phi(\alpha)$$
-such that S $in Z$
-$\phi_{max}=\phi(\alpha_{max})$ where $\alpha_{max}$ is the maximum stake value being $2^{64}$, following from the previous proof that the family of function having independent aggregation property is the exponential function $f^\alpha$, and $f \in Z | f>1$, the smallest value satisfying f is $f=2$, then $$\phi_{max} = 2^{2^{64}}$$
-note that since $ord(G)<<\phi_{max}$ thus $S<<1$, contradiction.
-
-
-### Leaky non-resettable beacon
-
-Built on top of globally synchronized clock, that leaks the nonce $\eta$
-of the next epoch a head of time (thus called leaky), non-resettable
-in the sense that the random nonce is deterministic at slot s, while
-assuring security against adversary controlling some stakeholders.
-
-For an epoch j, the nonce $\eta_j$ is calculated by hash function H, as:
-
-$$\eta_j = H(\eta_{j-1}||j||v)$$
-
-v is the concatenation of the value $\rho$ in all blocks from the
-beginning of epoch $e_{i-1}$ to the slot with timestamp up to $(j-2)R +
-\frac{16k}{1+\epsilon}$, note that k is a persistence security parameter,
-R is the epoch length in terms of slots.
-
-### toward better decentralization in ouroboros
-
-the randomization of the leader selection at each slot is hinged on the random $y$, $\mu_y$, $\rho_c$, those three values are derived from $\eta$, and root of the secret keys, the root of the secret keys for each stakeholder can be sampled, and derived beforehand, but $\eta$ is a response to global random oracle query, so it's security is hinged on $\textit{centralized global random node}$.
-
-#### solution
-
-to break this centralization, a decentralized emulation of $G_{ro}$ functionality for calculation of: $\eta_i=PRF^{G_{ro}}_{\eta_{i-1}}(\psi)$
-$$\psi   =  hash(tx^{ep}_{0})$$
-$$\eta_0 =  hash(\mathrm{"let\; there\; be\; dark!"})$$
-note that first transaction in the block, is the proof transaction.

+ 153 - 78
doc/src/arch/consensus.md

@@ -5,62 +5,82 @@ blockchain achieve consensus.
 
 ## Glossary
 
-| Name                   | Description                                                                               |
-|------------------------|-------------------------------------------------------------------------------------------|
-| Consensus              | Algorithm for reaching blockchain consensus between participating nodes                   |
-| Node                   | DarkFi daemon participating in the network                                                |
-| Slot                   | Specified timeframe for block production, measured in seconds (default=90)                |
-| Epoch                  | Specified timeframe for blockchain events, measured in slots (default=10)                 |
-| Leader                 | Block producer                                                                            |
-| Unproposed Transaction | Transaction that exists in the memory pool but has not yet been included in a block       |
-| Block proposal         | Block that has not yet been appended onto the canonical blockchain                        |
-| P2P network            | Peer-to-peer network on which Nodes communicate with each other                            |
-| Finalization           | State achieved when a block and its contents are appended to the canonical blockchain     |
-| Fork                   | Chain of block proposals that begins with the last block of the canonical blockchain      |
-
-## Node main loop
-
-As described in previous chapter, DarkFi is based on Ouroboros
-Crypsinous. Therefore, block production involves the following steps:
-
-At the start of every slot, each node runs the leader selection algorithm
-to determine if they are the slot's leader. If successful, they can
-produce a block containing unproposed transactions. This block is then
-appended to the largest known fork and shared with rest of the nodes on
-the P2P network as a block proposal.
-
-Before the end of every slot each node triggers a _finalization check_,
-to verify which block proposals can be finalized onto the canonical
-blockchain. This is also known as the finalization sync period.
+| Name                   | Description                                                                            |
+|------------------------|----------------------------------------------------------------------------------------|
+| Consensus              | Algorithm for reaching blockchain consensus between participating nodes                |
+| Node/Validator         | DarkFi daemon participating in the network                                             |
+| Miner                  | Block producer                                                                         |
+| Unproposed Transaction | Transaction that exists in the memory pool but has not yet been included in a proposal |
+| Block proposal         | Block that has not yet been appended onto the canonical blockchain                     |
+| P2P network            | Peer-to-peer network on which Nodes communicate with each other                        |
+| Finalization           | State achieved when a block and its contents are appended to the canonical blockchain  |
+| Fork                   | Chain of block proposals that begins with the last block of the canonical blockchain   |
+
+## Miner main loop
+
+DarkFi is using Proof of Work RandomX algorithm paired with Delayed finality.
+Therefore, block production involves the following steps:
+
+Miner grabs its current best ranking fork and composes a valid block using
+unproposed transactions from their mempool, extending it.
+Then they try to find a nonce that makes the blocks header hash 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 they find such a nonce, they can propose(broadcast their block proposal
+to the P2P network. After that, they trigger their finalization check, to
+see if their newlly extended fork can be finalized.
 
 Pseudocode:
 ```
 loop {
-    wait_for_next_slot_start()
+    fork = find_best_fork()
 
-    if is_slot_leader() {
-        block = propose_block()
-        p2p.broadcast_block(block)
-    }
+    block = generate_next_block(fork)
 
-    wait_for_slot_end()
+    mine_block(block)
+
+    p2p.broadcast_proposal(block)
+
+    fork.append_proposal(block)
 
     chain_finalization()
 }
 ```
 
-## Listening for blocks
+## Listening for block proposals
 
-Each node listens to new block proposals concurrently with the main
-loop. Upon receiving block proposals, nodes try to extend the proposals
+Each node listens to new block proposals from the network.
+Upon receiving block proposals, they try to extend the proposals
 onto a fork that they hold in memory. This process is described in the
-next section.
+next section. After that, they trigger their finalization check, to
+see if their newlly extended fork can be finalized.
+Miner, upon receiving a new block proposal, will also check if the
+extended fork rank is better than the one they currently try to extend,
+in order to stop mining its proposal and start mining the new best fork.
+
+## Ranking
+
+Each proposed block has a ranked based on the modulus of its nonce and its
+previous proposal previous proposal `VRF` proof, which is attached to the
+block producer reward transaction. Genesis block has rank 0.
+First 2 blocks rank is equal to their nonce, since their previous previous
+block producer doesn't exist, or have a `VRF` attached to their reward transaction.
+For rest blocks, the rank computes as following:
+1. Generate a `u64` using the first 8 bytes from the blocks nonce `pallas::Base`
+2. Grab the `VRF` proof from the reward transaction of the previous previous proposal
+3. Generate a `pallas::Base` from the `blake3::Hash` bytes of the proof
+4. Generate a `u64` using the first 8 bytes from the `pallas::Base` of the proofs hash
+5. Compute the rank: nonce_u64 % vrf_u64
+
+To calculate each fork rank, we simply sum all its block proposals ranks and multiply
+that with the forks length. We use the length multiplier to give a chance of higher
+ranking to longer forks.
 
 ## Fork extension
 
-Since there can be more than one slot leader, each node holds a set of
-known forks in memory.  When a node becomes a leader, they extend the
-longest fork they hold. 
+Since there can be more than one block producers, each node holds a set of
+known forks in memory. When a node produces a block, they extend the best
+ranking fork they hold.
 
 Upon receiving a block, one of the following cases may occur:
 
@@ -77,95 +97,150 @@ Upon receiving a block, one of the following cases may occur:
 |---------------|----------------------------------------|
 | [C]           | Canonical(finalized) blockchain block  |
 | [C]--...--[C] | Sequence of canonical blocks           |
-| [Ln]          | Proposal produced by Leader n          |
+| [Mn]          | Proposal produced by Miner n           |
 | Fn            | Fork name to identify them in examples |
 | +--           | Appending a block to fork              |
 | /--           | Dropped fork                           |
 
 Starting state:
 
-                   |--[L0] <-- F0
+                   |--[M0] <-- F0
     [C]--...--[C]--|
-                   |--[L1] <-- F1
+                   |--[M1] <-- F1
+
+Blocks on same Y axis have the same height.
 
 #### Case 1
 
 Extending F0 fork with a new block proposal:
 
-                   |--[L0]+--[L2] <-- F0
+                   |--[M0]+--[M2] <-- F0
     [C]--...--[C]--|
-                   |--[L1]        <-- F1
+                   |--[M1]        <-- F1
 
 #### Case 2
 
-Extending F0 fork at [L0] slot 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:
 
-                   |--[L0]--[L2]   <-- F0
+                   |--[M0]--[M2]   <-- F0
     [C]--...--[C]--|
-                   |--[L1]         <-- F1
+                   |--[M1]         <-- F1
                    |
-                   |+--[L0]+--[L3] <-- F2
+                   |+--[M0]+--[M3] <-- F2
 
 ##### Case 3
 
 Extending the canonical blockchain with a new block proposal:
 
-                   |--[L0]--[L2] <-- F0
+                   |--[M0]--[M2] <-- F0
     [C]--...--[C]--|
-                   |--[L1]       <-- F1
+                   |--[M1]       <-- F1
                    |
-                   |--[L0]--[L3] <-- F2
+                   |--[M0]--[M3] <-- F2
                    |
-                   |+--[L4]      <-- F3
+                   |+--[M4]      <-- F3
 
 
 ## Finalization
 
-When the finalization sync period kicks in, each node looks up the longest
-fork chain it holds. There must be no other fork chain with same length.
-If such a fork chain exists, nodes finalize all block proposals by appending them
-to the canonical blockchain.
+When the finalization check kicks in, each node will grab its best fork.
+If more than one forks exist with same rank, node doesn't finalize any of them.
+If the fork has reached greater length than the security threshold, node
+finalizes all block proposals, excluding the last one, by appending them to the
+canonical blockchain. We exclude the last proposal, to eliminate network race
+conditions for same height blocks.
 
-Once finalized, all fork chains are removed from the memory pool.
+Once finalized, all rest fork chains are removed from the nodes memory pool.
 Practically this means that no finalization can occur while there are
-competing fork chains of the same length. In such a case, finalization
-can only occur when we have a slot with a single leader.
+competing fork chains of the same rank, over the security threshold.
+In such a case, finalization will occur when we have a single highest ranking fork.
 
 We continue Case 3 from the previous section to visualize this logic.
-On slot 5, a node observes 2 proposals. One extends the F0 fork,
-and the other extends the F2 fork:
+The finalization threshold used in the example is 3 blocks.
+A node observes 2 proposals. One extends the F0 fork, and the other
+extends the F2 fork:
 
-                   |--[L0]--[L2]+--[L5a] <-- F0
+                   |--[M0]--[M2]+--[M5] <-- F0
     [C]--...--[C]--|
-                   |--[L1]               <-- F1
+                   |--[M1]              <-- F1
                    |
-                   |--[L0]--[L3]+--[L5b] <-- F2
+                   |--[M0]--[M3]+--[M6] <-- F2
                    |
-                   |--[L4]               <-- F3
+                   |--[M4]              <-- F3
 
-Since we have two competing fork chains finalization cannot occur.
+The two competing fork chains managed to also have the same rank,
+therefore finalization cannot occur.
 
-On next slot, a node only observes 1 proposal. So it extends the
-F2 fork:
+Later, the node only observes 1 proposal, extending the F2 fork:
 
-                   |--[L0]--[L2]--[L5a]        <-- F0
+                   |--[M0]--[M2]--[M5]        <-- F0
     [C]--...--[C]--|
-                   |--[L1]                     <-- F1
+                   |--[M1]                    <-- F1
                    |
-                   |--[L0]--[L3]--[L5b]+--[L6] <-- F2
+                   |--[M0]--[M3]--[M6]+--[M7] <-- F2
                    |
-                   |--[L4]                     <-- F3
+                   |--[M4]                    <-- F3
 
 When the finalization sync period starts, the node finalizes fork
 F2 and all other forks get dropped:
 
-                   |/--[L0]--[L2]--[L5a]      <-- F0
+                   |/--[M0]--[M2]--[M5]      <-- F0
     [C]--...--[C]--|
-                   |/--[L1]                   <-- F1
+                   |/--[M1]                  <-- F1
                    |
-                   |--[L0]--[L3]--[L5b]--[L6] <-- F2
+                   |--[M0]--[M3]--[M6]--[M7] <-- F2
                    |
-                   |/--[L4]                   <-- F3
+                   |/--[M4]                  <-- F3
+
+The canonical blockchain now contains blocks M0, M3, M6 from fork F2,
+and the current state is:
+
+    [C]--...--[C]--|--[M7] <-- F2
+
+# Appendix
+
+This section gives further details about the high level structures that will
+be used by the protocol.
+
+## Header
+
+| Field       | Type           | Description                                    |
+|-------------|----------------|------------------------------------------------|
+| `version`   | `u8`           | Block version                                  |
+| `previous`  | `blake3::Hash` | Previous block hash                            |
+| `epoch`     | `u64`          | Epoch number                                   |
+| `height`    | `u64`          | Block height                                   |
+| `timestamp` | `Timestamp`    | Block creation timestamp                       |
+| `nonce`     | `pallas::Base` | The block's nonce value                        |
+| `tree`      | `MerkleTree`   | Merkle tree of the block's transactions hashes |
+
+## Block
+
+| Field       | Type                | Description              |
+|-------------|---------------------|--------------------------|
+| `header`    | `blake3::Hash`      | Block header hash        |
+| `txs`       | `Vec<blake3::Hash>` | Transaction hashes       |
+| `signature` | `Signature`         | Block producer signature |
+
+## Blockchain
+
+| Field    | Type         | Description                                |
+|----------|--------------|--------------------------------------------|
+| `blocks` | `Vec<Block>` | Series of blocks consisting the Blockchain |
+| `module` | `PoWModule`  | Blocks difficulties state used by RandomX  |
+
+## Fork
+
+| Field       | Type                | Description                      |
+|-------------|---------------------|----------------------------------|
+| `chain`     | `Blockchain`        | Forks current blockchain state   |
+| `proposals` | `Vec<blake3::Hash>` | Fork proposal hashes sequence    |
+| `mempool`   | `Vec<blake3::Hash>` | Valid pending transaction hashes |
+
+## Validator
 
-The canonical blockchain now contains blocks L0, L3, L5b and L6 from fork F2.
+| Field       | Type              | Description                            |
+|-------------|-------------------|----------------------------------------|
+| `canonical` | `Blockchain`      | Canonical (finalized) blockchain       |
+| `forks`     | `Vec<Blockchain>` | Fork chains containing block proposals |
 

+ 6 - 6
doc/src/arch/overview.md

@@ -1,14 +1,14 @@
 # Overview
 
-DarkFi is a layer one proof-of-stake blockchain that supports anonymous
+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 stake Ouroboros Crypsinous, tuned with a discrete controller to achieve a stable supply, currently
-under development to achieve instant finality using parallel leader election
-blockchain. uses Drk consensus token.
-
-DarkFi blockchain's leadership, staking, unstaking, and transaction contracts are written in zkas language, on a P2P Network.
+**Blockchain:** The DarkFi blockchain is based off Proof of Work RandomX
+algorithm, paired with Delayed finality. Consensus participating nodes,
+called miners, produce and propose new blocks to the network, extending
+some fork chain, which once it reaches a finality security thresshold,
+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_

+ 56 - 56
doc/src/arch/tx_lifetime.md

@@ -6,13 +6,13 @@ _(Temporary document, to be integrated into other docs)_
 
 In our network context, we have two types of nodes.
 
-1. Consensus Participant (`CP`)
-2. Consensus Spectator (non-participant) (`CS`)
+1. Miner (`M`)
+2. Spectator (`S`)
 
-`CS` acts as a relayer for transactions in order to help out
-that transactions reach `CP`.
+`S` acts as a relayer for transactions in order to help out
+that transactions reach `M`.
 
-To avoid spam attacks, `CS` should keep $tx$ in their mempool for some
+To avoid spam attacks, `S` should keep $tx$ in their mempool for some
 period of time, and then prune it.
 
 ## Ideal simulation with instant finality
@@ -22,20 +22,20 @@ state transition can be applied on top of the finalized (canonical)
 chain:
 
 1. User creates a transaction $tx$
-2. User broadcasts $tx$ to `CS` 
-3. `CS` validates $tx$ state transition
-4. $tx$ enters `CS` `mempool`
-5. `CS` broadcasts $tx$ to `CP`
-6. `CP` validates $tx$ state transition
-7. $tx$ enters `CP` `mempool`
-8. `CP` validates all transactions in its `mempool` in sequence
-9. `CP` proposes a block finalization containing $tx$
-10. `CP` writes the state transition update of $tx$ to their chain
-11. `CP` removes $tx$ from their `mempool`
-12. `CP` broadcasts the finalized proposal
-13. `CS` receives the proposal and validates transactions
-14. `CS` writes the state updates to their chain
-15. `CS` removes $tx$ from their `mempool`
+2. User broadcasts $tx$ to `S`
+3. `S` validates $tx$ state transition
+4. $tx$ enters `S` `mempool`
+5. `S` broadcasts $tx$ to `M`
+6. `M` validates $tx$ state transition
+7. $tx$ enters `M` `mempool`
+8. `M` validates all transactions in its `mempool` in sequence
+9. `M` proposes a block finalization containing $tx$
+10. `M` writes the state transition update of $tx$ to their chain
+11. `M` removes $tx$ from their `mempool`
+12. `M` broadcasts the finalized proposal
+13. `S` receives the proposal and validates transactions
+14. `S` writes the state updates to their chain
+15. `S` removes $tx$ from their `mempool`
 
 ## Real-world simulation with non-instant finality
 
@@ -44,22 +44,22 @@ state transition is pending to be applied on top of the finalized (canonical)
 chain:
 
 1. User creates a transaction $tx$
-2. User broadcasts $tx$ to `CS`
-3. `CS` validates $tx$ state transition
-4. $tx$ enters `CS` `mempool`
-5. `CS` broadcasts $tx$ to `CP`
-6. `CP` validates $tx$ state transition
-7. $tx$ enters `CP` `mempool`
-8. `CP` proposes a block proposal containing $tx$
-9. `CP` proposes more block proposals
-10. When proposals can be finalized, `CP` validates all their transactions
+2. User broadcasts $tx$ to `S`
+3. `S` validates $tx$ state transition
+4. $tx$ enters `S` `mempool`
+5. `S` broadcasts $tx$ to `M`
+6. `M` validates $tx$ state transition
+7. $tx$ enters `M` `mempool`
+8. `M` proposes a block proposal containing $tx$
+9. `M` proposes more block proposals
+10. When proposals can be finalized, `M` validates all their transactions
 in sequence
-11. `CP` writes the state transition update of $tx$ to their chain
-12. `CP` removes $tx$ from their `mempool`
-13. `CP` broadcasts the finalized proposals sequence
-14. `CS` receives the proposals sequence and validates transactions
-15. `CS` writes the state updates to their chain
-16. `CS` removes $tx$ from their `mempool`
+11. `M` writes the state transition update of $tx$ to their chain
+12. `M` removes $tx$ from their `mempool`
+13. `M` broadcasts the finalized proposals sequence
+14. `S` receives the proposals sequence and validates transactions
+15. `S` writes the state updates to their chain
+16. `S` removes $tx$ from their `mempool`
 
 ## Real-world simulation with non-instant finality, forks and multiple `CP` nodes
 
@@ -68,31 +68,31 @@ state transition is pending to be applied on top of the finalized (canonical)
 chain:
 
 1. User creates a transaction $tx$
-2. User broadcasts $tx$ to `CS`
-3. `CS` validates $tx$ state transition against canonical chain state
-4. $tx$ enters `CS` `mempool`
-5. `CS` broadcasts $tx$ to `CP`
-6. `CP` validates $tx$ state transition against all known fork states
-7. $tx$ enters `CP` `mempool`
-8. `CP` broadcasts $tx$ to rest `CP` nodes
-9. Slot producer `CP` (`SCP`) node finds which fork to extend
-10. `SCP` validates all unproposed transactions in its `mempool` in sequence,
+2. User broadcasts $tx$ to `S`
+3. `S` validates $tx$ state transition against canonical chain state
+4. $tx$ enters `S` `mempool`
+5. `S` broadcasts $tx$ to `P`
+6. `M` validates $tx$ state transition against all known fork states
+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
-11. `SCP` creates a block proposal containing $tx$ extending the fork
-12. `CP` receives block proposal and validates its transactions against
+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
-13. `SCP` proposes more block proposals extending a fork state
-14. When a fork can be finalized, `CP` validates all its proposals
+13. `SM` proposes more block proposals extending a fork state
+14. When a fork can be finalized, `M` validates all its proposals
 transactions in sequence, against canonical state
-15. `CP` writes the state transition update of $tx$ to their chain
-16. `CP` removes $tx$ from their `mempool`
-17. `CP` drop rest forks and keeps only the finalized one
-18. `CP` broadcasts the finalized proposals sequence
-19. `CS` receives the proposals sequence and validates transactions
-20. `CS` writes the state updates to their chain
-21. `CS` removes $tx$ from their `mempool`
-
-`CP` will keep $tx$ in its `mempool` as long as it is a valid state transition
+15. `M` writes the state transition update of $tx$ to their chain
+16. `M` removes $tx$ from their `mempool`
+17. `M` drop rest forks and keeps only the finalized one
+18. `M` broadcasts the finalized proposals sequence
+19. `S` receives the proposals sequence and validates transactions
+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 finalized.
 
 Unproposed transactions refers to all $tx$ not included in a proposal of any fork.

+ 15 - 12
doc/src/spec/concepts.md

@@ -57,16 +57,19 @@ WASM scope.
 
 The current list of functions are:
 
-| Host function     | Permission                     | Description                         |
-|-------------------|--------------------------------|-------------------------------------|
-| `db_init`         | Deploy                         | Create a new database               |
-| `db_lookup`       | Deploy, Exec, Metadata, Update | Lookup a database handle by name    |
-| `db_set`          | Deploy, Update                 | Set a value                         |
-| `db_del`          | Deploy, Update                 | Remove a key                        |
-| `db_get`          | Deploy, Exec, Metadata         | Read a value from a key             |
-| `db_contains_key` | Deploy, Exec, Metadata, Update | Check if a given key exists         |
-| `zkas_db_set`     | Deploy                         | Insert a new ZK circuit             |
-| `merkle_add`      | Update                         | Add a leaf to a merkle tree         |
-| `set_return_data` | Exec, Metadata                 | Used for returning data to the host |
-| `get_slot`        | Deploy, Exec, Metadata         | Get the current slot                |
+| Host function                      | Permission                     | Description                                 |
+|------------------------------------|--------------------------------|---------------------------------------------|
+| `db_init`                          | Deploy                         | Create a new database                       |
+| `db_lookup`                        | Deploy, Exec, Metadata, Update | Lookup a database handle by name            |
+| `db_set`                           | Deploy, Update                 | Set a value                                 |
+| `db_del`                           | Deploy, Update                 | Remove a key                                |
+| `db_get`                           | Deploy, Exec, Metadata         | Read a value from a key                     |
+| `db_contains_key`                  | Deploy, Exec, Metadata, Update | Check if a given key exists                 |
+| `zkas_db_set`                      | Deploy                         | Insert a new ZK circuit                     |
+| `merkle_add`                       | Update                         | Add a leaf to a merkle tree                 |
+| `set_return_data`                  | Exec, Metadata                 | Used for returning data to the host         |
+| `get_verifying_block_height`       | Deploy, Exec, Metadata, Update | Runtime verifying block height              |
+| `get_verifying_block_height_epoch` | Deploy, Exec, Metadata, Update | Runtime verifying block height epoch        |
+| `get_blockchain_time`              | Deploy, Exec, Metadata, Update | Current blockchain (last block's) timestamp |
+| `get_last_block_info`              | Exec                           | Last block's info, used in VRF proofs       |
 

+ 1 - 2
src/blockchain/header_store.rs

@@ -45,9 +45,8 @@ pub struct Header {
     pub timestamp: Timestamp,
     /// The block's nonce.
     /// In PoW, this value changes arbitrarily with mining.
-    /// In PoS, we can use this value as our block producer ETA.
     pub nonce: pallas::Base,
-    /// Merkle tree of the transactions contained in this block
+    /// Merkle tree of the transactions hashes contained in this block
     pub tree: MerkleTree,
 }