Skip to content

Commit

Permalink
Replace result types with errors.
Browse files Browse the repository at this point in the history
  • Loading branch information
q-uint committed Mar 25, 2024
1 parent cddbb4c commit b8dc5b4
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 154 deletions.
38 changes: 20 additions & 18 deletions agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,11 @@ func (a Agent) GetCanisterInfo(canisterID principal.Principal, subPath string) (
if err != nil {
return nil, err
}
result := hashtree.NewHashTree(node).Lookup(path...)
if err := result.Found(); err != nil {
canisterInfo, err := hashtree.NewHashTree(node).Lookup(path...)
if err != nil {
return nil, err
}
return result.Value, nil
return canisterInfo, nil
}

func (a Agent) GetCanisterMetadata(canisterID principal.Principal, subPath string) ([]byte, error) {
Expand All @@ -165,11 +165,11 @@ func (a Agent) GetCanisterMetadata(canisterID principal.Principal, subPath strin
if err != nil {
return nil, err
}
result := hashtree.NewHashTree(node).Lookup(path...)
if err := result.Found(); err != nil {
metadata, err := hashtree.NewHashTree(node).Lookup(path...)
if err != nil {
return nil, err
}
return result.Value, nil
return metadata, nil
}

// GetCanisterModuleHash returns the module hash for the given canister.
Expand Down Expand Up @@ -239,11 +239,11 @@ func (a Agent) RequestStatus(canisterID principal.Principal, requestID RequestID
if err != nil {
return nil, nil, err
}
result := hashtree.NewHashTree(node).Lookup(append(path, hashtree.Label("status"))...)
if err := result.Found(); err != nil {
status, err := hashtree.NewHashTree(node).Lookup(append(path, hashtree.Label("status"))...)
if err != nil {
return nil, nil, err
}
return result.Value, node, nil
return status, node, nil
}

// Sender returns the principal that is sending the requests.
Expand Down Expand Up @@ -274,20 +274,22 @@ func (a Agent) poll(canisterID principal.Principal, requestID RequestID, delay,
switch string(data) {
case "rejected":
tree := hashtree.NewHashTree(node)
codeResult := tree.Lookup(append(path, hashtree.Label("reject_code"))...)
messageResult := tree.Lookup(append(path, hashtree.Label("reject_message"))...)
if codeResult.Found() != nil || messageResult.Found() != nil {
return nil, fmt.Errorf("no reject code or message found")
code, err := tree.Lookup(append(path, hashtree.Label("reject_code"))...)
if err != nil {
return nil, err
}
message, err := tree.Lookup(append(path, hashtree.Label("reject_message"))...)
if err != nil {
return nil, err
}
return nil, fmt.Errorf("(%d) %s", uint64FromBytes(codeResult.Value), string(messageResult.Value))
return nil, fmt.Errorf("(%d) %s", uint64FromBytes(code), string(message))
case "replied":
fmt.Println(node)
repliedResult := hashtree.NewHashTree(node).Lookup(append(path, hashtree.Label("reply"))...)
fmt.Println(repliedResult)
if repliedResult.Found() != nil {
replied, err := hashtree.NewHashTree(node).Lookup(append(path, hashtree.Label("reply"))...)
if err != nil {
return nil, fmt.Errorf("no reply found")
}
return repliedResult.Value, nil
return replied, nil
}
}
case <-timer.C:
Expand Down
15 changes: 7 additions & 8 deletions certification/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ func (c Certificate) getPublicKey() (*bls.PublicKey, error) {
}

cert := c.Cert.Delegation
canisterRangesResult := cert.Certificate.Cert.Tree.Lookup(
canisterRanges, err := cert.Certificate.Cert.Tree.Lookup(
hashtree.Label("subnet"), cert.SubnetId.Raw, hashtree.Label("canister_ranges"),
)
if canisterRangesResult.Found() != nil {
return nil, fmt.Errorf("no canister ranges found for subnet %s", cert.SubnetId)
if err != nil {
return nil, fmt.Errorf("no canister ranges found for subnet %s: %w", cert.SubnetId, err)
}
var rawRanges [][][]byte
if err := cbor.Unmarshal(canisterRangesResult.Value, &rawRanges); err != nil {
if err := cbor.Unmarshal(canisterRanges, &rawRanges); err != nil {
return nil, err
}

Expand All @@ -92,14 +92,13 @@ func (c Certificate) getPublicKey() (*bls.PublicKey, error) {
return nil, fmt.Errorf("canister %s is not in range", c.CanisterID)
}

publicKeyResult := cert.Certificate.Cert.Tree.Lookup(
publicKey, err := cert.Certificate.Cert.Tree.Lookup(
hashtree.Label("subnet"), cert.SubnetId.Raw, hashtree.Label("public_key"),
)
if publicKeyResult.Found() != nil {
return nil, fmt.Errorf("no public key found for subnet %s", cert.SubnetId)
if err != nil {
return nil, fmt.Errorf("no public key found for subnet %s: %w", cert.SubnetId, err)
}

publicKey := publicKeyResult.Value
if len(publicKey) != len(derPrefix)+96 {
return nil, fmt.Errorf("invalid public key length: %d", len(publicKey))
}
Expand Down
77 changes: 77 additions & 0 deletions certification/hashtree/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package hashtree

import (
"fmt"
"strings"
)

// pathToString converts a path to a string, by joining the (string) labels with a slash.
func pathToString(path []Label) string {
var sb strings.Builder
for i, p := range path {
if i > 0 {
sb.WriteByte('/')
}
sb.WriteString(string(p))
}
return sb.String()
}

type LookupError struct {
Type LookupResultType
Path string
}

// NewLookupAbsentError returns a new LookupError with type LookupResultAbsent.
func NewLookupAbsentError(path ...Label) LookupError {
return LookupError{
Type: LookupResultAbsent,
Path: pathToString(path),
}
}

// NewLookupError returns a new LookupError with type LookupResultError.
func NewLookupError(path ...Label) LookupError {
return LookupError{
Type: LookupResultError,
Path: pathToString(path),
}
}

// NewLookupUnknownError returns a new LookupError with type LookupResultUnknown.
func NewLookupUnknownError(path ...Label) LookupError {
return LookupError{
Type: LookupResultUnknown,
Path: pathToString(path),
}
}

func (l LookupError) Error() string {
return fmt.Sprintf("lookup error (path: %q): %s", l.Path, l.error())
}

func (l LookupError) error() string {
switch l.Type {
case LookupResultAbsent:
return "not found, not present in the tree"
case LookupResultUnknown:
return "not found, could be pruned"
case LookupResultError:
return "error, can not exist in the tree"
default:
return "unknown lookup error"
}
}

// LookupResultType is the type of the lookup result.
// It indicates whether the result is guaranteed to be absent, unknown or is an invalid tree.
type LookupResultType int

const (
// LookupResultAbsent means that the result is guaranteed to be absent.
LookupResultAbsent LookupResultType = iota
// LookupResultUnknown means that the result is unknown, some leaves were pruned.
LookupResultUnknown
// LookupResultError means that the result is an error, the path is not valid in this context.
LookupResultError
)
4 changes: 2 additions & 2 deletions certification/hashtree/hashtree.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ func (t HashTree) Digest() [32]byte {
}

// Lookup looks up a path in the hash tree.
func (t HashTree) Lookup(path ...Label) LookupResult {
func (t HashTree) Lookup(path ...Label) ([]byte, error) {
return lookupPath(t.Root, path...)
}

// LookupSubTree looks up a path in the hash tree and returns the sub-tree.
func (t HashTree) LookupSubTree(path ...Label) LookupSubTreeResult {
func (t HashTree) LookupSubTree(path ...Label) (Node, error) {
return lookupSubTree(t.Root, path...)
}

Expand Down
23 changes: 13 additions & 10 deletions certification/hashtree/hashtree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package hashtree
import (
"bytes"
"encoding/hex"
"errors"
"fmt"
"testing"
)
Expand All @@ -29,23 +30,24 @@ func TestHashTree_Lookup(t *testing.T) {
},
})

var lookupError LookupError
for _, i := range []int{0, 1} {
if result := tree.Lookup(Label(fmt.Sprintf("label %d", i))); result.Type != LookupResultAbsent {
if _, err := tree.Lookup(Label(fmt.Sprintf("label %d", i))); !errors.As(err, &lookupError) || lookupError.Type != LookupResultAbsent {
t.Fatalf("unexpected lookup result")
}
}
if result := tree.Lookup(Label("label 2")); result.Type != LookupResultUnknown {
if _, err := tree.Lookup(Label("label 2")); !errors.As(err, &lookupError) || lookupError.Type != LookupResultUnknown {
t.Fatalf("unexpected lookup result")
}
if result := tree.Lookup(Label("label 3")); result.Type != LookupResultFound {
if v, err := tree.Lookup(Label("label 3")); err != nil {
t.Fatalf("unexpected lookup result")
} else {
if !bytes.Equal(result.Value, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}) {
if !bytes.Equal(v, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}) {
t.Fatalf("unexpected node value")
}
}
for _, i := range []int{4, 5, 6} {
if result := tree.Lookup(Label(fmt.Sprintf("label %d", i))); result.Type != LookupResultAbsent {
if _, err := tree.Lookup(Label(fmt.Sprintf("label %d", i))); !errors.As(err, &lookupError) || lookupError.Type != LookupResultAbsent {
t.Fatalf("unexpected lookup result")
}
}
Expand Down Expand Up @@ -78,24 +80,25 @@ func TestHashTree_Lookup(t *testing.T) {
RightTree: Pruned{},
},
})
var lookupError LookupError
for _, i := range []int{0, 1, 2} {
if result := tree.Lookup(Label(fmt.Sprintf("label %d", i))); result.Type != LookupResultAbsent {
if _, err := tree.Lookup(Label(fmt.Sprintf("label %d", i))); !errors.As(err, &lookupError) || lookupError.Type != LookupResultAbsent {
t.Fatalf("unexpected lookup result")
}
}
if result := tree.Lookup(Label("label 3")); result.Type != LookupResultFound {
if v, err := tree.Lookup(Label("label 3")); err != nil {
t.Fatalf("unexpected lookup result")
} else {
if !bytes.Equal(result.Value, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}) {
if !bytes.Equal(v, []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}) {
t.Fatalf("unexpected node value")
}
}
for _, i := range []int{4, 5} {
if result := tree.Lookup(Label(fmt.Sprintf("label %d", i))); result.Type != LookupResultAbsent {
if _, err := tree.Lookup(Label(fmt.Sprintf("label %d", i))); !errors.As(err, &lookupError) || lookupError.Type != LookupResultAbsent {
t.Fatalf("unexpected lookup result")
}
}
if result := tree.Lookup(Label("label 6")); result.Type != LookupResultUnknown {
if _, err := tree.Lookup(Label("label 6")); !errors.As(err, &lookupError) || lookupError.Type != LookupResultUnknown {
t.Fatalf("unexpected lookup result")
}
})
Expand Down
Loading

0 comments on commit b8dc5b4

Please sign in to comment.