Disputes Flows

A component-free description in what-if form with addition state graphs of the dispute.

stateDiagram-v2
    [*] --> WaitForBackingVote: negative Vote received
    [*] --> WaitForDisputeVote: backing Vote received
    WaitForBackingVote --> Open: negative Vote received
    WaitForDisputeVote --> Open: backing Vote received
    Open --> Concluded: Incoming Vote via Gossip
    Open --> Open: No ⅔ supermajority
    Open --> [*]
    Concluded --> [*]

stateDiagram-v2
    [*] --> Open: First Vote(s) received
    Open --> HasPoV : Fetch Availability Store for PoV

    HasPoV --> HasCode : Fetch historical Code
    HasCode --> VerifyWithRuntime: All Data locally avail

    Open --> DisputeAvailabilityDataReceived
    DisputeAvailabilityDataReceived --> VerifyWithRuntime: Received Gossip

    HasPoV --> RequestDisputeAvailabilityData: nope
    HasCode --> RequestDisputeAvailabilityData: nope
    RequestDisputeAvailabilityData --> VerifyWithRuntime: Received
    RequestDisputeAvailabilityData --> RequestDisputeAvailabilityData: Timed out - pick another peer

    VerifyWithRuntime --> CastVoteValid: Block Valid
    VerifyWithRuntime --> CastVoteInvalid: Block Invalid
    CastVoteInvalid --> GossipVote
    CastVoteValid --> GossipVote
    GossipVote --> [*]


Dispute Availability Data

stateDiagram-v2
    [*] --> Open: First Vote(s) received
    Open --> DisputeDataAvail: somehow the data became available
    Open --> RespondUnavailable: Data not available
    IncomingRequestDisputeAvailabilityData --> RespondUnavailable
    IncomingRequestDisputeAvailabilityData --> DisputeDataAvail
    DisputeDataAvail --> RespondWithDisputeAvailabilityData: Send
    VoteGossipReceived --> Track: implies source peer has<br />dispute availablity data

Peer handling

stateDiagram-v2
    [*] --> Open: First Vote(s) received
    Open --> GossipVotes: for all current peers
    Open --> PeerConnected: another
    PeerConnected --> GossipVotes: Peer connects
    GossipVotes --> [*]

Conditional formulation

The set of validators eligible to vote consists of the validators that had duty at the time of backing, plus backing votes by the backing validators.

If a validator receives an initial dispute message (a set of votes where there are at least two opposing votes contained), and the PoV or Code are hence not reconstructable from local storage, that validator must request the required data from its peers.

The dispute availability message must contain code, persisted validation data, and the proof of validity.

Only peers that already voted shall be queried for the dispute availability data.

The peer to be queried for disputes data, must be picked at random.

A validator must retain code, persisted validation data and PoV until a block, that contains the dispute resolution, is finalized - plus an additional 24 hours.

Dispute availability gossip must continue beyond the dispute resolution, until the post resolution timeout expired (equiv to the timeout until which additional late votes are accepted).

Remote disputes are disputes that are in relation to a chain that is not part of the local validators active heads.

All incoming votes must be persisted.

Persisted votes stay persisted for N sessions, and are cleaned up on a per session basis.

Votes must be queryable by a particular validator, identified by its signing key.

Votes must be queryable by a particular validator, identified by a session index and the validator index valid in that session.

If there exists a negative and a positive vote for a particular block, a dispute is detected.

If a dispute is detected, all currently available votes for that block must be gossiped.

If an incoming dispute vote is detected, a validator must cast their own vote. The vote is determined by validating the PoV with the Code at the time of backing the block in question.

If the validator was also a backer of the block, validation and casting an additional vote should be skipped.

If the count of votes pro or cons regarding the disputed block, reaches the required ⅔ supermajority (including the backing votes), the conclusion must be recorded on chain and the voters on the loosing and no-shows being slashed appropriately.

If a block is found invalid by a dispute resolution, it must be blacklisted to avoid resync or further build on that chain if other chains are available (to be detailed in the grandpa fork choice rule).

A dispute accepts Votes after the dispute is resolved, for 1 day.

If a vote is received, after the dispute is resolved, the vote shall still be recorded in the state root, albeit yielding less reward.

Recording in the state root might happen batched, at timeout expiry.

If a new active head/chain appears, and the dispute resolution was not recorded on that chain yet, the dispute resolution or open dispute must be recorded / transplanted to that chain as well, since the disputes must be present on all chains to make sure the offender is punished.

If a validator votes in two opposing ways, this composes of a double vote like in other cases (backing, approval voting).

If a dispute is not resolved within due time, all validators are to be slashed for a small amount.

If a dispute is not resolved within due time, governance mode shall be entered for manual resolution.

If a validator unexpectedly restarts, the dispute shall be continued with the state based on votes being cast and being present in persistent storage.