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

Fix calls to management canister #17

Merged
merged 2 commits into from
Mar 28, 2024
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
46 changes: 26 additions & 20 deletions agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@ var DefaultConfig = Config{}
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 the canisterId is not aaaaa-aa (encoded as empty byte array), return it.
if len(canisterId.Raw) > 0 {
return canisterId
}

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

Expand Down Expand Up @@ -135,12 +139,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) %x", canisterID, ecID, 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 +261,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) {
nmattia marked this conversation as resolved.
Show resolved Hide resolved
a.logger.Printf("[AGENT] REQUEST STATUS %x", 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 +295,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) {
q-uint marked this conversation as resolved.
Show resolved Hide resolved
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) {
q-uint marked this conversation as resolved.
Show resolved Hide resolved
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: %x) ", requestID[:])
data, node, err := a.RequestStatus(ecID, requestID)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -346,16 +352,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) {
q-uint marked this conversation as resolved.
Show resolved Hide resolved
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) {
q-uint marked this conversation as resolved.
Show resolved Hide resolved
_, data, err := a.sign(Request{
Type: RequestTypeReadState,
Sender: a.Sender(),
Expand All @@ -365,8 +371,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)
nmattia marked this conversation as resolved.
Show resolved Hide resolved
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