ouroboros-consensus-0.1.0.1: Consensus layer for the Ouroboros blockchain protocol
Safe Haskell None
Language Haskell2010

Ouroboros.Consensus.Storage.LedgerDB.InMemory

Synopsis

LedgerDB proper

ledgerDbWithAnchor :: GetTip l => l -> LedgerDB l Source #

Ledger DB starting at the specified ledger state

opaque

data LedgerDB l Source #

Internal state of the ledger DB

The ledger DB looks like

anchor |> snapshots <| current

where anchor records the oldest known snapshot and current the most recent. The anchor is the oldest point we can roll back to.

We take a snapshot after each block is applied and keep in memory a window of the last k snapshots. We have verified empirically (#1936) that the overhead of keeping @k snapshots in memory is small, i.e., about 5% compared to keeping a snapshot every 100 blocks. This is thanks to sharing between consecutive snapshots.

As an example, suppose we have k = 6 . The ledger DB grows as illustrated below, where we indicate the anchor number of blocks, the stored snapshots, and the current ledger.

anchor |> #   [ snapshots ]                   <| tip
---------------------------------------------------------------------------
G      |> (0) [ ]                             <| G
G      |> (1) [ L1]                           <| L1
G      |> (2) [ L1,  L2]                      <| L2
G      |> (3) [ L1,  L2,  L3]                 <| L3
G      |> (4) [ L1,  L2,  L3,  L4]            <| L4
G      |> (5) [ L1,  L2,  L3,  L4,  L5]       <| L5
G      |> (6) [ L1,  L2,  L3,  L4,  L5,  L6]  <| L6
L1     |> (6) [ L2,  L3,  L4,  L5,  L6,  L7]  <| L7
L2     |> (6) [ L3,  L4,  L5,  L6,  L7,  L8]  <| L8
L3     |> (6) [ L4,  L5,  L6,  L7,  L8,  L9]  <| L9   (*)
L4     |> (6) [ L5,  L6,  L7,  L8,  L9,  L10] <| L10
L5     |> (6) [*L6,  L7,  L8,  L9,  L10, L11] <| L11
L6     |> (6) [ L7,  L8,  L9,  L10, L11, L12] <| L12
L7     |> (6) [ L8,  L9,  L10, L12, L12, L13] <| L13
L8     |> (6) [ L9,  L10, L12, L12, L13, L14] <| L14

The ledger DB must guarantee that at all times we are able to roll back k blocks. For example, if we are on line (*), and roll back 6 blocks, we get

L3 |> []

Instances

Instances details
Eq l => Eq ( LedgerDB l) Source #
Instance details

Defined in Ouroboros.Consensus.Storage.LedgerDB.InMemory

Show l => Show ( LedgerDB l) Source #
Instance details

Defined in Ouroboros.Consensus.Storage.LedgerDB.InMemory

Generic ( LedgerDB l) Source #
Instance details

Defined in Ouroboros.Consensus.Storage.LedgerDB.InMemory

Associated Types

type Rep ( LedgerDB l) :: Type -> Type Source #

NoThunks l => NoThunks ( LedgerDB l) Source #
Instance details

Defined in Ouroboros.Consensus.Storage.LedgerDB.InMemory

IsLedger l => IsLedger ( LedgerDB l) Source #
Instance details

Defined in Ouroboros.Consensus.Storage.LedgerDB.InMemory

IsLedger l => GetTip ( Ticked ( LedgerDB l)) Source #
Instance details

Defined in Ouroboros.Consensus.Storage.LedgerDB.InMemory

IsLedger l => GetTip ( LedgerDB l) Source #
Instance details

Defined in Ouroboros.Consensus.Storage.LedgerDB.InMemory

ApplyBlock l blk => ApplyBlock ( LedgerDB l) blk Source #
Instance details

Defined in Ouroboros.Consensus.Storage.LedgerDB.InMemory

type Rep ( LedgerDB l) Source #
Instance details

Defined in Ouroboros.Consensus.Storage.LedgerDB.InMemory

type HeaderHash ( LedgerDB l) Source #
Instance details

Defined in Ouroboros.Consensus.Storage.LedgerDB.InMemory

data Ticked ( LedgerDB l) Source #

Ticking the ledger DB just ticks the current state

We don't push the new state into the DB until we apply a block.

Instance details

Defined in Ouroboros.Consensus.Storage.LedgerDB.InMemory

type LedgerErr ( LedgerDB l) Source #
Instance details

Defined in Ouroboros.Consensus.Storage.LedgerDB.InMemory

type AuxLedgerEvent ( LedgerDB l) Source #
Instance details

Defined in Ouroboros.Consensus.Storage.LedgerDB.InMemory

type LedgerCfg ( LedgerDB l) Source #
Instance details

Defined in Ouroboros.Consensus.Storage.LedgerDB.InMemory

Serialisation

decodeSnapshotBackwardsCompatible :: forall l blk. Proxy blk -> ( forall s. Decoder s l) -> ( forall s. Decoder s ( HeaderHash blk)) -> forall s. Decoder s l Source #

To remain backwards compatible with existing snapshots stored on disk, we must accept the old format as well as the new format.

The old format: * The tip: WithOrigin (RealPoint blk) * The chain length: Word64 * The ledger state: l

The new format is described by snapshotEncodingVersion1 .

This decoder will accept and ignore them. The encoder ( encodeSnapshot ) will no longer encode them.

encodeSnapshot :: (l -> Encoding ) -> l -> Encoding Source #

Encoder to be used in combination with decodeSnapshotBackwardsCompatible .

Queries

ledgerDbAnchor :: LedgerDB l -> l Source #

Information about the state of the ledger at the anchor

ledgerDbBimap :: Anchorable ( WithOrigin SlotNo ) a b => (l -> a) -> (l -> b) -> LedgerDB l -> AnchoredSeq ( WithOrigin SlotNo ) a b Source #

Transform the underlying AnchoredSeq using the given functions.

ledgerDbCurrent :: GetTip l => LedgerDB l -> l Source #

The ledger state at the tip of the chain

ledgerDbPast :: ( HasHeader blk, IsLedger l, HeaderHash l ~ HeaderHash blk) => Point blk -> LedgerDB l -> Maybe l Source #

Get a past ledger state

\( O(\log(\min(i,n-i)) \)

When no ledger state (or anchor) has the given Point , Nothing is returned.

ledgerDbPrune :: GetTip l => SecurityParam -> LedgerDB l -> LedgerDB l Source #

Prune snapshots until at we have at most k snapshots in the LedgerDB, excluding the snapshots stored at the anchor.

ledgerDbSnapshots :: LedgerDB l -> [( Word64 , l)] Source #

All snapshots currently stored by the ledger DB (new to old)

This also includes the snapshot at the anchor. For each snapshot we also return the distance from the tip.

ledgerDbTip :: GetTip l => LedgerDB l -> Point l Source #

Reference to the block at the tip of the chain

Running updates

data AnnLedgerError l blk Source #

Annotated ledger errors

Constructors

AnnLedgerError

Fields

data Ap :: ( Type -> Type ) -> Type -> Type -> Constraint -> Type where Source #

Ap is used to pass information about blocks to ledger DB updates

The constructors serve two purposes:

  • Specify the various parameters a. Are we passing the block by value or by reference? b. Are we applying or reapplying the block?
  • Compute the constraint c on the monad m in order to run the query: a. If we are passing a block by reference, we must be able to resolve it. b. If we are applying rather than reapplying, we might have ledger errors.

Constructors

ReapplyVal :: blk -> Ap m l blk ()
ApplyVal :: blk -> Ap m l blk ( ThrowsLedgerError m l blk)
ReapplyRef :: RealPoint blk -> Ap m l blk ( ResolvesBlocks m blk)
ApplyRef :: RealPoint blk -> Ap m l blk ( ResolvesBlocks m blk, ThrowsLedgerError m l blk)
Weaken :: (c' => c) => Ap m l blk c -> Ap m l blk c'

Weaken increases the constraint on the monad m .

This is primarily useful when combining multiple Ap s in a single homogeneous structure.

type ResolveBlock m blk = RealPoint blk -> m blk Source #

Resolve a block

Resolving a block reference to the actual block lives in m because it might need to read the block from disk (and can therefore not be done inside an STM transaction).

NOTE: The ledger DB will only ask the ChainDB for blocks it knows must exist. If the ChainDB is unable to fulfill the request, data corruption must have happened and the ChainDB should trigger validation mode.

class Monad m => ResolvesBlocks m blk | m -> blk where Source #

Monads in which we can resolve blocks

To guide type inference, we insist that we must be able to infer the type of the block we are resolving from the type of the monad.

Updates

data ExceededRollback Source #

Exceeded maximum rollback supported by the current ledger DB state

Under normal circumstances this will not arise. It can really only happen in the presence of data corruption (or when switching to a shorter fork, but that is disallowed by all currently known Ouroboros protocols).

Records both the supported and the requested rollback.

ledgerDbPush :: forall m c l blk. ( ApplyBlock l blk, Monad m, c) => LedgerDbCfg l -> Ap m l blk c -> LedgerDB l -> m ( LedgerDB l) Source #

ledgerDbSwitch Source #

Arguments

:: ( ApplyBlock l blk, Monad m, c)
=> LedgerDbCfg l
-> Word64

How many blocks to roll back

-> ( UpdateLedgerDbTraceEvent blk -> m ())
-> [ Ap m l blk c]

New blocks to apply

-> LedgerDB l
-> m ( Either ExceededRollback ( LedgerDB l))

Switch to a fork

Exports for the benefit of tests

Additional queries

ledgerDbMaxRollback :: GetTip l => LedgerDB l -> Word64 Source #

How many blocks can we currently roll back?

Pure API