ouroboros-consensus-protocol-0.9.0.2: Cardano consensus protocols
Safe HaskellSafe-Inferred
LanguageHaskell2010

Ouroboros.Consensus.Protocol.Praos.Common

Contents

Description

Various things common to iterations of the Praos protocol.

Synopsis

Documentation

newtype MaxMajorProtVer Source #

The maximum major protocol version.

This refers to the largest ledger version that this node supports.

Once the ledger protocol version (as reported by the ledger state) exceeds this version we will consider all blocks invalid. This is called the "obsolete node check" (see the ObsoleteNode error constructor).

Major ledger protocol versions are used to trigger both intra and inter era hard forks, which can potentially change the set of ledger rules that are applied.

Minor ledger protocol versions were intended to signal soft forks but they're currently unused, and they're irrelevant for the consensus logic.

For Cardano mainnet, the Shelley era has major protocol version 2. For more details, see this table

Constructors

MaxMajorProtVer 

Instances

Instances details
Generic MaxMajorProtVer Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

Associated Types

type Rep MaxMajorProtVerTypeType #

Show MaxMajorProtVer Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

Eq MaxMajorProtVer Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

NoThunks MaxMajorProtVer Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

type Rep MaxMajorProtVer Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

type Rep MaxMajorProtVer = D1 ('MetaData "MaxMajorProtVer" "Ouroboros.Consensus.Protocol.Praos.Common" "ouroboros-consensus-protocol-0.9.0.2-inplace" 'True) (C1 ('MetaCons "MaxMajorProtVer" 'PrefixI 'True) (S1 ('MetaSel ('Just "getMaxMajorProtVer") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Version)))

data PraosCanBeLeader c Source #

Constructors

PraosCanBeLeader 

Fields

Instances

Instances details
Generic (PraosCanBeLeader c) Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

Associated Types

type Rep (PraosCanBeLeader c) ∷ TypeType #

Crypto c ⇒ NoThunks (PraosCanBeLeader c) Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

type Rep (PraosCanBeLeader c) Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

type Rep (PraosCanBeLeader c) = D1 ('MetaData "PraosCanBeLeader" "Ouroboros.Consensus.Protocol.Praos.Common" "ouroboros-consensus-protocol-0.9.0.2-inplace" 'False) (C1 ('MetaCons "PraosCanBeLeader" 'PrefixI 'True) (S1 ('MetaSel ('Just "praosCanBeLeaderOpCert") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 (OCert c)) :*: (S1 ('MetaSel ('Just "praosCanBeLeaderColdVerKey") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 (VKey 'BlockIssuer c)) :*: S1 ('MetaSel ('Just "praosCanBeLeaderSignKeyVRF") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 (SignKeyVRF c)))))

data PraosChainSelectView c Source #

View of the tip of a header fragment for chain selection.

Instances

Instances details
Generic (PraosChainSelectView c) Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

Associated Types

type Rep (PraosChainSelectView c) ∷ TypeType #

Crypto c ⇒ Show (PraosChainSelectView c) Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

Crypto c ⇒ Eq (PraosChainSelectView c) Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

Crypto c ⇒ Ord (PraosChainSelectView c) Source #

We order between chains as follows:

  1. By chain length, with longer chains always preferred.
  2. If the tip of each chain was issued by the same agent and they have the same slot number, prefer the chain whose tip has the highest ocert issue number.
  3. By a VRF value from the chain tip, with lower values preferred. See pTieBreakVRFValue for which one is used.

IMPORTANT: This is not a complete picture of the Praos chain order, do also consult the documentation of ChainOrder.

Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

Crypto c ⇒ NoThunks (PraosChainSelectView c) Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

Crypto c ⇒ ChainOrder (PraosChainSelectView c) Source #

IMPORTANT: This is not a SimpleChainOrder; rather, there are PraosChainSelectViews a, b such that a < b, but not $ preferCandidate cfg a b, namely for cfg = RestrictedVRFTiebreaker.

Rules

Concretely, we have preferCandidate cfg ours cand based on the following lexicographical criteria:

  1. Chain length, with longer chains always preferred.
  2. If the tip of each chain was issued by the same agent and had the same slot number, then we prefer the candidate if it has a higher ocert issue number.

    Note that this condition is equivalent to the VRFs being identical, as the VRF is a deterministic function of the issuer VRF key, the slot and the epoch nonce, and VRFs are collision-resistant.

  3. Depending on the VRFTiebreakerFlavor:

    • If UnrestrictedVRFTiebreaker: Compare via a VRF value from the chain tip, with lower values preferred. See pTieBreakVRFValue for which one is used.
    • If RestrictedVRFTiebreaker maxDist: Only do the VRF comparison (as in the previous step) if the slot numbers differ by at most maxDist.

Non-transitivity of RestrictedVRFTiebreaker

When using cfg = RestrictedVRFTiebreaker maxDist, the chain order is not transitive. As an example, suppose maxDist = 5 and consider three PraosChainSelectViews with the same chain length and pairwise different issuers and, as well as

abc
Slot036
VRF321

Then we have preferCandidate cfg a b and preferCandidate b c, but not preferCandidate a c (despite a < c).

Rationale for the rules

  1. The abstract Consensus layer requires that we first compare based on chain length (see Chain extension precedence in ChainOrder).
  1. Consider the scenario where the hot key of a block issuer was compromised, and the attacker is now minting blocks using that identity. The actual block issuer can use their cold key to issue a new hot key with a higher opcert issue number and set up a new pool. Due to this tiebreaker rule, the blocks minted by that pool will take precedence (allowing the actual block issuer to decide on eg the block contents and the predecessor) over blocks with the same block and slot number minted by the attacker, and they will end up on the honest chain quickly, which means that the adversary can't extend any chain containing such a block as it would violate the monotonicity requirement on opcert issue numbers.

    See "3.7 Block Validity and Operational Key Certificates" in "Design Specification for Delegation and Incentives in Cardano" by Kant et al for more context.

  2. The main motivation to do VRF comparisons is to avoid the "Frankfurt problem":

    With only the first two rules for the chain order, almost all blocks with equal block number are equally preferrable. Consider two block issuers minting blocks in very nearby slots. As we never change our selection from one chain to an equally preferrable one, the first block to arrive at another pool is the one to be adopted, and will be extended the next time the pool is elected if no blocks with a higher block number arrive in the meantime. We observed that this effectively incentivizes block producers to concentrate geographically (historically, in Frankfurt) in order to minimize their diffusion times. This works against the goal of geographic decentralisation.

    Also, with the VRF tiebreaker, a block with a somewhat lower propagation speed has a random chance to be selected instead of the one that arrived first by pools before the next block is forged.

    See VRFTiebreakerFlavor for more context on the exact conditions under which the VRF comparison takes place.

Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

type Rep (PraosChainSelectView c) Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

type Rep (PraosChainSelectView c) = D1 ('MetaData "PraosChainSelectView" "Ouroboros.Consensus.Protocol.Praos.Common" "ouroboros-consensus-protocol-0.9.0.2-inplace" 'False) (C1 ('MetaCons "PraosChainSelectView" 'PrefixI 'True) ((S1 ('MetaSel ('Just "csvChainLength") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 BlockNo) :*: S1 ('MetaSel ('Just "csvSlotNo") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 SlotNo)) :*: (S1 ('MetaSel ('Just "csvIssuer") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (VKey 'BlockIssuer c)) :*: (S1 ('MetaSel ('Just "csvIssueNo") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Word64) :*: S1 ('MetaSel ('Just "csvTieBreakVRF") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (OutputVRF (VRF c)))))))
type ChainOrderConfig (PraosChainSelectView c) Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

data VRFTiebreakerFlavor Source #

When to compare the VRF tiebreakers.

Constructors

UnrestrictedVRFTiebreaker

Always compare the VRF tiebreakers. This is the behavior of all eras before Conway. Once mainnet has transitioned to Conway, we can remove this option. (The honest historical Ouroboros chain cannot rely on tiebreakers to win, so retroactively disabling the tiebreaker won't matter.)

RestrictedVRFTiebreaker SlotNo

Only compare the VRF tiebreakers when the slot numbers differ by at most the given number of slots.

The main motivation is as follows:

When two blocks A and B with the same block number differ in their slot number by more than Δ (the maximum message delay from Praos), say slot(A) + Δ < slot(B), the issuer of B should have been able to mint a block with a block number higher than A (eg by minting on top of A) under normal circumstances. The reason for this not being the case might have been due to A being sent very late, or due to the issuer of B ignoring A (intentionally, or due to poor configuration/resource provision). In any case, we do not want to allow the block that was diffused later to still win by having a better VRF tiebreaker. This makes it less likely for properly configured pools to lose blocks because of poorly configured pools.

Instances

Instances details
Generic VRFTiebreakerFlavor Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

Associated Types

type Rep VRFTiebreakerFlavorTypeType #

Show VRFTiebreakerFlavor Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

Eq VRFTiebreakerFlavor Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

NoThunks VRFTiebreakerFlavor Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

type Rep VRFTiebreakerFlavor Source # 
Instance details

Defined in Ouroboros.Consensus.Protocol.Praos.Common

type Rep VRFTiebreakerFlavor = D1 ('MetaData "VRFTiebreakerFlavor" "Ouroboros.Consensus.Protocol.Praos.Common" "ouroboros-consensus-protocol-0.9.0.2-inplace" 'False) (C1 ('MetaCons "UnrestrictedVRFTiebreaker" 'PrefixI 'False) (U1TypeType) :+: C1 ('MetaCons "RestrictedVRFTiebreaker" 'PrefixI 'False) (S1 ('MetaSel ('NothingMaybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 SlotNo)))

node support

data PraosNonces Source #

Constructors

PraosNonces 

Fields

class ConsensusProtocol p ⇒ PraosProtocolSupportsNode p where Source #

The node has Praos-aware code that inspects nonces in order to support some Cardano API queries that are crucial to the user exprience

The interface being used for that has grown and needs review, but we're adding to it here under time pressure. See https://github.com/IntersectMBO/cardano-node/issues/3864