Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding verifiers to ProofService #5

Merged
merged 6 commits into from
Jun 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions fraudserv/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ type ProofService struct {
storesLk sync.RWMutex
stores map[fraud.ProofType]datastore.Datastore

pubsub *pubsub.PubSub
host host.Host
getter fraud.HeaderFetcher
ds datastore.Datastore
verifiersLk sync.RWMutex
verifiers map[fraud.ProofType]fraud.Verifier

pubsub *pubsub.PubSub
host host.Host
getter fraud.HeaderFetcher
ds datastore.Datastore
syncerEnabled bool
}

Expand All @@ -64,6 +66,7 @@ func NewProofService(
pubsub: p,
host: host,
getter: getter,
verifiers: make(map[fraud.ProofType]fraud.Verifier),
topics: make(map[fraud.ProofType]*pubsub.Topic),
stores: make(map[fraud.ProofType]datastore.Datastore),
ds: ds,
Expand Down Expand Up @@ -138,6 +141,16 @@ func (f *ProofService) Broadcast(ctx context.Context, p fraud.Proof) error {
return t.Publish(ctx, bin)
}

func (f *ProofService) AddVerifier(proofType fraud.ProofType, verifier fraud.Verifier) error {
gupadhyaya marked this conversation as resolved.
Show resolved Hide resolved
f.verifiersLk.Lock()
defer f.verifiersLk.Unlock()
if _, ok := f.verifiers[proofType]; ok {
return fmt.Errorf("verifier for proof type %s already exist", proofType)
gupadhyaya marked this conversation as resolved.
Show resolved Hide resolved
gupadhyaya marked this conversation as resolved.
Show resolved Hide resolved
}
f.verifiers[proofType] = verifier
return nil
}

// processIncoming encompasses the logic for validating fraud proofs.
func (f *ProofService) processIncoming(
ctx context.Context,
Expand Down Expand Up @@ -181,6 +194,23 @@ func (f *ProofService) processIncoming(
"err", err, "proofType", proof.Type(), "height", proof.Height())
return pubsub.ValidationIgnore
}

// execute the verifier for proof type if exists
f.verifiersLk.RLock()
verifier, ok := f.verifiers[proofType]
f.verifiersLk.RUnlock()
if ok {
status, err := verifier(proof)
if err != nil {
log.Errorw("failed to run the verifier", "err", err, "proofType", proof.Type())
return pubsub.ValidationReject
gupadhyaya marked this conversation as resolved.
Show resolved Hide resolved
}
if !status {
log.Errorw("invalid fraud proof", "proofType", proof.Type())
return pubsub.ValidationReject
gupadhyaya marked this conversation as resolved.
Show resolved Hide resolved
}
}

// validate the fraud proof.
// Peer will be added to black list if the validation fails.
err = proof.Validate(extHeader)
Expand Down
43 changes: 43 additions & 0 deletions fraudserv/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package fraudserv

import (
"context"
"errors"
"testing"
"time"

Expand All @@ -15,6 +16,7 @@ import (
"github.com/celestiaorg/go-header"
"github.com/celestiaorg/go-header/headertest"

gofraud "github.com/celestiaorg/go-fraud"
"github.com/celestiaorg/go-fraud/fraudtest"
)

Expand All @@ -35,6 +37,47 @@ func TestService_SubscribeBroadcastValid(t *testing.T) {
require.NoError(t, err)
}

func TestService_SubscribeBroadcastWithVerifiers(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
t.Cleanup(cancel)

serv := newTestService(ctx, t, false)
require.NoError(t, serv.Start(ctx))

fraud := fraudtest.NewValidProof()
require.NoError(t, serv.AddVerifier(fraud.Type(), func(fraudProof gofraud.Proof) (bool, error) {
return true, nil
}))

// test for error while adding the verifier for the second time
require.Error(t, serv.AddVerifier(fraud.Type(), func(fraudProof gofraud.Proof) (bool, error) {
return true, nil
}))
sub, err := serv.Subscribe(fraud.Type())
require.NoError(t, err)
defer sub.Cancel()

require.NoError(t, serv.Broadcast(ctx, fraud))
_, err = sub.Proof(ctx)
require.NoError(t, err)

// test for invalid fraud proof verifier
serv = newTestService(ctx, t, false)
require.NoError(t, serv.Start(ctx))
require.NoError(t, serv.AddVerifier(fraud.Type(), func(fraudProof gofraud.Proof) (bool, error) {
return false, nil
}))
require.Error(t, serv.Broadcast(ctx, fraud))

// test for error case of fraud proof verifier
serv = newTestService(ctx, t, false)
require.NoError(t, serv.Start(ctx))
require.NoError(t, serv.AddVerifier(fraud.Type(), func(fraudProof gofraud.Proof) (bool, error) {
return true, errors.New("throws error")
}))
require.Error(t, serv.Broadcast(ctx, fraud))
}

func TestService_SubscribeBroadcastInvalid(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
t.Cleanup(cancel)
Expand Down
7 changes: 7 additions & 0 deletions interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import (
// HeaderFetcher aliases a function that is used to fetch an ExtendedHeader from store by height.
type HeaderFetcher func(context.Context, uint64) (header.Header, error)

// Verifier is a function that is executed as part of processing the incoming fraud proof
type Verifier func(fraud Proof) (bool, error)

// ProofUnmarshaler aliases a function that parses data to `Proof`.
type ProofUnmarshaler func([]byte) (Proof, error)

Expand All @@ -35,6 +38,10 @@ type Broadcaster interface {
type Subscriber interface {
// Subscribe allows to subscribe on a Proof pub sub topic by its type.
Subscribe(ProofType) (Subscription, error)
// AddVerifier allows for supplying additional verification logic which
// will be run as part of processing the incoming fraud proof.
// This only supplements the main validation done by Proof.Validate
AddVerifier(ProofType, Verifier) error
}

// Getter encompasses the behavior to fetch stored fraud proofs.
Expand Down