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

Slashable FP offence won't be slashed #715

Open
maurolacy opened this issue Jul 16, 2024 · 0 comments
Open

Slashable FP offence won't be slashed #715

maurolacy opened this issue Jul 16, 2024 · 0 comments
Labels

Comments

@maurolacy
Copy link
Contributor

maurolacy commented Jul 16, 2024

Summary of Bug

Taking a look at the slashing logic in

// if this finality provider has also signed canonical block, slash it
canonicalSig, err := ms.GetSig(ctx, req.BlockHeight, fpPK)
if err == nil {
//set canonial sig
evidence.CanonicalFinalitySig = canonicalSig
// slash this finality provider, including setting its voting power to
// zero, extracting its BTC SK, and emit an event
ms.slashFinalityProvider(ctx, req.FpBtcPk, evidence)
}

noticed that a given FP will be slashed only when signing the canonical (i.e. indexed) block, and an alternative (fork) block at the same height.

This implies that a malicious FP could sign and submit any number of non-canonical block signatures for a given height. As long as he doesn’t sign and submit the canonical block signature as well, he won’t be slashed.

This is because slashing currently depends on a FP signing both, an offending / fork block, AND the canonical (i.e. indexed) block.

Perhaps the code / logic can be changed here. If a given FP signs two different blocks at any given height (independently of if one is the canonical or not), he’s slashed.

So, slash when signing both the canonical and other block, and also when signing two other blocks.

This seems easy to fix: If Evidence already exists in the store for this FP at that height, this is a double sign.

Update: Just noticed that the detection of double signing of forks is slightly below in the code

// if this finality provider has signed the canonical block before,
// slash it via extracting its secret key, and emit an event
if ms.HasEvidence(ctx, req.FpBtcPk, req.BlockHeight) {
// the finality provider has voted for a fork before!
// If this evidence is at the same height as this signature, slash this finality provider
// get evidence
evidence, err := ms.GetEvidence(ctx, req.FpBtcPk, req.BlockHeight)
if err != nil {
panic(fmt.Errorf("failed to get evidence despite HasEvidence returns true"))
}
// set canonical sig to this evidence
evidence.CanonicalFinalitySig = req.FinalitySig
ms.SetEvidence(ctx, evidence)
// slash this finality provider, including setting its voting power to
// zero, extracting its BTC SK, and emit an event
ms.slashFinalityProvider(ctx, req.FpBtcPk, evidence)
}

The bug is then that, since neither fork is the canonical block, this code is never reached (the if above always returns without error).

Version

Latest.

Steps to Reproduce

N/A.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants