Skip to content

Commit c9cafc1

Browse files
committed
Fix v3 reject errors.
1 parent 814e768 commit c9cafc1

File tree

6 files changed

+117
-65
lines changed

6 files changed

+117
-65
lines changed

agent.go

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,19 @@ func effectiveCanisterID(canisterID principal.Principal, args []any) principal.P
6262
}
6363
}
6464

65+
func handleStatus(path []hashtree.Label, certificate *certification.Certificate) ([]byte, hashtree.Node, error) {
66+
status, err := certificate.Tree.Lookup(append(path, hashtree.Label("status"))...)
67+
var lookupError hashtree.LookupError
68+
if errors.As(err, &lookupError) && lookupError.Type == hashtree.LookupResultAbsent {
69+
// The status might not be available immediately, since the request is still being processed.
70+
return nil, nil, nil
71+
}
72+
if err != nil {
73+
return nil, nil, err
74+
}
75+
return status, certificate.Tree.Root, nil
76+
}
77+
6578
func newNonce() ([]byte, error) {
6679
/* Read 10 bytes of random data, which is smaller than the max allowed by the IC (32 bytes)
6780
* and should still be enough from a practical point of view. */
@@ -320,19 +333,6 @@ func (a Agent) RequestStatus(ecID principal.Principal, requestID RequestID) ([]b
320333
return handleStatus(path, certificate)
321334
}
322335

323-
func handleStatus(path []hashtree.Label, certificate *certification.Certificate) ([]byte, hashtree.Node, error) {
324-
status, err := certificate.Tree.Lookup(append(path, hashtree.Label("status"))...)
325-
var lookupError hashtree.LookupError
326-
if errors.As(err, &lookupError) && lookupError.Type == hashtree.LookupResultAbsent {
327-
// The status might not be available immediately, since the request is still being processed.
328-
return nil, nil, nil
329-
}
330-
if err != nil {
331-
return nil, nil, err
332-
}
333-
return status, certificate.Tree.Root, nil
334-
}
335-
336336
// Sender returns the principal that is sending the requests.
337337
func (a Agent) Sender() principal.Principal {
338338
return a.identity.Sender()
@@ -362,6 +362,12 @@ func (a Agent) poll(ecID principal.Principal, requestID RequestID) ([]byte, erro
362362
if len(data) != 0 {
363363
path := []hashtree.Label{hashtree.Label("request_status"), requestID[:]}
364364
switch string(data) {
365+
case "replied":
366+
replied, err := hashtree.Lookup(node, append(path, hashtree.Label("reply"))...)
367+
if err != nil {
368+
return nil, fmt.Errorf("no reply found")
369+
}
370+
return replied, nil
365371
case "rejected":
366372
tree := hashtree.NewHashTree(node)
367373
code, err := tree.Lookup(append(path, hashtree.Label("reject_code"))...)
@@ -373,12 +379,6 @@ func (a Agent) poll(ecID principal.Principal, requestID RequestID) ([]byte, erro
373379
return nil, err
374380
}
375381
return nil, fmt.Errorf("(%d) %s", uint64FromBytes(code), string(message))
376-
case "replied":
377-
replied, err := hashtree.Lookup(node, append(path, hashtree.Label("reply"))...)
378-
if err != nil {
379-
return nil, fmt.Errorf("no reply found")
380-
}
381-
return replied, nil
382382
}
383383
}
384384
case <-timer.C:

agent_test.go

Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package agent_test
22

33
import (
4+
"encoding/hex"
45
"encoding/json"
56
"fmt"
67
"testing"
@@ -19,20 +20,38 @@ var (
1920

2021
var _ = new(testLogger)
2122

22-
func Example_anonymous_query() {
23+
func Example_anonymous_call() {
2324
a, _ := agent.New(agent.DefaultConfig)
24-
type Account struct {
25-
Account string `ic:"account"`
25+
var balance struct {
26+
E8S uint64 `ic:"e8s"`
2627
}
28+
29+
accountID, _ := hex.DecodeString("9523dc824aa062dcd9c91b98f4594ff9c6af661ac96747daef2090b7fe87037d")
30+
err := a.Call(LEDGER_PRINCIPAL, "account_balance", []any{
31+
struct {
32+
Account []byte `ic:"account"`
33+
}{Account: accountID},
34+
}, []any{&balance})
35+
fmt.Println(balance.E8S, err)
36+
// Output:
37+
// 0 <nil>
38+
}
39+
40+
func Example_anonymous_query() {
41+
a, _ := agent.New(agent.DefaultConfig)
2742
var balance struct {
2843
E8S uint64 `ic:"e8s"`
2944
}
30-
_ = a.Query(LEDGER_PRINCIPAL, "account_balance_dfx", []any{
31-
Account{"9523dc824aa062dcd9c91b98f4594ff9c6af661ac96747daef2090b7fe87037d"},
45+
46+
accountID, _ := hex.DecodeString("9523dc824aa062dcd9c91b98f4594ff9c6af661ac96747daef2090b7fe87037d")
47+
err := a.Query(LEDGER_PRINCIPAL, "account_balance", []any{
48+
struct {
49+
Account []byte `ic:"account"`
50+
}{Account: accountID},
3251
}, []any{&balance})
33-
fmt.Println(balance.E8S)
52+
fmt.Println(balance.E8S, err)
3453
// Output:
35-
// 0
54+
// 0 <nil>
3655
}
3756

3857
func Example_json() {
@@ -45,10 +64,11 @@ func Example_json() {
4564
fmt.Println(balance.E8S)
4665

4766
a, _ := agent.New(agent.DefaultConfig)
48-
if err := a.Query(LEDGER_PRINCIPAL, "account_balance_dfx", []any{struct {
49-
Account string `json:"account"`
67+
accountID, _ := hex.DecodeString("9523dc824aa062dcd9c91b98f4594ff9c6af661ac96747daef2090b7fe87037d")
68+
if err := a.Query(LEDGER_PRINCIPAL, "account_balance", []any{struct {
69+
Account []byte `json:"account"`
5070
}{
51-
Account: "9523dc824aa062dcd9c91b98f4594ff9c6af661ac96747daef2090b7fe87037d",
71+
Account: accountID,
5272
}}, []any{&balance}); err != nil {
5373
fmt.Println(err)
5474
}
@@ -66,8 +86,10 @@ func Example_query_ed25519() {
6686
var balance struct {
6787
E8S uint64 `ic:"e8s"`
6888
}
69-
_ = a.Query(ledgerID, "account_balance_dfx", []any{map[string]any{
70-
"account": "9523dc824aa062dcd9c91b98f4594ff9c6af661ac96747daef2090b7fe87037d",
89+
90+
accountID, _ := hex.DecodeString("9523dc824aa062dcd9c91b98f4594ff9c6af661ac96747daef2090b7fe87037d")
91+
_ = a.Query(ledgerID, "account_balance", []any{map[string]any{
92+
"account": accountID,
7193
}}, []any{&balance})
7294
fmt.Println(balance.E8S)
7395
// Output:
@@ -76,13 +98,14 @@ func Example_query_ed25519() {
7698

7799
func Example_query_prime256v1() {
78100
id, _ := identity.NewRandomPrime256v1Identity()
79-
ledgerID := principal.MustDecode("ryjl3-tyaaa-aaaaa-aaaba-cai")
80101
a, _ := agent.New(agent.Config{Identity: id})
81102
var balance struct {
82103
E8S uint64 `ic:"e8s"`
83104
}
84-
_ = a.Query(ledgerID, "account_balance_dfx", []any{map[string]any{
85-
"account": "9523dc824aa062dcd9c91b98f4594ff9c6af661ac96747daef2090b7fe87037d",
105+
106+
accountID, _ := hex.DecodeString("9523dc824aa062dcd9c91b98f4594ff9c6af661ac96747daef2090b7fe87037d")
107+
_ = a.Query(LEDGER_PRINCIPAL, "account_balance", []any{map[string]any{
108+
"account": accountID,
86109
}}, []any{&balance})
87110
fmt.Println(balance.E8S)
88111
// Output:
@@ -91,13 +114,14 @@ func Example_query_prime256v1() {
91114

92115
func Example_query_secp256k1() {
93116
id, _ := identity.NewRandomSecp256k1Identity()
94-
ledgerID := principal.MustDecode("ryjl3-tyaaa-aaaaa-aaaba-cai")
95117
a, _ := agent.New(agent.Config{Identity: id})
96118
var balance struct {
97119
E8S uint64 `ic:"e8s"`
98120
}
99-
_ = a.Query(ledgerID, "account_balance_dfx", []any{map[string]any{
100-
"account": "9523dc824aa062dcd9c91b98f4594ff9c6af661ac96747daef2090b7fe87037d",
121+
122+
accountID, _ := hex.DecodeString("9523dc824aa062dcd9c91b98f4594ff9c6af661ac96747daef2090b7fe87037d")
123+
_ = a.Query(LEDGER_PRINCIPAL, "account_balance", []any{map[string]any{
124+
"account": accountID,
101125
}}, []any{&balance})
102126
fmt.Println(balance.E8S)
103127
// Output:
@@ -129,14 +153,15 @@ func TestAgent_Query_Ed25519(t *testing.T) {
129153
a, _ := agent.New(agent.Config{
130154
Identity: id,
131155
})
132-
type Account struct {
133-
Account string `ic:"account"`
134-
}
135156
var balance struct {
136157
E8S uint64 `ic:"e8s"`
137158
}
138-
if err := a.Query(LEDGER_PRINCIPAL, "account_balance_dfx", []any{
139-
Account{"9523dc824aa062dcd9c91b98f4594ff9c6af661ac96747daef2090b7fe87037d"},
159+
160+
accountID, _ := hex.DecodeString("9523dc824aa062dcd9c91b98f4594ff9c6af661ac96747daef2090b7fe87037d")
161+
if err := a.Query(LEDGER_PRINCIPAL, "account_balance", []any{
162+
struct {
163+
Account []byte `ic:"account"`
164+
}{Account: accountID},
140165
}, []any{&balance}); err != nil {
141166
t.Fatal(err)
142167
}
@@ -150,14 +175,15 @@ func TestAgent_Query_Secp256k1(t *testing.T) {
150175
a, _ := agent.New(agent.Config{
151176
Identity: id,
152177
})
153-
type Account struct {
154-
Account string `ic:"account"`
155-
}
156178
var balance struct {
157179
E8S uint64 `ic:"e8s"`
158180
}
159-
if err := a.Query(LEDGER_PRINCIPAL, "account_balance_dfx", []any{
160-
Account{"9523dc824aa062dcd9c91b98f4594ff9c6af661ac96747daef2090b7fe87037d"},
181+
182+
accountID, _ := hex.DecodeString("9523dc824aa062dcd9c91b98f4594ff9c6af661ac96747daef2090b7fe87037d")
183+
if err := a.Query(LEDGER_PRINCIPAL, "account_balance", []any{
184+
struct {
185+
Account []byte `ic:"account"`
186+
}{Account: accountID},
161187
}, []any{&balance}); err != nil {
162188
t.Fatal(err)
163189
}
@@ -168,7 +194,6 @@ func TestAgent_Query_callback(t *testing.T) {
168194
if err != nil {
169195
t.Fatal(err)
170196
}
171-
ledgerCanisterID := principal.MustDecode("ryjl3-tyaaa-aaaaa-aaaba-cai")
172197

173198
type GetBlocksArgs struct {
174199
Start uint64 `ic:"start" json:"start"`
@@ -195,7 +220,7 @@ func TestAgent_Query_callback(t *testing.T) {
195220
}
196221
req, err := a.CreateCandidAPIRequest(
197222
agent.RequestTypeQuery,
198-
ledgerCanisterID,
223+
LEDGER_PRINCIPAL,
199224
"query_blocks",
200225
args,
201226
)
@@ -301,6 +326,15 @@ func TestAgent_Query_callback(t *testing.T) {
301326
}
302327
}
303328

329+
func TestCall_invalid(t *testing.T) {
330+
a, _ := agent.New(agent.DefaultConfig)
331+
qErr := a.Query(LEDGER_PRINCIPAL, "account_balance", []any{}, []any{})
332+
cErr := a.Call(LEDGER_PRINCIPAL, "account_balance", []any{}, []any{})
333+
if qErr != cErr {
334+
t.Error(qErr, cErr)
335+
}
336+
}
337+
304338
type testLogger struct{}
305339

306340
func (t testLogger) Printf(format string, v ...any) {

call.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package agent
22

33
import (
4-
"fmt"
5-
64
"github.com/aviate-labs/agent-go/certification"
75
"github.com/aviate-labs/agent-go/certification/hashtree"
86
"github.com/aviate-labs/agent-go/principal"
@@ -22,11 +20,28 @@ func (c APIRequest[_, Out]) CallAndWait(out Out) error {
2220
if err := cbor.Unmarshal(rawCertificate, &certificate); err != nil {
2321
return err
2422
}
25-
raw, err := hashtree.Lookup(certificate.Tree.Root, hashtree.Label("request_status"), c.requestID[:], hashtree.Label("reply"))
23+
path := []hashtree.Label{hashtree.Label("request_status"), c.requestID[:]}
24+
if raw, err := certificate.Tree.Lookup(append(path, hashtree.Label("reply"))...); err == nil {
25+
return c.unmarshal(raw, out)
26+
}
27+
28+
rejectCode, err := certificate.Tree.Lookup(append(path, hashtree.Label("reject_code"))...)
29+
if err != nil {
30+
return err
31+
}
32+
message, err := certificate.Tree.Lookup(append(path, hashtree.Label("reject_message"))...)
2633
if err != nil {
27-
return fmt.Errorf("no reply found")
34+
return err
35+
}
36+
errorCode, err := certificate.Tree.Lookup(append(path, hashtree.Label("error_code"))...)
37+
if err != nil {
38+
return err
39+
}
40+
return preprocessingError{
41+
RejectCode: uint64FromBytes(rejectCode),
42+
Message: string(message),
43+
ErrorCode: string(errorCode),
2844
}
29-
return c.unmarshal(raw, out)
3045
}
3146

3247
raw, err := c.a.poll(c.effectiveCanisterID, c.requestID)

client_test.go

Lines changed: 0 additions & 1 deletion
This file was deleted.

clients/registry/client_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,38 @@ import (
88
"github.com/aviate-labs/agent-go/principal"
99
)
1010

11-
func TestClient_GetNodeListSince(t *testing.T) {
11+
func TestClient_GetNNSSubnetID(t *testing.T) {
1212
checkEnabled(t)
1313

1414
c, err := registry.New()
1515
if err != nil {
1616
t.Fatal(err)
1717
}
1818

19-
latestVersion, err := c.GetLatestVersion()
19+
id, err := c.GetNNSSubnetID()
2020
if err != nil {
2121
t.Fatal(err)
2222
}
23-
24-
if _, err := c.GetNodeListSince(latestVersion - 100); err != nil {
25-
t.Fatal(err)
23+
if !id.Equal(principal.MustDecode("tdb26-jop6k-aogll-7ltgs-eruif-6kk7m-qpktf-gdiqx-mxtrf-vb5e6-eqe")) {
24+
t.Error(id)
2625
}
2726
}
2827

29-
func TestClient_GetNNSSubnetID(t *testing.T) {
28+
func TestClient_GetNodeListSince(t *testing.T) {
3029
checkEnabled(t)
3130

3231
c, err := registry.New()
3332
if err != nil {
3433
t.Fatal(err)
3534
}
3635

37-
id, err := c.GetNNSSubnetID()
36+
latestVersion, err := c.GetLatestVersion()
3837
if err != nil {
3938
t.Fatal(err)
4039
}
41-
if !id.Equal(principal.MustDecode("tdb26-jop6k-aogll-7ltgs-eruif-6kk7m-qpktf-gdiqx-mxtrf-vb5e6-eqe")) {
42-
t.Error(id)
40+
41+
if _, err := c.GetNodeListSince(latestVersion - 100); err != nil {
42+
t.Fatal(err)
4343
}
4444
}
4545

query.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,11 @@ func (q APIRequest[In, Out]) Query(out Out, skipVerification bool) error {
120120
}
121121
return q.unmarshal(reply.Arg, out)
122122
case "rejected":
123-
return fmt.Errorf("(%d) %s: %s", resp.RejectCode, resp.ErrorCode, resp.RejectMsg)
123+
return preprocessingError{
124+
RejectCode: resp.RejectCode,
125+
Message: resp.RejectMsg,
126+
ErrorCode: resp.ErrorCode,
127+
}
124128
default:
125129
panic("unreachable")
126130
}

0 commit comments

Comments
 (0)