Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify checkpoint pruning #3159

Closed

Conversation

HeinrichApfelmus
Copy link
Contributor

Issue number

ADP-1497

Overview

Previous work in epic ADP-1043 introduced delta encodings, DBVars, and an embedding of the wallet state and its delta encodings into a database table. It's time to integrate these tools with the wallet code. To facilitate code review, the integration proceeds in a sequence of refactorings that do not change functionality and pass all unit tests.

In this step, we consolidate and simplify the creation and pruning of checkpoints.

This step prepares the Checkpoints type so that it can accommodate the DeltaUTxO type: At the moment, checkpoints of UTxO can be pruned by simply dropping them from the Map, but in the future, checkpoints of DeltaUTxO need to be combined with the semigroup operation (<>). This would have been awkward to implement in the previous implementation of the checkpoint hygiene logic, which created and pruned checkpoints partially before they were written to the database, and partially after. By using a single predicate

keepWhereTip checkpointPolicy height tip :: Bool

which determines whether to keep a checkpoint with block height height when the blockchain tip is tip, the distinction between the cases "checkpoint before adding to Checkpoints" and "checkpoint after adding to Checkpoints" becomes irrelevant.

Details

  • The sparseArithmeticPolicy is modeled on the previous checkpointing policy, but it is not equal to it. Specifically, when synchronizing the chain far away from the tip, at most two checkpoints are kept: genesis and the latest synchronization point. We only keep multiple checkpoints when we are within epochStability of the tip, as we expect rollbacks only then.
  • The assumption that rollbacks may occur only within epochStability of the tip may no longer be valid in the upcoming Ouroboros Genesis protocol. We may have to revisit the checkpointing logic at that time, but by then, the full incorporation of delta encodings should allow us to keep a lot of checkpoints.
  • The property tests for the checkpoint policy have been rewritten and became much faster.

@HeinrichApfelmus HeinrichApfelmus changed the title Heinrich apfelmus/adp 1043/prune checkpoints Simplify checkpoint pruning Mar 3, 2022
Base automatically changed from HeinrichApfelmus/ADP-1043/DeltaUTxO to master March 4, 2022 08:51
@HeinrichApfelmus HeinrichApfelmus force-pushed the HeinrichApfelmus/ADP-1043/PruneCheckpoints branch from de08803 to db36b61 Compare March 4, 2022 09:10
HeinrichApfelmus and others added 6 commits March 4, 2022 15:44
… using a `CheckpointPolicy` which uses a predicate to determine whether a checkpoint should be kept.
… to the `Cardano.Wallet.DB.WalletState` module.
Use the new `extendAndPrune` function here as well.
@HeinrichApfelmus HeinrichApfelmus force-pushed the HeinrichApfelmus/ADP-1043/PruneCheckpoints branch from 6c1f5f5 to 09cf539 Compare March 4, 2022 14:44
@HeinrichApfelmus
Copy link
Contributor Author

bors try

iohk-bors bot added a commit that referenced this pull request Mar 4, 2022
@iohk-bors
Copy link
Contributor

iohk-bors bot commented Mar 4, 2022

try

Build failed:

@HeinrichApfelmus HeinrichApfelmus marked this pull request as draft March 8, 2022 14:19
Copy link
Contributor

@paweljakubas paweljakubas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @HeinrichApfelmus So we have CheckpointPolicy now introducing how we deal with "checkpoint denisty". What about having two checkpoint policies, sparseArithmeticPolicy and the one reflecting exactly the one in master. And having them we will compare how they perform in benchmarks. I am fond of this abstraction! At first look sparseArithemeticPolicy looks proper, rationale is sound, well know. I will give a second very soon.

@HeinrichApfelmus
Copy link
Contributor Author

I am fond of this abstraction! At first look sparseArithemeticPolicy looks proper, rationale is sound, well know.

😊

What about having two checkpoint policies, sparseArithmeticPolicy and the one reflecting exactly the one in master. And having them we will compare how they perform in benchmarks.

The idea is that sparseArithmeticPolicy should be very close to the policy that we currently have in master. Unfortunately, it's not possible to compare the checkpointing algorithms directly, because master currently has some "path dependence", where the checkpoint creation depends on how exactly the node provides blocks to the wallet, whereas the new CheckpointPolicy is deterministic and picks checkpoints based only on the current tip. This determinism makes the logic simpler to reason about, but precludes a direct comparison; sparseArithmeticPolicy is my best attempt to reformulate the logic of master in the new style.

Unfortunately for the entire pull request, I just noticed that light-mode will force path dependence upon us again, as we will not see every block in sequence anymore, only nondeterministic ranges of blocks. 🙈 I will have to rethink the checkpoint approach again — that is why I have moved this pull request back to draft status. Could I focus your attention to reviewing PR #3143 instead? Progressing further with light-mode will make it more clear to me how exactly I will need to adapt the new CheckpointPolicy to work with light-mode as well.

iohk-bors bot added a commit that referenced this pull request Jun 18, 2022
3327: Implement `CheckpointPolicy` data type r=HeinrichApfelmus a=HeinrichApfelmus

### Issue number

ADP-1497

### Overview

This pull request implements an abstract data type `CheckpointPolicy` which describes a policy for keeping and discarding checkpoints based on their BlockHeight.

Specifically, a boolean `keepWhereTip policy tip height` indicates whether the `policy` wants to store a checkpoint at the block height `height` , given that the blockchain is at `tip`.

### Details

* The implementation of the data type is based on a function
    ```
    nextCheckpoint policy tip height :: Maybe BlockHeight
    ```
    which returns the next block height (`>= height`) at which a checkpoint should be made. This function is an efficient balance between the purely boolean predicate (`keepWhereTip`) and a full listing of all checkpoints (`toListAtTip`).
* New policies can be created from old policies by using the semigroup operation `(<>)`, which represents the union of the checkpoint listings. This simplifies the implementation of the `sparseArithmetic` policy significantly.
* The `sparseArithmetic` policy is modeled on the checkpointing policy currently implemented in `cardano-wallet`, but it is not equal to it.

### Comments

* This pull request implements the data type, but does *not* use it yet, in order to keep this PR small and easy to review. The type will be used in a future pull request.
* This data type is a reimplementation of the data type introduced in the stale pull request #3159.
    * The main reason for not merging the old PR is that a purely boolean predicate `keepWhereTip` is not suitable for use with `lightSync`. The problem is that `lightSync` does not always read individual blocks and can (potentially) skip over many BlockHeights — which would result in *no* checkpoints being created, as the predicate always returns `False`. Put differently, the checkpoints would "fall between the cracks".
    In contrast, an implementation based on `nextCheckpoint` can be used with `lightSync`, as it can now *specifically target* the next block height, at which a checkpoint is created.

Co-authored-by: Heinrich Apfelmus <[email protected]>
iohk-bors bot added a commit that referenced this pull request Jun 19, 2022
3327: Implement `CheckpointPolicy` data type r=HeinrichApfelmus a=HeinrichApfelmus

### Issue number

ADP-1497

### Overview

This pull request implements an abstract data type `CheckpointPolicy` which describes a policy for keeping and discarding checkpoints based on their BlockHeight.

Specifically, a boolean `keepWhereTip policy tip height` indicates whether the `policy` wants to store a checkpoint at the block height `height` , given that the blockchain is at `tip`.

### Details

* The implementation of the data type is based on a function
    ```
    nextCheckpoint policy tip height :: Maybe BlockHeight
    ```
    which returns the next block height (`>= height`) at which a checkpoint should be made. This function is an efficient balance between the purely boolean predicate (`keepWhereTip`) and a full listing of all checkpoints (`toListAtTip`).
* New policies can be created from old policies by using the semigroup operation `(<>)`, which represents the union of the checkpoint listings. This simplifies the implementation of the `sparseArithmetic` policy significantly.
* The `sparseArithmetic` policy is modeled on the checkpointing policy currently implemented in `cardano-wallet`, but it is not equal to it.

### Comments

* This pull request implements the data type, but does *not* use it yet, in order to keep this PR small and easy to review. The type will be used in a future pull request.
* This data type is a reimplementation of the data type introduced in the stale pull request #3159.
    * The main reason for not merging the old PR is that a purely boolean predicate `keepWhereTip` is not suitable for use with `lightSync`. The problem is that `lightSync` does not always read individual blocks and can (potentially) skip over many BlockHeights — which would result in *no* checkpoints being created, as the predicate always returns `False`. Put differently, the checkpoints would "fall between the cracks".
    In contrast, an implementation based on `nextCheckpoint` can be used with `lightSync`, as it can now *specifically target* the next block height, at which a checkpoint is created.

Co-authored-by: Heinrich Apfelmus <[email protected]>
iohk-bors bot added a commit that referenced this pull request Jun 12, 2023
3988: [ADP-3031] Simplify checkpoint pruning, take 3 r=HeinrichApfelmus a=HeinrichApfelmus

### Overview


In this pull request, we consolidate and simplify the creation and pruning of checkpoints.

Specifically, we introduce a function `extendAndPrune` that computes a delta which

* adds new checkpoints
* prunes the existing checkpoints

based on their block height.

### Details

* The mechanism for creating checkpoints has changed. Specifically, when synchronizing the chain far away from the `tip`, at most two checkpoints are kept: genesis and the latest synchronization point. We only keep multiple checkpoints when we are within `epochStability` of the tip, as we expect rollbacks only then.
* The `CheckpointPolicy` is tested in the existing module `Cardano.Wallet.Checkpoints.PolicySpec`.

### Comments

* This task evolved out of ADP-1497. Previous attempts to implement this are
    * #3159
    * #3369 

### Issue Number

ADP-3031

Co-authored-by: Heinrich Apfelmus <[email protected]>
@HeinrichApfelmus HeinrichApfelmus deleted the HeinrichApfelmus/ADP-1043/PruneCheckpoints branch June 15, 2023 11:44
iohk-bors bot added a commit that referenced this pull request Jun 16, 2023
3988: [ADP-3031] Simplify checkpoint pruning, take 3 r=HeinrichApfelmus a=HeinrichApfelmus

### Overview


In this pull request, we consolidate and simplify the creation and pruning of checkpoints.

Specifically, we introduce a function `extendAndPrune` that computes a delta which

* adds new checkpoints
* prunes the existing checkpoints

based on their block height.

### Details

* The mechanism for creating checkpoints has changed. Specifically, when synchronizing the chain far away from the `tip`, at most two checkpoints are kept: genesis and the latest synchronization point. We only keep multiple checkpoints when we are within `epochStability` of the tip, as we expect rollbacks only then.
* The `CheckpointPolicy` is tested in the existing module `Cardano.Wallet.Checkpoints.PolicySpec`.

### Comments

* This task evolved out of ADP-1497. Previous attempts to implement this are
    * #3159
    * #3369 

### Issue Number

ADP-3031

Co-authored-by: Heinrich Apfelmus <[email protected]>
iohk-bors bot added a commit that referenced this pull request Jun 16, 2023
3988: [ADP-3031] Simplify checkpoint pruning, take 3 r=HeinrichApfelmus a=HeinrichApfelmus

### Overview


In this pull request, we consolidate and simplify the creation and pruning of checkpoints.

Specifically, we introduce a function `extendAndPrune` that computes a delta which

* adds new checkpoints
* prunes the existing checkpoints

based on their block height.

### Details

* The mechanism for creating checkpoints has changed. Specifically, when synchronizing the chain far away from the `tip`, at most two checkpoints are kept: genesis and the latest synchronization point. We only keep multiple checkpoints when we are within `epochStability` of the tip, as we expect rollbacks only then.
* The `CheckpointPolicy` is tested in the existing module `Cardano.Wallet.Checkpoints.PolicySpec`.

### Comments

* This task evolved out of ADP-1497. Previous attempts to implement this are
    * #3159
    * #3369 

### Issue Number

ADP-3031

Co-authored-by: Heinrich Apfelmus <[email protected]>
iohk-bors bot added a commit that referenced this pull request Jun 16, 2023
3988: [ADP-3031] Simplify checkpoint pruning, take 3 r=HeinrichApfelmus a=HeinrichApfelmus

### Overview


In this pull request, we consolidate and simplify the creation and pruning of checkpoints.

Specifically, we introduce a function `extendAndPrune` that computes a delta which

* adds new checkpoints
* prunes the existing checkpoints

based on their block height.

### Details

* The mechanism for creating checkpoints has changed. Specifically, when synchronizing the chain far away from the `tip`, at most two checkpoints are kept: genesis and the latest synchronization point. We only keep multiple checkpoints when we are within `epochStability` of the tip, as we expect rollbacks only then.
* The `CheckpointPolicy` is tested in the existing module `Cardano.Wallet.Checkpoints.PolicySpec`.

### Comments

* This task evolved out of ADP-1497. Previous attempts to implement this are
    * #3159
    * #3369 

### Issue Number

ADP-3031

Co-authored-by: Heinrich Apfelmus <[email protected]>
iohk-bors bot added a commit that referenced this pull request Jun 16, 2023
3988: [ADP-3031] Simplify checkpoint pruning, take 3 r=HeinrichApfelmus a=HeinrichApfelmus

### Overview


In this pull request, we consolidate and simplify the creation and pruning of checkpoints.

Specifically, we introduce a function `extendAndPrune` that computes a delta which

* adds new checkpoints
* prunes the existing checkpoints

based on their block height.

### Details

* The mechanism for creating checkpoints has changed. Specifically, when synchronizing the chain far away from the `tip`, at most two checkpoints are kept: genesis and the latest synchronization point. We only keep multiple checkpoints when we are within `epochStability` of the tip, as we expect rollbacks only then.
* The `CheckpointPolicy` is tested in the existing module `Cardano.Wallet.Checkpoints.PolicySpec`.

### Comments

* This task evolved out of ADP-1497. Previous attempts to implement this are
    * #3159
    * #3369 

### Issue Number

ADP-3031

Co-authored-by: Heinrich Apfelmus <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants