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

[consensus] Disable multi leader per round in universal committer #18206

Merged
merged 5 commits into from
Jun 13, 2024

Conversation

arun-koshy
Copy link
Contributor

@arun-koshy arun-koshy commented Jun 12, 2024

Description

On the boundaries of Leader Schedule change it is possible to elect a new leader for the same round resulting in multiple commits for the same round. This was unintended output from consensus as we have set the parameters to only commit 1 leader per round. Sui also only expects one commit per round, because of this the second commit of the same round is ignored by consensus handler. This led to an error in simtests where the EndOfPublish transaction was part of this ignored commit and we could not form a quorum to close the epoch without this node.

Changes

  • Explicitly set number of leaders per round to 1 for Mysticeti commits. I wanted to try and maintain this but it would be a much more intrusive change and we will probably have to do a larger refactor to fully support it anyways, so better off doing the cleaner mitigation for now.
  • Pass back the block that the transaction was included in as part of the tx acknowledgment and include that in the logging to help with debugging future issues.
  • Also a minor change to print if all tests pass during simtest seed-search

Test plan

❯ scripts/simtest/seed-search.py simtest --test test_reconfig_with_committee_change_basic --num-seeds 1000
    Updating git repository `https://github.com/MystenLabs/mysten-sim.git`
   Compiling consensus-core v0.1.0 (/Users/arunkoshy/Documents/GitHub/sui/consensus/core)
   ...
   All tests passed successfully!
  Killing child processes
  [1]    391 killed     scripts/simtest/seed-search.py simtest --test  --num-seeds 1000

Release notes

  • Protocol: Version 50 - Explicitly set number of leaders per round to 1 for Mysticeti commits
  • Nodes (Validators and Full nodes):
  • Indexer:
  • JSON-RPC:
  • GraphQL:
  • CLI:
  • Rust SDK:

Copy link

vercel bot commented Jun 12, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
sui-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 13, 2024 3:15pm
3 Ignored Deployments
Name Status Preview Comments Updated (UTC)
multisig-toolkit ⬜️ Ignored (Inspect) Visit Preview Jun 13, 2024 3:15pm
sui-kiosk ⬜️ Ignored (Inspect) Visit Preview Jun 13, 2024 3:15pm
sui-typescript-docs ⬜️ Ignored (Inspect) Visit Preview Jun 13, 2024 3:15pm

Copy link
Contributor

@akichidis akichidis left a comment

Choose a reason for hiding this comment

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

Great find and thanks for the fix @arun-koshy ! If indeed you won't try to do accounting based on the committer index then this PR looks good

Personally I would like us to have though a test that will specifically test this case - when schedule changes and different leader that the last_decided is elected. Since we do have the flag we can confirm that with the flag enabled/disabled we get either a double commit for same round and single with the fix. Do you believe we can add this?

crates/sui-core/src/mysticeti_adapter.rs Show resolved Hide resolved
@@ -172,7 +174,7 @@ impl TransactionClient {

/// Submits a list of transactions to be sequenced. The method returns when all the transactions have been successfully included
/// to next proposed blocks.
pub async fn submit(&self, transactions: Vec<Vec<u8>>) -> Result<(), ClientError> {
pub async fn submit(&self, transactions: Vec<Vec<u8>>) -> Result<BlockRef, ClientError> {
Copy link
Contributor

Choose a reason for hiding this comment

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

There is a small edge case here as we don't have a guarantee that all the provided transactions will be included in the same block - they might span across multiple blocks. So based on the current functionality this will return the BlockRef of the transactions that got included in the last block. We can ignore for now as this will consider only the soft bundle transactions, but maybe leave a TODO to potentially refactor in the future

Copy link
Contributor Author

@arun-koshy arun-koshy Jun 13, 2024

Choose a reason for hiding this comment

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

Good point! Left a todo but wanted to ensure my understanding is correct here, if we have too many transactions for one block we will acknowledge that the transactions were included in 'Block A' and then create a new TransactionGuard with the remaining transactions. The remaining transactions should get included in the subsequent block(s) but their acknowledgment will not be received by Sui? So like you said Sui will print out that all transactions were included in 'Block A' but may span 'Block B, C, etc.'

Copy link
Contributor

Choose a reason for hiding this comment

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

So on the above example the Block A transactions will not get acknowledged as the ack channel will only get passed with the last set of transactions. Let's assume that the transactions are enough to span across three blocks, Block A, B & C . The ack channel will only be provided to the closure that performs the acknowledgment only when the last transactions have been included to Block C. So the last block is the one that performs the acknowledgment

Copy link
Member

Choose a reason for hiding this comment

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

Personally I think just returning the last block is fine. When the last block is committed, blocks before should usually be committed. If we try to be precise here, we will need to return the mapping between transactions and blocks.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah I guess we could be as precise/less precise want to. As I said, this only concerns soft bundles so wouldn't prioritise any time soon if needs to change.

consensus/core/src/universal_committer.rs Outdated Show resolved Hide resolved
Copy link
Contributor Author

@arun-koshy arun-koshy left a comment

Choose a reason for hiding this comment

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

Spoke offline with the team and decided to stick with the simpler solution for now and will investigate multi leader per round in the future. Also added some tests for this case

@@ -172,7 +174,7 @@ impl TransactionClient {

/// Submits a list of transactions to be sequenced. The method returns when all the transactions have been successfully included
/// to next proposed blocks.
pub async fn submit(&self, transactions: Vec<Vec<u8>>) -> Result<(), ClientError> {
pub async fn submit(&self, transactions: Vec<Vec<u8>>) -> Result<BlockRef, ClientError> {
Copy link
Contributor Author

@arun-koshy arun-koshy Jun 13, 2024

Choose a reason for hiding this comment

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

Good point! Left a todo but wanted to ensure my understanding is correct here, if we have too many transactions for one block we will acknowledge that the transactions were included in 'Block A' and then create a new TransactionGuard with the remaining transactions. The remaining transactions should get included in the subsequent block(s) but their acknowledgment will not be received by Sui? So like you said Sui will print out that all transactions were included in 'Block A' but may span 'Block B, C, etc.'

consensus/core/src/universal_committer.rs Outdated Show resolved Hide resolved
@arun-koshy arun-koshy enabled auto-merge (squash) June 13, 2024 15:19
@arun-koshy arun-koshy merged commit 81d0217 into main Jun 13, 2024
47 checks passed
@arun-koshy arun-koshy deleted the ak/simtest-investigation branch June 13, 2024 16:34
tx-tomcat pushed a commit to tx-tomcat/sui-network that referenced this pull request Jul 29, 2024
…stenLabs#18206)

## Description 

On the boundaries of Leader Schedule change it is possible to elect a
new leader for the same round resulting in multiple commits for the same
round. This was unintended output from consensus as we have set the
parameters to only commit 1 leader per round. Sui also only expects one
commit per round, because of this the second commit of the same round is
ignored by consensus handler. This led to an error in simtests where the
`EndOfPublish` transaction was part of this ignored commit and we could
not form a quorum to close the epoch without this node.

Changes
- Explicitly set number of leaders per round to 1 for Mysticeti commits.
I wanted to try and maintain this but it would be a much more intrusive
change and we will probably have to do a larger refactor to fully
support it anyways, so better off doing the cleaner mitigation for now.
- Pass back the block that the transaction was included in as part of
the tx acknowledgment and include that in the logging to help with
debugging future issues.
- Also a minor change to print if all tests pass during simtest
seed-search

## Test plan 

```
❯ scripts/simtest/seed-search.py simtest --test test_reconfig_with_committee_change_basic --num-seeds 1000
    Updating git repository `https://github.com/MystenLabs/mysten-sim.git`
   Compiling consensus-core v0.1.0 (/Users/arunkoshy/Documents/GitHub/sui/consensus/core)
   ...
   All tests passed successfully!
  Killing child processes
  [1]    391 killed     scripts/simtest/seed-search.py simtest --test  --num-seeds 1000
```

---

## Release notes

- [X] Protocol: Version 50 - Explicitly set number of leaders per round
to 1 for Mysticeti commits
- [ ] Nodes (Validators and Full nodes): 
- [ ] Indexer: 
- [ ] JSON-RPC: 
- [ ] GraphQL: 
- [ ] CLI: 
- [ ] Rust SDK:

---------

Co-authored-by: Mark Logan <mark@mystenlabs.com>
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.

4 participants