Skip to content

Latest commit

 

History

History
147 lines (115 loc) · 5.13 KB

064.md

File metadata and controls

147 lines (115 loc) · 5.13 KB

Scruffy Gingerbread Cormorant

High

Jailed finality providers can incorrectly receive voting power causing consensus instability

Summary

A failure to preserve finality provider jailed status during voting power distribution will cause critical consensus instability for the Babylon network as jailed validators incorrectly receive voting power allocation. This can lead to chain halts, consensus failures, and improper voting power distribution.

Root Cause

In x/finality/keeper/power_dist.go, when processing new delegations for finality providers that were previously unbonded to zero, the code fails to initialize the jailed status from the persistent KVStore data:

// This section creates new FinalityProviderDistInfo objects
newFP := k.loadFP(ctx, fpByBtcPkHex, fpBTCPKHex)
fpDistInfo := ftypes.NewFinalityProviderDistInfo(newFP)

// Only checks CURRENT jailing events instead of preserved state
if _, ok := jailedFPs[fpBTCPKHex]; ok {
    fpDistInfo.IsJailed = true
}
if _, ok := unjailedFPs[fpBTCPKHex]; ok {
    fpDistInfo.IsJailed = false
}

The code doesn't properly initialize fpDistInfo.IsJailed from the underlying newFP.Jailed status stored in the KVStore, causing jailed status to be lost when providers go through an unbonding/rebonding cycle.

Internal Pre-conditions

NA

External Pre-conditions

NA

Attack Path

  1. A finality provider is jailed for protocol violations
  2. All delegations to this provider are unbonded, dropping it from the voting power cache
  3. The provider receives new delegations in a block with no jailing events for it
  4. A new FinalityProviderDistInfo is created without initializing IsJailed from KVStore data
  5. The jailed provider appears in the voting power distribution with IsJailed = false
  6. During recordVotingPowerAndCache, this provider is incorrectly assigned voting power
  7. Consensus calculations include the voting power of providers that should be jailed

Impact

The Babylon network suffers a critical consensus vulnerability as jailed finality providers incorrectly receive voting power allocation. This leads to several severe consequences:

  1. Incorrect consensus calculations: The system allocates voting power to validators that should have none
  2. Chain halts: If a significant portion of voting power is incorrectly assigned to jailed validators, consensus may fail to reach the required thresholds
  3. Incorrect quorum calculations: With jailed finality providers improperly included, the 2/3+ quorum calculations become incorrect as assumption of 1/3 non malicious finality providers is no longer applicable.

PoC

  1. Initial state - 2 FP with voting power, 1 FP is jailed (simulated by stopping the docker) docker exec babylondnode0 /bin/sh -c 'babylond query finality finality-providers-at-height 121'
finality_providers:
- btc_pk_hex: a4c215a7ba83182047ed3126355b048f13781379f33ba928ddbaf7f6d192661b
  height: "121"
  highest_voted_height: 122
  jailed: false
  slashed_babylon_height: "0"
  slashed_btc_height: 0
  voting_power: "1000000"
- btc_pk_hex: b4c208aa145c4f806372133d147c64ddb7efc68f3babe70ce1896f072a9a09fe
  height: "121"
  highest_voted_height: 121
  jailed: false
  slashed_babylon_height: "0"
  slashed_btc_height: 0
  voting_power: "1000000"
pagination:
  next_key: null
  total: "0"

The jailed FP can be seen in list of finality-providers as jailed

- addr: bbn1p6p80hq8mv5yunmejy2ur72cfkmphvqf3l3l76
  btc_pk: bac7863bc10865e7c74c2e964e5abb8f3afa760935e4ee50559d42a089c9d574
  commission: "0.050000000000000000"
  description:
    details: ""
    identity: ""
    moniker: Finality Provider 0
    security_contact: ""
    website: ""
  height: "121"
  highest_voted_height: 85
  jailed: true
  pop:
    btc_sig: DKkCCwRbdcX3WslDPB2NDzdXLeSkOBxzdBJsPp9LNW7FGJFgdUwCAPmB/Nxe5eOeG+cldzcRRbmJ3ztQzCUPjw==
    btc_sig_type: BIP340
  slashed_babylon_height: "0"
  slashed_btc_height: 0
pagination:
  next_key: null
  total: "0"
  1. Unbond and then stake for jailed FP, the jailed FP appears in the voting distribution.
docker exec babylondnode0 /bin/sh -c 'babylond query finality finality-providers-at-height 155'
finality_providers:
- btc_pk_hex: a4c215a7ba83182047ed3126355b048f13781379f33ba928ddbaf7f6d192661b
  height: "155"
  highest_voted_height: 178
  jailed: false
  slashed_babylon_height: "0"
  slashed_btc_height: 0
  voting_power: "1000000"
- btc_pk_hex: b4c208aa145c4f806372133d147c64ddb7efc68f3babe70ce1896f072a9a09fe
  height: "155"
  highest_voted_height: 177
  jailed: false
  slashed_babylon_height: "0"
  slashed_btc_height: 0
  voting_power: "1000000"
- btc_pk_hex: bac7863bc10865e7c74c2e964e5abb8f3afa760935e4ee50559d42a089c9d574
  height: "155"
  highest_voted_height: 85
  jailed: false
  slashed_babylon_height: "0"
  slashed_btc_height: 0
  voting_power: "1000000"
pagination:
  next_key: null
  total: "0"

Jailed FP is included in voting power when it should not be. The voted height doesnot increase (as jailed FP are not allowed to vote) but the the jailed FP is included in the voting distribution.

Mitigation

No response