Skip to content

Commit

Permalink
add backend
Browse files Browse the repository at this point in the history
  • Loading branch information
kanishkatn committed Jun 20, 2023
1 parent 6b71e22 commit 3f8174f
Show file tree
Hide file tree
Showing 3 changed files with 229 additions and 1 deletion.
225 changes: 225 additions & 0 deletions dot/parachain/dispute/backend.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
package dispute

import (
"bytes"
"fmt"
"github.com/ChainSafe/gossamer/lib/common"
"github.com/ChainSafe/gossamer/lib/parachain"
"github.com/ChainSafe/gossamer/pkg/scale"
"github.com/emirpasic/gods/maps/treemap"
"github.com/google/btree"
"time"
)

type CandidateHash common.Hash

type Comparator struct {
SessionIndex parachain.SessionIndex
CandidateHash CandidateHash
}

// Less returns true if the current item is less than the other item
// it uses the Key to determine the order
func (d Dispute) Less(than btree.Item) bool {
other := than.(*Dispute)

if d.comparator.SessionIndex == other.comparator.SessionIndex {
return bytes.Compare(d.comparator.CandidateHash[:], other.comparator.CandidateHash[:]) < 0
}

return d.comparator.SessionIndex < other.comparator.SessionIndex
}

type CandidateVotes struct {
candidateReceipt parachain.CandidateReceipt
valid *treemap.Map
invalid *treemap.Map
}

type Dispute struct {
comparator *Comparator
disputeStatus *Status
}

func NewCandidateVotes() *CandidateVotes {
return &CandidateVotes{
valid: treemap.NewWithIntComparator(),
invalid: treemap.NewWithIntComparator(),
}
}

type Active struct{}

func (Active) Index() uint {
return 0
}

type ConcludedFor struct {
Since uint64
}

func (ConcludedFor) Index() uint {
return 1
}

type ConcludedAgainst struct {
Since uint64
}

func (ConcludedAgainst) Index() uint {
return 2
}

type Confirmed struct{}

func (Confirmed) Index() uint {
return 3
}

type Status scale.VaryingDataType

// Set will set a VaryingDataTypeValue using the underlying VaryingDataType
func (ds *Status) Set(val scale.VaryingDataTypeValue) (err error) {
vdt := scale.VaryingDataType(*ds)
err = vdt.Set(val)
if err != nil {
return fmt.Errorf("setting value to varying data type: %w", err)
}
*ds = Status(vdt)
return nil
}

// Value returns the value from the underlying VaryingDataType
func (ds *Status) Value() (scale.VaryingDataTypeValue, error) {
vdt := scale.VaryingDataType(*ds)
return vdt.Value()
}

// TODO: check if we can avoid using pointers
func (ds *Status) ConcludedAt() (*uint64, error) {
vdt := scale.VaryingDataType(*ds)
val, err := vdt.Value()
if err != nil {
return nil, fmt.Errorf("getting value from DisputeStatus vdt: %w", err)
}

switch v := val.(type) {
case Active, Confirmed:
return nil, nil
case ConcludedFor:
return &v.Since, nil
case ConcludedAgainst:
return &v.Since, nil
default:
return nil, fmt.Errorf("invalid dispute status type")
}
}

func NewDisputeStatus() (Status, error) {
vdt, err := scale.NewVaryingDataType(Active{}, ConcludedFor{}, ConcludedAgainst{}, Confirmed{})
if err != nil {
return Status{}, fmt.Errorf("creating new dispute status vdt: %w", err)
}

return Status(vdt), nil
}

type Backend interface {
// GetEarliestSession returns the earliest session index, if any.
GetEarliestSession() (*parachain.SessionIndex, error)
// GetRecentDisputes returns the recent disputes, if any.
GetRecentDisputes() (*btree.BTree, error)
// GetCandidateVotes returns the votes for the given candidate for the specific session-candidate pair, if any.
GetCandidateVotes(session parachain.SessionIndex, candidateHash CandidateHash) (*CandidateVotes, error)

// GetActiveDisputes returns the active disputes, if any.
GetActiveDisputes(now int64) (*btree.BTree, error)

// TODO: need to explore further to see if we need these
SetEarliestSession(session parachain.SessionIndex)
SetRecentDisputes(recentDisputes *btree.BTree)
SetCandidateVotes(session parachain.SessionIndex, candidateHash CandidateHash, votes *CandidateVotes)
}

type backend struct {
// TODO: db
earliestSession *parachain.SessionIndex
recentDisputes *btree.BTree
candidateVotes map[Comparator]*CandidateVotes
}

func (b backend) GetEarliestSession() (*parachain.SessionIndex, error) {
if b.earliestSession != nil {
return b.earliestSession, nil
}

// TODO: read from db

return nil, nil
}

func (b backend) GetRecentDisputes() (*btree.BTree, error) {
if b.recentDisputes.Len() > 0 {
return b.recentDisputes, nil
}

// TODO: read from db

return nil, nil
}

func (b backend) GetCandidateVotes(session parachain.SessionIndex, candidateHash CandidateHash) (*CandidateVotes, error) {
key := Comparator{
SessionIndex: session,
CandidateHash: candidateHash,
}

if v, ok := b.candidateVotes[key]; ok {
return v, nil
}

// TODO: read from db

return nil, nil
}

func (b backend) SetEarliestSession(session parachain.SessionIndex) {
b.earliestSession = &session
}

func (b backend) SetRecentDisputes(recentDisputes *btree.BTree) {
b.recentDisputes = recentDisputes
}

func (b backend) SetCandidateVotes(session parachain.SessionIndex, candidateHash CandidateHash, votes *CandidateVotes) {
key := Comparator{
SessionIndex: session,
CandidateHash: candidateHash,
}

b.candidateVotes[key] = votes
}

const ActiveDuration = 180 * time.Second

func (b backend) GetActiveDisputes(now int64) (*btree.BTree, error) {
activeDisputes := btree.New(32)

b.recentDisputes.Ascend(func(i btree.Item) bool {
d := i.(*Dispute)
concludedAt, err := d.disputeStatus.ConcludedAt()
if err == nil && concludedAt != nil && *concludedAt+uint64(ActiveDuration.Seconds()) > uint64(now) {
activeDisputes.ReplaceOrInsert(d)
}
return true
})

return activeDisputes, nil
}

func NewBackend() Backend {
return &backend{
recentDisputes: btree.New(32),
candidateVotes: make(map[Comparator]*CandidateVotes),
}
}
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/dgraph-io/badger/v4 v4.1.0
github.com/dgraph-io/ristretto v0.1.1
github.com/disiqueira/gotree v1.0.0
github.com/emirpasic/gods v1.18.1
github.com/ethereum/go-ethereum v1.12.0
github.com/fatih/color v1.15.0
github.com/go-playground/validator/v10 v10.14.1
Expand Down Expand Up @@ -46,6 +47,7 @@ require (
golang.org/x/term v0.8.0
golang.org/x/text v0.9.0
google.golang.org/protobuf v1.30.0
gopkg.in/yaml.v3 v3.0.1
)

require (
Expand Down Expand Up @@ -193,7 +195,6 @@ require (
gonum.org/v1/gonum v0.11.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.1.7 // indirect
nhooyr.io/websocket v1.8.7 // indirect
)
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+m
github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4=
github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
Expand Down

0 comments on commit 3f8174f

Please sign in to comment.