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

refactor: Change counters to support encryption #2698

Conversation

fredcarle
Copy link
Collaborator

Relevant issue(s)

Resolves #2696

Description

This PR changes the counter CRDTs to make them support the document encryption feature. They previously stored their values as concrete types (int64 and float64) instead of bytes. Storing them as bytes allow them to be stored plainly or encrypted.

Tasks

  • I made sure the code is well commented, particularly hard-to-understand areas.
  • I made sure the repository-held documentation is changed accordingly.
  • I made sure the pull request title adheres to the conventional commit style (the subset used in the project can be found in tools/configs/chglog/config.yml).
  • I made sure to discuss its limitations such as threats to validity, vulnerability to mistake and misuse, robustness to invalidation of assumptions, resource requirements, ...

How has this been tested?

make test

Specify the platform(s) on which this was tested:

  • MacOS

@fredcarle fredcarle added area/crdt Related to the (Merkle) CRDT system refactor This issue specific to or requires *notable* refactoring of existing codebases and components labels Jun 7, 2024
@fredcarle fredcarle added this to the DefraDB v0.12 milestone Jun 7, 2024
@fredcarle fredcarle requested a review from a team June 7, 2024 20:18
@fredcarle fredcarle self-assigned this Jun 7, 2024
@fredcarle fredcarle force-pushed the fredcarle/refactor/i2696-counters-as-bytes branch 2 times, most recently from fc3e28a to 75f5522 Compare June 7, 2024 20:20
Copy link
Contributor

@islamaliev islamaliev left a comment

Choose a reason for hiding this comment

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

Looks good. I just have 1 question/preference to clarify before you merge.

@@ -120,7 +111,7 @@ func (c Counter[T]) Value(ctx context.Context) ([]byte, error) {
// WARNING: Incrementing an integer and causing it to overflow the int64 max value
// will cause the value to roll over to the int64 min value. Incremeting a float and
// causing it to overflow the float64 max value will act like a no-op.
func (c Counter[T]) Increment(ctx context.Context, value T) (*CounterDelta[T], error) {
func (c Counter) Increment(ctx context.Context, value []byte) (*CounterDelta, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

question: is it really necessary to change the API? I feel like changing CounterDelta to hold []byte instead of a number is enough to enable encryption. I'd prefer having strong types till as late as possible.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I didn't like needing an exact duplicate of the structure for the two types we support for counters. It would be like having a duplicate of the lww delta for every type it supports. I have an idea that will keep the strong typing from FieldValue. I'll see if it actually works.

Copy link
Collaborator Author

@fredcarle fredcarle Jun 10, 2024

Choose a reason for hiding this comment

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

FieldValue is only practical on save and quite inconvenient on merge. Maybe I can overlook the duplication in this case to help with simplifying the merge.

Copy link
Collaborator Author

@fredcarle fredcarle Jun 10, 2024

Choose a reason for hiding this comment

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

There are 3 ways of handling this.

  1. Use different deltas (generics) for every type
  2. Store the kind in the delta
  3. Pass the kind to NewCounter

1 and 2 are similar in that they both store type-related info in the data structure. 1 stores a differently named data structure and 2 stores extra bytes.
The disadvantage of 1 is that it requires maintaining more IPLD data structures and more types to support for coreblock.Block.
The disadvantage of 2 is that it store extra bytes and given that we need the field definition anyways to create the MerkleCounter, it doesn't make a lot of sense to store those extra bytes.
3 is equivalent to both 1 and 2 but depends on the field definition's kind that we pass along when we create the new counter. This is arguably the most type-safe way of doing things as it guarantees that we merge the proper type to the datastore on all code paths that call Merge.
One could think that keeping the concrete type as long as possible in the Increment path would be beneficial for strong typing but this falls apart when we look at the Merge path from a P2P sync which doesn't have access to that strong type safety.

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, looks like these is no perfect solution here. I'm fine then with keeping it as is.

Copy link
Member

@shahzadlone shahzadlone left a comment

Choose a reason for hiding this comment

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

LGTM

@fredcarle fredcarle force-pushed the fredcarle/refactor/i2696-counters-as-bytes branch from 75f5522 to ae40ad6 Compare June 10, 2024 16:48
@fredcarle fredcarle force-pushed the fredcarle/refactor/i2696-counters-as-bytes branch from ae40ad6 to 5b06bd5 Compare June 10, 2024 17:54
Copy link

codecov bot commented Jun 10, 2024

Codecov Report

Attention: Patch coverage is 73.33333% with 20 lines in your changes missing coverage. Please review.

Project coverage is 77.98%. Comparing base (ea68087) to head (5b06bd5).

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #2698      +/-   ##
===========================================
+ Coverage    77.97%   77.98%   +0.01%     
===========================================
  Files          308      308              
  Lines        23135    23125      -10     
===========================================
- Hits         18038    18032       -6     
+ Misses        3714     3711       -3     
+ Partials      1383     1382       -1     
Flag Coverage Δ
all-tests 77.98% <73.33%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Coverage Δ
internal/core/block/block.go 91.07% <100.00%> (-0.16%) ⬇️
internal/merkle/crdt/merklecrdt.go 84.38% <100.00%> (-3.43%) ⬇️
internal/core/crdt/errors.go 50.00% <0.00%> (-16.67%) ⬇️
internal/merkle/crdt/counter.go 66.67% <75.00%> (-6.67%) ⬇️
internal/core/crdt/ipld_union.go 75.81% <63.64%> (+1.83%) ⬆️
internal/core/crdt/counter.go 65.26% <72.09%> (-1.78%) ⬇️

... and 8 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ea68087...5b06bd5. Read the comment docs.

@fredcarle fredcarle merged commit 8d0c756 into sourcenetwork:develop Jun 10, 2024
38 of 39 checks passed
@fredcarle fredcarle deleted the fredcarle/refactor/i2696-counters-as-bytes branch June 10, 2024 18:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/crdt Related to the (Merkle) CRDT system refactor This issue specific to or requires *notable* refactoring of existing codebases and components
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Counter CRDT currently don't support encryption
3 participants