Skip to content

Commit

Permalink
Fix calls to management canister
Browse files Browse the repository at this point in the history
This fixes an issue in the RequestID computation where an empty slice
canister ID would be considered as "canister_id not set". This was not
quite correct, because the management canister ID is the empty slice
(encoded as "aaaaa-aa").

This changes the empty check for a `nil` check instead. Usages of the
effective canister ID vs. canister ID are also clarified.
  • Loading branch information
nmattia authored and q-uint committed Mar 28, 2024
1 parent 4990206 commit deac993
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 20 deletions.
45 changes: 26 additions & 19 deletions agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/aviate-labs/agent-go/certification/hashtree"
"github.com/aviate-labs/agent-go/identity"
"github.com/aviate-labs/agent-go/principal"
"github.com/aviate-labs/agent-go/ic"

"github.com/fxamacker/cbor/v2"
)
Expand All @@ -28,7 +29,11 @@ var icp0, _ = url.Parse("https://icp0.io/")

func effectiveCanisterID(canisterId principal.Principal, args []any) principal.Principal {
// If the canisterId is not aaaaa-aa, return it.
if len(canisterId.Raw) > 0 || len(args) == 0 {
if canisterId.Encode() != ic.MANAGEMENT_CANISTER_PRINCIPAL.Encode() {
return canisterId
}

if(len(args) < 1) {
return canisterId
}

Expand Down Expand Up @@ -135,12 +140,14 @@ func (a Agent) Call(canisterID principal.Principal, methodName string, args []an
if err != nil {
return err
}
canisterID = effectiveCanisterID(canisterID, args)
a.logger.Printf("[AGENT] CALL %s %s", canisterID, methodName)
if _, err := a.call(canisterID, data); err != nil {
ecID := effectiveCanisterID(canisterID, args)
a.logger.Printf("[AGENT] CALL %s (ecid: %s) %s", canisterID, ecID, hex.EncodeToString(a.identity.PublicKey()), methodName)

if _, err := a.call(ecID, data); err != nil {
return err
}
raw, err := a.poll(canisterID, *requestID, time.Second, time.Second*10)

raw, err := a.poll(ecID, *requestID, time.Second, time.Second*10)
if err != nil {
return err
}
Expand Down Expand Up @@ -255,18 +262,18 @@ func (a Agent) Query(canisterID principal.Principal, methodName string, args []a
}

// RequestStatus returns the status of the request with the given ID.
func (a Agent) RequestStatus(canisterID principal.Principal, requestID RequestID) ([]byte, hashtree.Node, error) {
a.logger.Printf("[AGENT] REQUEST STATUS %s", requestID)
func (a Agent) RequestStatus(ecID principal.Principal, requestID RequestID) ([]byte, hashtree.Node, error) {
a.logger.Printf("[AGENT] REQUEST STATUS %s", hex.EncodeToString(requestID[:]));
path := []hashtree.Label{hashtree.Label("request_status"), requestID[:]}
c, err := a.readStateCertificate(canisterID, [][]hashtree.Label{path})
c, err := a.readStateCertificate(ecID, [][]hashtree.Label{path})
if err != nil {
return nil, nil, err
}
var state map[string]any
if err := cbor.Unmarshal(c, &state); err != nil {
return nil, nil, err
}
cert, err := certification.New(canisterID, a.rootKey[len(a.rootKey)-96:], c)
cert, err := certification.New(ecID, a.rootKey[len(a.rootKey)-96:], c)
if err != nil {
return nil, nil, err
}
Expand All @@ -289,22 +296,22 @@ func (a Agent) Sender() principal.Principal {
return a.identity.Sender()
}

func (a Agent) call(canisterID principal.Principal, data []byte) ([]byte, error) {
return a.client.call(canisterID, data)
func (a Agent) call(ecid principal.Principal, data []byte) ([]byte, error) {
return a.client.call(ecid, data)
}

func (a Agent) expiryDate() uint64 {
return uint64(time.Now().Add(a.ingressExpiry).UnixNano())
}

func (a Agent) poll(canisterID principal.Principal, requestID RequestID, delay, timeout time.Duration) ([]byte, error) {
func (a Agent) poll(ecID principal.Principal, requestID RequestID, delay, timeout time.Duration) ([]byte, error) {
ticker := time.NewTicker(delay)
timer := time.NewTimer(timeout)
for {
select {
case <-ticker.C:
a.logger.Printf("[AGENT] POLL %s", requestID)
data, node, err := a.RequestStatus(canisterID, requestID)
a.logger.Printf("[AGENT] POLL (reqID: %s) ", hex.EncodeToString(requestID[:]))
data, node, err := a.RequestStatus(ecID, requestID)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -346,16 +353,16 @@ func (a Agent) query(canisterID principal.Principal, data []byte) (*Response, er
return queryResponse, cbor.Unmarshal(resp, queryResponse)
}

func (a Agent) readState(canisterID principal.Principal, data []byte) (map[string][]byte, error) {
resp, err := a.client.readState(canisterID, data)
func (a Agent) readState(ecID principal.Principal, data []byte) (map[string][]byte, error) {
resp, err := a.client.readState(ecID, data)
if err != nil {
return nil, err
}
var m map[string][]byte
return m, cbor.Unmarshal(resp, &m)
}

func (a Agent) readStateCertificate(canisterID principal.Principal, paths [][]hashtree.Label) ([]byte, error) {
func (a Agent) readStateCertificate(ecID principal.Principal, paths [][]hashtree.Label) ([]byte, error) {
_, data, err := a.sign(Request{
Type: RequestTypeReadState,
Sender: a.Sender(),
Expand All @@ -365,8 +372,8 @@ func (a Agent) readStateCertificate(canisterID principal.Principal, paths [][]ha
if err != nil {
return nil, err
}
a.logger.Printf("[AGENT] READ STATE %s", canisterID)
resp, err := a.readState(canisterID, data)
a.logger.Printf("[AGENT] READ STATE %s (ecID)", ecID)
resp, err := a.readState(ecID, data)
if err != nil {
return nil, err
}
Expand Down
4 changes: 3 additions & 1 deletion request.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ func NewRequestID(req Request) RequestID {
typeHash := sha256.Sum256([]byte(req.Type))
hashes = append(hashes, append(typeKey[:], typeHash[:]...))
}
if len(req.CanisterID.Raw) != 0 {
// NOTE: the canister ID may be the empty slice. The empty slice doesn't mean it's not
// set, it means it's the management canister (aaaaa-aa).
if req.CanisterID.Raw != nil {
canisterIDHash := sha256.Sum256(req.CanisterID.Raw)
hashes = append(hashes, append(canisterIDKey[:], canisterIDHash[:]...))
}
Expand Down

0 comments on commit deac993

Please sign in to comment.