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

add sorting into AccumulateChanges and add a unit test for it #584

Merged
merged 4 commits into from
Dec 13, 2022

Conversation

jtremback
Copy link
Contributor

Description

This adds sorting to the AccumulateChanges function to stop relying on Go map iteration order.

Linked issues

Closes: #505

Type of change

Please delete options that are not relevant.

  • Non-breaking changes
  • New feature (adding functionality)
  • Breaking change (fix, feature or refactoring that changes existing functionality)
  • Requires state migrations
  • Proto files changes
  • Updates in store keepers or store keys
  • Changes in genesis (import/export)
  • Testing
  • Dependency management (updates dependencies, adds replace calls in go.mod, go mod tidy)
  • Documentation updates

How was the feature tested?

  • Unit tests
  • E2E tests
  • Integration tests/simulation
  • Custom difference tests

Issues and further questions

Is not tested under actual map iteration nondeterminism because this is hard to trigger intentionally. Still, the code is simple enough that this probably is ok.

Other information

Checklist:

Please delete options that are not relevant.

  • Relevant issus are linked
  • PR depends on other features: #<issue>
  • Other PRs depend on this feature: #<issue>
  • Tests are passing (make test)
  • make proto-gen was run (for changes in .proto files)
  • make proto-lint was run (for changes in .proto files)
  • PR satisfies closing criteria defined in issue (remove if not applicable or issue has no criteria)
  • Added iterators follow SDK pattern (IterateX(ctx sdk.Context, cb func(arg1, arg2) (stop bool)))
  • testutil/e2e/debug_test.go is up-to-date with additional or changed e2e test names
  • Documentation has been updated

@@ -30,6 +31,16 @@ func AccumulateChanges(currentChanges, newChanges []abci.ValidatorUpdate) []abci
for _, update := range m {
out = append(out, update)
}

// The list of tendermint updates should hash the same across all consensus nodes
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Credit to @danwt

Copy link
Contributor

Choose a reason for hiding this comment

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

Note that this is currently not a requirement of ABCI, but I do agree that it's safer to have determinism. :)

},
},
{
name: "two changes",
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this use case even possible?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yea, if it is accumulating updates from several blocks

Copy link
Contributor

Choose a reason for hiding this comment

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

They will be overwritten here, but I don't see a problem with extra testing.

@@ -30,6 +31,16 @@ func AccumulateChanges(currentChanges, newChanges []abci.ValidatorUpdate) []abci
for _, update := range m {
out = append(out, update)
}

// The list of tendermint updates should hash the same across all consensus nodes
Copy link
Contributor

Choose a reason for hiding this comment

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

Note that this is currently not a requirement of ABCI, but I do agree that it's safer to have determinism. :)

@danwt
Copy link
Contributor

danwt commented Dec 13, 2022

I would add a comment saying that this is not strictly needed because the updates are never committed to the store at the end of the block, and Tendermint doesnt' care about the order.

@jtremback
Copy link
Contributor Author

I would add a comment saying that this is not strictly needed because the updates are never committed to the store at the end of the block, and Tendermint doesnt' care about the order.

The only reason this doesn't persist past the end of the block is because we happen to be sending updates each block. In theory, the fact that we send updates each block was supposed to be temporary. So to work as intended the sort is needed.

@jtremback jtremback merged commit 3e339ea into main Dec 13, 2022
@jtremback jtremback deleted the fix-determinism-accumulate-changes branch December 13, 2022 22:16
@danwt
Copy link
Contributor

danwt commented Dec 14, 2022

The only reason this doesn't persist past the end of the block is because we happen to be sending updates each block. In theory, the fact that we send updates each block was supposed to be temporary. So to work as intended the sort is needed.

By sending you mean sending from the consumer app to the consumer TM instance, right?

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.

Map iteration non determinism in consumer AccumulateChanges
5 participants