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

feat: block production misbehavior detection #1071

Merged
merged 53 commits into from
Oct 22, 2024
Merged

Conversation

faultytolly
Copy link
Contributor

@faultytolly faultytolly commented Sep 11, 2024

PR Standards

#1070

https://www.notion.so/dymension/ADR-x-generic-Dymint-fraud-handling-7425a9ef065b458c989404c42be6a6cd
https://www.notion.so/dymension/ADR-x-STF-fraud-detection-105a4a51f86a80f88225da364d798ddd
https://www.notion.so/dymension/ADR-x-timestamp-fraud-detection-105a4a51f86a80478c68d385b254459e

https://www.notion.so/dymension/ADR-L2-Block-Production-Misbehavior-10da4a51f86a806ab08cf0a4e1cecc37

Opening a pull request should be able to meet the following requirements

--

PR naming convention: https://hackmd.io/@nZpxHZ0CT7O5ngTp0TP9mg/HJP_jrm7A


Close #XXX

<-- Briefly describe the content of this pull request -->

For Author:

  • Targeted PR against correct branch
  • included the correct type prefix in the PR title
  • Linked to Github issue with discussion and accepted design
  • Targets only one github issue
  • Wrote unit and integration tests
  • All CI checks have passed
  • Added relevant godoc comments

For Reviewer:

  • confirmed the correct type prefix in the PR title
  • Reviewers assigned
  • confirmed all author checklist items have been addressed

After reviewer approval:

  • In case targets main branch, PR should be squashed and merged.
  • In case PR targets a release branch, PR should be rebased.

fraud/handler.go Fixed Show fixed Hide fixed
@@ -171,8 +180,8 @@
}()

// P2P Sync. Subscribe to P2P received blocks events
go uevent.MustSubscribe(ctx, m.Pubsub, "applyGossipedBlocksLoop", p2p.EventQueryNewGossipedBlock, m.onReceivedBlock, m.logger)
go uevent.MustSubscribe(ctx, m.Pubsub, "applyBlockSyncBlocksLoop", p2p.EventQueryNewBlockSyncBlock, m.onReceivedBlock, m.logger)
go uevent.MustSubscribe(ctx, m.Pubsub, "applyGossipedBlocksLoop", p2p.EventQueryNewGossipedBlock, m.OnReceivedBlock, m.logger)

Check notice

Code scanning / CodeQL

Spawning a Go routine Note

Spawning a Go routine may be a possible source of non-determinism
go uevent.MustSubscribe(ctx, m.Pubsub, "applyGossipedBlocksLoop", p2p.EventQueryNewGossipedBlock, m.onReceivedBlock, m.logger)
go uevent.MustSubscribe(ctx, m.Pubsub, "applyBlockSyncBlocksLoop", p2p.EventQueryNewBlockSyncBlock, m.onReceivedBlock, m.logger)
go uevent.MustSubscribe(ctx, m.Pubsub, "applyGossipedBlocksLoop", p2p.EventQueryNewGossipedBlock, m.OnReceivedBlock, m.logger)
go uevent.MustSubscribe(ctx, m.Pubsub, "applyBlockSyncBlocksLoop", p2p.EventQueryNewBlockSyncBlock, m.OnReceivedBlock, m.logger)

Check notice

Code scanning / CodeQL

Spawning a Go routine Note

Spawning a Go routine may be a possible source of non-determinism
types/validation.go Fixed Show fixed Hide fixed
types/validation.go Fixed Show fixed Hide fixed
@faultytolly faultytolly marked this pull request as ready for review September 17, 2024 13:32
@faultytolly faultytolly requested a review from a team as a code owner September 17, 2024 13:32
@danwt
Copy link
Contributor

danwt commented Sep 18, 2024

Please link the adr(s) and issue(s)

@danwt danwt requested review from srene and danwt September 19, 2024 10:44
Copy link
Contributor

@danwt danwt left a comment

Choose a reason for hiding this comment

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

Looking good

Aside from comments on the code, the main thing here

  • please over document everything wrt. security implications
  • what is envisioned for fraud handler?
  • dependence on accuracy of proposer addr

The fraud handler is going to need to check that everything is actually a fraud, rather than operator mistake (e.g. in wrong app-hash case) and that the fraud came from a particular slashable person. How do you envision that given the currently supplied data?

@@ -19,6 +19,18 @@ import (
// default minimum block max size allowed. not specific reason to set it to 10K, but we need to avoid no transactions can be included in a block.
const minBlockMaxBytes = 10000

type ExecutorI interface {
Copy link
Contributor

Choose a reason for hiding this comment

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

dont need I suffix in go

Copy link
Contributor

@danwt danwt Sep 19, 2024

Choose a reason for hiding this comment

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

and interfaces should be defined in consumer package

Copy link
Contributor

Choose a reason for hiding this comment

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

nvm it is already

block/fraud.go Show resolved Hide resolved
block/fraud.go Outdated Show resolved Hide resolved
block/manager.go Outdated Show resolved Hide resolved
block/manager_test.go Outdated Show resolved Hide resolved
block/manager_test.go Show resolved Hide resolved
block/block.go Outdated Show resolved Hide resolved
block/block.go Outdated Show resolved Hide resolved
types/validation_test.go Outdated Show resolved Hide resolved
types/errors.go Outdated Show resolved Hide resolved
@danwt danwt changed the title feat: include fraud detection handling feat: detect future timestamp and STF frauds Sep 19, 2024
fraud/types.go Outdated Show resolved Hide resolved
block/block.go Outdated Show resolved Hide resolved
types/errors.go Outdated Show resolved Hide resolved
types/validation.go Outdated Show resolved Hide resolved
block/fraud.go Show resolved Hide resolved
Comment on lines +23 to +25
func (f FreezeHandler) HandleFault(ctx context.Context, fault error) {
uevent.MustPublish(ctx, f.m.Pubsub, &events.DataHealthStatus{Error: fault}, events.HealthStatusList)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

what is the intended behaviour?
This will just log the error string? what about dumping to file etc, is that coming in another pr?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I never heard about those features

Copy link
Contributor Author

Choose a reason for hiding this comment

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

in theory this is what was commented, to set the node freeze by sending the event.

Copy link
Contributor

Choose a reason for hiding this comment

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

how does sending this event 'freeze' anything? what does freeze even mean?

Comment on lines +128 to +130
if c.Height != header.Height {
return NewErrInvalidBlockHeightFraud(c.Height, header.Height)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

invalid block height fraud is a bit undefined IMO
this is an invalid commit fraud

Copy link
Contributor Author

Choose a reason for hiding this comment

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

let me know your preferred name

Copy link
Contributor

Choose a reason for hiding this comment

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

why is there ErrFraudHeightMismatch and ErrInvalidBlockHeightFraud?
it's not clear what the intention is so hard to choose a name

invalid height is fine as a name but why are there two?

And the invalid height is only relevant when comparing to DA batch surely?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

One is for the header, the other from the commit.

Comment on lines 123 to +125
func (c *Commit) ValidateWithHeader(proposerPubKey tmcrypto.PubKey, header *Header) error {
if err := c.ValidateBasic(); err != nil {
return err
return NewErrInvalidSignatureFraud(err)
Copy link
Contributor

Choose a reason for hiding this comment

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

none of the frauds returned here will be caught in p2p case right? because there is no handler

dymint/p2p/validator.go

Lines 83 to 86 in 88ba1fe

if err := gossipedBlock.Validate(v.proposerGetter.GetProposerPubKey()); err != nil {
v.logger.Error("Failed to validate gossiped block.", "height", gossipedBlock.Block.Header.Height, "error", err)
return false
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it will when attemptApplyCachedBlocks

Copy link
Contributor

Choose a reason for hiding this comment

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

but they are already rejected at p2p level by this code? so they will never reach it

Comment on lines +139 to +142
type ErrLastHeaderHashMismatch struct {
Expected [32]byte
LastHeaderHash [32]byte
}
Copy link
Contributor

Choose a reason for hiding this comment

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

don't you need more info to validate this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did not heard that the error must contain all the info to validate. Is that documented?

Copy link
Contributor

Choose a reason for hiding this comment

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

I've asked @omritoptix for some confirmation that nothing was changed but I believe the original intention was that the frauds have to be actionable, so yes

types/errors.go Show resolved Hide resolved
types/errors.go Outdated Show resolved Hide resolved
Copy link
Contributor

@danwt danwt left a comment

Choose a reason for hiding this comment

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

Looks like the scope has drifted a bit from what I originally understood

I've posted on slack to get this confirmed

https://dymensionworkspace.slack.com/archives/C07HV4329LJ/p1729509868648489

Comment on lines +23 to +25
func (f FreezeHandler) HandleFault(ctx context.Context, fault error) {
uevent.MustPublish(ctx, f.m.Pubsub, &events.DataHealthStatus{Error: fault}, events.HealthStatusList)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

how does sending this event 'freeze' anything? what does freeze even mean?

types/validation.go Show resolved Hide resolved
Comment on lines 123 to +125
func (c *Commit) ValidateWithHeader(proposerPubKey tmcrypto.PubKey, header *Header) error {
if err := c.ValidateBasic(); err != nil {
return err
return NewErrInvalidSignatureFraud(err)
Copy link
Contributor

Choose a reason for hiding this comment

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

but they are already rejected at p2p level by this code? so they will never reach it

Comment on lines +75 to 78
nextHeight := state.NextHeight()
if b.Header.Height != nextHeight {
return NewErrFraudHeightMismatch(state.NextHeight(), b.Header.Height, b)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

ok can you please document that? defensive code is really hard to understand

Comment on lines +139 to +142
type ErrLastHeaderHashMismatch struct {
Expected [32]byte
LastHeaderHash [32]byte
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I've asked @omritoptix for some confirmation that nothing was changed but I believe the original intention was that the frauds have to be actionable, so yes

Comment on lines +128 to +130
if c.Height != header.Height {
return NewErrInvalidBlockHeightFraud(c.Height, header.Height)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

why is there ErrFraudHeightMismatch and ErrInvalidBlockHeightFraud?
it's not clear what the intention is so hard to choose a name

invalid height is fine as a name but why are there two?

And the invalid height is only relevant when comparing to DA batch surely?

types/validation.go Outdated Show resolved Hide resolved
@omritoptix omritoptix merged commit 9aef1d0 into main Oct 22, 2024
6 checks passed
@omritoptix omritoptix deleted the feat/adr-fraud-handling branch October 22, 2024 13:20
@omritoptix omritoptix linked an issue Oct 26, 2024 that may be closed by this pull request
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants