-
Notifications
You must be signed in to change notification settings - Fork 130
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1 parent
869d5a2
commit ee86336
Showing
1 changed file
with
183 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
package dispute | ||
|
||
import ( | ||
"fmt" | ||
"github.com/ChainSafe/gossamer/dot/parachain/dispute/types" | ||
"github.com/ChainSafe/gossamer/lib/parachain" | ||
) | ||
|
||
// ImportResult is an ongoing statement/vote import | ||
type ImportResult interface { | ||
VotesChanged() bool | ||
DisputeStateChanged() (bool, error) | ||
OldState() types.CandidateVoteState | ||
NewState() types.CandidateVoteState | ||
NewInvalidVoters() []parachain.ValidatorIndex | ||
ImportedValidVotes() uint32 | ||
ImportedInvalidVotes() uint32 | ||
ImportedApprovalVotes() uint32 | ||
IsFreshlyDisputed() bool | ||
IsFreshlyConfirmed() (bool, error) | ||
IsFreshlyConcludedFor() (bool, error) | ||
IsFreshlyConcludedAgainst() (bool, error) | ||
IsFreshlyConcluded() (bool, error) | ||
ImportApprovalVotes(approvalVotes []types.Vote, now uint64) (ImportResult, error) | ||
IntoUpdatedVotes() types.CandidateVotes | ||
} | ||
|
||
// importResult implements ImportResult interface | ||
type importResult struct { | ||
oldState types.CandidateVoteState | ||
newState types.CandidateVoteState | ||
newInvalidVoters []parachain.ValidatorIndex | ||
importedInvalidVotes uint32 | ||
importedValidVotes uint32 | ||
importedApprovalVotes uint32 | ||
} | ||
|
||
func (i importResult) VotesChanged() bool { | ||
return i.importedValidVotes != 0 || i.importedInvalidVotes != 0 | ||
} | ||
|
||
func (i importResult) DisputeStateChanged() (bool, error) { | ||
isFreshlyConfirmed, err := i.IsFreshlyConfirmed() | ||
if err != nil { | ||
return false, fmt.Errorf("checking if freshly confirmed: %w", err) | ||
} | ||
|
||
isFreshlyConcluded, err := i.IsFreshlyConcluded() | ||
if err != nil { | ||
return false, fmt.Errorf("checking if freshly concluded: %w", err) | ||
} | ||
|
||
return i.IsFreshlyDisputed() || isFreshlyConfirmed || isFreshlyConcluded, nil | ||
} | ||
|
||
func (i importResult) OldState() types.CandidateVoteState { | ||
return i.oldState | ||
} | ||
|
||
func (i importResult) NewState() types.CandidateVoteState { | ||
return i.newState | ||
} | ||
|
||
func (i importResult) NewInvalidVoters() []parachain.ValidatorIndex { | ||
return i.newInvalidVoters | ||
} | ||
|
||
func (i importResult) ImportedValidVotes() uint32 { | ||
return i.importedValidVotes | ||
} | ||
|
||
func (i importResult) ImportedInvalidVotes() uint32 { | ||
return i.importedInvalidVotes | ||
} | ||
|
||
func (i importResult) ImportedApprovalVotes() uint32 { | ||
return i.importedApprovalVotes | ||
} | ||
|
||
func (i importResult) IsFreshlyDisputed() bool { | ||
return !i.oldState.IsDisputed() && i.newState.IsDisputed() | ||
} | ||
|
||
func (i importResult) IsFreshlyConfirmed() (bool, error) { | ||
isOldStateConfirmed, err := i.oldState.IsConfirmed() | ||
if err != nil { | ||
return false, fmt.Errorf("checking if old state is confirmed: %w", err) | ||
} | ||
|
||
isNewStateConfirmed, err := i.newState.IsConfirmed() | ||
if err != nil { | ||
return false, fmt.Errorf("checking if new state is confirmed: %w", err) | ||
} | ||
|
||
return !isOldStateConfirmed && isNewStateConfirmed, nil | ||
} | ||
|
||
func (i importResult) IsFreshlyConcludedFor() (bool, error) { | ||
isOldStateConcludedFor, err := i.oldState.IsConcludedFor() | ||
if err != nil { | ||
return false, fmt.Errorf("checking if old state is concluded for: %w", err) | ||
} | ||
|
||
isNewStateConcludedFor, err := i.newState.IsConcludedFor() | ||
if err != nil { | ||
return false, fmt.Errorf("checking if new state is concluded for: %w", err) | ||
} | ||
|
||
return !isOldStateConcludedFor && isNewStateConcludedFor, nil | ||
} | ||
|
||
func (i importResult) IsFreshlyConcludedAgainst() (bool, error) { | ||
isOldStateConcludedAgainst, err := i.oldState.IsConcludedAgainst() | ||
if err != nil { | ||
return false, fmt.Errorf("checking if old state is concluded against: %w", err) | ||
} | ||
|
||
isNewStateConcludedAgainst, err := i.newState.IsConcludedAgainst() | ||
if err != nil { | ||
return false, fmt.Errorf("checking if new state is concluded against: %w", err) | ||
} | ||
|
||
return !isOldStateConcludedAgainst && isNewStateConcludedAgainst, nil | ||
} | ||
|
||
func (i importResult) IsFreshlyConcluded() (bool, error) { | ||
isFreshlyConcludedFor, err := i.IsFreshlyConcludedFor() | ||
if err != nil { | ||
return false, fmt.Errorf("checking if freshly concluded for: %w", err) | ||
} | ||
|
||
isFreshlyConcludedAgainst, err := i.IsFreshlyConcludedAgainst() | ||
if err != nil { | ||
return false, fmt.Errorf("checking if freshly concluded against: %w", err) | ||
} | ||
|
||
return isFreshlyConcludedFor || isFreshlyConcludedAgainst, nil | ||
} | ||
|
||
func (i importResult) ImportApprovalVotes(approvalVotes []types.Vote, now uint64) (ImportResult, error) { | ||
votes := i.newState.Votes | ||
|
||
for _, approvalVote := range approvalVotes { | ||
// TODO: validate signature | ||
|
||
if _, ok := votes.Valid.Tracker[approvalVote.ValidatorIndex]; !ok { | ||
votes.Valid.Votes = append(votes.Valid.Votes, approvalVote) | ||
votes.Valid.Tracker[approvalVote.ValidatorIndex] = struct{}{} | ||
i.importedValidVotes++ | ||
i.importedApprovalVotes++ | ||
} | ||
} | ||
|
||
newState, err := types.NewCandidateVoteState(votes, now) | ||
if err != nil { | ||
return nil, fmt.Errorf("creating new candidate vote state: %w", err) | ||
} | ||
|
||
if newState == nil { | ||
return nil, fmt.Errorf("new state is nil") | ||
} | ||
|
||
return &importResult{ | ||
oldState: i.oldState, | ||
newState: *newState, | ||
newInvalidVoters: i.newInvalidVoters, | ||
importedInvalidVotes: i.importedInvalidVotes, | ||
importedValidVotes: i.importedValidVotes, | ||
importedApprovalVotes: i.importedApprovalVotes, | ||
}, nil | ||
} | ||
|
||
func (i importResult) IntoUpdatedVotes() types.CandidateVotes { | ||
if !i.VotesChanged() { | ||
return types.CandidateVotes{} | ||
} | ||
|
||
return i.newState.Votes | ||
} | ||
|
||
func NewImportResult() ImportResult { | ||
return &importResult{} | ||
} |