Safe Haskell | None |
---|---|
Language | Haskell2010 |
Synopsis
- type LookupBlockInfo blk = HeaderHash blk -> Maybe ( BlockInfo blk)
- extendWithSuccessors :: forall blk. HasHeader blk => ( ChainHash blk -> Set ( HeaderHash blk)) -> LookupBlockInfo blk -> ChainDiff ( HeaderFields blk) -> NonEmpty ( ChainDiff ( HeaderFields blk))
- maximalCandidates :: forall blk. ( ChainHash blk -> Set ( HeaderHash blk)) -> Point blk -> [ NonEmpty ( HeaderHash blk)]
-
data
Path
blk
- = NotInVolatileDB ( RealPoint blk)
- | CompletelyInVolatileDB [ RealPoint blk]
- | PartiallyInVolatileDB ( HeaderHash blk) [ RealPoint blk]
- computePath :: forall blk. HasHeader blk => LookupBlockInfo blk -> StreamFrom blk -> StreamTo blk -> Maybe ( Path blk)
-
data
ReversePath
blk
- = StoppedAtGenesis
- | StoppedAt ( HeaderHash blk) BlockNo
- | ( ReversePath blk) ::> ( HeaderFields blk, IsEBB )
- computeReversePath :: forall blk. LookupBlockInfo blk -> HeaderHash blk -> Maybe ( ReversePath blk)
- isReachable :: forall blk. ( HasHeader blk, GetHeader blk) => LookupBlockInfo blk -> AnchoredFragment ( Header blk) -> RealPoint blk -> Maybe ( ChainDiff ( HeaderFields blk))
LookupBlockInfo
type LookupBlockInfo blk = HeaderHash blk -> Maybe ( BlockInfo blk) Source #
Return the block info for the block with the given hash. Return
Nothing
when not in the VolatileDB.
Candidates
extendWithSuccessors :: forall blk. HasHeader blk => ( ChainHash blk -> Set ( HeaderHash blk)) -> LookupBlockInfo blk -> ChainDiff ( HeaderFields blk) -> NonEmpty ( ChainDiff ( HeaderFields blk)) Source #
Extend the
ChainDiff
with the successors found by
maximalCandidates
.
In case no successors were found, the original
ChainDiff
is returned as a
singleton.
In case successors
were
found, the original
ChainDiff
is
not
included, only its extensions.
Only the longest possible extensions are returned, no intermediary prefixes of extensions.
:: forall blk. ( ChainHash blk -> Set ( HeaderHash blk)) |
filterByPredecessor |
-> Point blk |
B |
-> [ NonEmpty ( HeaderHash blk)] |
Each element in the list is a list of hashes from which we can
construct a fragment anchored at the point
|
Compute the maximal candidates starting at the specified point
As discussed in the Consensus Report, the set of maximal candidates doesn't include prefixes.
PRECONDITION: the block to which the given point corresponds is part of the VolatileDB.
The first element in each list of hashes is the hash after the specified hash. Thus, when building fragments from these lists of hashes, they fragments must be anchored at the specified hash, but not contain it.
NOTE: it is possible that no candidates are found, but don't forget that
the chain (fragment) ending with
B
is also a potential candidate.
Path
A path through the VolatileDB from a
StreamFrom
to a
StreamTo
.
Invariant: the
AnchoredFragment
(oldest first) constructed using the blocks
corresponding to the points in the path will be valid, i.e., the blocks
will fit onto each other.
NotInVolatileDB ( RealPoint blk) |
The
|
CompletelyInVolatileDB [ RealPoint blk] |
A complete path, from start point to end point was constructed from the VolatileDB. The list contains the points from oldest to newest.
|
PartiallyInVolatileDB ( HeaderHash blk) [ RealPoint blk] |
Only a partial path could be constructed from the VolatileDB. The missing predecessor could still be in the ImmutableDB. The list contains the points from oldest to newest.
Note: if the lower bound is exclusive, the block corresponding to it
doesn't have to be part of the VolatileDB, it will result in a
The same invariants hold for the upper bound as for
|
computePath :: forall blk. HasHeader blk => LookupBlockInfo blk -> StreamFrom blk -> StreamTo blk -> Maybe ( Path blk) Source #
Construct a path backwards through the VolatileDB.
We walk backwards through the VolatileDB, constructing a
Path
from the
StreamTo
to the
StreamFrom
.
If the range is invalid,
Nothing
is returned.
See the documentation of
Path
.
Reverse path
data ReversePath blk Source #
A reverse path through the VolatileDB starting at a block in the VolatileDB until we reach genesis or leave the VolatileDB.
StoppedAtGenesis |
The path stopped at genesis |
StoppedAt ( HeaderHash blk) BlockNo |
The path stopped at this hash, which is the hash of the predecessor of the last block in the path (that was still stored in the VolatileDB). The block corresponding to the predecessor is not stored in the VolatileDB. Either because it is missing, or because it is old and has been garbage collected. Since block numbers are consecutive, we subtract 1 from the block number of the last block to obtain the block number corresponding to this hash. EBBs share their block number with their predecessor: block: regular block 1 | EBB | regular block 2 block number: X | X | X + 1 So when the hash refers to regular block 1, we see that the successor block is an EBB and use its block number without subtracting 1. Edge case: if there are two or more consecutive EBBs, we might predict the wrong block number, but there are no consecutive EBBs in practice, they are one epoch apart. |
( ReversePath blk) ::> ( HeaderFields blk, IsEBB ) |
Snoc: the block with the given
NOTE: we are intentionally lazy in the spine, as constructing the path requires lookups in the VolatileDB's in-memory indices, which are logarithmic in the size of the index. |
:: forall blk. LookupBlockInfo blk | |
-> HeaderHash blk |
End hash |
-> Maybe ( ReversePath blk) |
Reverse path from the end point to genesis or the first predecessor not in the VolatileDB. Nothing when the end hash is not in the VolatileDB. |
Lazily compute the
ReversePath
that starts (i.e., ends) with the given
HeaderHash
.
Reachability
:: forall blk. ( HasHeader blk, GetHeader blk) | |
=> LookupBlockInfo blk | |
-> AnchoredFragment ( Header blk) |
Chain fragment to connect the point to |
-> RealPoint blk | |
-> Maybe ( ChainDiff ( HeaderFields blk)) |
Try to connect the point
P
to the chain fragment by chasing the
predecessors.
When successful, return a
ChainDiff
: the number of blocks to roll back
the chain fragment to the intersection point and a fragment anchored at the
intersection point containing the
HeaderFields
corresponding to the
blocks needed to connect to
P
. The intersection point will be the most
recent intersection point.
Returns
Nothing
when
P
is not in the VolatileDB or when
P
is not
connected to the given chain fragment.
POSTCONDITION: the returned number of blocks to roll back is less than or equal to the length of the given chain fragment.
Note that the number of returned points can be smaller than the number of
blocks to roll back. This means
P
is on a fork shorter than the given
chain fragment.
A
ChainDiff
is returned iff
P
is on the chain fragment. Moreover, when
the number of blocks to roll back is also 0, it must be that
P
is the tip
of the chain fragment.
When the suffix of the
ChainDiff
is non-empty,
P
will be the last point
in the suffix.