Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add disputes coordinator
Browse files Browse the repository at this point in the history
kanishkatn committed Aug 18, 2023
1 parent df3e7e3 commit 2048ee9
Showing 36 changed files with 1,251 additions and 84 deletions.
2 changes: 1 addition & 1 deletion dot/parachain/available_data_fetching.go
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ import (
// AvailableDataFetchingRequest represents a request to retrieve all available data for a specific candidate.
type AvailableDataFetchingRequest struct {
// Hash of the candidate for which the available data is requested.
CandidateHash CandidateHash
CandidateHash parachaintypes.CandidateHash
}

// Encode returns the SCALE encoding of the AvailableDataFetchingRequest
2 changes: 1 addition & 1 deletion dot/parachain/available_data_fetching_test.go
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ import (

func TestEncodeAvailableDataFetchingRequest(t *testing.T) {
availableDataFetchingRequest := AvailableDataFetchingRequest{
CandidateHash: CandidateHash{
CandidateHash: parachaintypes.CandidateHash{
common.MustHexToHash("0x677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c19"),
},
}
2 changes: 1 addition & 1 deletion dot/parachain/chunk_fetching.go
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ import (
// ChunkFetchingRequest represents a request to retrieve chunks of a parachain candidate
type ChunkFetchingRequest struct {
// Hash of candidate we want a chunk for.
CandidateHash CandidateHash `scale:"1"`
CandidateHash parachaintypes.CandidateHash `scale:"1"`

// The index of the chunk to fetch.
Index parachaintypes.ValidatorIndex `scale:"2"`
2 changes: 1 addition & 1 deletion dot/parachain/chunk_fetching_test.go
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ import (

func TestEncodeChunkFetchingRequest(t *testing.T) {
chunkFetchingRequest := ChunkFetchingRequest{
CandidateHash: CandidateHash{
CandidateHash: parachaintypes.CandidateHash{
common.MustHexToHash("0x677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c19"),
},
Index: parachaintypes.ValidatorIndex(8),
58 changes: 55 additions & 3 deletions dot/parachain/dispute/backend.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package dispute

import (
"fmt"
"sync"
"time"

"github.com/ChainSafe/gossamer/dot/parachain/dispute/types"
parachainTypes "github.com/ChainSafe/gossamer/dot/parachain/types"
"github.com/ChainSafe/gossamer/lib/common"
"github.com/dgraph-io/badger/v4"
"github.com/tidwall/btree"
)

@@ -32,10 +32,14 @@ type Backend interface {
type OverlayBackend interface {
Backend

// IsEmpty returns true if the overlay backend is empty.
IsEmpty() bool
// WriteToDB writes the given dispute to the database.
WriteToDB() error
// GetActiveDisputes returns the active disputes.
GetActiveDisputes(now int64) (*btree.BTree, error)
// NoteEarliestSession prunes data in the DB based on the provided session index.
NoteEarliestSession(session parachainTypes.SessionIndex) error
}

// DBBackend is the backend for the dispute coordinator module that uses a database.
@@ -159,16 +163,64 @@ func (b *overlayBackend) GetActiveDisputes(now int64) (*btree.BTree, error) {
return activeDisputes, nil
}

func (b *overlayBackend) IsEmpty() bool {
return b.earliestSession == nil && b.recentDisputes.Len() == 0 && len(b.candidateVotes) == 0
}

func (b *overlayBackend) WriteToDB() error {
return b.inner.Write(b.earliestSession, b.recentDisputes, b.candidateVotes)
}

func (b *overlayBackend) NoteEarliestSession(session parachainTypes.SessionIndex) error {
if b.earliestSession == nil {
b.earliestSession = &session
return nil
}

if *b.earliestSession > session {
b.earliestSession = &session
// clear recent disputes metadata
recentDisputes, err := b.GetRecentDisputes()
if err != nil {
return fmt.Errorf("get recent disputes: %w", err)
}

// determine new recent disputes
newRecentDisputes := btree.New(types.DisputeComparator)
recentDisputes.Ascend(nil, func(item interface{}) bool {
dispute := item.(*types.Dispute)
if dispute.Comparator.SessionIndex >= session {
newRecentDisputes.Set(dispute)
}
return true
})

// prune obsolete disputes
recentDisputes.Ascend(nil, func(item interface{}) bool {
dispute := item.(*types.Dispute)
if dispute.Comparator.SessionIndex < session {
recentDisputes.Delete(dispute)
}
return true
})

// update db
if recentDisputes.Len() > 0 {
if err = b.SetRecentDisputes(newRecentDisputes); err != nil {
return fmt.Errorf("set recent disputes: %w", err)
}
}
}

return nil
}

var _ OverlayBackend = (*overlayBackend)(nil)

// newOverlayBackend creates a new overlayBackend.
func newOverlayBackend(db *badger.DB) *overlayBackend {
func newOverlayBackend(backend DBBackend) *overlayBackend {
return &overlayBackend{
inner: NewDBBackend(db),
inner: backend,
recentDisputes: btree.New(types.DisputeComparator),
candidateVotes: make(map[types.Comparator]*types.CandidateVotes),
earliestSessionLock: new(sync.RWMutex),
12 changes: 8 additions & 4 deletions dot/parachain/dispute/backend_test.go
Original file line number Diff line number Diff line change
@@ -19,9 +19,10 @@ func TestOverlayBackend_EarliestSession(t *testing.T) {
// with
db, err := badger.Open(badger.DefaultOptions(t.TempDir()))
require.NoError(t, err)
dbBackend := NewDBBackend(db)

// when
backend := newOverlayBackend(db)
backend := newOverlayBackend(dbBackend)
err = backend.SetEarliestSession(getSessionIndex(1))
require.NoError(t, err)

@@ -38,6 +39,7 @@ func TestOverlayBackend_RecentDisputes(t *testing.T) {
// with
db, err := badger.Open(badger.DefaultOptions(t.TempDir()))
require.NoError(t, err)
dbBackend := NewDBBackend(db)
disputes := btree.New(types.DisputeComparator)

dispute1, err := types.NewTestDispute(1, common.Hash{1}, types.DisputeStatusActive)
@@ -49,7 +51,7 @@ func TestOverlayBackend_RecentDisputes(t *testing.T) {
disputes.Set(dispute2)

// when
backend := newOverlayBackend(db)
backend := newOverlayBackend(dbBackend)
err = backend.SetRecentDisputes(disputes)
require.NoError(t, err)

@@ -65,10 +67,11 @@ func TestOverlayBackend_CandidateVotes(t *testing.T) {
// with
db, err := badger.Open(badger.DefaultOptions(t.TempDir()))
require.NoError(t, err)
dbBackend := NewDBBackend(db)
candidateVotes1 := types.NewTestCandidateVotes(t)

// when
backend := newOverlayBackend(db)
backend := newOverlayBackend(dbBackend)
err = backend.SetCandidateVotes(1, common.Hash{1}, candidateVotes1)
require.NoError(t, err)

@@ -84,7 +87,8 @@ func TestOverlayBackend_Concurrency(t *testing.T) {
// with
db, err := badger.Open(badger.DefaultOptions(t.TempDir()))
require.NoError(t, err)
backend := newOverlayBackend(db)
dbBackend := NewDBBackend(db)
backend := newOverlayBackend(dbBackend)

numGoroutines := 10
numIterations := 1000
Loading

0 comments on commit 2048ee9

Please sign in to comment.