From 698f420e2798f99f136fc438fb1333c3b8d30c06 Mon Sep 17 00:00:00 2001 From: Maelkum Date: Sat, 7 Oct 2023 22:52:33 +0200 Subject: [PATCH] Add support for "one-of" attestors alongside "each" --- models/execute/request.go | 14 -------------- models/execute/request_attributes.go | 25 ++++++++++++++++++++++++ node/attributes.go | 29 +++++++++++++++++++++++----- 3 files changed, 49 insertions(+), 19 deletions(-) create mode 100644 models/execute/request_attributes.go diff --git a/models/execute/request.go b/models/execute/request.go index 402fdafd..877b195c 100644 --- a/models/execute/request.go +++ b/models/execute/request.go @@ -1,7 +1,5 @@ package execute -import "github.com/libp2p/go-libp2p/core/peer" - // Request describes an execution request. type Request struct { FunctionID string `json:"function_id"` @@ -49,15 +47,3 @@ type ResultAggregation struct { Type string `json:"type,omitempty"` Parameters []Parameter `json:"parameters,omitempty"` } - -type Attributes struct { - // Values specify which attributes the node in question should have. - // At the moment we support strict equality only, so no `if RAM >= 16GB` types of conditions. - Values []Parameter `json:"values,omitempty"` - - // Should we accept nodes whose attributes are not attested? - AttestationRequired bool `json:"attestation_required,omitempty"` - - // Explicitly request specific attestors. - Attestors []peer.ID `json:"attestors,omitempty"` -} diff --git a/models/execute/request_attributes.go b/models/execute/request_attributes.go new file mode 100644 index 00000000..8e1737fe --- /dev/null +++ b/models/execute/request_attributes.go @@ -0,0 +1,25 @@ +package execute + +import ( + "github.com/libp2p/go-libp2p/core/peer" +) + +type Attributes struct { + // Values specify which attributes the node in question should have. + // At the moment we support strict equality only, so no `if RAM >= 16GB` types of conditions. + Values []Parameter `json:"values,omitempty"` + + // Should we accept nodes whose attributes are not attested? + AttestationRequired bool `json:"attestation_required,omitempty"` + + // Explicitly request specific attestors. + Attestors AttributeAttestors `json:"attestors,omitempty"` +} + +type AttributeAttestors struct { + // Each of the listed attestors should be found. + Each []peer.ID `json:"each,omitempty"` + + // Any one of these attestors should be found. + OneOf []peer.ID `json:"one_of,omitempty"` +} diff --git a/node/attributes.go b/node/attributes.go index 46292bbb..5c0143e9 100644 --- a/node/attributes.go +++ b/node/attributes.go @@ -11,6 +11,7 @@ import ( "github.com/libp2p/go-libp2p/core/peer" "github.com/blocklessnetwork/b7s-attributes/attributes" + "github.com/blocklessnetwork/b7s/models/blockless" "github.com/blocklessnetwork/b7s/models/execute" ) @@ -62,15 +63,18 @@ func haveAttributes(have attributes.Attestation, want execute.Attributes) error return errors.New("attestors required but none found") } - // If the client wants specific attestors, check if they're present. - if len(want.Attestors) > 0 { - - attestors := make(map[peer.ID]struct{}, len(have.Attestors)) + // If we need to check attestors, create a map of them now. + var attestors map[peer.ID]struct{} + if len(want.Attestors.Each) > 0 || len(want.Attestors.OneOf) > 0 { + attestors = make(map[peer.ID]struct{}, len(have.Attestors)) for _, attestor := range have.Attestors { attestors[attestor.Signer] = struct{}{} } + } - for _, wa := range want.Attestors { + // If the client wants specific attestors, check if they're present. + if len(want.Attestors.Each) > 0 { + for _, wa := range want.Attestors.Each { _, ok := attestors[wa] if !ok { return fmt.Errorf("attestor %s explicitly requested but not found", wa.String()) @@ -78,6 +82,21 @@ func haveAttributes(have attributes.Attestation, want execute.Attributes) error } } + // If the client wants some of these attestors, check if at least one if found. + if len(want.Attestors.OneOf) > 0 { + var found bool + for _, wa := range want.Attestors.OneOf { + _, ok := attestors[wa] + if ok { + found = true + break + } + } + if !found { + return fmt.Errorf("at least one attestor wanted but none found (wanted: %s)", blockless.PeerIDsToStr(want.Attestors.OneOf)) + } + } + // It doesn't make a lot of sense to require attestors without wanting specific attributes, // but if that's the case, and there's no attributes wanted, we're done now. if len(want.Values) == 0 {