|
1 | 1 | \chapter{Ledger Database} |
2 | 2 | \label{ledgerdb} |
3 | 3 |
|
4 | | -The Ledger DB is responsible for the following tasks: |
5 | 4 |
|
6 | | -\begin{enumerate} |
7 | | -\item \textbf{Maintaining the ledger state at the tip}: Maintaining the ledger |
8 | | - state corresponding to the current tip in memory. When we try to extend our |
9 | | - chain with a new block fitting onto our tip, the block must first be validated |
10 | | - using the right ledger state, i.e., the ledger state corresponding to the tip. |
11 | | - The current ledger state is needed for various other purposes. |
12 | | - |
13 | | -\item \textbf{Maintaining the past $k$ ledger states}: As discussed in |
14 | | - \cref{consensus:overview:k}, we might roll back up to $k$ blocks when |
15 | | - switching to a more preferable fork. Consider the example below: |
16 | | - % |
17 | | - \begin{center} |
18 | | - \begin{tikzpicture} |
19 | | - \draw (0, 0) -- (50pt, 0) coordinate (I); |
20 | | - \draw (I) -- ++(20pt, 20pt) coordinate (C1) -- ++(20pt, 0) coordinate (C2); |
21 | | - \draw (I) -- ++(20pt, -20pt) coordinate (F1) -- ++(20pt, 0) coordinate (F2) -- ++(20pt, 0) coordinate (F3); |
22 | | - \node at (I) {$\bullet$}; |
23 | | - \node at (C1) {$\bullet$}; |
24 | | - \node at (C2) {$\bullet$}; |
25 | | - \node at (F1) {$\bullet$}; |
26 | | - \node at (F2) {$\bullet$}; |
27 | | - \node at (F3) {$\bullet$}; |
28 | | - \node at (I) [above left] {$I$}; |
29 | | - \node at (C1) [above] {$C_1$}; |
30 | | - \node at (C2) [above] {$C_2$}; |
31 | | - \node at (F1) [below] {$F_1$}; |
32 | | - \node at (F2) [below] {$F_2$}; |
33 | | - \node at (F3) [below] {$F_3$}; |
34 | | - \draw (60pt, 50pt) node {$\overbrace{\hspace{60pt}}$}; |
35 | | - \draw (60pt, 60pt) node[fill=white] {$k$}; |
36 | | - \draw [dashed] (30pt, -40pt) -- (30pt, 45pt); |
37 | | - \end{tikzpicture} |
38 | | - \end{center} |
39 | | - % |
40 | | - Our current chain's tip is $C_2$, but the fork containing blocks $F_1$, $F_2$, |
41 | | - and $F_3$ is more preferable. We roll back our chain to the intersection point |
42 | | - of the two chains, $I$, which must be not more than $k$ blocks back from our |
43 | | - current tip. Next, we must validate block $F_1$ using the ledger state at |
44 | | - block $I$, after which we can validate $F_2$ using the resulting ledger state, |
45 | | - and so on. |
46 | | - |
47 | | - This means that we need access to all ledger states of the past $k$ blocks, |
48 | | - i.e., the ledger states corresponding to the volatile part of the current |
49 | | - chain.\footnote{Applying a block to a ledger state is not an invertible |
50 | | - operation, so it is not possible to simply ``unapply'' $C_1$ and $C_2$ to |
51 | | - obtain $I$.} |
52 | | - |
53 | | - Access to the last $k$ ledger states is not only needed for validating candidate |
54 | | - chains, but also by the: |
55 | | - \begin{itemize} |
56 | | - \item \textbf{Local state query server}: To query any of the past $k$ ledger |
57 | | - states (\cref{servers:lsq}). |
58 | | - \item \textbf{Chain sync client}: To validate headers of a chain that |
59 | | - intersects with any of the past $k$ blocks |
60 | | - (\cref{chainsyncclient:validation}). |
61 | | - \end{itemize} |
62 | | - |
63 | | -\item \textbf{Storing on disk}: To obtain a ledger state for the current tip of |
64 | | - the chain, one has to apply \emph{all blocks in the chain} one-by-one to the |
65 | | - initial ledger state. When starting up the system with an on-disk chain |
66 | | - containing millions of blocks, all of them would have to be read from disk and |
67 | | - applied. This process can take tens of minutes, depending on the storage and |
68 | | - CPU speed, and is thus too costly to perform on each startup. |
69 | | - |
70 | | - For this reason, a recent snapshot of the ledger state should be periodically |
71 | | - written to disk. Upon the next startup, that snapshot can be read and used to |
72 | | - restore the current ledger state, as well as the past $k$ ledger states. |
73 | | -\end{enumerate} |
74 | | - |
75 | | -Note that whenever we say ``ledger state'', we mean the |
76 | | -\lstinline!ExtLedgerState blk! type described in \cref{storage:extledgerstate}. |
77 | | - |
78 | | -The above duties are divided across the following modules: |
79 | | - |
80 | | -\begin{itemize} |
81 | | -\item \lstinline!LedgerDB.InMemory!: this module defines a pure data structure, |
82 | | - named \lstinline!LedgerDB!, to represent the last $k$ ledger states in memory. |
83 | | - Operations to validate and append blocks, to switch to forks, to look up |
84 | | - ledger states, \ldots{} are provided. |
85 | | -\item \lstinline!LedgerDB.OnDisk!: this module contains the functionality to |
86 | | - write a snapshot of the \lstinline!LedgerDB! to disk and how to restore a |
87 | | - \lstinline!LedgerDB! from a snapshot. |
88 | | -\item \lstinline!LedgerDB.DiskPolicy!: this module contains the policy that |
89 | | - determines when a snapshot of the \lstinline!LedgerDB! is written to disk. |
90 | | -\item \lstinline!ChainDB.Impl.LgrDB!: this module is part of the Chain DB, and |
91 | | - is responsible for maintaining the pure \lstinline!LedgerDB! in a |
92 | | - \lstinline!StrictTVar!. |
93 | | -\end{itemize} |
94 | | - |
95 | | -We will now discuss the modules listed above. |
| 5 | +THIS PART WAS PORTED TO THE HADDOCKS |
96 | 6 |
|
97 | 7 | \section{In-memory representation} |
98 | 8 | \label{ledgerdb:in-memory} |
|
0 commit comments