Skip to content

Commit

Permalink
Add http response verification (v2).
Browse files Browse the repository at this point in the history
  • Loading branch information
q-uint committed Nov 22, 2023
1 parent c8becbe commit 8a9768d
Show file tree
Hide file tree
Showing 30 changed files with 1,019 additions and 147 deletions.
21 changes: 21 additions & 0 deletions agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,32 @@ func (a Agent) GetCanisterInfo(canisterID principal.Principal, subPath string) (
return certificate.Lookup(path, node), nil
}

func (a Agent) GetCanisterMetadata(canisterID principal.Principal, subPath string) ([]byte, error) {
path := [][]byte{[]byte("canister"), canisterID.Raw, []byte("metadata"), []byte(subPath)}
c, err := a.readStateCertificate(canisterID, [][][]byte{path})
if err != nil {
return nil, err
}
var state map[string]any
if err := cbor.Unmarshal(c, &state); err != nil {
return nil, err
}
node, err := certificate.DeserializeNode(state["tree"].([]any))
if err != nil {
return nil, err
}
return certificate.Lookup(path, node), nil
}

// GetCanisterModuleHash returns the module hash for the given canister.
func (a Agent) GetCanisterModuleHash(canisterID principal.Principal) ([]byte, error) {
return a.GetCanisterInfo(canisterID, "module_hash")
}

func (a Agent) GetRootKey() []byte {
return a.rootKey
}

func (a Agent) Query(canisterID principal.Principal, methodName string, args []any, values []any) error {
rawArgs, err := idl.Marshal(args)
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions candid/internal/blob/grammar.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Do not edit. This file is auto-generated.
// Grammar: CANDID-BLOB (v0.1.0) github.com/di-wu/candid-go/internal/blob
// Grammar: CANDID-BLOB (v0.1.0) github.com/aviate-labs/agent-go/candid/internal/blob

package blob

Expand All @@ -13,7 +13,7 @@ import (
const (
Unknown = iota

// CANDID-BLOB (github.com/di-wu/candid-go/internal/blob)
// CANDID-BLOB (github.com/aviate-labs/agent-go/candid/internal/blob)

BlobT // 001
AlphaT // 002
Expand All @@ -23,7 +23,7 @@ const (
var NodeTypes = []string{
"UNKNOWN",

// CANDID-BLOB (github.com/di-wu/candid-go/internal/blob)
// CANDID-BLOB (github.com/aviate-labs/agent-go/candid/internal/blob)

"Blob",
"Alpha",
Expand Down
2 changes: 1 addition & 1 deletion candid/internal/blob/grammar.pegn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# CANDID-BLOB (v0.1.0) github.com/di-wu/candid-go/internal/blob
# CANDID-BLOB (v0.1.0) github.com/aviate-labs/agent-go/candid/internal/blob

Blob <-- (Alpha / '\' Hex)+
Alpha <-- ([A-Z] / [a-z])+
Expand Down
8 changes: 4 additions & 4 deletions candid/internal/candid/grammar.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Do not edit. This file is auto-generated.
// Grammar: CANDID (v0.1.1) github.com/di-wu/candid-go/internal/candid
// Grammar: CANDID (v0.1.1) github.com/aviate-labs/agent-go/candid/internal/candid

package candid

Expand All @@ -13,7 +13,7 @@ import (
const (
Unknown = iota

// CANDID (github.com/di-wu/candid-go/internal/candid)
// CANDID (github.com/aviate-labs/agent-go/candid/internal/candid)

ProgT // 001
TypeT // 002
Expand Down Expand Up @@ -44,15 +44,15 @@ const (

// Token Definitions
const (
// CANDID (github.com/di-wu/candid-go/internal/candid)
// CANDID (github.com/aviate-labs/agent-go/candid/internal/candid)

ESC = 0x005C // \
)

var NodeTypes = []string{
"UNKNOWN",

// CANDID (github.com/di-wu/candid-go/internal/candid)
// CANDID (github.com/aviate-labs/agent-go/candid/internal/candid)

"Prog",
"Type",
Expand Down
2 changes: 1 addition & 1 deletion candid/internal/candid/grammar.pegn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# CANDID (v0.1.1) github.com/di-wu/candid-go/internal/candid
# CANDID (v0.1.1) github.com/aviate-labs/agent-go/candid/internal/candid

Prog <-- (Ws Def (';' Ws Def)*)? ';'? Ws
(Ws Actor (';' Ws Actor)*)? ';'? Ws
Expand Down
8 changes: 4 additions & 4 deletions candid/internal/candidtest/grammar.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Do not edit. This file is auto-generated.
// Grammar: CANDID-TEST (v0.1.0) github.com/di-wu/candid-go/internal/candidtest
// Grammar: CANDID-TEST (v0.1.0) github.com/aviate-labs/agent-go/candid/internal/candidtest

package candidtest

Expand All @@ -13,7 +13,7 @@ import (
const (
Unknown = iota

// CANDID-TEST (github.com/di-wu/candid-go/internal/candidtest)
// CANDID-TEST (github.com/aviate-labs/agent-go/candid/internal/candidtest)

TestDataT // 001
CommentTextT // 002
Expand All @@ -38,15 +38,15 @@ const (

// Token Definitions
const (
// CANDID-TEST (github.com/di-wu/candid-go/internal/candidtest)
// CANDID-TEST (github.com/aviate-labs/agent-go/candid/internal/candidtest)

ESC = 0x005C // \
)

var NodeTypes = []string{
"UNKNOWN",

// CANDID-TEST (github.com/di-wu/candid-go/internal/candidtest)
// CANDID-TEST (github.com/aviate-labs/agent-go/candid/internal/candidtest)

"TestData",
"CommentText",
Expand Down
2 changes: 1 addition & 1 deletion candid/internal/candidtest/grammar.pegn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# CANDID-TEST (v0.1.0) github.com/di-wu/candid-go/internal/candidtest
# CANDID-TEST (v0.1.0) github.com/aviate-labs/agent-go/candid/internal/candidtest

TestData <-- (Comment / Test / EndLine)+

Expand Down
8 changes: 4 additions & 4 deletions candid/internal/candidvalue/grammar.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Do not edit. This file is auto-generated.
// Grammar: CANDID (v0.1.0) github.com/di-wu/candid-go/internal/candid/candidvalue
// Grammar: CANDID (v0.1.0) github.com/aviate-labs/agent-go/candid/internal/candid/candidvalue

package candidvalue

Expand All @@ -13,7 +13,7 @@ import (
const (
Unknown = iota

// CANDID (github.com/di-wu/candid-go/internal/candid/candidvalue)
// CANDID (github.com/aviate-labs/agent-go/candid/internal/candid/candidvalue)

ValuesT // 001
OptValueT // 002
Expand All @@ -35,15 +35,15 @@ const (

// Token Definitions
const (
// CANDID (github.com/di-wu/candid-go/internal/candid/candidvalue)
// CANDID (github.com/aviate-labs/agent-go/candid/internal/candid/candidvalue)

ESC = 0x005C // \
)

var NodeTypes = []string{
"UNKNOWN",

// CANDID (github.com/di-wu/candid-go/internal/candid/candidvalue)
// CANDID (github.com/aviate-labs/agent-go/candid/internal/candid/candidvalue)

"Values",
"OptValue",
Expand Down
2 changes: 1 addition & 1 deletion candid/internal/candidvalue/grammar.pegn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# CANDID (v0.1.0) github.com/di-wu/candid-go/internal/candid/candidvalue
# CANDID (v0.1.0) github.com/aviate-labs/agent-go/candid/internal/candid/candidvalue

Values <-- '(' Sp (Value (Sp ',' Sp Value)*)? Sp ')' / Value
Value <- OptValue / Num / Bool / Null / Text / Record / Variant / Principal / Vec / Blob
Expand Down
3 changes: 2 additions & 1 deletion candid/internal/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package main

import (
"fmt"
pegn "github.com/pegn/pegn-go"
"io/ioutil"
"log"
)
Expand All @@ -20,7 +21,7 @@ func main() {
} {
rawGrammar, _ := ioutil.ReadFile(fmt.Sprintf("%s/grammar.pegn", grammar.path))
if err := pegn.GenerateFromFiles(fmt.Sprintf("%s/", grammar.path), pegn.Config{
ModulePath: fmt.Sprintf("github.com/di-wu/candid-go/%s", grammar.path),
ModulePath: fmt.Sprintf("github.com/aviate-labs/agent-go/candid/%s", grammar.path),
ModuleName: grammar.name,
IgnoreReserved: true,
TypeSuffix: "T",
Expand Down
33 changes: 17 additions & 16 deletions certificate/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ type Cert struct {
// Certificate is a certificate gets returned by the IC and can be used to verify
// the state root based on the root key and canister ID.
type Certificate struct {
cert Cert
rootKey []byte
canisterID principal.Principal
Cert Cert
RootKey []byte
CanisterID principal.Principal
}

// New creates a new certificate.
Expand All @@ -33,23 +33,23 @@ func New(canisterID principal.Principal, rootKey []byte, certificate []byte) (*C
return nil, err
}
return &Certificate{
cert: cert,
rootKey: rootKey,
canisterID: canisterID,
Cert: cert,
RootKey: rootKey,
CanisterID: canisterID,
}, nil
}

// Verify verifies the certificate.
func (c Certificate) Verify() error {
signature, err := bls.SignatureFromBytes(c.cert.Signature)
signature, err := bls.SignatureFromBytes(c.Cert.Signature)
if err != nil {
return err
}
publicKey, err := c.getPublicKey()
if err != nil {
return err
}
rootHash := c.cert.Tree.Digest()
rootHash := c.Cert.Tree.Digest()
message := append(DomainSeparator("ic-state-root"), rootHash[:]...)
if !signature.Verify(publicKey, string(message)) {
return fmt.Errorf("signature verification failed")
Expand All @@ -59,13 +59,14 @@ func (c Certificate) Verify() error {

// getPublicKey checks the delegation and returns the public key.
func (c Certificate) getPublicKey() (*bls.PublicKey, error) {
if c.cert.Delegation == nil {
return bls.PublicKeyFromBytes(c.rootKey)
if c.Cert.Delegation == nil {
return bls.PublicKeyFromBytes(c.RootKey)
}
cert := c.cert.Delegation

cert := c.Cert.Delegation
canisterRanges := Lookup(
LookupPath("subnet", string(cert.SubnetId.Raw), "canister_ranges"),
cert.Certificate.cert.Tree.root,
cert.Certificate.Cert.Tree.Root,
)
if canisterRanges == nil {
return nil, fmt.Errorf("no canister ranges found for subnet %s", cert.SubnetId)
Expand All @@ -80,18 +81,18 @@ func (c Certificate) getPublicKey() (*bls.PublicKey, error) {
if len(pair) != 2 {
return nil, fmt.Errorf("invalid range: %v", pair)
}
if slices.Compare(pair[0], c.canisterID.Raw) <= 0 && slices.Compare(c.canisterID.Raw, pair[1]) <= 0 {
if slices.Compare(pair[0], c.CanisterID.Raw) <= 0 && slices.Compare(c.CanisterID.Raw, pair[1]) <= 0 {
inRange = true
break
}
}
if !inRange {
return nil, fmt.Errorf("canister %s is not in range", c.canisterID)
return nil, fmt.Errorf("canister %s is not in range", c.CanisterID)
}

publicKey := Lookup(
LookupPath("subnet", string(cert.SubnetId.Raw), "public_key"),
cert.Certificate.cert.Tree.root,
cert.Certificate.Cert.Tree.Root,
)
if publicKey == nil {
return nil, fmt.Errorf("no public key found for subnet %s", cert.SubnetId)
Expand Down Expand Up @@ -131,7 +132,7 @@ func (d *Delegation) UnmarshalCBOR(bytes []byte) error {
Raw: v.([]byte),
}
case "certificate":
if err := cbor.Unmarshal(v.([]byte), &d.Certificate.cert); err != nil {
if err := cbor.Unmarshal(v.([]byte), &d.Certificate.Cert); err != nil {
return err
}
default:
Expand Down
5 changes: 5 additions & 0 deletions certificate/http/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# HTTP Gateway Protocol

## References

- [Specification](https://internetcomputer.org/docs/current/references/http-gateway-protocol-spec)
Loading

0 comments on commit 8a9768d

Please sign in to comment.