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

Adds Prepared Certificates to ensure Istanbul liveness #366

Merged
merged 134 commits into from
Sep 24, 2019

Conversation

trianglesphere
Copy link
Contributor

@trianglesphere trianglesphere commented Jul 30, 2019

Description

This PR removes the locking mechanism in IBFT and adds:

  • Optional PREPARED certificates to ROUND CHANGE messages, which are included when the node has seen 2F+1 PREPARE/COMMIT messages or a PREPARED certificate for this sequence.
  • ROUND CHANGE certificates to PREPREPARE messages, which are required for rounds > 0. If any of the messages in this certificate contain a PREPARED certificate, the PREPREPARE must propose the PREPARED block with the highest round number.

In addition, this overhauls the round change logic:

  • On timeout or f+1 round change messages, transition to StateWaitingForNewRound and if the new desired round (one past the timeout round or the RC message view), it will set the new desired round, send a round change message for the desired round, set a timeout for the desired round. (All these actions done in core.waitForDesiredRound)
  • On quorum RC messages or a round change certificate where the round associated with the messages is >= desired round, start a new round at the desired round and proceed with the normal consensus protocol.

This addresses a bug in which F nodes could lock onto block A, while 2F nodes could lock onto block B, causing a permanent loss of liveness.

This PR also changes how the randomness source is verified to fix an issues with validators correctly re-proposing blocks.

Tested

Unit tests in consensus pass.
Testnets for old versions were working, going to spin up a testnet with latest.

Testing Changes:

  • Changing the round change message payload is needed to match what validators
    actually do.
  • errIgnored -> nil exists b/c I no longer return errIgnored from handleRoundChange
  • Check for consistent commits in TestCommitsBlockAfterRoundChange and TestPreparedCertificatePersistsThroughRoundChange because prepared certificates are generated, but no single node has committed, so it is fine to commit a different block than the original block from validator 0 as long as there is not a fork.

Other changes

  • Verify the CommittedSeal included in COMMIT messages
  • Adds create empty block with empty randomness. Used for a null value when creating a prepared certificate.
  • Lots of testing changes, logging + match other changes
  • Removes src instanbul.Validator from being passed around endlessly
  • Namespaces istanbul types
  • BLS changes merged in (some slight changes in verifying commit seal)
  • More logging. Testing only shows core.current is nil in startNewRound and not in the message handlers, but I still included nil checks there.

Related issues

Backwards compatibility

No.

Joshua Gutow added 3 commits September 5, 2019 15:48
Edge case where prepared view could be round 0, but the prepared
certificate would never be recorded as the largest prepared
certificate seen in the round change certificate.
.circleci/config.yml Outdated Show resolved Hide resolved
consensus/istanbul/core/backlog.go Outdated Show resolved Hide resolved
consensus/istanbul/core/commit.go Show resolved Hide resolved
consensus/istanbul/core/commit.go Show resolved Hide resolved
consensus/istanbul/core/core.go Outdated Show resolved Hide resolved
@@ -33,8 +41,9 @@ func (c *core) handleRequest(request *istanbul.Request) error {
logger.Trace("handleRequest", "number", request.Proposal.Number(), "hash", request.Proposal.Hash())

c.current.pendingRequest = request
if c.state == StateAcceptRequest {
c.sendPreprepare(request)
// Must go through startNewRound to send a proposal that matches the round change certificate if not on the first round.
Copy link
Contributor

Choose a reason for hiding this comment

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

In that case, maybe change the comment to Must go through startNewRound to send proposals for round > 0?

}

// Verify ROUND CHANGE message is for a proper view
// TODO(joshua): May be able to relax to the proposal is >= than the round change message.
Copy link
Contributor

Choose a reason for hiding this comment

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

I still don't understand. Wouldn't the proposal need to be for the view that the round change certificate moves us to?

if err := c.verifyPreparedCertificate(roundChange.PreparedCertificate); err != nil {
return err
}
// The prepared certificate with the highest round number carries the proposal we must use
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you elaborate in the comment why the prepared certificate may have a previous view?

}
// The prepared certificate with the highest round number carries the proposal we must use
preparedView := roundChange.PreparedCertificate.View()
if preparedView != nil && preparedView.Round.Cmp(maxRound) > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

What happens if the prepared certificate has a later view than the round change messages?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch. My feeling is that we should reject the round change certificate for having an invalid round change message. I'd probably also need to change handleRoundChange to verify the prepared certificate view against the round change message view.

consensus/istanbul/core/roundchange.go Show resolved Hide resolved
Joshua Gutow added 12 commits September 6, 2019 09:57
Longer name, but more accurate.
This builds a logger with the current sequence, round, and state.
Explains why we need to use the proposal from the prepared certificate
with the largest round number.
Reject RC messages where the prepared view is greater than the
proposal view.
Joshua Gutow added 2 commits September 6, 2019 11:25
Reading through CalcProposer and LastProposal, the last proposer
is the proposer of the last block, and calc proposer does not
rely on the current proposer, thus I think it's fine if there
is a large jump in round number in this function.
Copy link
Contributor

@asaj asaj left a comment

Choose a reason for hiding this comment

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

Wow, this is a big one, nice work 👍

Please wait until @timmoreton or @kevjue finish reviewing before merging

@@ -96,6 +95,21 @@ type core struct {
consensusTimer metrics.Timer
}

// Appends the current view and state to the given context.
func (c *core) NewLogger(ctx ...interface{}) log.Logger {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice!

c.sendCommitForOldBlock(preprepare.View, preprepare.Proposal.Hash())
return nil
}
}
// Already in the next round b/c handleRoundChangeCertificate moves us to the next round.
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm okay I think I was just confused by the comment, consider making it more verbose/explicit

@trianglesphere
Copy link
Contributor Author

@timmoreton @asaj Are you ready yet?

@asaj asaj merged commit 0344742 into master Sep 24, 2019
kevjue added a commit that referenced this pull request Sep 24, 2019
* Adds Prepared Certificates to ensure Istanbul liveness (#366)

* Check message address against signature (#477)

* Check signing validator's address matches msg address

* Add comments about use of sig data in tests

* Try fix Circle build test failures

* Try fix Circle build test failures, take 2
kevjue added a commit that referenced this pull request Sep 24, 2019
* Add precompiles to access validator set (#441)

* set max gas to double of the charged gas for the 'intrinsic' smart contract calls (#472)

* set max gas to double of the charged gas for the 'intrinsic' evm operations

* addressed PR comments

* addressed pr comment

* Adds Prepared Certificates to ensure Istanbul liveness (#366)

* Check message address against signature (#477)

* Check signing validator's address matches msg address

* Add comments about use of sig data in tests

* Try fix Circle build test failures

* Try fix Circle build test failures, take 2
kevjue added a commit that referenced this pull request Sep 25, 2019
* contract_comm/currency/currency.go

* fixed the txn price-sorted min-heap

* merge master (#490)

* Add precompiles to access validator set (#441)

* set max gas to double of the charged gas for the 'intrinsic' smart contract calls (#472)

* set max gas to double of the charged gas for the 'intrinsic' evm operations

* addressed PR comments

* addressed pr comment

* Adds Prepared Certificates to ensure Istanbul liveness (#366)

* Check message address against signature (#477)

* Check signing validator's address matches msg address

* Add comments about use of sig data in tests

* Try fix Circle build test failures

* Try fix Circle build test failures, take 2
kevjue added a commit that referenced this pull request Sep 25, 2019
* added new option --use-in-memory-discovery-table

* merge master (#489)

* Adds Prepared Certificates to ensure Istanbul liveness (#366)

* Check message address against signature (#477)

* Check signing validator's address matches msg address

* Add comments about use of sig data in tests

* Try fix Circle build test failures

* Try fix Circle build test failures, take 2
kevjue added a commit that referenced this pull request Sep 25, 2019
* Check message address against signature (#477)

* Check signing validator's address matches msg address

* Add comments about use of sig data in tests

* Try fix Circle build test failures

* Try fix Circle build test failures, take 2

* tx price heap fix (#471)

* contract_comm/currency/currency.go

* fixed the txn price-sorted min-heap

* merge master (#490)

* Add precompiles to access validator set (#441)

* set max gas to double of the charged gas for the 'intrinsic' smart contract calls (#472)

* set max gas to double of the charged gas for the 'intrinsic' evm operations

* addressed PR comments

* addressed pr comment

* Adds Prepared Certificates to ensure Istanbul liveness (#366)

* Check message address against signature (#477)

* Check signing validator's address matches msg address

* Add comments about use of sig data in tests

* Try fix Circle build test failures

* Try fix Circle build test failures, take 2

* added new option --use-in-memory-discovery-table (#479)

* added new option --use-in-memory-discovery-table

* merge master (#489)

* Adds Prepared Certificates to ensure Istanbul liveness (#366)

* Check message address against signature (#477)

* Check signing validator's address matches msg address

* Add comments about use of sig data in tests

* Try fix Circle build test failures

* Try fix Circle build test failures, take 2

* Allow v4/v5 on a bootnode simultaneously, allow mobile to use discv5 (#454)

* changes for isolating celo networks

* changes to get unit tests working

* changes to add salt in the discovery packets

* removed checking for the ip address when handling a reply

* added ping-ip-from-packet option to bootnode

* for handling expected replies, don't filter on expected sender ip address if --pingIPFromPacket is used

* Add v4 flag

* Add unhandled and quicken docker builds

* Add salt & logs

* Add v4 flag

* Add PeerDiscovery to mobile node config

* Remove logs

* Remove hardcoded bootnodes

* Add salt & turn on discv5

* Delete hardcoded eth bootnodes

* Make Discoveryv5 configurable

* Lint

* Add comment to bootnode v4/v5 handling

* Change PeerDiscovery -> NoDiscovery

* Remove mobile geth no discovery

* Reduce istanbul default timeout, cap exp backoff (#475)

* Reduce istanbul default timeout, cap exp backoff

* Ensure round 0 timeout factors in block period

* Sanitize logs (#495)

* Change registry lookup and infrastructure lookup error logs to debug level

* Sanitize logs regarding registry deployment

* Change empty abi logging and comment

* Lower log level from error to warning for potentially outdated istanbul messages

* Change back to an error message

* Add input length checks for precompiled contracts (#476)

* add input length checks

* check exact input length. add a new error for input length. check input in a few more places

* add tests that verify the input-length checks for contracts that don't require an evm instance

* fix formatting

* add comments to explain input length checks

* run the formatter

* e2e transfer test was failing because it passes in a transaction options object, making the input larger than 96 bytes

* e2e tests have revealed that our precompiled contracts need to be tolerant of inputs that are longer than the bytes that are actually read
kevjue pushed a commit that referenced this pull request Sep 26, 2019
* Log on ValidatorElections

* merge master (#496)

* Check message address against signature (#477)

* Check signing validator's address matches msg address

* Add comments about use of sig data in tests

* Try fix Circle build test failures

* Try fix Circle build test failures, take 2

* tx price heap fix (#471)

* contract_comm/currency/currency.go

* fixed the txn price-sorted min-heap

* merge master (#490)

* Add precompiles to access validator set (#441)

* set max gas to double of the charged gas for the 'intrinsic' smart contract calls (#472)

* set max gas to double of the charged gas for the 'intrinsic' evm operations

* addressed PR comments

* addressed pr comment

* Adds Prepared Certificates to ensure Istanbul liveness (#366)

* Check message address against signature (#477)

* Check signing validator's address matches msg address

* Add comments about use of sig data in tests

* Try fix Circle build test failures

* Try fix Circle build test failures, take 2

* added new option --use-in-memory-discovery-table (#479)

* added new option --use-in-memory-discovery-table

* merge master (#489)

* Adds Prepared Certificates to ensure Istanbul liveness (#366)

* Check message address against signature (#477)

* Check signing validator's address matches msg address

* Add comments about use of sig data in tests

* Try fix Circle build test failures

* Try fix Circle build test failures, take 2

* Allow v4/v5 on a bootnode simultaneously, allow mobile to use discv5 (#454)

* changes for isolating celo networks

* changes to get unit tests working

* changes to add salt in the discovery packets

* removed checking for the ip address when handling a reply

* added ping-ip-from-packet option to bootnode

* for handling expected replies, don't filter on expected sender ip address if --pingIPFromPacket is used

* Add v4 flag

* Add unhandled and quicken docker builds

* Add salt & logs

* Add v4 flag

* Add PeerDiscovery to mobile node config

* Remove logs

* Remove hardcoded bootnodes

* Add salt & turn on discv5

* Delete hardcoded eth bootnodes

* Make Discoveryv5 configurable

* Lint

* Add comment to bootnode v4/v5 handling

* Change PeerDiscovery -> NoDiscovery

* Remove mobile geth no discovery

* Reduce istanbul default timeout, cap exp backoff (#475)

* Reduce istanbul default timeout, cap exp backoff

* Ensure round 0 timeout factors in block period

* Sanitize logs (#495)

* Change registry lookup and infrastructure lookup error logs to debug level

* Sanitize logs regarding registry deployment

* Change empty abi logging and comment

* Lower log level from error to warning for potentially outdated istanbul messages

* Change back to an error message

* Add input length checks for precompiled contracts (#476)

* add input length checks

* check exact input length. add a new error for input length. check input in a few more places

* add tests that verify the input-length checks for contracts that don't require an evm instance

* fix formatting

* add comments to explain input length checks

* run the formatter

* e2e transfer test was failing because it passes in a transaction options object, making the input larger than 96 bytes

* e2e tests have revealed that our precompiled contracts need to be tolerant of inputs that are longer than the bytes that are actually read
@trianglesphere trianglesphere deleted the trianglesphere/istanbul-liveness branch October 8, 2019 00:22
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.

Devs SBAT be sure of Istanbul liveness
6 participants