├── .gitignore ├── utils ├── idl │ ├── field.go │ ├── null_test.go │ ├── interface_test.go │ ├── tuple.go │ ├── vec_test.go │ ├── opt_test.go │ ├── principal_test.go │ ├── text_test.go │ ├── errors.go │ ├── hash.go │ ├── tdt.go │ ├── bool_test.go │ ├── rec_test.go │ ├── func_test.go │ ├── service_test.go │ ├── reserved.go │ ├── variant_test.go │ ├── empty.go │ ├── null.go │ ├── Interface.go │ ├── bool.go │ ├── float_test.go │ ├── float.go │ ├── text.go │ ├── util_test.go │ ├── principal.go │ ├── encode.go │ ├── nat.go │ ├── opt.go │ ├── int.go │ ├── vec.go │ ├── int_test.go │ ├── nat_test.go │ ├── tdt_test.go │ ├── rec.go │ ├── type.go │ ├── service.go │ ├── util.go │ ├── variant.go │ ├── func.go │ ├── decode.go │ └── testdata │ │ └── prim.test.did ├── identity │ ├── priv.pem │ ├── identity_test.go │ └── identity.go ├── principal │ └── principal.go └── decode.go ├── constants.go ├── go.mod ├── status_test.go ├── example └── registry │ ├── proto │ ├── mixed_hash_tree.proto │ ├── routing_table.proto │ ├── types.proto │ ├── node_operator.proto │ ├── node.proto │ ├── transport.proto │ ├── subnet.proto │ └── pb │ │ ├── node_operator.pb.go │ │ ├── routing_table.pb.go │ │ └── mixed_hash_tree.pb.go │ ├── registry_test.go │ └── registry.go ├── go.sum ├── request_test.go ├── status.go ├── README.md ├── client.go ├── cerificate.go ├── request.go ├── agent.go ├── agent_test.go └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | utils/idl/.DS_Store 3 | -------------------------------------------------------------------------------- /utils/idl/field.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | type Field struct { 4 | Name string 5 | Type Type 6 | } 7 | -------------------------------------------------------------------------------- /constants.go: -------------------------------------------------------------------------------- 1 | package agent 2 | 3 | const IC_REQUEST_DOMAIN_SEPARATOR = "\x0Aic-request" 4 | const IC_STATE_ROOT_DOMAIN_SEPARATOR = "\x0Dic-state-root" 5 | -------------------------------------------------------------------------------- /utils/identity/priv.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MC4CAQAwBQYDK2VwBCIEIIM/5iQJI3udYux3WHUgkR6adZzsHRl1W32pAbltyj1C 3 | -----END PRIVATE KEY----- 4 | -------------------------------------------------------------------------------- /utils/idl/null_test.go: -------------------------------------------------------------------------------- 1 | package idl_test 2 | 3 | import "github.com/openos-labs/IC-Go/utils/idl" 4 | 5 | func ExampleNull() { 6 | test([]idl.Type{new(idl.Null)}, []interface{}{nil}) 7 | // Output: 8 | // 4449444c00017f 9 | } 10 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/openos-labs/IC-Go 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/aviate-labs/leb128 v0.3.0 7 | github.com/fxamacker/cbor/v2 v2.4.0 8 | github.com/golang/protobuf v1.5.2 9 | google.golang.org/protobuf v1.27.1 10 | ) 11 | -------------------------------------------------------------------------------- /utils/idl/interface_test.go: -------------------------------------------------------------------------------- 1 | package idl_test 2 | 3 | func ExampleInterface() { 4 | //v := new(idl.Bool) 5 | //idl.NewInterface(v) 6 | // Output: 7 | // 4449444c000173000000bf 8 | // 4449444c00017300000000 9 | // 4449444c0001730000003f 10 | // 4449444c00017300004040 11 | } 12 | -------------------------------------------------------------------------------- /status_test.go: -------------------------------------------------------------------------------- 1 | package agent_test 2 | 3 | import ( 4 | "testing" 5 | 6 | agent "github.com/openos-labs/IC-Go" 7 | ) 8 | 9 | func TestClientStatus(t *testing.T) { 10 | c := agent.NewClient("https://ic0.app") 11 | status, _ := c.Status() 12 | t.Log(status.Version) 13 | // Output: 14 | // 0.18.0 15 | } -------------------------------------------------------------------------------- /utils/idl/tuple.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | type Tuple []Type 9 | 10 | func (ts Tuple) String() string { 11 | var s []string 12 | for _, t := range ts { 13 | s = append(s, t.String()) 14 | } 15 | return fmt.Sprintf("(%s)", strings.Join(s, ", ")) 16 | } 17 | -------------------------------------------------------------------------------- /utils/idl/vec_test.go: -------------------------------------------------------------------------------- 1 | package idl_test 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/openos-labs/IC-Go/utils/idl" 7 | ) 8 | 9 | func ExampleVec() { 10 | test([]idl.Type{idl.NewVec(new(idl.Int))}, []interface{}{ 11 | []interface{}{big.NewInt(0), big.NewInt(1), big.NewInt(2), big.NewInt(3)}, 12 | }) 13 | // Output: 14 | // 4449444c016d7c01000400010203 15 | } 16 | -------------------------------------------------------------------------------- /utils/idl/opt_test.go: -------------------------------------------------------------------------------- 1 | package idl_test 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/openos-labs/IC-Go/utils/idl" 7 | ) 8 | 9 | func ExampleOpt() { 10 | test([]idl.Type{idl.NewOpt(new(idl.Nat))}, []interface{}{nil}) 11 | test([]idl.Type{idl.NewOpt(new(idl.Nat))}, []interface{}{big.NewInt(1)}) 12 | // Output: 13 | // 4449444c016e7d010000 14 | // 4449444c016e7d01000101 15 | } 16 | -------------------------------------------------------------------------------- /utils/idl/principal_test.go: -------------------------------------------------------------------------------- 1 | package idl_test 2 | 3 | import ( 4 | "github.com/openos-labs/IC-Go/utils/idl" 5 | "github.com/openos-labs/IC-Go/utils/principal" 6 | ) 7 | 8 | func ExamplePrincipal() { 9 | p, _ := principal.Decode("gvbup-jyaaa-aaaah-qcdwa-cai") 10 | test([]idl.Type{new(idl.Principal)}, []interface{}{p}) 11 | // Output: 12 | // 4449444c000168010a0000000000f010ec0101 13 | } 14 | -------------------------------------------------------------------------------- /utils/idl/text_test.go: -------------------------------------------------------------------------------- 1 | package idl_test 2 | 3 | import "github.com/openos-labs/IC-Go/utils/idl" 4 | 5 | func ExampleText() { 6 | test([]idl.Type{new(idl.Text)}, []interface{}{""}) 7 | test([]idl.Type{new(idl.Text)}, []interface{}{"Motoko"}) 8 | test([]idl.Type{new(idl.Text)}, []interface{}{"Hi ☃\n"}) 9 | // Output: 10 | // 4449444c00017100 11 | // 4449444c000171064d6f746f6b6f 12 | // 4449444c00017107486920e298830a 13 | } 14 | -------------------------------------------------------------------------------- /utils/idl/errors.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import "fmt" 4 | 5 | type DecodeError struct { 6 | Types Tuple 7 | Description string 8 | } 9 | 10 | func (e DecodeError) Error() string { 11 | return fmt.Sprintf("%s %s", e.Types.String(), e.Description) 12 | } 13 | 14 | type FormatError struct { 15 | Description string 16 | } 17 | 18 | func (e FormatError) Error() string { 19 | return fmt.Sprintf("() %s", e.Description) 20 | } 21 | -------------------------------------------------------------------------------- /utils/idl/hash.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import "math/big" 4 | 5 | // Hashes a string to a number. 6 | // ( Sum_(i=0..k) utf8(id)[i] * 223^(k-i) ) mod 2^32 where k = |utf8(id)|-1 7 | func Hash(s string) *big.Int { 8 | h := big.NewInt(0) 9 | i := big.NewInt(2) 10 | i = i.Exp(i, big.NewInt(32), nil) 11 | for _, r := range s { 12 | h = h.Mul(h, big.NewInt(223)) 13 | h = h.Add(h, big.NewInt(int64(r))) 14 | h = h.Mod(h, i) 15 | } 16 | return h 17 | } 18 | -------------------------------------------------------------------------------- /utils/idl/tdt.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | type TypeDefinitionTable struct { 4 | Types [][]byte 5 | Indexes map[string]int 6 | } 7 | 8 | func (tdt *TypeDefinitionTable) Add(t Type, bs []byte) { 9 | if tdt.Has(t) { 10 | return 11 | } 12 | i := len(tdt.Types) 13 | tdt.Indexes[t.String()] = i 14 | tdt.Types = append(tdt.Types, bs) 15 | } 16 | 17 | func (tdt *TypeDefinitionTable) Has(t Type) bool{ 18 | _, ok := tdt.Indexes[t.String()] 19 | return ok 20 | } -------------------------------------------------------------------------------- /utils/idl/bool_test.go: -------------------------------------------------------------------------------- 1 | package idl_test 2 | 3 | import ( 4 | "github.com/openos-labs/IC-Go/utils/idl" 5 | ) 6 | 7 | func ExampleBool() { 8 | test([]idl.Type{new(idl.Bool)}, []interface{}{true}) 9 | test([]idl.Type{new(idl.Bool)}, []interface{}{false}) 10 | test([]idl.Type{new(idl.Bool)}, []interface{}{0}) 11 | test([]idl.Type{new(idl.Bool)}, []interface{}{"false"}) 12 | // Output: 13 | // 4449444c00017e01 14 | // 4449444c00017e00 15 | // enc: invalid argument: 0 16 | // enc: invalid argument: false 17 | } 18 | -------------------------------------------------------------------------------- /utils/idl/rec_test.go: -------------------------------------------------------------------------------- 1 | package idl_test 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/openos-labs/IC-Go/utils/idl" 7 | ) 8 | 9 | func ExampleRec() { 10 | test([]idl.Type{idl.NewRec(nil)}, []interface{}{nil}) 11 | test_([]idl.Type{idl.NewRec(map[string]idl.Type{ 12 | "foo": new(idl.Text), 13 | "bar": new(idl.Int), 14 | })}, []interface{}{ 15 | map[string]interface{}{ 16 | "foo": "💩", 17 | "bar": big.NewInt(42), 18 | "baz": big.NewInt(0), 19 | }, 20 | }) 21 | // Output: 22 | // 4449444c016c000100 23 | // 4449444c016c02d3e3aa027c868eb7027101002a04f09f92a9 24 | } 25 | -------------------------------------------------------------------------------- /utils/idl/func_test.go: -------------------------------------------------------------------------------- 1 | package idl_test 2 | 3 | import ( 4 | "github.com/openos-labs/IC-Go/utils/idl" 5 | "github.com/openos-labs/IC-Go/utils/principal" 6 | ) 7 | 8 | func ExampleFunc() { 9 | p, _ := principal.Decode("w7x7r-cok77-xa") 10 | test_( 11 | []idl.Type{ 12 | idl.NewFunc( 13 | []idl.Type{new(idl.Text)}, 14 | []idl.Type{new(idl.Nat)}, 15 | nil, 16 | ), 17 | }, 18 | []interface{}{ 19 | idl.PrincipalMethod{ 20 | Principal: p, 21 | Method: "foo", 22 | }, 23 | }, 24 | ) 25 | // Output: 26 | // 4449444c016a0171017d000100010103caffee03666f6f 27 | } 28 | -------------------------------------------------------------------------------- /utils/idl/service_test.go: -------------------------------------------------------------------------------- 1 | package idl_test 2 | 3 | import ( 4 | "github.com/openos-labs/IC-Go/utils/idl" 5 | "github.com/openos-labs/IC-Go/utils/principal" 6 | ) 7 | 8 | func ExampleService() { 9 | p, _ := principal.Decode("w7x7r-cok77-xa") 10 | test( 11 | []idl.Type{idl.NewService( 12 | map[string]*idl.Func{ 13 | "foo": idl.NewFunc( 14 | []idl.Type{new(idl.Text)}, 15 | []idl.Type{new(idl.Nat)}, 16 | nil, 17 | ), 18 | }, 19 | )}, 20 | []interface{}{ 21 | p, 22 | }, 23 | ) 24 | // Output: 25 | // 4449444c026a0171017d00690103666f6f0001010103caffee 26 | } 27 | -------------------------------------------------------------------------------- /utils/idl/reserved.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "math/big" 6 | 7 | "github.com/aviate-labs/leb128" 8 | ) 9 | 10 | type Reserved struct { 11 | primType 12 | } 13 | 14 | func (Reserved) Decode(*bytes.Reader) (interface{}, error) { 15 | return nil, nil 16 | } 17 | 18 | func (Reserved) EncodeType(_ *TypeDefinitionTable) ([]byte, error) { 19 | return leb128.EncodeSigned(big.NewInt(reservedType)) 20 | } 21 | 22 | func (Reserved) EncodeValue(_ interface{}) ([]byte, error) { 23 | return []byte{}, nil 24 | } 25 | 26 | func (Reserved) String() string { 27 | return "reserved" 28 | } 29 | -------------------------------------------------------------------------------- /utils/idl/variant_test.go: -------------------------------------------------------------------------------- 1 | package idl_test 2 | 3 | import "github.com/openos-labs/IC-Go/utils/idl" 4 | 5 | func ExampleVariant() { 6 | result := map[string]idl.Type{ 7 | "ok": new(idl.Text), 8 | "err": new(idl.Text), 9 | } 10 | test_([]idl.Type{idl.NewVariant(result)}, []interface{}{idl.FieldValue{ 11 | Name: "ok", 12 | Value: "good", 13 | }}) 14 | test_([]idl.Type{idl.NewVariant(result)}, []interface{}{idl.FieldValue{ 15 | Name: "err", 16 | Value: "uhoh", 17 | }}) 18 | // Output: 19 | // 4449444c016b029cc20171e58eb4027101000004676f6f64 20 | // 4449444c016b029cc20171e58eb402710100010475686f68 21 | } 22 | -------------------------------------------------------------------------------- /utils/idl/empty.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math/big" 7 | 8 | "github.com/aviate-labs/leb128" 9 | ) 10 | 11 | type Empty struct { 12 | primType 13 | } 14 | 15 | func (Empty) Decode(*bytes.Reader) (interface{}, error) { 16 | return nil, fmt.Errorf("cannot decode empty type") 17 | } 18 | 19 | func (Empty) EncodeType(_ *TypeDefinitionTable) ([]byte, error) { 20 | return leb128.EncodeSigned(big.NewInt(emptyType)) 21 | } 22 | 23 | func (Empty) EncodeValue(_ interface{}) ([]byte, error) { 24 | return []byte{}, nil 25 | } 26 | 27 | func (Empty) String() string { 28 | return "empty" 29 | } 30 | -------------------------------------------------------------------------------- /utils/idl/null.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math/big" 7 | 8 | "github.com/aviate-labs/leb128" 9 | ) 10 | 11 | type Null struct { 12 | primType 13 | } 14 | 15 | func (n *Null) Decode(_ *bytes.Reader) (interface{}, error) { 16 | return nil, nil 17 | } 18 | 19 | func (Null) EncodeType(_ *TypeDefinitionTable) ([]byte, error) { 20 | return leb128.EncodeSigned(big.NewInt(nullType)) 21 | } 22 | 23 | func (Null) EncodeValue(v interface{}) ([]byte, error) { 24 | if v != nil { 25 | return nil, fmt.Errorf("invalid argument: %v", v) 26 | } 27 | return []byte{}, nil 28 | } 29 | 30 | func (n Null) String() string { 31 | return "null" 32 | } 33 | -------------------------------------------------------------------------------- /example/registry/proto/mixed_hash_tree.proto: -------------------------------------------------------------------------------- 1 | // Protocol buffer mirror of `ic_crypto_tree_hash::MixedHashTree`. 2 | 3 | syntax = "proto3"; 4 | option go_package="./pb"; 5 | 6 | package messaging.xnet.v1; 7 | 8 | import "google/protobuf/empty.proto"; 9 | 10 | // A tree containing both data and merkle proofs. 11 | message MixedHashTree { 12 | message Fork { 13 | MixedHashTree left_tree = 1; 14 | MixedHashTree right_tree = 2; 15 | } 16 | 17 | message Labeled { 18 | bytes label = 1; 19 | MixedHashTree subtree = 2; 20 | } 21 | 22 | oneof tree_enum { 23 | google.protobuf.Empty empty = 1; 24 | Fork fork = 2; 25 | Labeled labeled = 3; 26 | bytes leaf_data = 4; 27 | bytes pruned_digest = 5; 28 | } 29 | } -------------------------------------------------------------------------------- /utils/idl/Interface.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | ) 7 | 8 | type Interface struct { 9 | _Type Type 10 | primType 11 | } 12 | 13 | //func NewInterface(t Type) *Interface { 14 | // return &Interface{ 15 | // Type: t, 16 | // } 17 | //} 18 | 19 | func (i *Interface) Fill(t Type) { 20 | i._Type = t 21 | } 22 | 23 | func (i *Interface) Decode(r *bytes.Reader) (interface{}, error) { 24 | return i._Type.Decode(r) 25 | } 26 | func (i Interface) EncodeType(tdt *TypeDefinitionTable) ([]byte, error) { 27 | return i._Type.EncodeType(tdt) 28 | } 29 | func (i Interface) EncodeValue(value interface{}) ([]byte, error) { 30 | return i._Type.EncodeValue(value) 31 | } 32 | func (i Interface) String() string { 33 | return fmt.Sprintf("interface %s", i._Type) 34 | } 35 | -------------------------------------------------------------------------------- /example/registry/proto/routing_table.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | option go_package="./pb"; 3 | 4 | package routing_table.v1; 5 | 6 | import "types.proto"; 7 | 8 | message CanisterIdRange { 9 | reserved 1; 10 | reserved "start"; // Originally was defined as a uint64 11 | reserved 2; 12 | reserved "end"; // Originally was defined as a uint64 13 | types.v1.CanisterId start_canister_id = 3; 14 | types.v1.CanisterId end_canister_id = 4; 15 | } 16 | 17 | // A list of closed ranges of canister Ids. 18 | message CanisterIdRanges { 19 | repeated CanisterIdRange ranges = 1; 20 | } 21 | 22 | // Maps a closed range of canister Ids to a subnet id. 23 | message RoutingTable { 24 | message Entry { 25 | CanisterIdRange range = 1; 26 | types.v1.SubnetId subnet_id = 2; 27 | } 28 | 29 | // Defined as `repeated` instead of `map` in order to preserve ordering. 30 | repeated Entry entries = 1; 31 | } 32 | -------------------------------------------------------------------------------- /utils/idl/bool.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math/big" 7 | 8 | "github.com/aviate-labs/leb128" 9 | ) 10 | 11 | type Bool struct { 12 | primType 13 | } 14 | 15 | func (b Bool) Decode(r *bytes.Reader) (interface{}, error) { 16 | v, err := r.ReadByte() 17 | if err != nil { 18 | return nil, err 19 | } 20 | switch v { 21 | case 0x00: 22 | return false, nil 23 | case 0x01: 24 | return true, nil 25 | default: 26 | return nil, fmt.Errorf("invalid bool values: %x", b) 27 | } 28 | } 29 | 30 | func (Bool) EncodeType(_ *TypeDefinitionTable) ([]byte, error) { 31 | return leb128.EncodeSigned(big.NewInt(boolType)) 32 | } 33 | 34 | func (b Bool) EncodeValue(v interface{}) ([]byte, error) { 35 | v_, ok := v.(bool) 36 | if !ok { 37 | return nil, fmt.Errorf("invalid argument: %v", v) 38 | } 39 | if v_ { 40 | return []byte{0x01}, nil 41 | } 42 | return []byte{0x00}, nil 43 | } 44 | 45 | func (Bool) String() string { 46 | return "bool" 47 | } 48 | -------------------------------------------------------------------------------- /utils/idl/float_test.go: -------------------------------------------------------------------------------- 1 | package idl_test 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/openos-labs/IC-Go/utils/idl" 7 | ) 8 | 9 | func ExampleFloat32() { 10 | test([]idl.Type{idl.Float32()}, []interface{}{big.NewFloat(-0.5)}) 11 | test([]idl.Type{idl.Float32()}, []interface{}{big.NewFloat(0)}) 12 | test([]idl.Type{idl.Float32()}, []interface{}{big.NewFloat(0.5)}) 13 | test([]idl.Type{idl.Float32()}, []interface{}{big.NewFloat(3)}) 14 | // Output: 15 | // 4449444c000173000000bf 16 | // 4449444c00017300000000 17 | // 4449444c0001730000003f 18 | // 4449444c00017300004040 19 | } 20 | 21 | func ExampleFloat64() { 22 | test([]idl.Type{idl.Float64()}, []interface{}{big.NewFloat(-0.5)}) 23 | test([]idl.Type{idl.Float64()}, []interface{}{big.NewFloat(0)}) 24 | test([]idl.Type{idl.Float64()}, []interface{}{big.NewFloat(0.5)}) 25 | test([]idl.Type{idl.Float64()}, []interface{}{big.NewFloat(3)}) 26 | // Output: 27 | // 4449444c000172000000000000e0bf 28 | // 4449444c0001720000000000000000 29 | // 4449444c000172000000000000e03f 30 | // 4449444c0001720000000000000840 31 | } 32 | -------------------------------------------------------------------------------- /utils/idl/float.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math/big" 7 | 8 | "github.com/aviate-labs/leb128" 9 | ) 10 | 11 | type Float struct { 12 | Base uint8 13 | primType 14 | } 15 | 16 | func Float32() *Float { 17 | return &Float{ 18 | Base: 32, 19 | } 20 | } 21 | 22 | func Float64() *Float { 23 | return &Float{ 24 | Base: 64, 25 | } 26 | } 27 | 28 | func (f *Float) Decode(r *bytes.Reader) (interface{}, error) { 29 | return readFloat(r, int(f.Base/8)) 30 | } 31 | 32 | func (f Float) EncodeType(_ *TypeDefinitionTable) ([]byte, error) { 33 | floatXType := new(big.Int).Set(big.NewInt(floatXType)) 34 | if f.Base == 64 { 35 | floatXType.Add(floatXType, big.NewInt(-1)) 36 | } 37 | return leb128.EncodeSigned(floatXType) 38 | } 39 | 40 | func (f Float) EncodeValue(v interface{}) ([]byte, error) { 41 | v_, ok := v.(*big.Float) 42 | if !ok { 43 | return nil, fmt.Errorf("invalid argument: %v", v) 44 | } 45 | return writeFloat(v_, int(f.Base/8)), nil 46 | } 47 | 48 | func (f Float) String() string { 49 | return fmt.Sprintf("float%d", f.Base) 50 | } 51 | -------------------------------------------------------------------------------- /example/registry/proto/types.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | import "google/protobuf/wrappers.proto"; 3 | 4 | option go_package="./pb"; 5 | 6 | package types.v1; 7 | 8 | message PrincipalId { 9 | bytes raw = 1; 10 | } 11 | 12 | message CanisterId { 13 | PrincipalId principal_id = 1; 14 | } 15 | 16 | message SubnetId { 17 | PrincipalId principal_id = 1; 18 | } 19 | 20 | message UserId { 21 | PrincipalId principal_id = 1; 22 | } 23 | 24 | message NodeId { 25 | PrincipalId principal_id = 1; 26 | } 27 | 28 | // A non-interactive distributed key generation (NI-DKG) ID. 29 | message NiDkgId { 30 | reserved "receiver_subnet"; 31 | reserved 3; // this is from receiver_subnet consisting of bytes 32 | uint64 start_block_height = 1; 33 | bytes dealer_subnet = 2; 34 | NiDkgTag dkg_tag = 4; 35 | google.protobuf.BytesValue remote_target_id = 5; 36 | } 37 | 38 | // A non-interactive distributed key generation (NI-DKG) tag. 39 | enum NiDkgTag { 40 | NI_DKG_TAG_UNSPECIFIED = 0; 41 | NI_DKG_TAG_LOW_THRESHOLD = 1; 42 | NI_DKG_TAG_HIGH_THRESHOLD = 2; 43 | } 44 | 45 | message NominalCycles { 46 | uint64 high = 1; 47 | uint64 low = 2; 48 | } -------------------------------------------------------------------------------- /utils/identity/identity_test.go: -------------------------------------------------------------------------------- 1 | package identity 2 | 3 | import ( 4 | "crypto/ed25519" 5 | "encoding/hex" 6 | "fmt" 7 | "strconv" 8 | "testing" 9 | ) 10 | 11 | func TestKeys(t *testing.T) { 12 | pkBytes, _ := hex.DecodeString("833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42") 13 | identity := New(false, pkBytes) 14 | t.Log(hex.EncodeToString([]byte("pyd"))) 15 | sign, _ := identity.Sign([]byte("pyd")) 16 | t.Log(hex.EncodeToString(sign), len(sign)) 17 | } 18 | 19 | func TestNew(t *testing.T) { 20 | var a []byte 21 | result := strconv.AppendInt(a, -24, 8) 22 | t.Logf("%x", result) 23 | } 24 | 25 | func TestToPem(t *testing.T) { 26 | pkBytes, _ := hex.DecodeString("833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42") 27 | privKey := ed25519.NewKeyFromSeed(pkBytes) 28 | ToPem(privKey, "./priv.pem") 29 | } 30 | 31 | func TestFromPem(t *testing.T) { 32 | pkBytes, _ := hex.DecodeString("833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42") 33 | privKey := ed25519.NewKeyFromSeed(pkBytes) 34 | priv, _ := FromPem("./priv.pem") 35 | t.Log(hex.EncodeToString(priv.Seed())) 36 | if priv.Equal(privKey) { 37 | fmt.Println("pass test") 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /utils/idl/text.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "math/big" 8 | "unicode/utf8" 9 | 10 | "github.com/aviate-labs/leb128" 11 | ) 12 | 13 | type Text struct { 14 | primType 15 | } 16 | 17 | func (t *Text) Decode(r *bytes.Reader) (interface{}, error) { 18 | n, err := leb128.DecodeUnsigned(r) 19 | if err != nil { 20 | return nil, err 21 | } 22 | bs := make([]byte, n.Int64()) 23 | i, err := r.Read(bs) 24 | if err != nil { 25 | return "", nil 26 | } 27 | if i != int(n.Int64()) { 28 | return nil, io.EOF 29 | } 30 | if !utf8.Valid(bs) { 31 | return nil, fmt.Errorf("invalid utf8 text") 32 | } 33 | 34 | return string(bs), nil 35 | } 36 | 37 | func (t Text) EncodeType(_ *TypeDefinitionTable) ([]byte, error) { 38 | return leb128.EncodeSigned(big.NewInt(textType)) 39 | } 40 | 41 | func (t Text) EncodeValue(v interface{}) ([]byte, error) { 42 | v_, ok := v.(string) 43 | if !ok { 44 | return nil, fmt.Errorf("invalid argument: %v", v) 45 | } 46 | bs, err := leb128.EncodeUnsigned(big.NewInt(int64(len(v_)))) 47 | if err != nil { 48 | return nil, err 49 | } 50 | return append(bs, []byte(v_)...), nil 51 | } 52 | 53 | func (t Text) String() string { 54 | return "text" 55 | } 56 | -------------------------------------------------------------------------------- /utils/idl/util_test.go: -------------------------------------------------------------------------------- 1 | package idl_test 2 | 3 | import ( 4 | "fmt" 5 | "math/big" 6 | "reflect" 7 | "testing" 8 | 9 | "github.com/openos-labs/IC-Go/utils/idl" 10 | ) 11 | 12 | func TestHash(t *testing.T) { 13 | if h := idl.Hash("foo"); h.Cmp(big.NewInt(5097222)) != 0 { 14 | t.Errorf("expected '5097222', got '%s'", h) 15 | } 16 | if h := idl.Hash("bar"); h.Cmp(big.NewInt(4895187)) != 0 { 17 | t.Errorf("expected '4895187', got '%s'", h) 18 | } 19 | } 20 | 21 | func test(types []idl.Type, args []interface{}) { 22 | e, err := idl.Encode(types, args) 23 | if err != nil { 24 | fmt.Println("enc:", err) 25 | return 26 | } 27 | fmt.Printf("%x\n", e) 28 | 29 | ts, vs, err := idl.Decode(e) 30 | if err != nil { 31 | fmt.Println("dec:", err) 32 | return 33 | } 34 | if !reflect.DeepEqual(ts, types) { 35 | fmt.Println("types:", types, ts) 36 | } 37 | if !reflect.DeepEqual(vs, args) { 38 | fmt.Println("args:", args, vs) 39 | } 40 | } 41 | 42 | func test_(types []idl.Type, args []interface{}) { 43 | e, err := idl.Encode(types, args) 44 | if err != nil { 45 | fmt.Println("enc:", err) 46 | return 47 | } 48 | fmt.Printf("%x\n", e) 49 | 50 | if _, _, err := idl.Decode(e); err != nil { 51 | fmt.Println("dec:", err) 52 | return 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /example/registry/proto/node_operator.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package="./pb"; 4 | 5 | package registry.node_operator.v1; 6 | 7 | // A record for a node operator. Each node operator is associated with a 8 | // unique principal id, a.k.a. NOID. 9 | // 10 | // Note that while a node operator might host nodes for more than 11 | // one funding parter, its principal ID must be unique. 12 | message NodeOperatorRecord { 13 | // The principal id of the node operator. This principal is the entity that 14 | // is able to add and remove nodes. 15 | // 16 | // This must be unique across NodeOperatorRecords. 17 | bytes node_operator_principal_id = 1; 18 | 19 | // The remaining number of nodes that could be added by this node operator. 20 | // This number should never go below 0. 21 | uint64 node_allowance = 2; 22 | 23 | // The principal id of this node operator's provider. 24 | bytes node_provider_principal_id = 3; 25 | 26 | // The ID of the data center where this Node Operator hosts nodes. 27 | string dc_id = 4; 28 | 29 | // A map from node type to the number of nodes for which the associated Node 30 | // Provider should be rewarded. 31 | map rewardable_nodes = 5; 32 | } 33 | 34 | /// The payload of a request to remove Node Operator records from the Registry 35 | message RemoveNodeOperatorsPayload { 36 | repeated bytes node_operators_to_remove = 1; 37 | } -------------------------------------------------------------------------------- /utils/idl/principal.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math/big" 7 | 8 | "github.com/aviate-labs/leb128" 9 | "github.com/openos-labs/IC-Go/utils/principal" 10 | ) 11 | 12 | type Principal struct { 13 | primType 14 | } 15 | 16 | func (t *Principal) Decode(r *bytes.Reader) (interface{}, error) { 17 | { 18 | bs := make([]byte, 1) 19 | n, err := r.Read(bs) 20 | if err != nil { 21 | return nil, err 22 | } 23 | if n != 1 || bs[0] != 0x01 { 24 | return nil, fmt.Errorf("invalid func reference: %d", bs) 25 | } 26 | } 27 | l, err := leb128.DecodeUnsigned(r) 28 | if err != nil { 29 | return nil, err 30 | } 31 | pid := make([]byte, l.Int64()) 32 | n, err := r.Read(pid) 33 | if err != nil { 34 | return nil, err 35 | } 36 | if n != int(l.Int64()) { 37 | return nil, fmt.Errorf("invalid principal id: %d", pid) 38 | } 39 | return pid, nil 40 | } 41 | 42 | func (t Principal) EncodeType(_ *TypeDefinitionTable) ([]byte, error) { 43 | return leb128.EncodeSigned(big.NewInt(principalType)) 44 | } 45 | 46 | func (t Principal) EncodeValue(v interface{}) ([]byte, error) { 47 | p, ok := v.(principal.Principal) 48 | if !ok { 49 | return nil, fmt.Errorf("invalid argument: %v", v) 50 | } 51 | l, err := leb128.EncodeUnsigned(big.NewInt(int64(len(p)))) 52 | if err != nil { 53 | return nil, err 54 | } 55 | return concat([]byte{0x01}, l, p), nil 56 | } 57 | 58 | func (t Principal) String() string { 59 | return "principal" 60 | } 61 | -------------------------------------------------------------------------------- /utils/idl/encode.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "fmt" 5 | "math/big" 6 | 7 | "github.com/aviate-labs/leb128" 8 | ) 9 | 10 | func Encode(argumentTypes []Type, arguments []interface{}) ([]byte, error) { 11 | if len(arguments) < len(argumentTypes) { 12 | return nil, fmt.Errorf("invalid number of arguments") 13 | } 14 | 15 | // T 16 | tdt := &TypeDefinitionTable{ 17 | Indexes: make(map[string]int), 18 | } 19 | for _, t := range argumentTypes { 20 | t.AddTypeDefinition(tdt) 21 | } 22 | 23 | tdtl, err := leb128.EncodeSigned(big.NewInt(int64(len(tdt.Indexes)))) 24 | if err != nil { 25 | return nil, err 26 | } 27 | var tdte []byte 28 | for _, t := range tdt.Types { 29 | tdte = append(tdte, t...) 30 | } 31 | 32 | tsl, err := leb128.EncodeSigned(big.NewInt(int64(len(argumentTypes)))) 33 | if err != nil { 34 | return nil, err 35 | } 36 | var ( 37 | ts []byte 38 | vs []byte 39 | ) 40 | for i, t := range argumentTypes { 41 | { // I 42 | t, err := t.EncodeType(tdt) 43 | if err != nil { 44 | return nil, err 45 | } 46 | ts = append(ts, t...) 47 | } 48 | { // M 49 | v, err := t.EncodeValue(arguments[i]) 50 | if err != nil { 51 | return nil, err 52 | } 53 | vs = append(vs, v...) 54 | } 55 | } 56 | 57 | return concat( 58 | // magic number 59 | []byte{'D', 'I', 'D', 'L'}, 60 | // type definition table: T*(*) 61 | tdtl, tdte, 62 | // types of the argument list: I*(*) 63 | tsl, ts, 64 | // values of argument list: M(*) 65 | vs, 66 | ), nil 67 | } 68 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/aviate-labs/leb128 v0.3.0 h1:s9htRv3OYk8nuHqJu9PiVFJxv1jIUTIcpEeiURa91uQ= 2 | github.com/aviate-labs/leb128 v0.3.0/go.mod h1:GclhBOjhIKmcDlgHKhj0AEZollzERfZUbcRUKiQVqgY= 3 | github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88= 4 | github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= 5 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 6 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 7 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 8 | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 9 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 10 | github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= 11 | github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= 12 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 13 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 14 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 15 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 16 | google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= 17 | google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 18 | -------------------------------------------------------------------------------- /utils/idl/nat.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math/big" 7 | 8 | "github.com/aviate-labs/leb128" 9 | ) 10 | 11 | type Nat struct { 12 | Base uint8 13 | primType 14 | } 15 | 16 | func Nat16() *Nat { 17 | return &Nat{ 18 | Base: 16, 19 | } 20 | } 21 | 22 | func Nat32() *Nat { 23 | return &Nat{ 24 | Base: 32, 25 | } 26 | } 27 | 28 | func Nat64() *Nat { 29 | return &Nat{ 30 | Base: 64, 31 | } 32 | } 33 | 34 | func Nat8() *Nat { 35 | return &Nat{ 36 | Base: 8, 37 | } 38 | } 39 | 40 | func (n *Nat) Decode(r *bytes.Reader) (interface{}, error) { 41 | if n.Base == 0 { 42 | return leb128.DecodeUnsigned(r) 43 | } 44 | return readUInt(r, int(n.Base/8)) 45 | } 46 | 47 | func (n Nat) EncodeType(_ *TypeDefinitionTable) ([]byte, error) { 48 | if n.Base == 0 { 49 | return leb128.EncodeSigned(big.NewInt(natType)) 50 | } 51 | natXType := new(big.Int).Set(big.NewInt(natXType)) 52 | natXType = natXType.Add( 53 | natXType, 54 | big.NewInt(3-int64(log2(n.Base))), 55 | ) 56 | return leb128.EncodeSigned(natXType) 57 | } 58 | 59 | func (n Nat) EncodeValue(v interface{}) ([]byte, error) { 60 | v_, ok := v.(*big.Int) 61 | if !ok { 62 | return nil, fmt.Errorf("invalid argument: %v", v) 63 | } 64 | if n.Base == 0 { 65 | return leb128.EncodeUnsigned(v_) 66 | } 67 | { 68 | lim := big.NewInt(2) 69 | lim = lim.Exp(lim, big.NewInt(int64(n.Base)), nil) 70 | if lim.Cmp(v_) <= 0 { 71 | return nil, fmt.Errorf("invalid value: %s", v_) 72 | } 73 | } 74 | return writeInt(v_, int(n.Base/8)), nil 75 | } 76 | 77 | func (n Nat) String() string { 78 | if n.Base == 0 { 79 | return "nat" 80 | } 81 | return fmt.Sprintf("nat%d", n.Base) 82 | } 83 | -------------------------------------------------------------------------------- /request_test.go: -------------------------------------------------------------------------------- 1 | package agent_test 2 | 3 | import ( 4 | "crypto/sha256" 5 | "encoding/hex" 6 | "fmt" 7 | "testing" 8 | 9 | agent "github.com/openos-labs/IC-Go" 10 | ) 11 | 12 | func TestNewRequestID(t *testing.T) { 13 | req := agent.Request{ 14 | Type: agent.RequestTypeCall, 15 | CanisterID: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xD2}, 16 | MethodName: "hello", 17 | Arguments: []byte("DIDL\x00\xFD*"), 18 | } 19 | //t.Log(idl.Decode([]byte("DIDL\x00\xFD*"))) 20 | h := fmt.Sprintf("%x", agent.NewRequestID(req)) 21 | if h != "8781291c347db32a9d8c10eb62b710fce5a93be676474c42babc74c51858f94b" { 22 | t.Fatal(h) 23 | } 24 | } 25 | 26 | func TestEncodeRequestID(t *testing.T) { 27 | req := make(map[string]interface{}) 28 | req["request_type"] = agent.RequestTypeCall 29 | req["canister_id"] = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xD2} 30 | req["method_name"] = "hello" 31 | req["arg"] = []byte("DIDL\x00\xFD*") 32 | 33 | id := agent.EncodeRequestID(req) 34 | h := fmt.Sprintf("%x", id) 35 | if h != "8781291c347db32a9d8c10eb62b710fce5a93be676474c42babc74c51858f94b" { 36 | t.Fatal(h) 37 | } 38 | } 39 | 40 | func TestEncodeList(t *testing.T) { 41 | a := [][]byte{[]byte("i"),[]byte("love"),[]byte("you")} 42 | res := encodeList(a) 43 | t.Log(hex.EncodeToString([]byte("i"))) 44 | t.Log(hex.EncodeToString([]byte("love"))) 45 | t.Log(hex.EncodeToString([]byte("you"))) 46 | t.Log(hex.EncodeToString(res[:])) 47 | } 48 | 49 | func encodeList(paths [][]byte) [32]byte { 50 | var pathsBytes []byte 51 | for _, path := range paths { 52 | pathBytes := sha256.Sum256(path) 53 | pathsBytes = append(pathsBytes, pathBytes[:]...) 54 | } 55 | return sha256.Sum256(pathsBytes) 56 | } 57 | 58 | -------------------------------------------------------------------------------- /status.go: -------------------------------------------------------------------------------- 1 | package agent 2 | 3 | import ( 4 | "github.com/fxamacker/cbor/v2" 5 | ) 6 | 7 | // Implementation identifies the implementation of the Internet Computer. 8 | type Implementation struct { 9 | // Source is the canonical location of the source code. 10 | Source string 11 | // Version is the version number of the implementation. 12 | Version string 13 | // Revision is the precise git revision of the implementation. 14 | Revision string 15 | } 16 | 17 | // Status describes various status fields of the Internet Computer. 18 | type Status struct { 19 | // Identifies the interface version supported. 20 | Version string 21 | // Impl describes the implementation of the Internet Computer. 22 | Impl *Implementation 23 | // The public identity (a DER-encoded BLS identity) of the root identity of this Internet Computer instance. 24 | RootKey []byte 25 | } 26 | 27 | func (s *Status) UnmarshalCBOR(data []byte) error { 28 | var status struct { 29 | APIVersion string `cbor:"ic_api_version"` 30 | ImplSource string `cbor:"impl_source"` 31 | ImplVersion string `cbor:"impl_version"` 32 | ImplRevision string `cbor:"impl_revision"` 33 | RootKey []byte `cbor:"root_key"` 34 | } 35 | if err := cbor.Unmarshal(data, &status); err != nil { 36 | return err 37 | } 38 | s.Version = status.APIVersion 39 | s.Impl = &Implementation{ 40 | Source: status.ImplSource, 41 | Version: status.ImplVersion, 42 | Revision: status.ImplRevision, 43 | } 44 | s.RootKey = status.RootKey 45 | return nil 46 | } 47 | 48 | type QueryResponse struct { 49 | Status string `cbor:"status"` 50 | Reply map[string][]byte `cbor:"reply"` 51 | RejectCode uint64 `cbor:"reject_code"` 52 | RejectMsg string `cbor:"reject_message"` 53 | } 54 | -------------------------------------------------------------------------------- /utils/idl/opt.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math/big" 7 | 8 | "github.com/aviate-labs/leb128" 9 | ) 10 | 11 | type Opt struct { 12 | Type Type 13 | } 14 | 15 | func NewOpt(t Type) *Opt { 16 | return &Opt{ 17 | Type: t, 18 | } 19 | } 20 | 21 | func (o Opt) AddTypeDefinition(tdt *TypeDefinitionTable) error { 22 | if err := o.Type.AddTypeDefinition(tdt); err != nil { 23 | return err 24 | } 25 | 26 | id, err := leb128.EncodeSigned(big.NewInt(optType)) 27 | if err != nil { 28 | return err 29 | } 30 | v, err := o.Type.EncodeType(tdt) 31 | if err != nil { 32 | return err 33 | } 34 | tdt.Add(o, concat(id, v)) 35 | return nil 36 | } 37 | 38 | func (o Opt) Decode(r *bytes.Reader) (interface{}, error) { 39 | l, err := r.ReadByte() 40 | if err != nil { 41 | return nil, err 42 | } 43 | switch l { 44 | case 0x00: 45 | return map[string]interface{}{"none": big.NewInt(1)}, nil 46 | case 0x01: 47 | v, err := o.Type.Decode(r) 48 | if err != nil { 49 | return nil, err 50 | } 51 | return map[string]interface{}{"some": v}, nil 52 | //return o.Type.Decode(r) 53 | default: 54 | return nil, fmt.Errorf("invalid option value") 55 | } 56 | } 57 | 58 | func (o Opt) EncodeType(tdt *TypeDefinitionTable) ([]byte, error) { 59 | idx, ok := tdt.Indexes[o.String()] 60 | if !ok { 61 | return nil, fmt.Errorf("missing type index for: %s", o) 62 | } 63 | return leb128.EncodeSigned(big.NewInt(int64(idx))) 64 | } 65 | 66 | func (o Opt) EncodeValue(v interface{}) ([]byte, error) { 67 | if v == nil { 68 | return []byte{0x00}, nil 69 | } 70 | v_, err := o.Type.EncodeValue(v) 71 | if err != nil { 72 | return nil, err 73 | } 74 | return concat([]byte{0x01}, v_), nil 75 | } 76 | func (Opt) Fill(Type) { 77 | 78 | } 79 | 80 | func (o Opt) String() string { 81 | return fmt.Sprintf("opt %s", o.Type) 82 | } 83 | -------------------------------------------------------------------------------- /utils/idl/int.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math/big" 7 | 8 | "github.com/aviate-labs/leb128" 9 | ) 10 | 11 | type Int struct { 12 | Base uint8 13 | primType 14 | } 15 | 16 | func Int16() *Int { 17 | return &Int{ 18 | Base: 16, 19 | } 20 | } 21 | 22 | func Int32() *Int { 23 | return &Int{ 24 | Base: 32, 25 | } 26 | } 27 | 28 | func Int64() *Int { 29 | return &Int{ 30 | Base: 64, 31 | } 32 | } 33 | 34 | func Int8() *Int { 35 | return &Int{ 36 | Base: 8, 37 | } 38 | } 39 | 40 | func (n *Int) Decode(r *bytes.Reader) (interface{}, error) { 41 | if n.Base == 0 { 42 | return leb128.DecodeSigned(r) 43 | } 44 | return readInt(r, int(n.Base/8)) 45 | } 46 | 47 | func (n Int) EncodeType(_ *TypeDefinitionTable) ([]byte, error) { 48 | if n.Base == 0 { 49 | return leb128.EncodeSigned(big.NewInt(intType)) 50 | } 51 | intXType := new(big.Int).Set(big.NewInt(intXType)) 52 | intXType = intXType.Add( 53 | intXType, 54 | big.NewInt(3-int64(log2(n.Base))), 55 | ) 56 | return leb128.EncodeSigned(intXType) 57 | } 58 | 59 | func (n Int) EncodeValue(v interface{}) ([]byte, error) { 60 | v_, ok := v.(*big.Int) 61 | if !ok { 62 | return nil, fmt.Errorf("invalid argument: %v", v) 63 | } 64 | if n.Base == 0 { 65 | return leb128.EncodeSigned(v_) 66 | } 67 | { 68 | exp := big.NewInt(int64(n.Base) - 1) 69 | lim := big.NewInt(2) 70 | lim = lim.Exp(lim, exp, nil) 71 | min := new(big.Int).Set(lim) 72 | min = min.Mul(min, big.NewInt(-1)) 73 | max := new(big.Int).Set(lim) 74 | max = max.Add(max, big.NewInt(-1)) 75 | if v_.Cmp(min) < 0 || max.Cmp(v_) < 0 { 76 | return nil, fmt.Errorf("invalid value: %s", v_) 77 | } 78 | } 79 | return writeInt(v_, int(n.Base/8)), nil 80 | } 81 | 82 | func (n Int) String() string { 83 | if n.Base == 0 { 84 | return "int" 85 | } 86 | return fmt.Sprintf("int%d", n.Base) 87 | } 88 | -------------------------------------------------------------------------------- /utils/principal/principal.go: -------------------------------------------------------------------------------- 1 | package principal 2 | 3 | import ( 4 | "crypto/sha256" 5 | "encoding/base32" 6 | "encoding/binary" 7 | "fmt" 8 | "hash/crc32" 9 | "strings" 10 | ) 11 | 12 | var encoding = base32.StdEncoding.WithPadding(base32.NoPadding) 13 | 14 | // AnonymousID is used for the anonymous caller. It can be used in call and query requests without a signature. 15 | var AnonymousID = Principal([]byte{0x04}) 16 | 17 | // NewSelfAuthenticating returns a self authenticating principal identifier based on the given public key. 18 | func NewSelfAuthenticating(pub []byte) Principal { 19 | hash := sha256.Sum224(pub) 20 | return append(hash[:], 0x02) 21 | } 22 | 23 | // Principal are generic identifiers for canisters, users and possibly other concepts in the future. 24 | type Principal []byte 25 | 26 | // New new principal from bytes 27 | func New(b []byte) Principal { 28 | p := Principal{} 29 | p = append(p,b...) 30 | return p 31 | } 32 | 33 | 34 | // Decode converts a textual representation into a principal. 35 | func Decode(s string) (Principal, error) { 36 | s = strings.ReplaceAll(s, "-", "") 37 | s = strings.ToUpper(s) 38 | b32, err := encoding.DecodeString(s) 39 | if err != nil { 40 | return nil, err 41 | } 42 | if len(b32) < 4 { 43 | return nil, fmt.Errorf("invalid length: %s", b32) 44 | } 45 | if crc32.ChecksumIEEE(b32[4:]) != binary.BigEndian.Uint32(b32[:4]) { 46 | return nil, fmt.Errorf("invalid checksum: %s", b32) 47 | } 48 | return b32[4:], err 49 | } 50 | 51 | // Encode converts the principal to its textual representation. 52 | func (p Principal) Encode() string { 53 | cs := make([]byte, 4) 54 | binary.BigEndian.PutUint32(cs, crc32.ChecksumIEEE(p)) 55 | b32 := encoding.EncodeToString(append(cs, p...)) 56 | b32 = strings.ToLower(b32) 57 | var str string 58 | for i, c := range b32 { 59 | if i != 0 && i%5 == 0 { 60 | str += "-" 61 | } 62 | str += string(c) 63 | } 64 | return str 65 | } 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IC-Go: Go Agent for the Internet Computer 2 | 3 | Here is the beta version of go agent for IC 4 | 5 | Please send us the issues you found, thanks! 6 | 7 | You can find the examples to use IC-Go in agent_test.go 8 | 9 | The implementations of IDL and principal are borrowed from [candid-go](https://github.com/aviate-labs/candid-go) and [principal](https://github.com/aviate-labs/principal-go), and fix the bugs 10 | 11 | **[update 2022.3.6]** fix the bugs for the recursive structs during decode, (like a struct A with a field which is a vec of A) 12 | 13 | **[update 2022.1.24]** add the auto-decoder to decode the result to the data structure in Golang automatically, see utils/decode.go 14 | 15 | Tips for the auto-decoder: 16 | 17 | - Due to the limitation of member variable name in Golang, you should put the label for member variable in the tag of `ic:"**"` 18 | 19 | - You are supposed to define Enum class as a struct. The extra member variant with tag `ic:"EnumIndex"`, whose value is set as the final result's tag, is used to formulate the enumeration in such a "enum" struct 20 | 21 | - "Option" should be defined as a struct, and the tag of the member variants in such a struct are "none" and "some", the member variant with tag "none" is initialized as 0, and once the option is nil, it will be set to 1 22 | 23 | - "Tuple" is also defined as a struct, the tag for the first member in tuple should be `ic:"0"`, and so on. 24 | 25 | - "Nat" is also supposed to be defined as big.Int 26 | 27 | - The type of members in record or enum without type of value in motoko should be set as a *uint8. The tag of members in record or enum without name in motoko should be set as `ic:"0"`, `ic:"1"` and so on. 28 | 29 | - See more details in utils/decode.go and agent_test.go 30 | 31 | 32 | 33 | 34 | **[update 2022.1.14]** add the new function of agent from pem file and show an example to decode the result to the data structure in Golang -------------------------------------------------------------------------------- /utils/idl/vec.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math/big" 7 | 8 | "github.com/aviate-labs/leb128" 9 | ) 10 | 11 | type Vec struct { 12 | Type Type 13 | } 14 | 15 | func NewVec(t Type) *Vec { 16 | return &Vec{ 17 | Type: t, 18 | } 19 | } 20 | 21 | func (v Vec) AddTypeDefinition(tdt *TypeDefinitionTable) error { 22 | if err := v.Type.AddTypeDefinition(tdt); err != nil { 23 | return err 24 | } 25 | 26 | id, err := leb128.EncodeSigned(big.NewInt(vecType)) 27 | if err != nil { 28 | return err 29 | } 30 | v_, err := v.Type.EncodeType(tdt) 31 | if err != nil { 32 | return err 33 | } 34 | tdt.Add(v, concat(id, v_)) 35 | return nil 36 | } 37 | 38 | func (v Vec) Decode(r *bytes.Reader) (interface{}, error) { 39 | l, err := leb128.DecodeUnsigned(r) 40 | if err != nil { 41 | return nil, err 42 | } 43 | var vs []interface{} 44 | for i := 0; i < int(l.Int64()); i++ { 45 | v_, err := v.Type.Decode(r) 46 | if err != nil { 47 | return nil, err 48 | } 49 | vs = append(vs, v_) 50 | } 51 | return vs, nil 52 | } 53 | 54 | func (v Vec) EncodeType(tdt *TypeDefinitionTable) ([]byte, error) { 55 | idx, ok := tdt.Indexes[v.String()] 56 | if !ok { 57 | return nil, fmt.Errorf("missing type index for: %s", v) 58 | } 59 | return leb128.EncodeSigned(big.NewInt(int64(idx))) 60 | } 61 | 62 | func (v Vec) EncodeValue(value interface{}) ([]byte, error) { 63 | vs_, ok := value.([]interface{}) 64 | if !ok { 65 | return nil, fmt.Errorf("invalid argument: %v", v) 66 | } 67 | l, err := leb128.EncodeSigned(big.NewInt(int64(len(vs_)))) 68 | if err != nil { 69 | return nil, err 70 | } 71 | var vs []byte 72 | for _, value := range vs_ { 73 | v_, err := v.Type.EncodeValue(value) 74 | if err != nil { 75 | return nil, err 76 | } 77 | vs = append(vs, v_...) 78 | } 79 | return concat(l, vs), nil 80 | } 81 | 82 | func (v Vec) String() string { 83 | return fmt.Sprintf("vec %s", v.Type) 84 | } 85 | 86 | func (Vec) Fill(Type) { 87 | 88 | } 89 | -------------------------------------------------------------------------------- /utils/idl/int_test.go: -------------------------------------------------------------------------------- 1 | package idl_test 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/openos-labs/IC-Go/utils/idl" 7 | ) 8 | 9 | func ExampleInt() { 10 | test([]idl.Type{new(idl.Int)}, []interface{}{big.NewInt(0)}) 11 | test([]idl.Type{new(idl.Int)}, []interface{}{big.NewInt(42)}) 12 | test([]idl.Type{new(idl.Int)}, []interface{}{big.NewInt(1234567890)}) 13 | test([]idl.Type{new(idl.Int)}, []interface{}{big.NewInt(-1234567890)}) 14 | test([]idl.Type{new(idl.Int)}, []interface{}{func() *big.Int { 15 | bi, _ := new(big.Int).SetString("60000000000000000", 10) 16 | return bi 17 | }()}) 18 | // Output: 19 | // 4449444c00017c00 20 | // 4449444c00017c2a 21 | // 4449444c00017cd285d8cc04 22 | // 4449444c00017caefaa7b37b 23 | // 4449444c00017c808098f4e9b5caea00 24 | } 25 | 26 | func ExampleInt32() { 27 | test([]idl.Type{idl.Int32()}, []interface{}{big.NewInt(-1234567890)}) 28 | test([]idl.Type{idl.Int32()}, []interface{}{big.NewInt(-42)}) 29 | test([]idl.Type{idl.Int32()}, []interface{}{big.NewInt(42)}) 30 | test([]idl.Type{idl.Int32()}, []interface{}{big.NewInt(1234567890)}) 31 | // Output: 32 | // 4449444c0001752efd69b6 33 | // 4449444c000175d6ffffff 34 | // 4449444c0001752a000000 35 | // 4449444c000175d2029649 36 | } 37 | 38 | func ExampleInt8() { 39 | test([]idl.Type{idl.Int8()}, []interface{}{big.NewInt(-129)}) 40 | test([]idl.Type{idl.Int8()}, []interface{}{big.NewInt(-128)}) 41 | test([]idl.Type{idl.Int8()}, []interface{}{big.NewInt(-42)}) 42 | test([]idl.Type{idl.Int8()}, []interface{}{big.NewInt(-1)}) 43 | test([]idl.Type{idl.Int8()}, []interface{}{big.NewInt(0)}) 44 | test([]idl.Type{idl.Int8()}, []interface{}{big.NewInt(1)}) 45 | test([]idl.Type{idl.Int8()}, []interface{}{big.NewInt(42)}) 46 | test([]idl.Type{idl.Int8()}, []interface{}{big.NewInt(127)}) 47 | test([]idl.Type{idl.Int8()}, []interface{}{big.NewInt(128)}) 48 | // Output: 49 | // enc: invalid value: -129 50 | // 4449444c00017780 51 | // 4449444c000177d6 52 | // 4449444c000177ff 53 | // 4449444c00017700 54 | // 4449444c00017701 55 | // 4449444c0001772a 56 | // 4449444c0001777f 57 | // enc: invalid value: 128 58 | } 59 | -------------------------------------------------------------------------------- /utils/idl/nat_test.go: -------------------------------------------------------------------------------- 1 | package idl_test 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/openos-labs/IC-Go/utils/idl" 7 | ) 8 | 9 | func ExampleNat() { 10 | test([]idl.Type{new(idl.Nat)}, []interface{}{big.NewInt(-1)}) 11 | test([]idl.Type{new(idl.Nat)}, []interface{}{big.NewInt(0)}) 12 | test([]idl.Type{new(idl.Nat)}, []interface{}{big.NewInt(42)}) 13 | test([]idl.Type{new(idl.Nat)}, []interface{}{big.NewInt(1234567890)}) 14 | test([]idl.Type{new(idl.Nat)}, []interface{}{func() *big.Int { 15 | bi, _ := new(big.Int).SetString("60000000000000000", 10) 16 | return bi 17 | }()}) 18 | // Output: 19 | // enc: can not leb128 encode negative values 20 | // 4449444c00017d00 21 | // 4449444c00017d2a 22 | // 4449444c00017dd285d8cc04 23 | // 4449444c00017d808098f4e9b5ca6a 24 | } 25 | 26 | func ExampleNat16() { 27 | test([]idl.Type{idl.Nat16()}, []interface{}{big.NewInt(0)}) 28 | test([]idl.Type{idl.Nat16()}, []interface{}{big.NewInt(42)}) 29 | test([]idl.Type{idl.Nat16()}, []interface{}{big.NewInt(65535)}) 30 | test([]idl.Type{idl.Nat16()}, []interface{}{big.NewInt(65536)}) 31 | // Output: 32 | // 4449444c00017a0000 33 | // 4449444c00017a2a00 34 | // 4449444c00017affff 35 | // enc: invalid value: 65536 36 | } 37 | 38 | func ExampleNat32() { 39 | test([]idl.Type{idl.Nat32()}, []interface{}{big.NewInt(0)}) 40 | test([]idl.Type{idl.Nat32()}, []interface{}{big.NewInt(42)}) 41 | test([]idl.Type{idl.Nat32()}, []interface{}{big.NewInt(4294967295)}) 42 | test([]idl.Type{idl.Nat32()}, []interface{}{big.NewInt(4294967296)}) 43 | // Output: 44 | // 4449444c00017900000000 45 | // 4449444c0001792a000000 46 | // 4449444c000179ffffffff 47 | // enc: invalid value: 4294967296 48 | } 49 | 50 | func ExampleNat64() { 51 | test([]idl.Type{idl.Nat64()}, []interface{}{big.NewInt(0)}) 52 | test([]idl.Type{idl.Nat64()}, []interface{}{big.NewInt(42)}) 53 | test([]idl.Type{idl.Nat64()}, []interface{}{big.NewInt(1234567890)}) 54 | // Output: 55 | // 4449444c0001780000000000000000 56 | // 4449444c0001782a00000000000000 57 | // 4449444c000178d202964900000000 58 | } 59 | 60 | func ExampleNat8() { 61 | test([]idl.Type{idl.Nat8()}, []interface{}{big.NewInt(0)}) 62 | test([]idl.Type{idl.Nat8()}, []interface{}{big.NewInt(42)}) 63 | test([]idl.Type{idl.Nat8()}, []interface{}{big.NewInt(255)}) 64 | test([]idl.Type{idl.Nat8()}, []interface{}{big.NewInt(256)}) 65 | // Output: 66 | // 4449444c00017b00 67 | // 4449444c00017b2a 68 | // 4449444c00017bff 69 | // enc: invalid value: 256 70 | } 71 | -------------------------------------------------------------------------------- /example/registry/proto/node.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package="./pb"; 4 | 5 | package registry.node.v1; 6 | 7 | // A connection endpoint. 8 | message ConnectionEndpoint { 9 | enum Protocol { 10 | PROTOCOL_UNSPECIFIED = 0; 11 | PROTOCOL_HTTP1 = 1; 12 | PROTOCOL_HTTP1_TLS_1_3 = 2; 13 | PROTOCOL_P2P1_TLS_1_3 = 3; 14 | } 15 | 16 | // The IP address. Senders SHOULD use dotted-quad notation for IPv4 addresses 17 | // and RFC5952 representation for IPv6 addresses (which means that IPv6 18 | // addresses are *not* enclosed in `[` and `]`, as they are not written 19 | // with the port in the same field). 20 | // 21 | // Clients MUST be prepared to accept IPv6 addresses in the forms shown in 22 | // RFC4291. 23 | string ip_addr = 1; 24 | uint32 port = 2; 25 | 26 | // Protocol that is used on this endpoint. If PROTOCOL_UNSPECIFIED then 27 | // code should default to PROTOCOL_HTTP1 for backwards compatability. 28 | Protocol protocol = 4; 29 | } 30 | 31 | message FlowEndpoint { 32 | // The flow identifier (tag). This has to be unique per NodeRecord. 33 | uint32 flow_tag = 1; 34 | 35 | // The IP/port for this flow. 36 | ConnectionEndpoint endpoint = 2; 37 | } 38 | 39 | // A node: one machine running a replica instance. 40 | message NodeRecord { 41 | // the node_id is redundant as it is already contained in the key for this 42 | // value. 43 | reserved 1; 44 | reserved "node_id"; 45 | reserved 2; 46 | reserved "gossip_advert"; 47 | reserved 3; 48 | reserved "gossip_request"; 49 | reserved 4; 50 | reserved "gossip_artifact"; 51 | 52 | // The endpoint where this node receives xnet messages. 53 | ConnectionEndpoint xnet = 5; 54 | 55 | // The endpoint where this node receives http requests. 56 | ConnectionEndpoint http = 6; 57 | 58 | reserved 7; 59 | reserved "transport_tls_certificate"; 60 | 61 | // The P2P flow end points. 62 | repeated FlowEndpoint p2p_flow_endpoints = 8; 63 | 64 | reserved 9; 65 | reserved "dcop_principal_id"; 66 | 67 | // Endpoint where the node provides Prometheus format metrics over HTTP 68 | ConnectionEndpoint prometheus_metrics_http = 10; 69 | 70 | // Endpoints on which the public API is served. 71 | repeated ConnectionEndpoint public_api = 11; 72 | 73 | // Endpoints on which private APIs are served. 74 | repeated ConnectionEndpoint private_api = 12; 75 | 76 | // Endpoints on which metrics compatible with the Prometheus export 77 | // format are served. 78 | repeated ConnectionEndpoint prometheus_metrics = 13; 79 | 80 | // Endpoints on which the XNet API is served 81 | repeated ConnectionEndpoint xnet_api = 14; 82 | 83 | // The id of the node operator that added this node. 84 | bytes node_operator_id = 15; 85 | } 86 | -------------------------------------------------------------------------------- /example/registry/registry_test.go: -------------------------------------------------------------------------------- 1 | package registry 2 | 3 | import ( 4 | "encoding/binary" 5 | "fmt" 6 | "testing" 7 | 8 | agent "github.com/openos-labs/IC-Go" 9 | "github.com/openos-labs/IC-Go/utils/principal" 10 | ) 11 | 12 | func TestGetRoutingTable(t *testing.T) { 13 | a := agent.New(true, "") 14 | routingTable, err := GetRoutingTable(a) 15 | if err != nil { 16 | t.Log("error:", err) 17 | } 18 | for i, entry := range routingTable.Entries { 19 | t.Log("subnet index:", i) 20 | fmt.Println("subnetID:", principal.New(entry.SubnetId.PrincipalId.Raw).Encode()) 21 | fmt.Println("start canister ID:", principal.New(entry.Range.StartCanisterId.PrincipalId.Raw).Encode()) 22 | fmt.Println("start canister ID raw:", entry.Range.StartCanisterId.PrincipalId.Raw) 23 | fmt.Println("start canister ID to uint64:", binary.BigEndian.Uint64(entry.Range.StartCanisterId.PrincipalId.Raw[:8])) 24 | 25 | 26 | fmt.Println("end canister ID:", principal.New(entry.Range.EndCanisterId.PrincipalId.Raw).Encode()) 27 | fmt.Println("end canister ID raw:", entry.Range.EndCanisterId.PrincipalId.Raw) 28 | fmt.Println("end canister ID to uint64:", binary.BigEndian.Uint64(entry.Range.EndCanisterId.PrincipalId.Raw[:8])) 29 | } 30 | } 31 | 32 | func TestGetSubnetList(t *testing.T) { 33 | a := agent.New(true, "") 34 | subnetList, err := GetSubnetList(a) 35 | if err != nil { 36 | t.Log("error:", err) 37 | } 38 | for _, entry := range subnetList.Subnets { 39 | t.Log("subnetID:", principal.New(entry).Encode()) 40 | } 41 | } 42 | 43 | func TestGetSubnetRecord(t *testing.T) { 44 | a := agent.New(true, "") 45 | subnet, err := GetSubnetRecord(a, "tdb26-jop6k-aogll-7ltgs-eruif-6kk7m-qpktf-gdiqx-mxtrf-vb5e6-eqe") 46 | if err != nil { 47 | t.Log("error:", err) 48 | } 49 | 50 | t.Log("subnet Type:",subnet.SubnetType) 51 | t.Log("max canister amount",subnet.MaxNumberOfCanisters) 52 | for _, node := range subnet.Membership { 53 | t.Log("node:", principal.New(node).Encode()) 54 | } 55 | } 56 | 57 | func TestGetNodeInfo(t *testing.T) { 58 | a := agent.New(true, "") 59 | node, err := GetNodeInfo(a, "btuxg-lwlbn-43hlo-iag4h-plf64-b3u7d-ugvay-nbvrl-jkhlx-nhvw4-gae") 60 | if err != nil { 61 | t.Log("error:", err) 62 | } 63 | t.Log("operator:", principal.New(node.NodeOperatorId).Encode()) 64 | } 65 | 66 | func TestGetOperatorInfo(t *testing.T) { 67 | a := agent.New(true, "") 68 | op, err := GetOperatorInfo(a, "redpf-rrb5x-sa2it-zhbh7-q2fsp-bqlwz-4mf4y-tgxmj-g5y7p-ezjtj-5qe") 69 | if err != nil { 70 | t.Log("error:", err) 71 | } 72 | t.Log("operator:", principal.New(op.NodeOperatorPrincipalId).Encode()) 73 | t.Log("provider:", principal.New(op.NodeProviderPrincipalId).Encode()) 74 | 75 | t.Log("Node Allowance:", op.NodeAllowance) 76 | t.Log("Rewardable Nodes:", op.RewardableNodes) 77 | } 78 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package agent 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "net/http" 8 | ) 9 | 10 | type Client struct { 11 | client http.Client 12 | host string 13 | } 14 | 15 | func NewClient(host string) Client { 16 | return Client{ 17 | client: http.Client{}, 18 | host: host, 19 | } 20 | } 21 | 22 | func (c *Client) Status() (Status, error) { 23 | raw, err := c.get("/api/v2/status") 24 | if err != nil { 25 | return Status{}, err 26 | } 27 | status := new(Status) 28 | err = status.UnmarshalCBOR(raw) 29 | return *status, err 30 | } 31 | 32 | func (c *Client) query(canisterId string, data []byte) ([]byte, error) { 33 | buffer := bytes.NewBuffer(data) 34 | endpoint := c.host + "/api/v2/canister/" + canisterId + "/query" 35 | //fmt.Println("post url:", endpoint) 36 | resp, err := c.client.Post(endpoint, "application/cbor", buffer) 37 | if err != nil { 38 | fmt.Println("error:", err) 39 | return nil, err 40 | } else if resp.StatusCode != 200 { 41 | //fmt.Println( 42 | // "status:", resp.Status, "\n", 43 | // "StatusCode:", resp.StatusCode, "\n", 44 | // "Proto:", resp.Proto, "\n", 45 | // "ProtoMajor:", resp.ProtoMajor, "\n", 46 | // "ProtoMinor:", resp.ProtoMinor, "\n", 47 | // "Header:", resp.Header, "\n", 48 | // "Body:", resp.Body, "\n", 49 | // "ContentLength:", resp.ContentLength, "\n", 50 | // "TransferEncoding:", resp.TransferEncoding, "\n", 51 | // "Request:", resp.Request, 52 | //) 53 | return nil, fmt.Errorf("fail to post ic with status: %v", resp.Status) 54 | } 55 | defer resp.Body.Close() 56 | return io.ReadAll(resp.Body) 57 | } 58 | 59 | func (c *Client) call(canisterId string, reqId RequestID, data []byte) (RequestID, error) { 60 | buffer := bytes.NewBuffer(data) 61 | endpoint := c.host + "/api/v2/canister/" + canisterId + "/call" 62 | //fmt.Println("endpoint:", endpoint) 63 | contentType := "application/cbor" 64 | resp, err := c.client.Post(endpoint, contentType, buffer) 65 | if err != nil { 66 | return reqId, err 67 | } 68 | if resp.StatusCode != 202 { 69 | fmt.Println(resp) 70 | return reqId, fmt.Errorf("fail to call ic with status: %v", resp.Status) 71 | } 72 | return reqId, nil 73 | } 74 | 75 | func (c *Client) readState(canisterId string, data []byte) ([]byte, error) { 76 | buffer := bytes.NewBuffer(data) 77 | endpoint := c.host + "/api/v2/canister/" + canisterId + "/read_state" 78 | contentType := "application/cbor" 79 | resp, err := c.client.Post(endpoint, contentType, buffer) 80 | if err != nil { 81 | return nil, err 82 | } 83 | if resp.StatusCode != 200 { 84 | return []byte{}, fmt.Errorf("fail to read state with status: %v", resp.Status) 85 | } 86 | return io.ReadAll(resp.Body) 87 | } 88 | 89 | func (c Client) get(path string) ([]byte, error) { 90 | a := c.host + path 91 | resp, err := c.client.Get(a) 92 | if err != nil { 93 | return nil, err 94 | } 95 | return io.ReadAll(resp.Body) 96 | } -------------------------------------------------------------------------------- /utils/idl/tdt_test.go: -------------------------------------------------------------------------------- 1 | package idl_test 2 | 3 | //import ( 4 | // "encoding/hex" 5 | // "fmt" 6 | // "io/ioutil" 7 | // "testing" 8 | // 9 | // "github.com/aviate-labs/candid-go/idl" 10 | // "github.com/aviate-labs/candid-go/internal/blob" 11 | // "github.com/aviate-labs/candid-go/internal/candidtest" 12 | // "github.com/di-wu/parser" 13 | // "github.com/di-wu/parser/ast" 14 | //) 15 | // 16 | //func TestTypeDefinitionTable(t *testing.T) { 17 | // rawDid, err := ioutil.ReadFile("testdata/prim.test.did") 18 | // if err != nil { 19 | // t.Fatal(err) 20 | // } 21 | // p, err := ast.New(rawDid) 22 | // if err != nil { 23 | // t.Fatal(err) 24 | // } 25 | // n, err := candidtest.TestData(p) 26 | // if err != nil { 27 | // t.Fatal(err) 28 | // } 29 | // if _, err := p.Expect(parser.EOD); err != nil { 30 | // t.Error(err) 31 | // } 32 | // for _, n := range n.Children() { 33 | // switch n.Type { 34 | // case candidtest.CommentTextT: // ignore 35 | // case candidtest.TestT: 36 | // var ( 37 | // in []byte 38 | // test *ast.Node 39 | // desc string 40 | // ) 41 | // for _, n := range n.Children() { 42 | // switch n.Type { 43 | // case candidtest.BlobInputT: 44 | // b, err := parseBlob(n) 45 | // if err != nil { 46 | // t.Fatal(err) 47 | // } 48 | // in = b 49 | // case candidtest.TestBadT, 50 | // candidtest.TestGoodT, // TODO 51 | // candidtest.TestTestT: // TODO 52 | // test = n 53 | // case candidtest.DescriptionT: 54 | // desc = n.Value 55 | // default: 56 | // t.Fatal(n) 57 | // } 58 | // } 59 | // switch test.Type { 60 | // case candidtest.TestBadT: 61 | // ts, as, err := idl.Decode(in) 62 | // if err == nil { 63 | // t.Errorf("%s: %v, %v", desc, ts, as) 64 | // } 65 | // } 66 | // default: 67 | // t.Fatal(n) 68 | // } 69 | // } 70 | //} 71 | // 72 | //func parseBlob(n *ast.Node) ([]byte, error) { 73 | // if n.Type != candidtest.BlobInputT { 74 | // return nil, fmt.Errorf("invalid type: %s", n.TypeString()) 75 | // } 76 | // if len(n.Value) == 0 { 77 | // return []byte{}, nil 78 | // } 79 | // p, err := ast.New([]byte(n.Value)) 80 | // if err != nil { 81 | // return nil, err 82 | // } 83 | // b, err := blob.Blob(p) 84 | // if err != nil { 85 | // return nil, err 86 | // } 87 | // if _, err := p.Expect(parser.EOD); err != nil { 88 | // return nil, err 89 | // } 90 | // var bs []byte 91 | // for _, n := range b.Children() { 92 | // switch n.Type { 93 | // case blob.AlphaT: 94 | // bs = append(bs, []byte(n.Value)...) 95 | // case blob.HexT: 96 | // h, err := hex.DecodeString(n.Value) 97 | // if err != nil { 98 | // return nil, err 99 | // } 100 | // bs = append(bs, h...) 101 | // default: 102 | // return nil, fmt.Errorf("invalid type: %s", n.TypeString()) 103 | // } 104 | // } 105 | // return bs, nil 106 | //} 107 | -------------------------------------------------------------------------------- /utils/idl/rec.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math/big" 7 | "sort" 8 | "strings" 9 | 10 | "github.com/aviate-labs/leb128" 11 | ) 12 | 13 | type Rec struct { 14 | Fields []Field 15 | } 16 | 17 | func NewRec(fields map[string]Type) *Rec { 18 | var rec Rec 19 | for k, v := range fields { 20 | rec.Fields = append(rec.Fields, Field{ 21 | Name: k, 22 | Type: v, 23 | }) 24 | } 25 | sort.Slice(rec.Fields, func(i, j int) bool { 26 | return Hash(rec.Fields[i].Name).Cmp(Hash(rec.Fields[j].Name)) < 0 27 | }) 28 | return &rec 29 | } 30 | 31 | func (r Rec) AddTypeDefinition(tdt *TypeDefinitionTable) error { 32 | for _, f := range r.Fields { 33 | if err := f.Type.AddTypeDefinition(tdt); err != nil { 34 | return err 35 | } 36 | } 37 | 38 | id, err := leb128.EncodeSigned(big.NewInt(recType)) 39 | if err != nil { 40 | return err 41 | } 42 | l, err := leb128.EncodeUnsigned(big.NewInt(int64(len(r.Fields)))) 43 | if err != nil { 44 | return err 45 | } 46 | var vs []byte 47 | for _, f := range r.Fields { 48 | l, err := leb128.EncodeUnsigned(Hash(f.Name)) 49 | if err != nil { 50 | return nil 51 | } 52 | t, err := f.Type.EncodeType(tdt) 53 | if err != nil { 54 | return nil 55 | } 56 | vs = append(vs, concat(l, t)...) 57 | } 58 | 59 | tdt.Add(r, concat(id, l, vs)) 60 | return nil 61 | } 62 | 63 | func (r Rec) Decode(r_ *bytes.Reader) (interface{}, error) { 64 | rec := make(map[string]interface{}) 65 | for _, f := range r.Fields { 66 | v, err := f.Type.Decode(r_) 67 | if err != nil { 68 | return nil, err 69 | } 70 | rec[f.Name] = v 71 | } 72 | if len(rec) == 0 { 73 | return nil, nil 74 | } 75 | return rec, nil 76 | } 77 | 78 | func (r Rec) EncodeType(tdt *TypeDefinitionTable) ([]byte, error) { 79 | idx, ok := tdt.Indexes[r.String()] 80 | if !ok { 81 | return nil, fmt.Errorf("missing type index for: %s", r) 82 | } 83 | return leb128.EncodeSigned(big.NewInt(int64(idx))) 84 | } 85 | 86 | func (r Rec) EncodeValue(v interface{}) ([]byte, error) { 87 | if v == nil { 88 | return nil, nil 89 | } 90 | fs, ok := v.(map[string]interface{}) 91 | if !ok { 92 | return nil, fmt.Errorf("invalid argument: %v", v) 93 | } 94 | var vs_ []interface{} 95 | for _, f := range r.Fields { 96 | vs_ = append(vs_, fs[f.Name]) 97 | } 98 | var vs []byte 99 | for i, f := range r.Fields { 100 | v_, err := f.Type.EncodeValue(vs_[i]) 101 | if err != nil { 102 | return nil, err 103 | } 104 | vs = append(vs, v_...) 105 | } 106 | return vs, nil 107 | } 108 | 109 | func (Rec) Fill(Type) { 110 | 111 | } 112 | 113 | func (r Rec) String() string { 114 | var s []string 115 | for _, f := range r.Fields { 116 | s = append(s, fmt.Sprintf("%s:%s", f.Name, f.Type.String())) 117 | } 118 | return fmt.Sprintf("record {%s}", strings.Join(s, "; ")) 119 | } 120 | -------------------------------------------------------------------------------- /example/registry/registry.go: -------------------------------------------------------------------------------- 1 | package registry 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/golang/protobuf/proto" 7 | agent "github.com/openos-labs/IC-Go" 8 | "github.com/openos-labs/IC-Go/example/registry/proto/pb" 9 | ) 10 | 11 | const CanisterId = "rwlgt-iiaaa-aaaaa-aaaaa-cai" 12 | 13 | func getValue(agent *agent.Agent, key string) (*pb.RegistryGetValueResponse, error) { 14 | getValueResponse := new(pb.RegistryGetValueResponse) 15 | requestKey := []byte(key) 16 | request := &pb.RegistryGetValueRequest{ 17 | Version: nil, 18 | Key: requestKey, 19 | } 20 | requestBuf, err := proto.Marshal(request) 21 | if err != nil { 22 | return nil, err 23 | } 24 | resp, ErrMsg, err := agent.QueryRaw(CanisterId, "get_value", requestBuf) 25 | if ErrMsg != "" { 26 | return nil, errors.New(ErrMsg) 27 | } else if err != nil { 28 | return nil, err 29 | } 30 | err = proto.Unmarshal(resp, getValueResponse) 31 | if err != nil { 32 | return nil, err 33 | } 34 | return getValueResponse, nil 35 | } 36 | 37 | func GetRoutingTable(agent *agent.Agent) (*pb.RoutingTable, error) { 38 | routingTable := new(pb.RoutingTable) 39 | resp, err := getValue(agent, "routing_table") 40 | if err != nil { 41 | return nil, err 42 | } 43 | err = proto.Unmarshal(resp.Value, routingTable) 44 | if err != nil { 45 | return nil, err 46 | } 47 | return routingTable, nil 48 | } 49 | 50 | func GetSubnetList(agent *agent.Agent) (*pb.SubnetListRecord, error) { 51 | subnetList := new(pb.SubnetListRecord) 52 | resp, err := getValue(agent, "subnet_list") 53 | if err != nil { 54 | return nil, err 55 | } 56 | err = proto.Unmarshal(resp.Value, subnetList) 57 | if err != nil { 58 | return nil, err 59 | } 60 | return subnetList, nil 61 | } 62 | 63 | func GetSubnetRecord(agent *agent.Agent, subnetID string) (*pb.SubnetRecord, error) { 64 | subnetRecord := new(pb.SubnetRecord) 65 | key := "subnet_record_" + subnetID 66 | resp, err := getValue(agent, key) 67 | if err != nil { 68 | return nil, err 69 | } 70 | err = proto.Unmarshal(resp.Value, subnetRecord) 71 | if err != nil { 72 | return nil, err 73 | } 74 | return subnetRecord, nil 75 | } 76 | 77 | func GetNodeInfo(agent *agent.Agent, nodeID string) (*pb.NodeRecord, error) { 78 | nodeRecord := new(pb.NodeRecord) 79 | key := "node_record_" + nodeID 80 | resp, err := getValue(agent, key) 81 | if err != nil { 82 | return nil, err 83 | } 84 | err = proto.Unmarshal(resp.Value, nodeRecord) 85 | if err != nil { 86 | return nil, err 87 | } 88 | return nodeRecord, nil 89 | } 90 | 91 | func GetOperatorInfo(agent *agent.Agent, operatorID string) (*pb.NodeOperatorRecord, error) { 92 | operatorRecord := new(pb.NodeOperatorRecord) 93 | key := "node_operator_record_" + operatorID 94 | resp, err := getValue(agent, key) 95 | if err != nil { 96 | return nil, err 97 | } 98 | err = proto.Unmarshal(resp.Value, operatorRecord) 99 | if err != nil { 100 | return nil, err 101 | } 102 | return operatorRecord, nil 103 | } 104 | -------------------------------------------------------------------------------- /utils/idl/type.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | ) 7 | 8 | var ( 9 | nullType int64 = -1 // 0x7f 10 | boolType int64 = -2 // 0x7e 11 | natType int64 = -3 // 0x7d 12 | intType int64 = -4 // 0x7c 13 | natXType int64 = -5 // 0x7b-0x78 14 | intXType int64 = -9 // 0x77-0x73 15 | floatXType int64 = -13 // 0x72 16 | textType int64 = -15 // 0x71 17 | reservedType int64 = -16 // 0x70 18 | emptyType int64 = -17 // 0x6f 19 | optType int64 = -18 // 0x6e 20 | vecType int64 = -19 // 0x6d 21 | recType int64 = -20 // 0x6c 22 | varType int64 = -21 // 0x6b 23 | funcType int64 = -22 // 0x6a 24 | serviceType int64 = -23 // 0x69 25 | principalType int64 = -24 // 0x68 26 | ) 27 | 28 | type PrimType interface { 29 | prim() 30 | } 31 | 32 | type Type interface { 33 | // AddTypeDefinition adds itself to the definition table if it is not a primitive type. 34 | AddTypeDefinition(*TypeDefinitionTable) error 35 | 36 | // Decodes the value from the reader. 37 | Decode(*bytes.Reader) (interface{}, error) 38 | 39 | // Encodes the type. 40 | EncodeType(*TypeDefinitionTable) ([]byte, error) 41 | 42 | // Encodes the value. 43 | EncodeValue(v interface{}) ([]byte, error) 44 | 45 | Fill(v Type) 46 | 47 | fmt.Stringer 48 | } 49 | 50 | func getType(t int64) (Type, error) { 51 | // if t >= 0 { 52 | // if int(t) >= len(tds) { 53 | // return nil, fmt.Errorf("type index out of range: %d", t) 54 | // } 55 | // return tds[t], nil 56 | // } 57 | 58 | switch t { 59 | case nullType: 60 | return new(Null), nil 61 | case boolType: 62 | return new(Bool), nil 63 | case natType: 64 | return new(Nat), nil 65 | case intType: 66 | return new(Int), nil 67 | case natXType: 68 | return Nat8(), nil 69 | case natXType - 1: 70 | return Nat16(), nil 71 | case natXType - 2: 72 | return Nat32(), nil 73 | case natXType - 3: 74 | return Nat64(), nil 75 | case intXType: 76 | return Int8(), nil 77 | case intXType - 1: 78 | return Int16(), nil 79 | case intXType - 2: 80 | return Int32(), nil 81 | case intXType - 3: 82 | return Int64(), nil 83 | case floatXType: 84 | return Float32(), nil 85 | case floatXType - 1: 86 | return Float64(), nil 87 | case textType: 88 | return new(Text), nil 89 | case reservedType: 90 | return new(Reserved), nil 91 | case emptyType: 92 | return new(Empty), nil 93 | case principalType: 94 | return new(Principal), nil 95 | default: 96 | if t < -24 { 97 | return nil, &FormatError{ 98 | Description: "type: out of range", 99 | } 100 | } 101 | return nil, &FormatError{ 102 | Description: "type: not primitive", 103 | } 104 | } 105 | } 106 | 107 | type primType struct{} 108 | 109 | func (primType) AddTypeDefinition(_ *TypeDefinitionTable) error { 110 | return nil // No need to add primitive types to the type definition table. 111 | } 112 | 113 | func (primType) Fill(Type) { 114 | 115 | } 116 | func (primType) prim() {} 117 | -------------------------------------------------------------------------------- /utils/decode.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "math/big" 5 | "reflect" 6 | "unsafe" 7 | 8 | "github.com/openos-labs/IC-Go/utils/idl" 9 | ) 10 | 11 | 12 | 13 | func Decode(target interface{}, source interface{}) { 14 | Type := reflect.TypeOf(target).Elem() 15 | Value := reflect.ValueOf(target) 16 | _Decode(Value, Type, source) 17 | } 18 | 19 | func _Decode(target reflect.Value, targetType reflect.Type,source interface{}) { 20 | if targetType.Kind() == reflect.Struct { 21 | if targetType.Name() == "Int" { 22 | value := source.(*big.Int) 23 | ptarget := (*big.Int)(unsafe.Pointer(target.Elem().UnsafeAddr())) 24 | ptarget.Set(value) 25 | return 26 | } 27 | 28 | sourceField := source.(map[string]interface{}) 29 | 30 | for k, v := range(sourceField) { 31 | for i := 0; i < targetType.NumField(); i++ { 32 | targetFiledType := targetType.Field(i) 33 | 34 | if idl.Hash(targetFiledType.Tag.Get("ic")).String() == k { 35 | targetFiledValue := target.Elem().Field(i) 36 | _Decode(targetFiledValue.Addr(), targetFiledType.Type, v) 37 | break 38 | } 39 | 40 | if targetFiledType.Tag.Get("ic") == k { 41 | targetFiledValue := target.Elem().Field(i) 42 | if k == "EnumIndex" { 43 | //to solve enum struct 44 | for j := 0; j < targetType.NumField(); j++ { 45 | labelFiledType := targetType.Field(j) 46 | if idl.Hash(labelFiledType.Tag.Get("ic")).String() == v.(string) { 47 | targetFiledValue.SetString(labelFiledType.Tag.Get("ic")) 48 | } 49 | } 50 | continue 51 | } 52 | 53 | _Decode(targetFiledValue.Addr(), targetFiledType.Type, v) 54 | } 55 | } 56 | } 57 | } else if targetType.Kind() == reflect.String { 58 | sourceFiled := source.(string) 59 | target.Elem().SetString(sourceFiled) 60 | } else if targetType.Kind() == reflect.Int || targetType.Kind() == reflect.Int8 || targetType.Kind() == reflect.Int16 || targetType.Kind() == reflect.Int32 || targetType.Kind() == reflect.Int64 { 61 | source_ := source.(*big.Int) 62 | sourceFiled := source_.Int64() 63 | target.Elem().SetInt(sourceFiled) 64 | } else if targetType.Kind() == reflect.Uint || targetType.Kind() == reflect.Uint8 || targetType.Kind() == reflect.Uint16 || targetType.Kind() == reflect.Uint32 || targetType.Kind() == reflect.Uint64 { 65 | source_ := source.(*big.Int) 66 | sourceFiled := source_.Uint64() 67 | target.Elem().SetUint(sourceFiled) 68 | } else if targetType.Kind() == reflect.Float32 || targetType.Kind() == reflect.Float64 { 69 | source_ := source.(*big.Float) 70 | sourceFiled, _ := source_.Float64() 71 | target.Elem().SetFloat(sourceFiled) 72 | } else if targetType.Kind() == reflect.Slice { 73 | if targetType.Name() == "Principal" { 74 | sourceFiled := source.([]uint8) 75 | target.Elem().SetBytes(sourceFiled) 76 | return 77 | } 78 | sourceFiled := source.([]interface{}) 79 | var elem reflect.Value 80 | Type := targetType.Elem() 81 | for _, v := range(sourceFiled) { 82 | elem = reflect.New(Type) 83 | _Decode(elem, elem.Type().Elem(), v) 84 | target.Elem().Set(reflect.Append(target.Elem(), elem.Elem())) 85 | } 86 | } 87 | 88 | 89 | 90 | } 91 | -------------------------------------------------------------------------------- /cerificate.go: -------------------------------------------------------------------------------- 1 | package agent 2 | 3 | import ( 4 | "encoding/hex" 5 | 6 | "github.com/fxamacker/cbor/v2" 7 | ) 8 | 9 | const ( 10 | Empty uint64 = iota 11 | Fork 12 | Labeled 13 | Leaf 14 | Pruned 15 | ) 16 | 17 | func LookUp(paths [][]byte, cert []byte)([]byte, error) { 18 | var certificate interface{} 19 | err := cbor.Unmarshal(cert, &certificate) 20 | if err != nil{ 21 | return nil,err 22 | } 23 | certi_struct, ok := certificate.(map[interface{}]interface{}) 24 | if !ok{ 25 | return nil, nil 26 | } 27 | for k, v := range(certi_struct){ 28 | k_value, ok := k.(string) 29 | if ok && k_value == "tree"{ 30 | tree_value, ok := v.([]interface{}) 31 | if !ok { 32 | continue 33 | } 34 | 35 | return lookupPath(paths, tree_value) 36 | 37 | } 38 | } 39 | 40 | return nil, nil 41 | } 42 | 43 | func lookupPath(paths [][]byte, tree []interface{})([]byte, error) { 44 | if tree == nil{ 45 | return nil, nil 46 | } 47 | offset := 0 48 | if len(paths) == 0{ 49 | if tree == nil{ 50 | return nil, nil 51 | } 52 | tree_0, ok := tree[0].(uint64) 53 | if !ok{ 54 | return nil, nil 55 | } 56 | if tree_0 == Leaf{ 57 | tree_1, ok := tree[1].([]byte) 58 | if !ok{ 59 | return nil, nil 60 | } 61 | return tree_1, nil 62 | } else { 63 | return nil, nil 64 | } 65 | } 66 | label := paths[0] 67 | 68 | 69 | t_flatten, _ := flattenForks(tree) 70 | t, _ := findLabel(label, t_flatten) 71 | offset += 1 72 | return lookupPath(paths[offset:], t) 73 | } 74 | 75 | func flattenForks(tree []interface{}) ([][]interface{}, error){ 76 | tree_0, ok := tree[0].(uint64) 77 | if !ok{ 78 | return nil, nil 79 | } 80 | if tree_0 == Empty{ 81 | return [][]interface{}{}, nil 82 | } else if tree_0 == Fork{ 83 | t_1, ok := tree[1].([]interface{}) 84 | if !ok{ 85 | return nil, nil 86 | } 87 | t_2, ok := tree[2].([]interface{}) 88 | if !ok{ 89 | return nil, nil 90 | } 91 | left, _ := flattenForks(t_1) 92 | right, _ := flattenForks(t_2) 93 | return append(left, right...), nil 94 | } else { 95 | return [][]interface{}{tree}, nil 96 | } 97 | } 98 | 99 | func findLabel(label []byte, trees [][]interface{}) ([]interface{}, error) { 100 | if len(trees) == 0{ 101 | return nil, nil 102 | } 103 | 104 | for _, t := range(trees) { 105 | t_0, ok := t[0].(uint64) 106 | if !ok{ 107 | return nil, nil 108 | } 109 | if t_0 == Labeled{ 110 | t_1, ok := t[1].([]byte) 111 | 112 | if !ok { 113 | 114 | return nil, nil 115 | } 116 | if (hex.EncodeToString(t_1) != hex.EncodeToString(label)) { 117 | //fmt.Println(label, " error") 118 | continue 119 | } 120 | t_2, ok := t[2].([]interface{}) 121 | if !ok{ 122 | return nil, nil 123 | } 124 | return t_2, nil 125 | } 126 | } 127 | return nil, nil 128 | } 129 | 130 | 131 | type Certificate struct { 132 | Tree Tree `cbor:"tree"` 133 | Signature []byte `cbor:"signature"` 134 | Delegation []byte `cbor:"delegation"` 135 | } 136 | 137 | type Tree struct { 138 | _ struct{} `cbor:",toarray"` 139 | sym byte 140 | a []byte 141 | b []byte 142 | } 143 | -------------------------------------------------------------------------------- /utils/idl/service.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | 7 | "github.com/aviate-labs/leb128" 8 | "github.com/openos-labs/IC-Go/utils/principal" 9 | 10 | "math/big" 11 | "sort" 12 | "strings" 13 | ) 14 | 15 | type Method struct { 16 | Name string 17 | Func *Func 18 | } 19 | 20 | type Service struct { 21 | methods []Method 22 | } 23 | 24 | func NewService(methods map[string]*Func) *Service { 25 | var service Service 26 | for k, v := range methods { 27 | service.methods = append(service.methods, Method{ 28 | Name: k, 29 | Func: v, 30 | }) 31 | } 32 | sort.Slice(service.methods, func(i, j int) bool { 33 | return Hash(service.methods[i].Name).Cmp(Hash(service.methods[j].Name)) < 0 34 | }) 35 | return &service 36 | } 37 | 38 | func (s Service) AddTypeDefinition(tdt *TypeDefinitionTable) error { 39 | for _, f := range s.methods { 40 | if err := f.Func.AddTypeDefinition(tdt); err != nil { 41 | return err 42 | } 43 | } 44 | 45 | id, err := leb128.EncodeSigned(big.NewInt(serviceType)) 46 | if err != nil { 47 | return err 48 | } 49 | l, err := leb128.EncodeUnsigned(big.NewInt(int64(len(s.methods)))) 50 | if err != nil { 51 | return err 52 | } 53 | var vs []byte 54 | for _, f := range s.methods { 55 | id := []byte(f.Name) 56 | l, err := leb128.EncodeUnsigned(big.NewInt(int64(len((id))))) 57 | if err != nil { 58 | return nil 59 | } 60 | t, err := f.Func.EncodeType(tdt) 61 | if err != nil { 62 | return nil 63 | } 64 | vs = append(vs, concat(l, id, t)...) 65 | } 66 | 67 | tdt.Add(s, concat(id, l, vs)) 68 | return nil 69 | } 70 | 71 | func (s Service) Decode(r *bytes.Reader) (interface{}, error) { 72 | { 73 | bs := make([]byte, 1) 74 | n, err := r.Read(bs) 75 | if err != nil { 76 | return nil, err 77 | } 78 | if n != 1 || bs[0] != 0x01 { 79 | return nil, fmt.Errorf("invalid func reference: %d", bs) 80 | } 81 | } 82 | l, err := leb128.DecodeUnsigned(r) 83 | if err != nil { 84 | return nil, err 85 | } 86 | pid := make(principal.Principal, l.Int64()) 87 | n, err := r.Read(pid) 88 | if err != nil { 89 | return nil, err 90 | } 91 | if n != int(l.Int64()) { 92 | return nil, fmt.Errorf("invalid principal id: %d", pid) 93 | } 94 | return pid, nil 95 | } 96 | 97 | func (s Service) EncodeType(tdt *TypeDefinitionTable) ([]byte, error) { 98 | idx, ok := tdt.Indexes[s.String()] 99 | if !ok { 100 | return nil, fmt.Errorf("missing type index for: %s", s) 101 | } 102 | return leb128.EncodeSigned(big.NewInt(int64(idx))) 103 | } 104 | 105 | func (s Service) EncodeValue(v interface{}) ([]byte, error) { 106 | p, ok := v.(principal.Principal) 107 | if !ok { 108 | return nil, fmt.Errorf("invalid argument: %v", v) 109 | } 110 | l, err := leb128.EncodeUnsigned(big.NewInt(int64(len(p)))) 111 | if err != nil { 112 | return nil, err 113 | } 114 | return concat([]byte{0x01}, l, []byte(p)), nil 115 | } 116 | 117 | func (Service) Fill(Type) { 118 | 119 | } 120 | func (s Service) String() string { 121 | var methods []string 122 | for _, m := range s.methods { 123 | methods = append(methods, fmt.Sprintf("%s:%s", m.Name, m.Func.String())) 124 | } 125 | return fmt.Sprintf("service {%s}", strings.Join(methods, "; ")) 126 | } 127 | -------------------------------------------------------------------------------- /utils/idl/util.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "io" 7 | "math" 8 | "math/big" 9 | ) 10 | 11 | func concat(bs ...[]byte) []byte { 12 | var c []byte 13 | for _, b := range bs { 14 | c = append(c, b...) 15 | } 16 | return c 17 | } 18 | 19 | func log2(n uint8) uint8 { 20 | return uint8(math.Log2(float64(n))) 21 | } 22 | 23 | func pad0(n int, bs []byte) []byte { 24 | for len(bs) != n { 25 | bs = append(bs, 0) 26 | } 27 | return bs 28 | } 29 | 30 | func pad1(n int, bs []byte) []byte { 31 | for len(bs) != n { 32 | bs = append(bs, 0xff) 33 | } 34 | return bs 35 | } 36 | 37 | func readFloat(r *bytes.Reader, n int) (*big.Float, error) { 38 | bs := make([]byte, n) 39 | i, err := r.Read(bs) 40 | if err != nil { 41 | return nil, err 42 | } 43 | if i != n { 44 | return nil, io.EOF 45 | } 46 | switch n { 47 | case 4: 48 | return big.NewFloat( 49 | float64(math.Float32frombits( 50 | binary.LittleEndian.Uint32(bs), 51 | )), 52 | ), nil 53 | default: 54 | f := math.Float64frombits( 55 | binary.LittleEndian.Uint64(bs), 56 | ) 57 | if math.IsNaN(f) { 58 | return big.NewFloat(0.), nil 59 | //return nil, fmt.Errorf("float: NaN") 60 | } 61 | return big.NewFloat(f), nil 62 | } 63 | } 64 | 65 | func readInt(r *bytes.Reader, n int) (*big.Int, error) { 66 | bi, err := readUInt(r, n) 67 | if err != nil { 68 | return nil, err 69 | } 70 | m := big.NewInt(2) 71 | m = m.Exp(m, big.NewInt(int64((n-1)*8+7)), nil) 72 | if bi.Cmp(m) >= 0 { 73 | v := new(big.Int).Set(m) 74 | v = v.Mul(v, big.NewInt(-2)) 75 | bi = bi.Add(bi, v) 76 | } 77 | return bi, nil 78 | } 79 | 80 | func readUInt(r *bytes.Reader, n int) (*big.Int, error) { 81 | var ( 82 | bi = new(big.Int) 83 | xFF = big.NewInt(256) 84 | m = big.NewInt(1) 85 | ) 86 | for i := 0; i < n; i++ { 87 | b, err := r.ReadByte() 88 | if err != nil { 89 | return nil, err 90 | } 91 | v := new(big.Int).SetBytes([]byte{b}) 92 | bi = bi.Add(bi, v.Mul(v, m)) 93 | m = m.Mul(m, xFF) 94 | } 95 | return bi, nil 96 | } 97 | 98 | func reverse(s []byte) []byte { 99 | for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { 100 | s[i], s[j] = s[j], s[i] 101 | } 102 | return s 103 | } 104 | 105 | func twosCompl(bi *big.Int) *big.Int { 106 | inv := bi.Bytes() 107 | for i, b := range inv { 108 | inv[i] = ^b 109 | } 110 | bi.SetBytes(inv) 111 | return bi.Add(bi, big.NewInt(1)) 112 | } 113 | 114 | func writeFloat(f *big.Float, n int) []byte { 115 | bs := make([]byte, n) 116 | switch n { 117 | case 4: 118 | f32, _ := f.Float32() 119 | binary.LittleEndian.PutUint32(bs, math.Float32bits(f32)) 120 | default: 121 | f64, _ := f.Float64() 122 | binary.LittleEndian.PutUint64(bs, math.Float64bits(f64)) 123 | } 124 | return bs 125 | } 126 | 127 | func writeInt(bi *big.Int, n int) []byte { 128 | switch bi.Sign() { 129 | case 0: 130 | return zeros(n) 131 | case -1: 132 | bi := new(big.Int).Set(bi) 133 | return pad1(n, reverse(twosCompl(bi).Bytes())) 134 | default: 135 | return pad0(n, reverse(bi.Bytes())) 136 | } 137 | } 138 | 139 | func zeros(n int) []byte { 140 | var z []byte 141 | for i := 0; i < n; i++ { 142 | z = append(z, 0) 143 | } 144 | return z 145 | } 146 | -------------------------------------------------------------------------------- /utils/idl/variant.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math/big" 7 | "sort" 8 | "strings" 9 | 10 | "github.com/aviate-labs/leb128" 11 | ) 12 | 13 | type FieldValue struct { 14 | Name string 15 | Value interface{} 16 | } 17 | 18 | type Variant struct { 19 | Fields []Field 20 | } 21 | 22 | func NewVariant(fields map[string]Type) *Variant { 23 | var variant Variant 24 | for k, v := range fields { 25 | variant.Fields = append(variant.Fields, Field{ 26 | Name: k, 27 | Type: v, 28 | }) 29 | } 30 | sort.Slice(variant.Fields, func(i, j int) bool { 31 | return Hash(variant.Fields[i].Name).Cmp(Hash(variant.Fields[j].Name)) < 0 32 | }) 33 | return &variant 34 | } 35 | 36 | func (v Variant) AddTypeDefinition(tdt *TypeDefinitionTable) error { 37 | for _, f := range v.Fields { 38 | if err := f.Type.AddTypeDefinition(tdt); err != nil { 39 | return err 40 | } 41 | } 42 | 43 | id, err := leb128.EncodeSigned(big.NewInt(varType)) 44 | if err != nil { 45 | return err 46 | } 47 | l, err := leb128.EncodeUnsigned(big.NewInt(int64(len(v.Fields)))) 48 | if err != nil { 49 | return err 50 | } 51 | var vs []byte 52 | for _, f := range v.Fields { 53 | id, err := leb128.EncodeUnsigned(Hash(f.Name)) 54 | if err != nil { 55 | return nil 56 | } 57 | t, err := f.Type.EncodeType(tdt) 58 | if err != nil { 59 | return nil 60 | } 61 | vs = append(vs, concat(id, t)...) 62 | } 63 | 64 | tdt.Add(v, concat(id, l, vs)) 65 | return nil 66 | } 67 | 68 | func (v Variant) Decode(r *bytes.Reader) (interface{}, error) { 69 | id, err := leb128.DecodeUnsigned(r) 70 | if err != nil { 71 | return nil, err 72 | } 73 | if id.Cmp(big.NewInt(int64(len(v.Fields)))) >= 0 { 74 | return nil, fmt.Errorf("invalid variant index: %v", id) 75 | } 76 | v_, err := v.Fields[int(id.Int64())].Type.Decode(r) 77 | if err != nil { 78 | return nil, err 79 | } 80 | return map[string]interface{}{v.Fields[int(id.Int64())].Name: v_, "EnumIndex": v.Fields[int(id.Int64())].Name}, nil 81 | } 82 | 83 | // func (v Variant) Decode(r *bytes.Reader) (interface{}, error) { 84 | // id, err := leb128.DecodeUnsigned(r) 85 | // if err != nil { 86 | // return nil, err 87 | // } 88 | // if id.Cmp(big.NewInt(int64(len(v.Fields)))) >= 0 { 89 | // return nil, fmt.Errorf("invalid variant index: %v", id) 90 | // } 91 | // v_, err := v.Fields[int(id.Int64())].Type.Decode(r) 92 | // if err != nil { 93 | // return nil, err 94 | // } 95 | // return &FieldValue{ 96 | // Name: v.Fields[int(id.Int64())].Name, 97 | // Value: v_, 98 | // }, nil 99 | // } 100 | 101 | func (v Variant) EncodeType(tdt *TypeDefinitionTable) ([]byte, error) { 102 | idx, ok := tdt.Indexes[v.String()] 103 | if !ok { 104 | return nil, fmt.Errorf("missing type index for: %s", v) 105 | } 106 | return leb128.EncodeSigned(big.NewInt(int64(idx))) 107 | } 108 | 109 | func (v Variant) EncodeValue(value interface{}) ([]byte, error) { 110 | fs, ok := value.(FieldValue) 111 | if !ok { 112 | return nil, fmt.Errorf("invalid argument: %v", v) 113 | } 114 | for i, f := range v.Fields { 115 | if f.Name == fs.Name { 116 | id, err := leb128.EncodeUnsigned(big.NewInt(int64(i))) 117 | if err != nil { 118 | return nil, err 119 | } 120 | v_, err := f.Type.EncodeValue(fs.Value) 121 | if err != nil { 122 | return nil, err 123 | } 124 | return concat(id, v_), nil 125 | } 126 | } 127 | return nil, fmt.Errorf("unknown variant: %v", value) 128 | } 129 | 130 | func (v Variant) String() string { 131 | var s []string 132 | for _, f := range v.Fields { 133 | s = append(s, fmt.Sprintf("%s:%s", f.Name, f.Type.String())) 134 | } 135 | return fmt.Sprintf("variant {%s}", strings.Join(s, "; ")) 136 | } 137 | 138 | func (Variant) Fill(Type) { 139 | 140 | } 141 | -------------------------------------------------------------------------------- /utils/idl/func.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | 7 | "math/big" 8 | "strings" 9 | 10 | "github.com/aviate-labs/leb128" 11 | "github.com/openos-labs/IC-Go/utils/principal" 12 | ) 13 | 14 | func encodeTypes(ts []Type, tdt *TypeDefinitionTable) ([]byte, error) { 15 | l, err := leb128.EncodeUnsigned(big.NewInt(int64(len(ts)))) 16 | if err != nil { 17 | return nil, err 18 | } 19 | var vs []byte 20 | for _, t := range ts { 21 | v, err := t.EncodeType(tdt) 22 | if err != nil { 23 | return nil, err 24 | } 25 | vs = append(vs, v...) 26 | } 27 | return concat(l, vs), nil 28 | } 29 | 30 | type Func struct { 31 | ArgTypes []Type 32 | RetTypes []Type 33 | Annotations []string 34 | } 35 | 36 | func NewFunc(argumentTypes []Type, returnTypes []Type, annotations []string) *Func { 37 | return &Func{ 38 | ArgTypes: argumentTypes, 39 | RetTypes: returnTypes, 40 | Annotations: annotations, 41 | } 42 | } 43 | 44 | func (f Func) AddTypeDefinition(tdt *TypeDefinitionTable) error { 45 | for _, t := range f.ArgTypes { 46 | t.AddTypeDefinition(tdt) 47 | } 48 | for _, t := range f.RetTypes { 49 | t.AddTypeDefinition(tdt) 50 | } 51 | 52 | id, err := leb128.EncodeSigned(big.NewInt(funcType)) 53 | if err != nil { 54 | return err 55 | } 56 | vsa, err := encodeTypes(f.ArgTypes, tdt) 57 | if err != nil { 58 | return err 59 | } 60 | vsr, err := encodeTypes(f.RetTypes, tdt) 61 | if err != nil { 62 | return err 63 | } 64 | l, err := leb128.EncodeUnsigned(big.NewInt(int64(len(f.Annotations)))) 65 | if err != nil { 66 | return err 67 | } 68 | var vs []byte 69 | for _, t := range f.Annotations { 70 | switch t { 71 | case "query": 72 | vs = []byte{0x01} 73 | case "oneway": 74 | vs = []byte{0x02} 75 | default: 76 | return fmt.Errorf("invalid function annotation: %s", t) 77 | } 78 | } 79 | 80 | tdt.Add(f, concat(id, vsa, vsr, l, vs)) 81 | return nil 82 | } 83 | 84 | func (f Func) Decode(r *bytes.Reader) (interface{}, error) { 85 | { 86 | bs := make([]byte, 2) 87 | n, err := r.Read(bs) 88 | if err != nil { 89 | return nil, err 90 | } 91 | if n != 2 || bs[0] != 0x01 || bs[1] != 0x01 { 92 | return nil, fmt.Errorf("invalid func reference: %d", bs) 93 | } 94 | } 95 | l, err := leb128.DecodeUnsigned(r) 96 | if err != nil { 97 | return nil, err 98 | } 99 | pid := make(principal.Principal, l.Int64()) 100 | { 101 | n, err := r.Read(pid) 102 | if err != nil { 103 | return nil, err 104 | } 105 | if n != int(l.Int64()) { 106 | return nil, fmt.Errorf("invalid principal id: %d", pid) 107 | } 108 | } 109 | ml, err := leb128.DecodeUnsigned(r) 110 | if err != nil { 111 | return nil, err 112 | } 113 | m := make([]byte, ml.Int64()) 114 | { 115 | n, err := r.Read(pid) 116 | if err != nil { 117 | return nil, err 118 | } 119 | if n != int(l.Int64()) { 120 | return nil, fmt.Errorf("invalid method: %d", pid) 121 | } 122 | } 123 | return &PrincipalMethod{ 124 | Principal: pid, 125 | Method: string(m), 126 | }, nil 127 | } 128 | 129 | func (f Func) EncodeType(tdt *TypeDefinitionTable) ([]byte, error) { 130 | idx, ok := tdt.Indexes[f.String()] 131 | if !ok { 132 | return nil, fmt.Errorf("missing type index for: %s", f) 133 | } 134 | return leb128.EncodeSigned(big.NewInt(int64(idx))) 135 | } 136 | 137 | func (f Func) EncodeValue(v interface{}) ([]byte, error) { 138 | pm, ok := v.(PrincipalMethod) 139 | if !ok { 140 | return nil, fmt.Errorf("invalid argument: %v", v) 141 | } 142 | l, err := leb128.EncodeUnsigned(big.NewInt(int64(len(pm.Principal)))) 143 | if err != nil { 144 | return nil, err 145 | } 146 | lm, err := leb128.EncodeUnsigned(big.NewInt(int64(len(pm.Method)))) 147 | if err != nil { 148 | return nil, err 149 | } 150 | return concat([]byte{0x01, 0x01}, l, pm.Principal, lm, []byte(pm.Method)), nil 151 | } 152 | 153 | func (f Func) String() string { 154 | var args []string 155 | for _, t := range f.ArgTypes { 156 | args = append(args, t.String()) 157 | } 158 | var rets []string 159 | for _, t := range f.RetTypes { 160 | rets = append(rets, t.String()) 161 | } 162 | var ann string 163 | if len(f.Annotations) != 0 { 164 | ann = fmt.Sprintf(" %s", strings.Join(f.Annotations, " ")) 165 | } 166 | return fmt.Sprintf("(%s) -> (%s)%s", strings.Join(args, ", "), strings.Join(rets, ", "), ann) 167 | } 168 | 169 | func (Func) Fill(Type) { 170 | 171 | } 172 | 173 | type PrincipalMethod struct { 174 | Principal principal.Principal 175 | Method string 176 | } 177 | -------------------------------------------------------------------------------- /request.go: -------------------------------------------------------------------------------- 1 | package agent 2 | 3 | import ( 4 | "bytes" 5 | "crypto/sha256" 6 | 7 | "github.com/aviate-labs/leb128" 8 | "github.com/openos-labs/IC-Go/utils/principal" 9 | 10 | "math/big" 11 | "sort" 12 | ) 13 | 14 | var ( 15 | typeKey = sha256.Sum256([]byte("request_type")) 16 | canisterIDKey = sha256.Sum256([]byte("canister_id")) 17 | nonceKey = sha256.Sum256([]byte("nonce")) 18 | methodNameKey = sha256.Sum256([]byte("method_name")) 19 | argumentsKey = sha256.Sum256([]byte("arg")) 20 | ingressExpiryKey = sha256.Sum256([]byte("ingress_expiry")) 21 | senderKey = sha256.Sum256([]byte("sender")) 22 | pathKey = sha256.Sum256([]byte("paths")) 23 | ) 24 | 25 | type RequestType = string 26 | 27 | const ( 28 | RequestTypeCall RequestType = "call" 29 | RequestTypeQuery RequestType = "query" 30 | RequestTypeReadState RequestType = "read_state" 31 | ) 32 | 33 | // DOCS: https://smartcontracts.org/docs/interface-spec/index.html#http-call 34 | type Request struct { 35 | Type RequestType `cbor:"request_type,omitempty"` 36 | // The user who issued the request. 37 | Sender principal.Principal `cbor:"sender,omitempty"` 38 | // Arbitrary user-provided data, typically randomly generated. This can be 39 | // used to create distinct requests with otherwise identical fields. 40 | Nonce []byte `cbor:"nonce,omitempty"` 41 | // An upper limit on the validity of the request, expressed in nanoseconds 42 | // since 1970-01-01 (like ic0.time()). 43 | IngressExpiry uint64 `cbor:"ingress_expiry,omitempty"` 44 | // The principal of the canister to call. 45 | CanisterID principal.Principal `cbor:"canister_id"` 46 | // Name of the canister method to call. 47 | MethodName string `cbor:"method_name,omitempty"` 48 | // Argument to pass to the canister method. 49 | Arguments []byte `cbor:"arg,omitempty"` 50 | // Paths (sequence of paths): A list of paths, where a path is itself a sequence of blobs. 51 | Paths [][][]byte `cbor:"paths,omitempty"` 52 | } 53 | 54 | type RequestID [32]byte 55 | 56 | func EncodeRequestID(request map[string]interface{}) RequestID { 57 | var hashes [][]byte 58 | for k, v := range request { 59 | switch k { 60 | case "request_type": 61 | typeKey := sha256.Sum256([]byte("request_type")) 62 | typeValue := sha256.Sum256([]byte(v.(string))) 63 | result := append(typeKey[:], typeValue[:]...) 64 | hashes = append(hashes, result) 65 | case "sender": 66 | typeKey := sha256.Sum256([]byte("sender")) 67 | typeValue := sha256.Sum256(v.([]byte)) 68 | result := append(typeKey[:], typeValue[:]...) 69 | hashes = append(hashes, result) 70 | case "nonce": 71 | typeKey := sha256.Sum256([]byte("nonce")) 72 | typeValue := sha256.Sum256(v.([]byte)) 73 | result := append(typeKey[:], typeValue[:]...) 74 | hashes = append(hashes, result) 75 | case "ingress_expiry": 76 | typeKey := sha256.Sum256([]byte("ingress_expiry")) 77 | typeValue := sha256.Sum256(encodeLEB128(v.(uint64))) 78 | result := append(typeKey[:], typeValue[:]...) 79 | hashes = append(hashes, result) 80 | case "canister_id": 81 | typeKey := sha256.Sum256([]byte("canister_id")) 82 | typeValue := sha256.Sum256(v.([]byte)) 83 | result := append(typeKey[:], typeValue[:]...) 84 | hashes = append(hashes, result) 85 | case "method_name": 86 | typeKey := sha256.Sum256([]byte("method_name")) 87 | typeValue := sha256.Sum256([]byte(v.(string))) 88 | result := append(typeKey[:], typeValue[:]...) 89 | hashes = append(hashes, result) 90 | case "arg": 91 | typeKey := sha256.Sum256([]byte("arg")) 92 | typeValue := sha256.Sum256(v.([]byte)) 93 | result := append(typeKey[:], typeValue[:]...) 94 | hashes = append(hashes, result) 95 | default: 96 | } 97 | } 98 | sort.Slice(hashes, func(i, j int) bool { 99 | return bytes.Compare(hashes[i], hashes[j]) == -1 100 | }) 101 | return sha256.Sum256(bytes.Join(hashes, nil)) 102 | } 103 | 104 | // DOCS: https://smartcontracts.org/docs/interface-spec/index.html#request-id 105 | func NewRequestID(req Request) RequestID { 106 | var ( 107 | typeHash = sha256.Sum256([]byte(req.Type)) 108 | canisterIDHash = sha256.Sum256(req.CanisterID) 109 | methodNameHash = sha256.Sum256([]byte(req.MethodName)) 110 | argumentsHash = sha256.Sum256(req.Arguments) 111 | ) 112 | hashes := [][]byte{} 113 | if len(req.Type) != 0 { 114 | hashes = append(hashes, append(typeKey[:], typeHash[:]...)) 115 | } 116 | if req.CanisterID != nil { 117 | hashes = append(hashes, append(canisterIDKey[:], canisterIDHash[:]...)) 118 | } 119 | if len(req.MethodName) != 0 { 120 | hashes = append(hashes, append(methodNameKey[:], methodNameHash[:]...)) 121 | } 122 | if req.Arguments != nil { 123 | hashes = append(hashes, append(argumentsKey[:], argumentsHash[:]...)) 124 | } 125 | 126 | if len(req.Sender) != 0 { 127 | senderHash := sha256.Sum256(req.Sender) 128 | hashes = append(hashes, append(senderKey[:], senderHash[:]...)) 129 | } 130 | if req.IngressExpiry != 0 { 131 | ingressExpiryHash := sha256.Sum256(encodeLEB128(req.IngressExpiry)) 132 | hashes = append(hashes, append(ingressExpiryKey[:], ingressExpiryHash[:]...)) 133 | } 134 | if len(req.Nonce) != 0 { 135 | nonceHash := sha256.Sum256(req.Nonce) 136 | hashes = append(hashes, append(nonceKey[:], nonceHash[:]...)) 137 | } 138 | if len(req.Paths) != 0 { 139 | pathHash:= encodeList3D(req.Paths) 140 | hashes = append(hashes, append(pathKey[:], pathHash[:]...)) 141 | } 142 | sort.Slice(hashes, func(i, j int) bool { 143 | return bytes.Compare(hashes[i], hashes[j]) == -1 144 | }) 145 | return sha256.Sum256(bytes.Join(hashes, nil)) 146 | } 147 | 148 | func encodeLEB128(i uint64) []byte { 149 | bi := big.NewInt(int64(i)) 150 | e, _ := leb128.EncodeUnsigned(bi) 151 | return e 152 | } 153 | //todo:之后用reflect写成一个函数 154 | func encodeList3D(lists [][][]byte) [32]byte { 155 | var res []byte 156 | for _, v := range lists { 157 | code := encodeList2D(v) 158 | res = append(res, code[:]...) 159 | } 160 | return sha256.Sum256(res) 161 | } 162 | 163 | func encodeList2D(lists [][]byte) [32]byte { 164 | var res []byte 165 | for _, v := range lists { 166 | pathBytes := sha256.Sum256(v) 167 | res = append(res, pathBytes[:]...) 168 | } 169 | return sha256.Sum256(res) 170 | } 171 | type Envelope struct { 172 | Content Request `cbor:"content,omitempty"` 173 | SenderPubkey []byte `cbor:"sender_pubkey,omitempty"` 174 | SenderSig []byte `cbor:"sender_sig,omitempty"` 175 | } 176 | -------------------------------------------------------------------------------- /utils/identity/identity.go: -------------------------------------------------------------------------------- 1 | package identity 2 | 3 | import ( 4 | "crypto" 5 | "crypto/x509" 6 | "crypto/x509/pkix" 7 | "encoding/asn1" 8 | "encoding/pem" 9 | "errors" 10 | "fmt" 11 | "io/ioutil" 12 | 13 | "crypto/ed25519" 14 | ) 15 | 16 | var errEd25519WrongID = errors.New("incorrect object identifier") 17 | var errEd25519WrongKeyType = errors.New("incorrect key type") 18 | 19 | // ed25519OID is the OID for the Ed25519 signature scheme: see 20 | // https://datatracker.ietf.org/doc/draft-ietf-curdle-pkix-04. 21 | var ed25519OID = asn1.ObjectIdentifier{1, 3, 101, 112} 22 | 23 | // subjectPublicKeyInfo reflects the ASN.1 object defined in the X.509 standard. 24 | // 25 | // This is defined in crypto/x509 as "publicKeyInfo". 26 | type subjectPublicKeyInfo struct { 27 | Algorithm pkix.AlgorithmIdentifier 28 | PublicKey asn1.BitString 29 | } 30 | 31 | // MarshalEd25519PublicKey creates a DER-encoded SubjectPublicKeyInfo for an 32 | // ed25519 public key, as defined in 33 | // https://tools.ietf.org/html/draft-ietf-curdle-pkix-04. This is analogous to 34 | // MarshalPKIXPublicKey in crypto/x509, which doesn't currently support Ed25519. 35 | func MarshalEd25519PublicKey(pk crypto.PublicKey) ([]byte, error) { 36 | pub, ok := pk.(ed25519.PublicKey) 37 | if !ok { 38 | return nil, errEd25519WrongKeyType 39 | } 40 | 41 | spki := subjectPublicKeyInfo{ 42 | Algorithm: pkix.AlgorithmIdentifier{ 43 | Algorithm: ed25519OID, 44 | }, 45 | PublicKey: asn1.BitString{ 46 | BitLength: len(pub) * 8, 47 | Bytes: pub, 48 | }, 49 | } 50 | return asn1.Marshal(spki) 51 | } 52 | 53 | // ParseEd25519PublicKey returns the Ed25519 public key encoded by the input. 54 | func ParseEd25519PublicKey(der []byte) (crypto.PublicKey, error) { 55 | var spki subjectPublicKeyInfo 56 | if rest, err := asn1.Unmarshal(der, &spki); err != nil { 57 | return nil, err 58 | } else if len(rest) > 0 { 59 | return nil, errors.New("SubjectPublicKeyInfo too long") 60 | } 61 | 62 | if !spki.Algorithm.Algorithm.Equal(ed25519OID) { 63 | return nil, errEd25519WrongID 64 | } 65 | 66 | if spki.PublicKey.BitLength != ed25519.PublicKeySize*8 { 67 | return nil, errors.New("SubjectPublicKeyInfo PublicKey length mismatch") 68 | } 69 | 70 | return ed25519.PublicKey(spki.PublicKey.Bytes), nil 71 | } 72 | 73 | // oneAsymmetricKey reflects the ASN.1 structure for storing private keys in 74 | // https://tools.ietf.org/html/draft-ietf-curdle-pkix-04, excluding the optional 75 | // fields, which we don't use here. 76 | // 77 | // This is identical to pkcs8 in crypto/x509. 78 | type oneAsymmetricKey struct { 79 | Version int 80 | Algorithm pkix.AlgorithmIdentifier 81 | PrivateKey []byte 82 | } 83 | 84 | // curvePrivateKey is the innter type of the PrivateKey field of 85 | // oneAsymmetricKey. 86 | type curvePrivateKey []byte 87 | 88 | // MarshalEd25519PrivateKey returns a DER encoding of the input private key as 89 | // specified in https://tools.ietf.org/html/draft-ietf-curdle-pkix-04. 90 | func MarshalEd25519PrivateKey(sk crypto.PrivateKey) ([]byte, error) { 91 | priv, ok := sk.(ed25519.PrivateKey) 92 | if !ok { 93 | return nil, errEd25519WrongKeyType 94 | } 95 | 96 | // Marshal the innter CurvePrivateKey. 97 | curvePrivateKey, err := asn1.Marshal(priv.Seed()) 98 | if err != nil { 99 | return nil, err 100 | } 101 | 102 | // Marshal the OneAsymmetricKey. 103 | asym := oneAsymmetricKey{ 104 | Version: 0, 105 | Algorithm: pkix.AlgorithmIdentifier{ 106 | Algorithm: ed25519OID, 107 | }, 108 | PrivateKey: curvePrivateKey, 109 | } 110 | return asn1.Marshal(asym) 111 | } 112 | 113 | // ParseEd25519PrivateKey returns the Ed25519 private key encoded by the input. 114 | func ParseEd25519PrivateKey(der []byte) (crypto.PrivateKey, error) { 115 | asym := new(oneAsymmetricKey) 116 | if rest, err := asn1.Unmarshal(der, asym); err != nil { 117 | return nil, err 118 | } else if len(rest) > 0 { 119 | return nil, errors.New("OneAsymmetricKey too long") 120 | } 121 | 122 | // Check that the key type is correct. 123 | if !asym.Algorithm.Algorithm.Equal(ed25519OID) { 124 | return nil, errEd25519WrongID 125 | } 126 | 127 | // Unmarshal the inner CurvePrivateKey. 128 | seed := new(curvePrivateKey) 129 | if rest, err := asn1.Unmarshal(asym.PrivateKey, seed); err != nil { 130 | return nil, err 131 | } else if len(rest) > 0 { 132 | return nil, errors.New("CurvePrivateKey too long") 133 | } 134 | 135 | return ed25519.NewKeyFromSeed(*seed), nil 136 | } 137 | 138 | func ToPem(sk crypto.PrivateKey, path string) error { 139 | var ( 140 | err error 141 | b []byte 142 | block *pem.Block 143 | priv ed25519.PrivateKey 144 | ) 145 | 146 | priv, ok := sk.(ed25519.PrivateKey) 147 | if !ok { 148 | return errEd25519WrongKeyType 149 | } 150 | b, err = x509.MarshalPKCS8PrivateKey(priv) 151 | 152 | block = &pem.Block{ 153 | Type: "PRIVATE KEY", 154 | Bytes: b, 155 | } 156 | 157 | err = ioutil.WriteFile(path, pem.EncodeToMemory(block), 0600) 158 | if err != nil { 159 | return err 160 | } 161 | return nil 162 | } 163 | 164 | func FromPem(file string) (ed25519.PrivateKey, error) { 165 | b, err := ioutil.ReadFile(file) 166 | if err != nil { 167 | return nil, err 168 | } 169 | block, _ := pem.Decode(b) 170 | if block.Type != "PRIVATE KEY" || block == nil { 171 | return nil, fmt.Errorf("failed to decode PEM block containing private key") 172 | } 173 | sk, err := x509.ParsePKCS8PrivateKey(block.Bytes) 174 | if err != nil { 175 | return nil, err 176 | } 177 | return sk.(ed25519.PrivateKey), nil 178 | } 179 | 180 | func New(anonymous bool, pkBytes []byte) *Identity { 181 | if anonymous == true { 182 | return &Identity{ 183 | Anonymous: anonymous, 184 | } 185 | } 186 | privKey := ed25519.NewKeyFromSeed(pkBytes) 187 | //fmt.Println(privKey) 188 | pubKey := privKey.Public() 189 | 190 | //fmt.Println(pubKey) 191 | 192 | return &Identity{ 193 | anonymous, 194 | privKey, 195 | pubKey, 196 | } 197 | } 198 | 199 | type Identity struct { 200 | Anonymous bool 201 | PriKey ed25519.PrivateKey 202 | PubKey crypto.PublicKey 203 | } 204 | 205 | func (identity *Identity) Sign(m []byte) ([]byte, error) { 206 | 207 | if identity.Anonymous == true { 208 | return []byte{}, nil 209 | } 210 | 211 | sign := ed25519.Sign(identity.PriKey, m[:]) 212 | 213 | return sign, nil 214 | } 215 | 216 | func (identity *Identity) PubKeyBytes() []byte { 217 | var senderPubKey []byte 218 | if identity.Anonymous == false { 219 | pkBytes, _ := MarshalEd25519PublicKey(identity.PubKey) 220 | return pkBytes 221 | } 222 | return senderPubKey 223 | } 224 | -------------------------------------------------------------------------------- /utils/idl/decode.go: -------------------------------------------------------------------------------- 1 | package idl 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math/big" 7 | 8 | "github.com/aviate-labs/leb128" 9 | ) 10 | 11 | type typePair struct { 12 | Type int64 13 | single_value int64 14 | pair_value [][]big.Int 15 | } 16 | 17 | func _Decode(raw_table []typePair, table []Type, index int64) (Type, error) { 18 | pair := raw_table[index] 19 | switch pair.Type { 20 | case optType: 21 | tid := pair.single_value 22 | var v Type 23 | var err error 24 | if tid >= 0 { 25 | if int(tid) >= len(raw_table) { 26 | return nil, nil 27 | } 28 | v = table[tid] 29 | } else { 30 | v, err = getType(tid) 31 | } 32 | if err != nil { 33 | return nil, err 34 | } 35 | return &Opt{v}, nil 36 | case vecType: 37 | tid := pair.single_value 38 | var v Type 39 | var err error 40 | if tid >= 0 { 41 | if int(tid) >= len(raw_table) { 42 | return nil, nil 43 | } 44 | v = table[tid] 45 | } else { 46 | v, err = getType(tid) 47 | } 48 | if err != nil { 49 | return nil, err 50 | } 51 | return &Vec{v}, nil 52 | //tds = append(tds, &Vec{v}) 53 | case recType: 54 | l := len(pair.pair_value) 55 | var fields []Field 56 | for i := 0; i < int(l); i++ { 57 | h := pair.pair_value[i][0] 58 | tid := pair.pair_value[i][1] 59 | var v Type 60 | var err error 61 | if tid.Int64() >= 0 { 62 | if int(tid.Int64()) >= len(raw_table) { 63 | return nil, nil 64 | } 65 | v = table[tid.Int64()] 66 | } else { 67 | v, err = getType(tid.Int64()) 68 | } 69 | 70 | if err != nil { 71 | return nil, err 72 | } 73 | fields = append(fields, Field{ 74 | Name: h.String(), 75 | Type: v, 76 | }) 77 | } 78 | return &Rec{Fields: fields}, nil 79 | case varType: 80 | l := len(pair.pair_value) 81 | var fields []Field 82 | for i := 0; i < int(l); i++ { 83 | h := pair.pair_value[i][0] 84 | tid := pair.pair_value[i][1] 85 | var v Type 86 | var err error 87 | if tid.Int64() >= 0 { 88 | if int(tid.Int64()) >= len(raw_table) { 89 | return nil, nil 90 | } 91 | v = table[tid.Int64()] 92 | } else { 93 | v, err = getType(tid.Int64()) 94 | } 95 | 96 | if err != nil { 97 | return nil, err 98 | } 99 | fields = append(fields, Field{ 100 | Name: h.String(), 101 | Type: v, 102 | }) 103 | } 104 | return &Variant{Fields: fields}, nil 105 | } 106 | return nil, nil 107 | } 108 | 109 | func Decode(bs []byte) ([]Type, []interface{}, error) { 110 | if len(bs) == 0 { 111 | return nil, nil, &FormatError{ 112 | Description: "empty", 113 | } 114 | } 115 | 116 | r := bytes.NewReader(bs) 117 | 118 | { // 'DIDL' 119 | 120 | magic := make([]byte, 4) 121 | n, err := r.Read(magic) 122 | if err != nil { 123 | return nil, nil, err 124 | } 125 | if n < 4 { 126 | return nil, nil, &FormatError{ 127 | Description: "no magic bytes", 128 | } 129 | } 130 | if !bytes.Equal(magic, []byte{'D', 'I', 'D', 'L'}) { 131 | return nil, nil, &FormatError{ 132 | Description: "wrong magic bytes", 133 | } 134 | } 135 | } 136 | var raw_table []typePair 137 | { // T 138 | tdtl, err := leb128.DecodeUnsigned(r) 139 | if err != nil { 140 | return nil, nil, err 141 | } 142 | for i := 0; i < int(tdtl.Int64()); i++ { 143 | tid, err := leb128.DecodeSigned(r) 144 | if err != nil { 145 | return nil, nil, err 146 | } 147 | switch tid.Int64() { 148 | case optType: 149 | t, err := leb128.DecodeSigned(r) 150 | if err != nil { 151 | return nil, nil, err 152 | } 153 | raw_table = append(raw_table, typePair{ 154 | Type: tid.Int64(), 155 | single_value: t.Int64(), 156 | pair_value: nil, 157 | }) 158 | case vecType: 159 | t, err := leb128.DecodeSigned(r) 160 | if err != nil { 161 | return nil, nil, err 162 | } 163 | raw_table = append(raw_table, typePair{ 164 | Type: tid.Int64(), 165 | single_value: t.Int64(), 166 | pair_value: nil, 167 | }) 168 | case recType: 169 | l, err := leb128.DecodeUnsigned(r) 170 | if err != nil { 171 | return nil, nil, err 172 | } 173 | var fields [][]big.Int 174 | for i := 0; i < int(l.Int64()); i++ { 175 | h, err := leb128.DecodeUnsigned(r) 176 | if err != nil { 177 | return nil, nil, err 178 | } 179 | t, err := leb128.DecodeSigned(r) 180 | if err != nil { 181 | return nil, nil, err 182 | } 183 | fields = append(fields, []big.Int{*h, *t}) 184 | } 185 | raw_table = append(raw_table, typePair{ 186 | Type: tid.Int64(), 187 | single_value: 99, 188 | pair_value: fields, 189 | }) 190 | case varType: 191 | l, err := leb128.DecodeUnsigned(r) 192 | if err != nil { 193 | return nil, nil, err 194 | } 195 | var fields [][]big.Int 196 | for i := 0; i < int(l.Int64()); i++ { 197 | h, err := leb128.DecodeUnsigned(r) 198 | if err != nil { 199 | return nil, nil, err 200 | } 201 | t, err := leb128.DecodeSigned(r) 202 | if err != nil { 203 | return nil, nil, err 204 | } 205 | fields = append(fields, []big.Int{*h, *t}) 206 | } 207 | raw_table = append(raw_table, typePair{ 208 | Type: tid.Int64(), 209 | single_value: 99, 210 | pair_value: fields, 211 | }) 212 | case funcType: 213 | //TODO 214 | return nil, nil, nil 215 | case serviceType: 216 | //TODO 217 | return nil, nil, nil 218 | } 219 | } 220 | } 221 | var tds []Type 222 | for _, _ = range raw_table { 223 | tds = append(tds, &Interface{}) 224 | } 225 | { // T 226 | for i, _ := range raw_table { 227 | t, err := _Decode(raw_table, tds, int64(i)) 228 | tds[i].Fill(t) 229 | if err != nil { 230 | return nil, nil, err 231 | } 232 | 233 | } 234 | } 235 | 236 | tsl, err := leb128.DecodeUnsigned(r) 237 | if err != nil { 238 | return nil, nil, err 239 | } 240 | 241 | var ts []Type 242 | { // I 243 | for i := 0; i < int(tsl.Int64()); i++ { 244 | tid, err := leb128.DecodeSigned(r) 245 | var t Type 246 | if err != nil { 247 | return nil, nil, err 248 | } 249 | if tid.Int64() < 0 { 250 | t, err = getType(tid.Int64()) 251 | if err != nil { 252 | return nil, nil, err 253 | } 254 | } else { 255 | t = tds[int(tid.Int64())] 256 | } 257 | ts = append(ts, t) 258 | } 259 | } 260 | 261 | var vs []interface{} 262 | { // M 263 | for i := 0; i < int(tsl.Int64()); i++ { 264 | v, err := ts[i].Decode(r) 265 | if err != nil { 266 | return nil, nil, err 267 | } 268 | vs = append(vs, v) 269 | } 270 | } 271 | 272 | if r.Len() != 0 { 273 | return nil, nil, fmt.Errorf("too long") 274 | } 275 | return ts, vs, nil 276 | } 277 | -------------------------------------------------------------------------------- /example/registry/proto/transport.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | option go_package="./pb"; 3 | 4 | // Set of messages used to interact with the registry canister. 5 | // 6 | // The registry canister implements the following three methods: 7 | // 8 | // get_latest_version(RegistryGetLatestVersionRequest) -> 9 | // RegistryGetLatestVersionResponse 10 | // 11 | // get_value(RegistryGetValueRequest) -> RegistryGetValueResponse 12 | // 13 | // atomic_mutate(RegistryAtomicMutateRequest) -> RegistryAtomicMutateResponse 14 | // 15 | // get_latest_version() returns the latest version of the registry, i.e. the 16 | // version of the last update made to the registry. 17 | // 18 | // get_value() returns the a value for specified version of a specified key from 19 | // the registry, or the latest version if a version was not specified. 20 | // get_value() returns a RegistryError if the key was not present. 21 | // 22 | // atomic_mutate() inserts, updates or deletes a set of keys in the registry. 23 | // Mutations are atomic, meaning either all mutations are applied, or none 24 | // are applied. 25 | // 26 | // Note that registry versions are always strictly >= 0, a -1 value is used 27 | // to signal that no version was assigned. 28 | package ic_registry_transport.pb.v1; 29 | 30 | import "google/protobuf/wrappers.proto"; 31 | import "mixed_hash_tree.proto"; 32 | 33 | // Message corresponding to an error while performing 34 | // an operation on the registry. 35 | message RegistryError { 36 | enum Code { 37 | // The message had a problem like a missing field 38 | // or a field that was set when it shouldn't. 39 | MALFORMED_MESSAGE = 0; 40 | // The 'key' specified on the request was not present 41 | // in the registry. 42 | KEY_NOT_PRESENT = 1; 43 | // The 'key' specified on the request was already present. 44 | KEY_ALREADY_PRESENT = 2; 45 | // The 'version' specified in a precondition for a mutation 46 | // was not the lastest version. 47 | VERSION_NOT_LATEST = 3; 48 | // The 'version' specified in a precondition for a mutation 49 | // is beyond the latest version in the registry. 50 | VERSION_BEYOND_LATEST = 4; 51 | 52 | // A generic internal error occurred in the registry. 53 | INTERNAL_ERROR = 999; 54 | } 55 | 56 | Code code = 1; 57 | 58 | // The reason for the error. 59 | // This is optional. 60 | string reason = 2; 61 | 62 | // The key on which the error occurred. 63 | // This is optional and only present for by-key errors. 64 | bytes key = 3; 65 | } 66 | 67 | // A single change made to a key in the registry. 68 | message RegistryValue { 69 | // The value that was set in this mutation. If the 70 | // mutation is a deletion, the field has no meaning. 71 | bytes value = 1; 72 | 73 | // The version at which this mutation happened. 74 | uint64 version = 2; 75 | 76 | // If true, this change represents a deletion. 77 | bool deletion_marker = 3; 78 | } 79 | 80 | // A sequence of changes made to a key in the registry. 81 | message RegistryDelta { 82 | bytes key = 1; 83 | repeated RegistryValue values = 2; 84 | } 85 | 86 | // Message to retrieve all the changes from the registry 87 | // since 'version'. 88 | message RegistryGetChangesSinceRequest { uint64 version = 1; } 89 | 90 | // Message corresponding to the response from the registry 91 | // canister to a get_latest_version() request. 92 | message RegistryGetChangesSinceResponse { 93 | // If anything went wrong, the registry canister 94 | // will set this error. 95 | RegistryError error = 1; 96 | // The last version of the registry. 97 | uint64 version = 2; 98 | // A list of all the keys and all the values that change 99 | // and all the intermediate changes since the version 100 | // requested. 101 | repeated RegistryDelta deltas = 3; 102 | } 103 | 104 | // Message to retrieve a version of some registry key 105 | // from the registry canister. 106 | message RegistryGetValueRequest { 107 | // The version of the registry key to retrieve. 108 | // Optional: If not set (or set to the default value, 0), the method 109 | // will return the last version. 110 | google.protobuf.UInt64Value version = 1; 111 | // The byte array corresponding to the key to retrieve 112 | // from the registry. 113 | // Required. 114 | bytes key = 2; 115 | } 116 | 117 | // Message corresponding to the response from the canister 118 | // to a get_value() request. 119 | // 120 | // Both 'version' and 'value' are mandatorily set if 'error' 121 | // is not set. 122 | message RegistryGetValueResponse { 123 | // If anything went wrong, the registry canister 124 | // will set this error. 125 | RegistryError error = 1; 126 | // the version at which the value corresponding to the queried 127 | // key was last mutated (inserted, updated, or deleted) 128 | // before at or at the version specified 129 | // in the RegistryGetValueRequest. 130 | uint64 version = 2; 131 | // The value retrieved from the registry. 132 | bytes value = 3; 133 | } 134 | 135 | // Message corresponding to the response from the canister 136 | // to a get_latest_version() request. 137 | message RegistryGetLatestVersionResponse { 138 | // the latest registry version 139 | uint64 version = 1; 140 | } 141 | 142 | // A single mutation in the registry. 143 | message RegistryMutation { 144 | enum Type { 145 | // Key is expected to not exist in the registry at the current version. 146 | // (This includes the case of a key that has existed in the past and 147 | // later got deleted). 148 | // The mutation will fail otherwise. 149 | INSERT = 0; 150 | // Key is expected to exist in the registry at the current version. 151 | // The mutation will fail otherwise. 152 | UPDATE = 1; 153 | // Key is expected to exist in the registry at the current version. 154 | // The mutation will fail otherwise. 155 | DELETE = 2; 156 | // If the key does not exist at the current version, it will be created. 157 | // Otherwise, the value will be updated. The name is common in the 158 | // database world, and means Update or Insert. 159 | UPSERT = 4; 160 | } 161 | 162 | // The type of the mutation to apply to the registry. 163 | // Always required. 164 | Type mutation_type = 1; 165 | 166 | // The key of the entry to mutate in the registry. 167 | // Always required. 168 | bytes key = 2; 169 | 170 | // The value to mutate in the registry. 171 | // Required for insert, update, but not for delete. 172 | bytes value = 3; 173 | } 174 | 175 | // A precondition on the version at which the value of a given key was 176 | // last mutated. 177 | message Precondition { 178 | bytes key = 1; 179 | 180 | // The precondition is satisfied if and only is the version in the 181 | // RegistryValue for the key is equal to this. 182 | uint64 expected_version = 2; 183 | } 184 | 185 | // Message corresponding to a list of mutations to apply, atomically, to the 186 | // registry canister. If any of the mutations fails, the whole operation will fail. 187 | message RegistryAtomicMutateRequest { 188 | // The set of mutations to apply to the registry. 189 | repeated RegistryMutation mutations = 1; 190 | 191 | // Preconditions at the key level. 192 | repeated Precondition preconditions = 5; 193 | 194 | reserved 4; 195 | } 196 | 197 | // Message corresponding to the response of an atomic_mutate request. If any of 198 | // mutations failed the corresponding errors will be reflected in 'errors'. 199 | // Otherwise 'version' will contain the version under which all the mutations 200 | // were applied. 201 | message RegistryAtomicMutateResponse { 202 | // If anything went wrong, the registry canister 203 | // will set this error. 204 | repeated RegistryError errors = 1; 205 | // The last version of the registry. 206 | uint64 version = 2; 207 | } 208 | 209 | // Message encoding a response to any *_certified method call. 210 | message CertifiedResponse { 211 | // The hash tree encoding both the response and the intermediate 212 | // nodes required to recompute the root hash stored in 213 | // "certified_data" of the canister. 214 | // 215 | // Note that the contents of the tree depends on the type of request 216 | // issued. 217 | messaging.xnet.v1.MixedHashTree hash_tree = 1; 218 | // The certificate obtained from the system using 219 | // ic0.data_certificate_copy. 220 | bytes certificate = 2; 221 | } 222 | -------------------------------------------------------------------------------- /example/registry/proto/subnet.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package="./pb"; 4 | 5 | package registry.subnet.v1; 6 | 7 | import "types.proto"; 8 | 9 | // A subnet: A logical group of nodes that run consensus 10 | message SubnetRecord { 11 | // The the list of node_ids that represent the set of nodes 12 | // that are part of this subnet. 13 | reserved 1; // this is from membership consisting of uint64 14 | reserved 6; 15 | reserved "ic_version_id"; 16 | repeated bytes membership = 3; 17 | 18 | reserved 2; 19 | reserved "initial_dkg_transcript"; 20 | 21 | reserved 4; 22 | reserved "ingress_bytes_per_block_soft_cap"; 23 | 24 | // Maximum amount of bytes per message. This is a hard cap, which means 25 | // ingress messages greater than the limit will be dropped. 26 | uint64 max_ingress_bytes_per_message = 5; 27 | 28 | // Unit delay for blockmaker (in milliseconds). 29 | uint64 unit_delay_millis = 7; 30 | 31 | // Initial delay for notary (in milliseconds), to give time to rank-0 block 32 | // propagation. 33 | uint64 initial_notary_delay_millis = 8; 34 | 35 | // ID of the Replica version to run 36 | string replica_version_id = 9; 37 | 38 | // The length of all DKG intervals. The DKG interval length is the number of rounds following the DKG summary. 39 | uint64 dkg_interval_length = 10; 40 | 41 | // Gossip Config 42 | GossipConfig gossip_config = 13; 43 | 44 | // If set to yes, the subnet starts as a (new) NNS 45 | bool start_as_nns = 14; 46 | 47 | // The type of subnet. 48 | SubnetType subnet_type = 15; 49 | 50 | // The upper bound for the number of dealings we allow in a block. 51 | uint64 dkg_dealings_per_block = 16; 52 | 53 | // If `true`, the subnet will be halted: it will no longer create or execute blocks. 54 | bool is_halted = 17; 55 | 56 | // Max number of ingress messages per block. 57 | uint64 max_ingress_messages_per_block = 18; 58 | 59 | // The maximum combined size of the ingress and xnet messages that fit into a block. 60 | uint64 max_block_payload_size = 19; 61 | 62 | // The maximum number of instructions a message can execute. 63 | // See the comments in `subnet_config.rs` for more details. 64 | uint64 max_instructions_per_message = 20; 65 | 66 | // The maximum number of instructions a round can execute. 67 | // See the comments in `subnet_config.rs` for more details. 68 | uint64 max_instructions_per_round = 21; 69 | 70 | // The maximum number of instructions an `install_code` message can execute. 71 | // See the comments in `subnet_config.rs` for more details. 72 | uint64 max_instructions_per_install_code = 22; 73 | 74 | // Information on whether a feature is supported by this subnet. 75 | SubnetFeatures features = 23; 76 | 77 | // The number of canisters allowed to be created on this subnet. 78 | // 79 | // A value of 0 is equivalent to setting no limit. This also provides an easy way 80 | // to maintain compatibility of different versions of replica and registry. 81 | uint64 max_number_of_canisters = 24; 82 | 83 | // The list of public keys whose owners have "readonly" SSH access to all replicas on this subnet, 84 | // in case it is necessary to perform subnet recovery. 85 | repeated string ssh_readonly_access = 25; 86 | 87 | // The list of public keys whose owners have "backup" SSH access to nodes on the NNS subnet 88 | // to make sure the NNS can be backed up. 89 | repeated string ssh_backup_access = 26; 90 | 91 | // ECDSA Config 92 | EcdsaConfig ecdsa_config = 27; 93 | } 94 | 95 | // Contains the initial DKG transcripts for the subnet and materials to construct a base CUP (i.e. 96 | // a CUP with no dependencies on previous CUPs or blocks). Such CUP materials can be used to 97 | // construct the genesis CUP or a recovery CUP in the event of a subnet stall. 98 | message CatchUpPackageContents { 99 | // Initial non-interactive low-threshold DKG transcript 100 | InitialNiDkgTranscriptRecord initial_ni_dkg_transcript_low_threshold = 1; 101 | 102 | // Initial non-interactive high-threshold DKG transcript 103 | InitialNiDkgTranscriptRecord initial_ni_dkg_transcript_high_threshold = 2; 104 | 105 | // The blockchain height that the CUP should have 106 | uint64 height = 3; 107 | 108 | // Block time for the CUP's block 109 | uint64 time = 4; 110 | 111 | // The hash of the state that the subnet should use 112 | bytes state_hash = 5; 113 | 114 | // A uri from which data to replace the registry local store should be downloaded 115 | RegistryStoreUri registry_store_uri = 6; 116 | } 117 | 118 | message RegistryStoreUri { 119 | /// The uri at which the registry store data should be retrieved. The data 120 | /// must be provided as gzipped tar archive 121 | string uri = 1; 122 | /// A SHA-256, hex encoded hash of the contents of the data stored at the 123 | /// provided URI 124 | string hash = 2; 125 | /// The registry version that should be used for the catch up package contents 126 | uint64 registry_version = 3; 127 | } 128 | 129 | // A list of subnet ids of all subnets present in this instance of the IC. 130 | message SubnetListRecord { 131 | reserved 1; // this is from subnet id being a uint64 132 | repeated bytes subnets = 2; 133 | } 134 | 135 | // Initial non-interactive DKG transcript record 136 | message InitialNiDkgTranscriptRecord { 137 | types.v1.NiDkgId id = 1; 138 | uint32 threshold = 2; 139 | repeated bytes committee = 3; 140 | uint64 registry_version = 4; 141 | bytes internal_csp_transcript = 5; 142 | } 143 | 144 | // Per subnet P2P configuration 145 | // Note: protoc is mangling the name P2PConfig to P2pConfig 146 | message GossipConfig { 147 | reserved 9; 148 | reserved "relay_config"; 149 | 150 | // max outstanding request per peer MIN/DEFAULT/MAX 1/20/200 151 | uint32 max_artifact_streams_per_peer = 1; 152 | // timeout for a outstanding request 3_000/15_000/180_000 153 | uint32 max_chunk_wait_ms = 2 ; 154 | // max duplicate requests in underutilized networks 1/28/6000 155 | uint32 max_duplicity = 3; 156 | // maximum chunk size supported on this subnet 1024/4096/131_072 157 | uint32 max_chunk_size = 4; 158 | // history size for receive check 1_000/5_000/30_000 159 | uint32 receive_check_cache_size = 5; 160 | // period for re evaluating the priority function. 1_000/3_000/30_000 161 | uint32 pfn_evaluation_period_ms = 6; 162 | // period for polling the registry for updates 1_000/3_000/30_000 163 | uint32 registry_poll_period_ms = 7; 164 | // period for sending a retransmission request 165 | uint32 retransmission_request_ms = 8; 166 | // config for advert distribution. 167 | // If this field is not specified, the feature is turned off. 168 | GossipAdvertConfig advert_config = 10; 169 | } 170 | 171 | // Per subnet config for advert distribution. 172 | message GossipAdvertConfig { 173 | // The subset of peers to broadcast to, specified in percentage. 174 | // This is only used when the P2P clients mark the advert as 175 | // requiring best effort distribution. In future, this fixed 176 | // percentage could be replaced by dynamic computation of the 177 | // distribution set size, as a function of subnet size. 178 | // 0 < best_effort_percentage <= 100 179 | uint32 best_effort_percentage = 1; 180 | } 181 | 182 | // Represents the type of subnet. Subnets of different type might exhibit different 183 | // behavior, e.g. being more restrictive in what operations are allowed or privileged 184 | // compared to other subnet types. 185 | enum SubnetType { 186 | SUBNET_TYPE_UNSPECIFIED = 0; 187 | // A normal subnet where no restrictions are applied. 188 | SUBNET_TYPE_APPLICATION = 1; 189 | // A more privileged subnet where certain restrictions are applied, 190 | // like not charging for cycles or restricting who can create and 191 | // install canisters on it. 192 | SUBNET_TYPE_SYSTEM = 2; 193 | reserved 3; 194 | reserved "SUBNET_TYPE_PREMIUM_APPLICATION"; 195 | // A subnet type that is like application subnets but can have some 196 | // additional features. 197 | SUBNET_TYPE_VERIFIED_APPLICATION = 4; 198 | } 199 | 200 | message SubnetFeatures { 201 | // This feature flag controls, whether canisters of this subnet are capable of 202 | // issuing threshold ecdsa signatures. 203 | bool ecdsa_signatures = 1; 204 | // This feature flag controls whether canister execution happens 205 | // in sandboxed process or not. It is disabled by default. 206 | bool canister_sandboxing = 2; 207 | // This feature flag controls whether canisters of this subnet are capable of 208 | // performing http(s) requests to the web2. 209 | bool http_requests = 3; 210 | } 211 | 212 | // Per subnet P2P configuration 213 | // Note: protoc is mangling the name P2PConfig to P2pConfig 214 | message EcdsaConfig { 215 | // Number of quadruples to create in advance. 216 | uint32 quadruples_to_create_in_advance = 1; 217 | } 218 | -------------------------------------------------------------------------------- /agent.go: -------------------------------------------------------------------------------- 1 | package agent 2 | 3 | import ( 4 | "encoding/hex" 5 | "fmt" 6 | "time" 7 | 8 | "github.com/fxamacker/cbor/v2" 9 | "github.com/openos-labs/IC-Go/utils/identity" 10 | "github.com/openos-labs/IC-Go/utils/idl" 11 | "github.com/openos-labs/IC-Go/utils/principal" 12 | ) 13 | 14 | type Agent struct { 15 | client *Client 16 | identity *identity.Identity 17 | ingressExpiry time.Duration 18 | rootKey []byte //ICP root identity 19 | } 20 | 21 | func NewFromPem(anonymous bool, pemPath string) (*Agent, error) { 22 | var id *identity.Identity 23 | c := NewClient("https://ic0.app") 24 | //todo:是否需要从ic拉取rootKey信息 25 | status, _ := c.Status() 26 | 27 | if anonymous == true { 28 | id = &identity.Identity{ 29 | Anonymous: anonymous, 30 | } 31 | } 32 | privKey, err := identity.FromPem(pemPath) 33 | if err != nil { 34 | return nil, err 35 | } 36 | pubKey := privKey.Public() 37 | 38 | id = &identity.Identity{ 39 | anonymous, 40 | privKey, 41 | pubKey, 42 | } 43 | ingressExpiry := time.Second * 10 44 | return &Agent{ 45 | client: &c, 46 | identity: id, 47 | ingressExpiry: ingressExpiry, 48 | rootKey: status.RootKey, 49 | }, nil 50 | } 51 | 52 | func New(anonymous bool, privKey string) *Agent { 53 | c := NewClient("https://ic0.app") 54 | //todo:是否需要从ic拉取rootKey信息 55 | status, _ := c.Status() 56 | pbBytes, _ := hex.DecodeString(privKey) 57 | id := identity.New(anonymous, pbBytes) 58 | 59 | ingressExpiry := time.Second * 10 60 | return &Agent{ 61 | client: &c, 62 | identity: id, 63 | ingressExpiry: ingressExpiry, 64 | rootKey: status.RootKey, 65 | } 66 | } 67 | 68 | func (agent *Agent) Sender() principal.Principal { 69 | if agent.identity.Anonymous == true { 70 | return principal.AnonymousID 71 | } 72 | sender := principal.NewSelfAuthenticating(agent.identity.PubKeyBytes()) 73 | return sender 74 | } 75 | 76 | func (agent *Agent) getExpiryDate() time.Time { 77 | return time.Now().Add(agent.ingressExpiry) 78 | } 79 | 80 | func (agent *Agent) queryEndpoint(canisterID string, data []byte) (*QueryResponse, error) { 81 | resp, err := agent.client.query(canisterID, data) 82 | if err != nil { 83 | return nil, err 84 | } 85 | result := new(QueryResponse) 86 | err = cbor.Unmarshal(resp, result) 87 | if err != nil { 88 | return result, err 89 | } 90 | return result, nil 91 | } 92 | 93 | func (agent *Agent) callEndpoint(canisterID string, reqId RequestID, data []byte) (RequestID, error) { 94 | return agent.client.call(canisterID, reqId, data) 95 | } 96 | 97 | func (agent *Agent) readStateEndpoint(canisterID string, data []byte) ([]byte, error) { 98 | return agent.client.readState(canisterID, data) 99 | } 100 | 101 | func (agent *Agent) Query(canisterID, methodName string, arg []byte) ([]idl.Type, []interface{}, string, error) { 102 | resp, ErrMsg, err := agent.QueryRaw(canisterID, methodName, arg) 103 | if err != nil { 104 | return nil, nil, "", err 105 | } 106 | types, values, err := idl.Decode(resp) 107 | if err != nil { 108 | return nil, nil, "", err 109 | } 110 | return types, values, ErrMsg, nil 111 | } 112 | 113 | func (agent *Agent) QueryRaw(canisterID, methodName string, arg []byte) ([]byte, string, error) { 114 | canisterIDPrincipal, err := principal.Decode(canisterID) 115 | if err != nil { 116 | return nil, "", err 117 | } 118 | req := Request{ 119 | Type: RequestTypeQuery, 120 | Sender: agent.Sender(), 121 | CanisterID: canisterIDPrincipal, 122 | MethodName: methodName, 123 | Arguments: arg, 124 | IngressExpiry: uint64(agent.getExpiryDate().UnixNano()), 125 | } 126 | _, data, err := agent.signRequest(req) 127 | if err != nil { 128 | return nil, "", err 129 | } 130 | 131 | resp, err := agent.queryEndpoint(canisterID, data) 132 | 133 | if err != nil { 134 | return nil, "", err 135 | } 136 | if resp.Status == "replied" { 137 | 138 | return resp.Reply["arg"], "", nil 139 | } else if resp.Status == "rejected" { 140 | return nil, resp.RejectMsg, nil 141 | } 142 | return nil, "", err 143 | } 144 | 145 | func (agent *Agent) Update(canisterID, methodName string, arg []byte, timeout uint64) ([]idl.Type, []interface{}, error) { 146 | resp, err := agent.UpdateRaw(canisterID, methodName, arg, timeout) 147 | if err != nil { 148 | return nil, nil, err 149 | } 150 | types, values, err := idl.Decode(resp) 151 | if err != nil { 152 | return nil, nil, err 153 | } 154 | return types, values, nil 155 | } 156 | 157 | func (agent *Agent) UpdateRaw(canisterID, methodName string, arg []byte, timeout uint64) ([]byte, error) { 158 | canisterIDPrincipal, err := principal.Decode(canisterID) 159 | if err != nil { 160 | return nil, err 161 | } 162 | req := Request{ 163 | Type: RequestTypeCall, 164 | Sender: agent.Sender(), 165 | CanisterID: canisterIDPrincipal, 166 | MethodName: methodName, 167 | Arguments: arg, 168 | IngressExpiry: uint64(agent.getExpiryDate().UnixNano()), 169 | } 170 | 171 | requestID, data, err := agent.signRequest(req) 172 | if err != nil { 173 | return nil, err 174 | } 175 | 176 | _, err = agent.callEndpoint(canisterID, *requestID, data) 177 | if err != nil { 178 | return nil, err 179 | } 180 | //poll requestID to get result 181 | //todo:这个时间写成配置之后 182 | return agent.poll(canisterID, *requestID, time.Second, time.Second*time.Duration(timeout)) 183 | 184 | } 185 | 186 | func (agent *Agent) poll(canisterID string, requestID RequestID, delay time.Duration, timeout time.Duration) ([]byte, error) { 187 | finalStatus := "" 188 | var finalCert []byte 189 | timer := time.NewTimer(timeout) 190 | ticker := time.NewTicker(delay) 191 | stopped := true 192 | for stopped { 193 | select { 194 | case <-ticker.C: 195 | status, cert, err := agent.requestStatusRaw(canisterID, requestID) 196 | if err != nil { 197 | fmt.Printf("can not request status raw with error : %v\n", err) 198 | } 199 | finalStatus = string(status) 200 | finalCert = cert 201 | if finalStatus == "replied" || finalStatus == "done" || finalStatus == "rejected" { 202 | stopped = false 203 | } 204 | case <-timer.C: 205 | stopped = false 206 | } 207 | } 208 | if finalStatus == "replied" { 209 | paths := [][]byte{[]byte("request_status"), requestID[:], []byte("reply")} 210 | res, err := LookUp(paths, finalCert) 211 | if err != nil { 212 | return nil, err 213 | } 214 | return res, nil 215 | } 216 | defer timer.Stop() 217 | defer ticker.Stop() 218 | return nil, fmt.Errorf("call poll fail with status %v", finalStatus) 219 | } 220 | 221 | func (agent *Agent) requestStatusRaw(canisterID string, requestId RequestID) ([]byte, []byte, error) { 222 | 223 | paths := [][][]byte{{[]byte("request_status"), requestId[:]}} 224 | cert, err := agent.readStateRaw(canisterID, paths) 225 | 226 | if err != nil { 227 | return nil, nil, err 228 | } 229 | path := [][]byte{[]byte("request_status"), requestId[:], []byte("status")} 230 | status, err := LookUp(path, cert) 231 | return status, cert, err 232 | } 233 | 234 | func (agent *Agent) readStateRaw(canisterID string, paths [][][]byte) ([]byte, error) { 235 | req := Request{ 236 | Type: RequestTypeReadState, 237 | Sender: agent.Sender(), 238 | Paths: paths, 239 | IngressExpiry: uint64(agent.getExpiryDate().UnixNano()), 240 | } 241 | 242 | _, data, err := agent.signRequest(req) 243 | 244 | if err != nil { 245 | return nil, err 246 | } 247 | resp, err := agent.readStateEndpoint(canisterID, data) 248 | if err != nil { 249 | return nil, err 250 | } 251 | 252 | result := map[string][]byte{} 253 | 254 | err = cbor.Unmarshal(resp, &result) 255 | if err != nil { 256 | return nil, err 257 | } 258 | return result["certificate"], nil 259 | } 260 | 261 | func (agent *Agent) signRequest(req Request) (*RequestID, []byte, error) { 262 | requestID := NewRequestID(req) 263 | msg := []byte(IC_REQUEST_DOMAIN_SEPARATOR) 264 | msg = append(msg, requestID[:]...) 265 | sig, err := agent.identity.Sign(msg) 266 | if err != nil { 267 | return nil, nil, err 268 | } 269 | envelope := Envelope{ 270 | Content: req, 271 | SenderPubkey: agent.identity.PubKeyBytes(), 272 | SenderSig: sig, 273 | } 274 | 275 | marshaledEnvelope, err := cbor.Marshal(envelope) 276 | if err != nil { 277 | return nil, nil, err 278 | } 279 | return &requestID, marshaledEnvelope, nil 280 | } 281 | 282 | func (agent *Agent) GetCanisterControllers(canisterID string) ([]principal.Principal, error) { 283 | info, err := agent.GetCanisterInfo(canisterID, "controllers") 284 | if err != nil { 285 | return nil, err 286 | } 287 | var mResult [][]byte 288 | var result []principal.Principal 289 | err = cbor.Unmarshal(info, &mResult) 290 | if err != nil { 291 | return nil, err 292 | } 293 | for _, p := range mResult { 294 | result = append(result, principal.New(p)) 295 | } 296 | return result, nil 297 | } 298 | 299 | func (agent *Agent) GetCanisterModule(canisterID string) ([]byte, error) { 300 | return agent.GetCanisterInfo(canisterID, "module_hash") 301 | } 302 | 303 | func (agent Agent) GetCanisterInfo(canisterID, subPath string) ([]byte, error) { 304 | canisterBytes, err := principal.Decode(canisterID) 305 | if err != nil { 306 | return nil, err 307 | } 308 | paths := [][][]byte{{[]byte("canister"), canisterBytes, []byte(subPath)}} 309 | cert, err := agent.readStateRaw(canisterID, paths) 310 | if err != nil { 311 | return nil, err 312 | } 313 | path := [][]byte{[]byte("canister"), canisterBytes, []byte(subPath)} 314 | return LookUp(path, cert) 315 | } 316 | 317 | func (agent Agent) GetCanisterTime(canisterID string) ([]byte, error) { 318 | paths := [][][]byte{{[]byte("time")}} 319 | cert, err := agent.readStateRaw(canisterID, paths) 320 | if err != nil { 321 | return nil, err 322 | } 323 | path := [][]byte{[]byte("time")} 324 | return LookUp(path, cert) 325 | } 326 | -------------------------------------------------------------------------------- /agent_test.go: -------------------------------------------------------------------------------- 1 | package agent 2 | 3 | import ( 4 | "encoding/hex" 5 | "fmt" 6 | "math/big" 7 | "testing" 8 | 9 | "github.com/fxamacker/cbor/v2" 10 | "github.com/openos-labs/IC-Go/utils" 11 | "github.com/openos-labs/IC-Go/utils/identity" 12 | "github.com/openos-labs/IC-Go/utils/idl" 13 | "github.com/openos-labs/IC-Go/utils/principal" 14 | ) 15 | 16 | //EXT data structure 17 | type supply struct { 18 | Ok uint64 `ic:"ok"` 19 | Err string `ic:"err"` 20 | } 21 | type Time struct { 22 | Some big.Int `ic:"some"` 23 | None uint8 `ic:"none"` 24 | } 25 | type listing struct { 26 | Locked Time `ic:locked` 27 | Price uint64 `ic:"price"` 28 | Seller principal.Principal `ic:"seller"` 29 | } 30 | type listingTuple struct { 31 | A uint32 `ic:"0"` 32 | B listing `ic:"1"` 33 | } 34 | type listings []listingTuple 35 | 36 | type TokenIndex uint32 37 | type RegistryTuple struct { 38 | A TokenIndex `ic:"0"` 39 | B string `ic:"1"` 40 | } 41 | type Registrys []RegistryTuple 42 | 43 | //PUNK data structure 44 | type principalOp struct { 45 | Some principal.Principal `ic:"some"` 46 | None uint8 `ic:"none"` 47 | } 48 | type priceOp struct { 49 | Some uint64 `ic:"some"` 50 | None uint8 `ic:"none"` 51 | } 52 | 53 | type NULL *uint8 54 | 55 | type Operation struct { 56 | Delist NULL `ic:"delist"` 57 | Init NULL `ic:"init"` 58 | List NULL `ic:"list"` 59 | Mint NULL `ic:"mint"` 60 | Purchase NULL `ic:"purchase"` 61 | Transfer NULL `ic:"transfer"` 62 | 63 | //To formulate a enum struct 64 | Index string `ic:"EnumIndex"` 65 | } 66 | 67 | type transaction struct { 68 | Caller principal.Principal `ic:"caller"` 69 | To principalOp `ic:"to"` 70 | From principalOp `ic:"from"` 71 | Index big.Int `ic:"index"` 72 | Price priceOp `ic:"price"` 73 | Timestamp big.Int `ic:"timestamp"` 74 | TokenId big.Int `ic:"tokenId"` 75 | Op Operation `ic:"op"` 76 | } 77 | 78 | type DetailValue struct { 79 | I64 int64 `ic:"I64"` 80 | U64 uint64 `ic:"U64"` 81 | Vec []DetailValue `ic:"Vec"` 82 | Slice []uint8 `ic:"Slice"` 83 | TokenIdU64 uint64 `ic:"TokenIdU64"` 84 | Text string `ic:"Text"` 85 | True *uint8 `ic:"True"` 86 | False *uint8 `ic:"False"` 87 | Float float64 `ic:"Float"` 88 | Principal principal.Principal `ic:"Principal"` 89 | 90 | Index string `ic:"EnumIndex"` 91 | } 92 | 93 | type Details struct { 94 | Text string `ic:"0"` 95 | Value DetailValue `ic:"1"` 96 | } 97 | type Event struct { 98 | Time uint64 `ic:"time"` 99 | Operation string `ic:"operation"` 100 | Details []Details `ic:"details"` 101 | Caller principal.Principal `ic:"caller"` 102 | } 103 | 104 | type GetTransactionsResponseBorrowed struct { 105 | Data []Event `ic:"data"` 106 | Page uint32 `ic:"page"` 107 | } 108 | 109 | func TestAgent_QueryRaw(t *testing.T) { 110 | //EXT canister 111 | //canisterID := "bzsui-sqaaa-aaaah-qce2a-cai" 112 | 113 | //PUNK canister 114 | // canisterID := "qfh5c-6aaaa-aaaah-qakeq-cai" 115 | agent := New(true, "") 116 | //agent := New(false, "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42") 117 | // agent, err := NewFromPem(false, "./utils/identity/priv.pem") 118 | // if err != nil { 119 | // t.Log(err) 120 | // } 121 | 122 | // canisterID := principal.Principal([]byte{0, 0, 0, 0, 0, 240, 17, 32, 1, 1}).Encode() 123 | 124 | // testRec := idl.NewRec(map[string]idl.Type{ 125 | // "a": idl.NewVec(idl.Int32()), 126 | // "b": idl.NewVec(idl.Int32()), 127 | // }) 128 | // testRecValue := map[string]interface{}{ 129 | // "a":[]interface{}{}, 130 | // "b":[]interface{}{}, 131 | // } 132 | 133 | // arg, _ := idl.Encode([]idl.Type{testRec}, []interface{}{testRecValue}) 134 | // fmt.Println(arg) 135 | // methodName := "get_transactions" 136 | 137 | // rec := map[string]idl.Type{} 138 | // rec["page"] = idl.NewOpt(idl.Nat32()) 139 | // rec["witness"] = new(idl.Bool) 140 | // value := map[string]interface{}{} 141 | // value["page"] = big.NewInt(1) 142 | // value["witness"] = false 143 | 144 | // arg, _ := idl.Encode([]idl.Type{idl.NewRec(rec)}, []interface{}{value}) 145 | // fmt.Println(arg, canisterID, methodName) 146 | // _, result, errMsg, err := agent.Query(canisterID, methodName, arg) 147 | // myresult := GetTransactionsResponseBorrowed{} 148 | // utils.Decode(&myresult, result[0]) 149 | //fmt.Println(result) 150 | // 151 | ////EXT method 152 | // methodName := "supply" 153 | ////methodName := "listings" 154 | ////methodName := "getRegistry" 155 | // 156 | ////PUNK method 157 | //methodName := "getHistoryByIndex" 158 | // 159 | ////arg, err := idl.Encode([]idl.Type{new(idl.Null)}, []interface{}{nil}) 160 | //arg, err := idl.Encode([]idl.Type{new(idl.Nat)}, []interface{}{big.NewInt(10)}) 161 | //if err != nil { 162 | // t.Error(err) 163 | //} 164 | // Type, result, errMsg, err := agent.Query(canisterID, methodName, arg) 165 | // 166 | ////myresult := supply{} 167 | ////myresult := listings{} 168 | ////myresult := Registrys{} 169 | // 170 | //myresult := transaction{} 171 | ////fmt.Println(result[0]) 172 | //utils.Decode(&myresult, result[0]) 173 | 174 | // t.Log("errMsg:", errMsg, "err:", err, "result:", myresult) 175 | // fmt.Println(myresult.Data[1]) 176 | 177 | methodName := "getAllToken" 178 | canister := "cuvse-myaaa-aaaan-qas6a-cai" 179 | arg, _ := idl.Encode([]idl.Type{idl.NewOpt(new(idl.Nat))}, []interface{}{nil}) 180 | _, result, _, err := agent.Query(canister, methodName, arg) 181 | if err != nil { 182 | panic(err) 183 | } 184 | fmt.Println(result[0]) 185 | } 186 | 187 | func TestAgent_UpdateRaw(t *testing.T) { 188 | // canisterID := "gvbup-jyaaa-aaaah-qcdwa-cai" 189 | // agent := New(false, "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42") 190 | 191 | // methodName := "transfer" 192 | // var argType []idl.Type 193 | // var argValue []interface{} 194 | // p, _ := principal.Decode("aaaaa-aa") 195 | // argType = append(argType, new(idl.Principal)) 196 | // argType = append(argType, new(idl.Nat)) 197 | // argValue = append(argValue, p) 198 | // argValue = append(argValue, big.NewInt(10000000000)) 199 | var myresult uint64 200 | canisterID := "d24m2-dqaaa-aaaah-aa4zq-cai" 201 | ag := New(false, "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42") 202 | methodName := "total" 203 | arg, _ := idl.Encode([]idl.Type{new(idl.Null)}, []interface{}{nil}) 204 | _, result, err := ag.Update(canisterID, methodName, arg, 30) 205 | if err != nil { 206 | panic(err) 207 | } 208 | utils.Decode(&myresult, result[0]) 209 | 210 | // arg, _ := idl.Encode(argType, argValue) 211 | // _, result, err := agent.Update(canisterID, methodName, arg) 212 | 213 | t.Log("errMsg:", err, "result:", myresult) 214 | } 215 | 216 | func TestAgent_GetCanisterModule(t *testing.T) { 217 | canisterID := "bzsui-sqaaa-aaaah-qce2a-cai" 218 | agent := New(false, "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42") 219 | result, err := agent.GetCanisterModule(canisterID) 220 | if err != nil { 221 | t.Log("err:", err) 222 | } else if result == nil { 223 | t.Log("no module") 224 | } else { 225 | t.Log("hash:", hex.EncodeToString(result)) 226 | } 227 | } 228 | 229 | func TestAgent_GetCanisterControllers(t *testing.T) { 230 | canisterID := "6b4pv-sqaaa-aaaah-qaava-cai" 231 | agent := New(false, "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42") 232 | result, err := agent.GetCanisterControllers(canisterID) 233 | if err != nil { 234 | t.Log("err:", err) 235 | } else { 236 | for _, i := range result { 237 | t.Log("controller:", i.Encode()) 238 | } 239 | } 240 | t.Log(result) 241 | } 242 | 243 | func TestPrincipal(t *testing.T) { 244 | pkBytes, _ := hex.DecodeString("833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42") 245 | identity := identity.New(false, pkBytes) 246 | p := principal.NewSelfAuthenticating(identity.PubKeyBytes()) 247 | t.Log(p.Encode(), len(identity.PubKeyBytes())) 248 | } 249 | 250 | func TestCbor(t *testing.T) { 251 | canisterID, _ := principal.Decode("gvbup-jyaaa-aaaah-qcdwa-cai") 252 | agent := New(true, "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42") 253 | 254 | req := Request{ 255 | Type: "call", 256 | Sender: agent.Sender(), 257 | IngressExpiry: uint64(agent.getExpiryDate().UnixNano()), 258 | CanisterID: canisterID, 259 | MethodName: "transfer", 260 | Arguments: []byte("i love vivian"), 261 | } 262 | 263 | envelope := Envelope{ 264 | req, 265 | []byte{}, 266 | []byte{}, 267 | } 268 | 269 | data, _ := cbor.Marshal(envelope) 270 | resp := new(Envelope) 271 | cbor.Unmarshal(data, resp) 272 | t.Log("sender", resp.Content.Sender.Encode()) 273 | t.Log("type", resp.Content.Type) 274 | t.Log("ingress expiryt", resp.Content.IngressExpiry) 275 | t.Log("method", resp.Content.MethodName) 276 | t.Log("arg", resp.Content.Arguments) 277 | t.Log("canister", resp.Content.CanisterID.Encode()) 278 | } 279 | 280 | func TestAgent_GetCanisterTime(t *testing.T) { 281 | canisterID := "b65vx-3qaaa-aaaaa-7777q-cai" 282 | agent := New(false, "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42") 283 | result, err := agent.GetCanisterTime(canisterID) 284 | if err != nil { 285 | t.Log("err:", err) 286 | } else { 287 | t.Log("result:", result) 288 | 289 | } 290 | } 291 | 292 | func TestAgent_GetCanisterCandid(t *testing.T) { 293 | canisterID := "oeee4-qaaaa-aaaak-qaaeq-cai" 294 | agent := New(false, "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42") 295 | arg, _ := idl.Encode([]idl.Type{new(idl.Null)}, []interface{}{nil}) 296 | methodName := "__get_candid_interface_tmp_hack" 297 | _, result, err := agent.Update(canisterID, methodName, arg, 30) 298 | if err != nil { 299 | panic(err) 300 | } 301 | if err != nil { 302 | t.Log("err:", err) 303 | } else { 304 | t.Log("result:", result) 305 | 306 | } 307 | } 308 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2021 Quint Daenen 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /example/registry/proto/pb/node_operator.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.26.0 4 | // protoc v3.19.2 5 | // source: node_operator.proto 6 | 7 | package pb 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | reflect "reflect" 13 | sync "sync" 14 | ) 15 | 16 | const ( 17 | // Verify that this generated code is sufficiently up-to-date. 18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 19 | // Verify that runtime/protoimpl is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 21 | ) 22 | 23 | // A record for a node operator. Each node operator is associated with a 24 | // unique principal id, a.k.a. NOID. 25 | // 26 | // Note that while a node operator might host nodes for more than 27 | // one funding parter, its principal ID must be unique. 28 | type NodeOperatorRecord struct { 29 | state protoimpl.MessageState 30 | sizeCache protoimpl.SizeCache 31 | unknownFields protoimpl.UnknownFields 32 | 33 | // The principal id of the node operator. This principal is the entity that 34 | // is able to add and remove nodes. 35 | // 36 | // This must be unique across NodeOperatorRecords. 37 | NodeOperatorPrincipalId []byte `protobuf:"bytes,1,opt,name=node_operator_principal_id,json=nodeOperatorPrincipalId,proto3" json:"node_operator_principal_id,omitempty"` 38 | // The remaining number of nodes that could be added by this node operator. 39 | // This number should never go below 0. 40 | NodeAllowance uint64 `protobuf:"varint,2,opt,name=node_allowance,json=nodeAllowance,proto3" json:"node_allowance,omitempty"` 41 | // The principal id of this node operator's provider. 42 | NodeProviderPrincipalId []byte `protobuf:"bytes,3,opt,name=node_provider_principal_id,json=nodeProviderPrincipalId,proto3" json:"node_provider_principal_id,omitempty"` 43 | // The ID of the data center where this Node Operator hosts nodes. 44 | DcId string `protobuf:"bytes,4,opt,name=dc_id,json=dcId,proto3" json:"dc_id,omitempty"` 45 | // A map from node type to the number of nodes for which the associated Node 46 | // Provider should be rewarded. 47 | RewardableNodes map[string]uint32 `protobuf:"bytes,5,rep,name=rewardable_nodes,json=rewardableNodes,proto3" json:"rewardable_nodes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` 48 | } 49 | 50 | func (x *NodeOperatorRecord) Reset() { 51 | *x = NodeOperatorRecord{} 52 | if protoimpl.UnsafeEnabled { 53 | mi := &file_node_operator_proto_msgTypes[0] 54 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 55 | ms.StoreMessageInfo(mi) 56 | } 57 | } 58 | 59 | func (x *NodeOperatorRecord) String() string { 60 | return protoimpl.X.MessageStringOf(x) 61 | } 62 | 63 | func (*NodeOperatorRecord) ProtoMessage() {} 64 | 65 | func (x *NodeOperatorRecord) ProtoReflect() protoreflect.Message { 66 | mi := &file_node_operator_proto_msgTypes[0] 67 | if protoimpl.UnsafeEnabled && x != nil { 68 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 69 | if ms.LoadMessageInfo() == nil { 70 | ms.StoreMessageInfo(mi) 71 | } 72 | return ms 73 | } 74 | return mi.MessageOf(x) 75 | } 76 | 77 | // Deprecated: Use NodeOperatorRecord.ProtoReflect.Descriptor instead. 78 | func (*NodeOperatorRecord) Descriptor() ([]byte, []int) { 79 | return file_node_operator_proto_rawDescGZIP(), []int{0} 80 | } 81 | 82 | func (x *NodeOperatorRecord) GetNodeOperatorPrincipalId() []byte { 83 | if x != nil { 84 | return x.NodeOperatorPrincipalId 85 | } 86 | return nil 87 | } 88 | 89 | func (x *NodeOperatorRecord) GetNodeAllowance() uint64 { 90 | if x != nil { 91 | return x.NodeAllowance 92 | } 93 | return 0 94 | } 95 | 96 | func (x *NodeOperatorRecord) GetNodeProviderPrincipalId() []byte { 97 | if x != nil { 98 | return x.NodeProviderPrincipalId 99 | } 100 | return nil 101 | } 102 | 103 | func (x *NodeOperatorRecord) GetDcId() string { 104 | if x != nil { 105 | return x.DcId 106 | } 107 | return "" 108 | } 109 | 110 | func (x *NodeOperatorRecord) GetRewardableNodes() map[string]uint32 { 111 | if x != nil { 112 | return x.RewardableNodes 113 | } 114 | return nil 115 | } 116 | 117 | /// The payload of a request to remove Node Operator records from the Registry 118 | type RemoveNodeOperatorsPayload struct { 119 | state protoimpl.MessageState 120 | sizeCache protoimpl.SizeCache 121 | unknownFields protoimpl.UnknownFields 122 | 123 | NodeOperatorsToRemove [][]byte `protobuf:"bytes,1,rep,name=node_operators_to_remove,json=nodeOperatorsToRemove,proto3" json:"node_operators_to_remove,omitempty"` 124 | } 125 | 126 | func (x *RemoveNodeOperatorsPayload) Reset() { 127 | *x = RemoveNodeOperatorsPayload{} 128 | if protoimpl.UnsafeEnabled { 129 | mi := &file_node_operator_proto_msgTypes[1] 130 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 131 | ms.StoreMessageInfo(mi) 132 | } 133 | } 134 | 135 | func (x *RemoveNodeOperatorsPayload) String() string { 136 | return protoimpl.X.MessageStringOf(x) 137 | } 138 | 139 | func (*RemoveNodeOperatorsPayload) ProtoMessage() {} 140 | 141 | func (x *RemoveNodeOperatorsPayload) ProtoReflect() protoreflect.Message { 142 | mi := &file_node_operator_proto_msgTypes[1] 143 | if protoimpl.UnsafeEnabled && x != nil { 144 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 145 | if ms.LoadMessageInfo() == nil { 146 | ms.StoreMessageInfo(mi) 147 | } 148 | return ms 149 | } 150 | return mi.MessageOf(x) 151 | } 152 | 153 | // Deprecated: Use RemoveNodeOperatorsPayload.ProtoReflect.Descriptor instead. 154 | func (*RemoveNodeOperatorsPayload) Descriptor() ([]byte, []int) { 155 | return file_node_operator_proto_rawDescGZIP(), []int{1} 156 | } 157 | 158 | func (x *RemoveNodeOperatorsPayload) GetNodeOperatorsToRemove() [][]byte { 159 | if x != nil { 160 | return x.NodeOperatorsToRemove 161 | } 162 | return nil 163 | } 164 | 165 | var File_node_operator_proto protoreflect.FileDescriptor 166 | 167 | var file_node_operator_proto_rawDesc = []byte{ 168 | 0x0a, 0x13, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 169 | 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 170 | 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 171 | 0x22, 0xfd, 0x02, 0x0a, 0x12, 0x4e, 0x6f, 0x64, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 172 | 0x72, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, 0x3b, 0x0a, 0x1a, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 173 | 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 174 | 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x17, 0x6e, 0x6f, 0x64, 175 | 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 176 | 0x61, 0x6c, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x61, 0x6c, 0x6c, 177 | 0x6f, 0x77, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x6e, 0x6f, 178 | 0x64, 0x65, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x3b, 0x0a, 0x1a, 0x6e, 179 | 0x6f, 0x64, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x69, 180 | 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 181 | 0x17, 0x6e, 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x50, 0x72, 0x69, 182 | 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x13, 0x0a, 0x05, 0x64, 0x63, 0x5f, 0x69, 183 | 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x63, 0x49, 0x64, 0x12, 0x6d, 0x0a, 184 | 0x10, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 185 | 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 186 | 0x72, 0x79, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 187 | 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 188 | 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x2e, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x61, 0x62, 0x6c, 189 | 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x72, 0x65, 0x77, 190 | 0x61, 0x72, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x1a, 0x42, 0x0a, 0x14, 191 | 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x45, 192 | 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 193 | 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 194 | 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 195 | 0x22, 0x55, 0x0a, 0x1a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x4f, 0x70, 196 | 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x37, 197 | 0x0a, 0x18, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, 198 | 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 199 | 0x52, 0x15, 0x6e, 0x6f, 0x64, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x54, 200 | 0x6f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 201 | 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 202 | } 203 | 204 | var ( 205 | file_node_operator_proto_rawDescOnce sync.Once 206 | file_node_operator_proto_rawDescData = file_node_operator_proto_rawDesc 207 | ) 208 | 209 | func file_node_operator_proto_rawDescGZIP() []byte { 210 | file_node_operator_proto_rawDescOnce.Do(func() { 211 | file_node_operator_proto_rawDescData = protoimpl.X.CompressGZIP(file_node_operator_proto_rawDescData) 212 | }) 213 | return file_node_operator_proto_rawDescData 214 | } 215 | 216 | var file_node_operator_proto_msgTypes = make([]protoimpl.MessageInfo, 3) 217 | var file_node_operator_proto_goTypes = []interface{}{ 218 | (*NodeOperatorRecord)(nil), // 0: registry.node_operator.v1.NodeOperatorRecord 219 | (*RemoveNodeOperatorsPayload)(nil), // 1: registry.node_operator.v1.RemoveNodeOperatorsPayload 220 | nil, // 2: registry.node_operator.v1.NodeOperatorRecord.RewardableNodesEntry 221 | } 222 | var file_node_operator_proto_depIdxs = []int32{ 223 | 2, // 0: registry.node_operator.v1.NodeOperatorRecord.rewardable_nodes:type_name -> registry.node_operator.v1.NodeOperatorRecord.RewardableNodesEntry 224 | 1, // [1:1] is the sub-list for method output_type 225 | 1, // [1:1] is the sub-list for method input_type 226 | 1, // [1:1] is the sub-list for extension type_name 227 | 1, // [1:1] is the sub-list for extension extendee 228 | 0, // [0:1] is the sub-list for field type_name 229 | } 230 | 231 | func init() { file_node_operator_proto_init() } 232 | func file_node_operator_proto_init() { 233 | if File_node_operator_proto != nil { 234 | return 235 | } 236 | if !protoimpl.UnsafeEnabled { 237 | file_node_operator_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 238 | switch v := v.(*NodeOperatorRecord); i { 239 | case 0: 240 | return &v.state 241 | case 1: 242 | return &v.sizeCache 243 | case 2: 244 | return &v.unknownFields 245 | default: 246 | return nil 247 | } 248 | } 249 | file_node_operator_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 250 | switch v := v.(*RemoveNodeOperatorsPayload); i { 251 | case 0: 252 | return &v.state 253 | case 1: 254 | return &v.sizeCache 255 | case 2: 256 | return &v.unknownFields 257 | default: 258 | return nil 259 | } 260 | } 261 | } 262 | type x struct{} 263 | out := protoimpl.TypeBuilder{ 264 | File: protoimpl.DescBuilder{ 265 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 266 | RawDescriptor: file_node_operator_proto_rawDesc, 267 | NumEnums: 0, 268 | NumMessages: 3, 269 | NumExtensions: 0, 270 | NumServices: 0, 271 | }, 272 | GoTypes: file_node_operator_proto_goTypes, 273 | DependencyIndexes: file_node_operator_proto_depIdxs, 274 | MessageInfos: file_node_operator_proto_msgTypes, 275 | }.Build() 276 | File_node_operator_proto = out.File 277 | file_node_operator_proto_rawDesc = nil 278 | file_node_operator_proto_goTypes = nil 279 | file_node_operator_proto_depIdxs = nil 280 | } 281 | -------------------------------------------------------------------------------- /utils/idl/testdata/prim.test.did: -------------------------------------------------------------------------------- 1 | /* 2 | Encoding tests for primitive types 3 | 4 | Corresponding to spec version version 0.1.3 5 | */ 6 | 7 | // fundamentally wrong 8 | assert blob "" !: () "empty"; 9 | assert blob "\00\00" !: () "no magic bytes"; 10 | assert blob "DADL" !: () "wrong magic bytes"; 11 | assert blob "DADL\00\00" !: () "wrong magic bytes"; 12 | assert blob "DIDL\80\00\00" : () "overlong typ table length"; 13 | assert blob "DIDL\00\80\00" : () "overlong arg length"; 14 | 15 | // nullary input 16 | assert blob "DIDL\00\00" : (); 17 | assert blob "DIDL\00\00\00" !: () "nullary: too long"; 18 | assert blob "DIDL\00\01\7f" : () "Additional parameters are ignored"; 19 | assert blob "DIDL\00\01\6e" !: () "Not a primitive type"; 20 | assert blob "DIDL\00\01\5e" !: () "Out of range type"; 21 | 22 | // primitive types 23 | assert blob "DIDL\00\01\7f" : (null); 24 | assert blob "DIDL\00\01\7e" !: (null) "wrong type"; 25 | assert blob "DIDL\00\01\7f\00" !: (null) "null: too long"; 26 | assert blob "DIDL\00\00" : (null) "null: extra null values"; 27 | 28 | assert blob "DIDL\00\01\7e\00" == "(false)" : (bool) "bool: false"; 29 | assert blob "DIDL\00\01\7e\01" == "(true)" : (bool) "bool: true"; 30 | assert blob "DIDL\00\01\7e" !: (bool) "bool: missing"; 31 | assert blob "DIDL\00\01\7e\02" !: (bool) "bool: out of range"; 32 | assert blob "DIDL\00\01\7e\ff" !: (bool) "bool: out of range"; 33 | 34 | assert blob "DIDL\00\01\7d\00" == "(0)" : (nat) "nat: 0"; 35 | assert blob "DIDL\00\01\7d\01" == "(1)" : (nat) "nat: 1"; 36 | assert blob "DIDL\00\01\7d\7f" == "(127)" : (nat) "nat: 0x7f"; 37 | assert blob "DIDL\00\01\7d\80\01" == "(128)" : (nat) "nat: leb (two bytes)"; 38 | assert blob "DIDL\00\01\7d\ff\7f" == "(16383)" : (nat) "nat: leb (two bytes, all bits)"; 39 | assert blob "DIDL\00\01\7d\80" !: (nat) "nat: leb too short"; 40 | assert blob "DIDL\00\01\7d\80\00" == "(0)" : (nat) "nat: leb overlong"; 41 | assert blob "DIDL\00\01\7d\ff\00" == "(127)" : (nat) "nat: leb overlong"; 42 | assert blob "DIDL\00\01\7d\80\80\98\f4\e9\b5\ca\6a" == "(60000000000000000)" : (nat) "nat: big number"; 43 | 44 | assert blob "DIDL\00\01\7c\00" == "(0)" : (int) "int: 0"; 45 | assert blob "DIDL\00\01\7c\01" == "(1)" : (int) "int: 1"; 46 | assert blob "DIDL\00\01\7c\7f" == "(-1)" : (int) "int: -1"; 47 | assert blob "DIDL\00\01\7c\40" == "(-64)" : (int) "int: -64"; 48 | assert blob "DIDL\00\01\7c\80\01" == "(128)" : (int) "int: leb (two bytes)"; 49 | assert blob "DIDL\00\01\7c\80" !: (int) "int: leb too short"; 50 | assert blob "DIDL\00\01\7c\80\00" == "(0)" : (int) "int: leb overlong (0s)"; 51 | assert blob "DIDL\00\01\7c\ff\7f" == "(-1)" : (int) "int: leb overlong (1s)"; 52 | assert blob "DIDL\00\01\7c\ff\00" == "(127)" : (int) "int: leb not overlong when signed"; 53 | assert blob "DIDL\00\01\7c\80\7f" == "(-128)" : (int) "int: leb not overlong when signed"; 54 | assert blob "DIDL\00\01\7c\80\80\98\f4\e9\b5\ca\ea\00" == "(60000000000000000)" : (int) "int: big number"; 55 | assert blob "DIDL\00\01\7c\80\80\e8\8b\96\ca\b5\95\7f" == "(-60000000000000000)" : (int) "int: negative big number"; 56 | 57 | assert blob "DIDL\00\01\7d\00" == "(0)" : (int) "nat <: int: 0"; 58 | assert blob "DIDL\00\01\7d\01" == "(1)" : (int) "nat <: int: 1"; 59 | assert blob "DIDL\00\01\7d\7f" == "(127)" : (int) "nat <: int: leb (two bytes)"; 60 | assert blob "DIDL\00\01\7d\80\01" == "(128)" : (int) "nat <: int: leb (two bytes)"; 61 | assert blob "DIDL\00\01\7d\ff\7f" == "(16383)" : (int) "nat <: int: leb (two bytes, all bits)"; 62 | 63 | assert blob "DIDL\00\01\7b\00" == "(0)" : (nat8) "nat8: 0"; 64 | assert blob "DIDL\00\01\7b\01" == "(1)" : (nat8) "nat8: 1"; 65 | assert blob "DIDL\00\01\7b\ff" == "(255)" : (nat8) "nat8: 255"; 66 | assert blob "DIDL\00\01\7b" !: (nat8) "nat8: too short"; 67 | assert blob "DIDL\00\01\7b\00\00" !: (nat8) "nat8: too long"; 68 | 69 | assert blob "DIDL\00\01\7a\00\00" == "(0)" : (nat16) "nat16: 0"; 70 | assert blob "DIDL\00\01\7a\01\00" == "(1)" : (nat16) "nat16: 1"; 71 | assert blob "DIDL\00\01\7a\ff\00" == "(255)" : (nat16) "nat16: 255"; 72 | assert blob "DIDL\00\01\7a\00\01" == "(256)" : (nat16) "nat16: 256"; 73 | assert blob "DIDL\00\01\7a\ff\ff" == "(65535)" : (nat16) "nat16: 65535"; 74 | assert blob "DIDL\00\01\7a" !: (nat16) "nat16: too short"; 75 | assert blob "DIDL\00\01\7a\00" !: (nat16) "nat16: too short"; 76 | assert blob "DIDL\00\01\7a\00\00\00" !: (nat16) "nat16: too long"; 77 | 78 | assert blob "DIDL\00\01\79\00\00\00\00" == "(0)" : (nat32) "nat32: 0"; 79 | assert blob "DIDL\00\01\79\01\00\00\00" == "(1)" : (nat32) "nat32: 1"; 80 | assert blob "DIDL\00\01\79\ff\00\00\00" == "(255)" : (nat32) "nat32: 255"; 81 | assert blob "DIDL\00\01\79\00\01\00\00" == "(256)" : (nat32) "nat32: 256"; 82 | assert blob "DIDL\00\01\79\ff\ff\00\00" == "(65535)" : (nat32) "nat32: 65535"; 83 | assert blob "DIDL\00\01\79\ff\ff\ff\ff" == "(4294967295)" : (nat32) "nat32: 4294967295"; 84 | assert blob "DIDL\00\01\79" !: (nat32) "nat32: too short"; 85 | assert blob "DIDL\00\01\79\00" !: (nat32) "nat32: too short"; 86 | assert blob "DIDL\00\01\79\00\00" !: (nat32) "nat32: too short"; 87 | assert blob "DIDL\00\01\79\00\00\00" !: (nat32) "nat32: too short"; 88 | assert blob "DIDL\00\01\79\00\00\00\00\00" !: (nat32) "nat32: too long"; 89 | 90 | assert blob "DIDL\00\01\78\00\00\00\00\00\00\00\00" == "(0)" : (nat64) "nat64: 0"; 91 | assert blob "DIDL\00\01\78\01\00\00\00\00\00\00\00" == "(1)" : (nat64) "nat64: 1"; 92 | assert blob "DIDL\00\01\78\ff\00\00\00\00\00\00\00" == "(255)" : (nat64) "nat64: 255"; 93 | assert blob "DIDL\00\01\78\00\01\00\00\00\00\00\00" == "(256)" : (nat64) "nat64: 256"; 94 | assert blob "DIDL\00\01\78\ff\ff\00\00\00\00\00\00" == "(65535)" : (nat64) "nat64: 65535"; 95 | assert blob "DIDL\00\01\78\ff\ff\ff\ff\00\00\00\00" == "(4294967295)" : (nat64) "nat64: 4294967295"; 96 | assert blob "DIDL\00\01\78\ff\ff\ff\ff\ff\ff\ff\ff" == "(18446744073709551615)" : (nat64) "nat64: 18446744073709551615"; 97 | assert blob "DIDL\00\01\78" !: (nat64) "nat64: too short"; 98 | assert blob "DIDL\00\01\78\00" !: (nat64) "nat64: too short"; 99 | assert blob "DIDL\00\01\78\00\00" !: (nat64) "nat64: too short"; 100 | assert blob "DIDL\00\01\78\00\00\00" !: (nat64) "nat64: too short"; 101 | assert blob "DIDL\00\01\78\00\00\00\00" !: (nat64) "nat64: too short"; 102 | assert blob "DIDL\00\01\78\00\00\00\00\00" !: (nat64) "nat64: too short"; 103 | assert blob "DIDL\00\01\78\00\00\00\00\00\00" !: (nat64) "nat64: too short"; 104 | assert blob "DIDL\00\01\78\00\00\00\00\00\00\00" !: (nat64) "nat64: too short"; 105 | assert blob "DIDL\00\01\78\00\00\00\00\00\00\00\00\00" !: (nat64) "nat64: too long"; 106 | 107 | assert blob "DIDL\00\01\77\00" == "(0)" : (int8) "int8: 0"; 108 | assert blob "DIDL\00\01\77\01" == "(1)" : (int8) "int8: 1"; 109 | assert blob "DIDL\00\01\77\ff" == "(-1)" : (int8) "int8: -1"; 110 | assert blob "DIDL\00\01\77" !: (int8) "int8: too short"; 111 | assert blob "DIDL\00\01\77\00\00" !: (int8) "int8: too long"; 112 | 113 | assert blob "DIDL\00\01\76\00\00" == "(0)" : (int16) "int16: 0"; 114 | assert blob "DIDL\00\01\76\01\00" == "(1)" : (int16) "int16: 1"; 115 | assert blob "DIDL\00\01\76\ff\00" == "(255)" : (int16) "int16: 255"; 116 | assert blob "DIDL\00\01\76\00\01" == "(256)" : (int16) "int16: 256"; 117 | assert blob "DIDL\00\01\76\ff\ff" == "(-1)" : (int16) "int16: -1"; 118 | assert blob "DIDL\00\01\76" !: (int16) "int16: too short"; 119 | assert blob "DIDL\00\01\76\00" !: (int16) "int16: too short"; 120 | assert blob "DIDL\00\01\76\00\00\00" !: (int16) "int16: too long"; 121 | 122 | assert blob "DIDL\00\01\75\00\00\00\00" == "(0)" : (int32) "int32: 0"; 123 | assert blob "DIDL\00\01\75\01\00\00\00" == "(1)" : (int32) "int32: 1"; 124 | assert blob "DIDL\00\01\75\ff\00\00\00" == "(255)" : (int32) "int32: 255"; 125 | assert blob "DIDL\00\01\75\00\01\00\00" == "(256)" : (int32) "int32: 256"; 126 | assert blob "DIDL\00\01\75\ff\ff\00\00" == "(65535)" : (int32) "int32: 65535"; 127 | assert blob "DIDL\00\01\75\ff\ff\ff\ff" == "(-1)" : (int32) "int32: -1"; 128 | assert blob "DIDL\00\01\75" !: (int32) "int32: too short"; 129 | assert blob "DIDL\00\01\75\00" !: (int32) "int32: too short"; 130 | assert blob "DIDL\00\01\75\00\00" !: (int32) "int32: too short"; 131 | assert blob "DIDL\00\01\75\00\00\00" !: (int32) "int32: too short"; 132 | assert blob "DIDL\00\01\75\00\00\00\00\00" !: (int32) "int32: too long"; 133 | 134 | assert blob "DIDL\00\01\74\00\00\00\00\00\00\00\00" == "(0)" : (int64) "int64: 0"; 135 | assert blob "DIDL\00\01\74\01\00\00\00\00\00\00\00" == "(1)" : (int64) "int64: 1"; 136 | assert blob "DIDL\00\01\74\ff\00\00\00\00\00\00\00" == "(255)" : (int64) "int64: 255"; 137 | assert blob "DIDL\00\01\74\00\01\00\00\00\00\00\00" == "(256)" : (int64) "int64: 256"; 138 | assert blob "DIDL\00\01\74\ff\ff\00\00\00\00\00\00" == "(65535)" : (int64) "int64: 65535"; 139 | assert blob "DIDL\00\01\74\ff\ff\ff\ff\00\00\00\00" == "(4294967295)" : (int64) "int64: 4294967295"; 140 | assert blob "DIDL\00\01\74\ff\ff\ff\ff\ff\ff\ff\ff" == "(-1)" : (int64) "int64: -1"; 141 | assert blob "DIDL\00\01\74" !: (int64) "int64: too short"; 142 | assert blob "DIDL\00\01\74\00" !: (int64) "int64: too short"; 143 | assert blob "DIDL\00\01\74\00\00" !: (int64) "int64: too short"; 144 | assert blob "DIDL\00\01\74\00\00\00" !: (int64) "int64: too short"; 145 | assert blob "DIDL\00\01\74\00\00\00\00" !: (int64) "int64: too short"; 146 | assert blob "DIDL\00\01\74\00\00\00\00\00" !: (int64) "int64: too short"; 147 | assert blob "DIDL\00\01\74\00\00\00\00\00\00" !: (int64) "int64: too short"; 148 | assert blob "DIDL\00\01\74\00\00\00\00\00\00\00" !: (int64) "int64: too short"; 149 | assert blob "DIDL\00\01\74\00\00\00\00\00\00\00\00\00" !: (int64) "int64: too long"; 150 | 151 | assert blob "DIDL\00\01\73\00\00\00\00" == "(0.)" : (float32) "float32: 0"; 152 | assert blob "DIDL\00\01\73\00\00\40\40" == "(3.)" : (float32) "float32: 3"; 153 | assert blob "DIDL\00\01\73\00\00\00\3f" == "(0.5)" : (float32) "float32: 0.5"; 154 | assert blob "DIDL\00\01\73\00\00\00\bf" == "(-0.5)" : (float32) "float32: -0.5"; 155 | assert blob "DIDL\00\01\73\00\00" !: (float32) "float32: too short"; 156 | assert blob "DIDL\00\01\73\00\00\00\00\00" !: (float32) "float32: too long"; 157 | 158 | assert blob "DIDL\00\01\72\00\00\00\00\00\00\00\00" == "(0.)" : (float64) "float64: 0"; 159 | assert blob "DIDL\00\01\72\00\00\00\00\00\00\08\40" == "(3.)" : (float64) "float64: 3"; 160 | assert blob "DIDL\00\01\72\00\00\00\00\00\00\e0\3f" == "(0.5)" : (float64) "float64: 0.5"; 161 | assert blob "DIDL\00\01\72\00\00\00\00\00\00\e0\bf" == "(-0.5)" : (float64) "float64: -0.5"; 162 | assert blob "DIDL\00\01\72\01\00\00\00\00\00\f0\7f" : (float64) "float64: NaN"; 163 | assert blob "DIDL\00\01\72\ff\ff\ff\ff\ff\ff\ef\7f" : (float64) "float64: max value"; 164 | assert blob "DIDL\00\01\72\00\00\00\00" !: (float64) "float64: too short"; 165 | assert blob "DIDL\00\01\72\00\00\00\00\00\00\00\00\00" !: (float64) "float64: too long"; 166 | 167 | assert blob "DIDL\00\01\71\00" == "(\"\")" : (text) "text: empty string"; 168 | assert blob "DIDL\00\01\71\06Motoko" == "(\"Motoko\")" : (text) "text: Motoko"; 169 | assert blob "DIDL\00\01\71\05Motoko" !: (text) "text: too long"; 170 | assert blob "DIDL\00\01\71\07Motoko" !: (text) "text: too short"; 171 | assert blob "DIDL\00\01\71\86\00Motoko" : (text) "text: overlong length leb"; 172 | // assert blob "DIDL\00\01\71\03\e2\98\83" == "(\"☃\")" : (text) "text: Unicode"; 173 | // assert "(\"\\u{2603}\")" == "(\"☃\")" : (text) "text: Unicode escape" 174 | // assert "(\"\\u{2603\")" !: (text) "text: Unicode escape (unclosed)"; 175 | assert blob "DIDL\00\01\71\03\e2\28\a1" !: (text) "text: Invalid utf8"; 176 | assert blob "DIDL\00\01\71\02\e2\98\83" !: (text) "text: Unicode overshoots"; 177 | assert blob "DIDL\00\01\71\06\09\0A\0D\22\27\5C" == "(\"\\t\\n\\r\\\"\\\'\\\\\")" : (text) "text: Escape sequences"; 178 | 179 | assert blob "DIDL\00\01\70" == blob "DIDL\00\01\7f" : (reserved) "reserved from null"; 180 | assert blob "DIDL\00\01\70" == blob "DIDL\00\01\7e\01" : (reserved) "reserved from bool"; 181 | assert blob "DIDL\00\01\70" == blob "DIDL\00\01\7d\80\01" : (reserved) "reserved from nat"; 182 | assert blob "DIDL\00\01\70" == blob "DIDL\00\01\71\06Motoko" : (reserved) "reserved from text"; 183 | assert blob "DIDL\00\00" : (reserved) "reserved extra value"; 184 | assert blob "DIDL\00\01\71\05Motoko" !: (reserved) "reserved from too short text"; 185 | assert blob "DIDL\00\01\71\03\e2\28\a1" !: (reserved) "reserved from invalid utf8 text"; 186 | 187 | assert blob "DIDL\00\01\6f" !: (empty) "cannot decode empty type"; 188 | assert blob "DIDL\01\6e\6f\01\00\00" == "(null)" : (opt empty) "okay to decode non-empty value"; 189 | 190 | assert blob "DIDL\00\0a\7f\7e\7d\7c\7f\70\7f\7b\7a\79\01\2a\2a\2a\2a\00\2a\00\00\00" 191 | == "(null, true, 42, 42, null, null, null, 42, 42, 42)" : (null, bool, nat, int, null, reserved, null, nat8, nat16, nat32) "multiple arguments"; 192 | -------------------------------------------------------------------------------- /example/registry/proto/pb/routing_table.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.26.0 4 | // protoc v3.19.2 5 | // source: routing_table.proto 6 | 7 | package pb 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | reflect "reflect" 13 | sync "sync" 14 | ) 15 | 16 | const ( 17 | // Verify that this generated code is sufficiently up-to-date. 18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 19 | // Verify that runtime/protoimpl is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 21 | ) 22 | 23 | type CanisterIdRange struct { 24 | state protoimpl.MessageState 25 | sizeCache protoimpl.SizeCache 26 | unknownFields protoimpl.UnknownFields 27 | 28 | StartCanisterId *CanisterId `protobuf:"bytes,3,opt,name=start_canister_id,json=startCanisterId,proto3" json:"start_canister_id,omitempty"` 29 | EndCanisterId *CanisterId `protobuf:"bytes,4,opt,name=end_canister_id,json=endCanisterId,proto3" json:"end_canister_id,omitempty"` 30 | } 31 | 32 | func (x *CanisterIdRange) Reset() { 33 | *x = CanisterIdRange{} 34 | if protoimpl.UnsafeEnabled { 35 | mi := &file_routing_table_proto_msgTypes[0] 36 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 37 | ms.StoreMessageInfo(mi) 38 | } 39 | } 40 | 41 | func (x *CanisterIdRange) String() string { 42 | return protoimpl.X.MessageStringOf(x) 43 | } 44 | 45 | func (*CanisterIdRange) ProtoMessage() {} 46 | 47 | func (x *CanisterIdRange) ProtoReflect() protoreflect.Message { 48 | mi := &file_routing_table_proto_msgTypes[0] 49 | if protoimpl.UnsafeEnabled && x != nil { 50 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 51 | if ms.LoadMessageInfo() == nil { 52 | ms.StoreMessageInfo(mi) 53 | } 54 | return ms 55 | } 56 | return mi.MessageOf(x) 57 | } 58 | 59 | // Deprecated: Use CanisterIdRange.ProtoReflect.Descriptor instead. 60 | func (*CanisterIdRange) Descriptor() ([]byte, []int) { 61 | return file_routing_table_proto_rawDescGZIP(), []int{0} 62 | } 63 | 64 | func (x *CanisterIdRange) GetStartCanisterId() *CanisterId { 65 | if x != nil { 66 | return x.StartCanisterId 67 | } 68 | return nil 69 | } 70 | 71 | func (x *CanisterIdRange) GetEndCanisterId() *CanisterId { 72 | if x != nil { 73 | return x.EndCanisterId 74 | } 75 | return nil 76 | } 77 | 78 | // A list of closed ranges of canister Ids. 79 | type CanisterIdRanges struct { 80 | state protoimpl.MessageState 81 | sizeCache protoimpl.SizeCache 82 | unknownFields protoimpl.UnknownFields 83 | 84 | Ranges []*CanisterIdRange `protobuf:"bytes,1,rep,name=ranges,proto3" json:"ranges,omitempty"` 85 | } 86 | 87 | func (x *CanisterIdRanges) Reset() { 88 | *x = CanisterIdRanges{} 89 | if protoimpl.UnsafeEnabled { 90 | mi := &file_routing_table_proto_msgTypes[1] 91 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 92 | ms.StoreMessageInfo(mi) 93 | } 94 | } 95 | 96 | func (x *CanisterIdRanges) String() string { 97 | return protoimpl.X.MessageStringOf(x) 98 | } 99 | 100 | func (*CanisterIdRanges) ProtoMessage() {} 101 | 102 | func (x *CanisterIdRanges) ProtoReflect() protoreflect.Message { 103 | mi := &file_routing_table_proto_msgTypes[1] 104 | if protoimpl.UnsafeEnabled && x != nil { 105 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 106 | if ms.LoadMessageInfo() == nil { 107 | ms.StoreMessageInfo(mi) 108 | } 109 | return ms 110 | } 111 | return mi.MessageOf(x) 112 | } 113 | 114 | // Deprecated: Use CanisterIdRanges.ProtoReflect.Descriptor instead. 115 | func (*CanisterIdRanges) Descriptor() ([]byte, []int) { 116 | return file_routing_table_proto_rawDescGZIP(), []int{1} 117 | } 118 | 119 | func (x *CanisterIdRanges) GetRanges() []*CanisterIdRange { 120 | if x != nil { 121 | return x.Ranges 122 | } 123 | return nil 124 | } 125 | 126 | // Maps a closed range of canister Ids to a subnet id. 127 | type RoutingTable struct { 128 | state protoimpl.MessageState 129 | sizeCache protoimpl.SizeCache 130 | unknownFields protoimpl.UnknownFields 131 | 132 | // Defined as `repeated` instead of `map` in order to preserve ordering. 133 | Entries []*RoutingTable_Entry `protobuf:"bytes,1,rep,name=entries,proto3" json:"entries,omitempty"` 134 | } 135 | 136 | func (x *RoutingTable) Reset() { 137 | *x = RoutingTable{} 138 | if protoimpl.UnsafeEnabled { 139 | mi := &file_routing_table_proto_msgTypes[2] 140 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 141 | ms.StoreMessageInfo(mi) 142 | } 143 | } 144 | 145 | func (x *RoutingTable) String() string { 146 | return protoimpl.X.MessageStringOf(x) 147 | } 148 | 149 | func (*RoutingTable) ProtoMessage() {} 150 | 151 | func (x *RoutingTable) ProtoReflect() protoreflect.Message { 152 | mi := &file_routing_table_proto_msgTypes[2] 153 | if protoimpl.UnsafeEnabled && x != nil { 154 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 155 | if ms.LoadMessageInfo() == nil { 156 | ms.StoreMessageInfo(mi) 157 | } 158 | return ms 159 | } 160 | return mi.MessageOf(x) 161 | } 162 | 163 | // Deprecated: Use RoutingTable.ProtoReflect.Descriptor instead. 164 | func (*RoutingTable) Descriptor() ([]byte, []int) { 165 | return file_routing_table_proto_rawDescGZIP(), []int{2} 166 | } 167 | 168 | func (x *RoutingTable) GetEntries() []*RoutingTable_Entry { 169 | if x != nil { 170 | return x.Entries 171 | } 172 | return nil 173 | } 174 | 175 | type RoutingTable_Entry struct { 176 | state protoimpl.MessageState 177 | sizeCache protoimpl.SizeCache 178 | unknownFields protoimpl.UnknownFields 179 | 180 | Range *CanisterIdRange `protobuf:"bytes,1,opt,name=range,proto3" json:"range,omitempty"` 181 | SubnetId *SubnetId `protobuf:"bytes,2,opt,name=subnet_id,json=subnetId,proto3" json:"subnet_id,omitempty"` 182 | } 183 | 184 | func (x *RoutingTable_Entry) Reset() { 185 | *x = RoutingTable_Entry{} 186 | if protoimpl.UnsafeEnabled { 187 | mi := &file_routing_table_proto_msgTypes[3] 188 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 189 | ms.StoreMessageInfo(mi) 190 | } 191 | } 192 | 193 | func (x *RoutingTable_Entry) String() string { 194 | return protoimpl.X.MessageStringOf(x) 195 | } 196 | 197 | func (*RoutingTable_Entry) ProtoMessage() {} 198 | 199 | func (x *RoutingTable_Entry) ProtoReflect() protoreflect.Message { 200 | mi := &file_routing_table_proto_msgTypes[3] 201 | if protoimpl.UnsafeEnabled && x != nil { 202 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 203 | if ms.LoadMessageInfo() == nil { 204 | ms.StoreMessageInfo(mi) 205 | } 206 | return ms 207 | } 208 | return mi.MessageOf(x) 209 | } 210 | 211 | // Deprecated: Use RoutingTable_Entry.ProtoReflect.Descriptor instead. 212 | func (*RoutingTable_Entry) Descriptor() ([]byte, []int) { 213 | return file_routing_table_proto_rawDescGZIP(), []int{2, 0} 214 | } 215 | 216 | func (x *RoutingTable_Entry) GetRange() *CanisterIdRange { 217 | if x != nil { 218 | return x.Range 219 | } 220 | return nil 221 | } 222 | 223 | func (x *RoutingTable_Entry) GetSubnetId() *SubnetId { 224 | if x != nil { 225 | return x.SubnetId 226 | } 227 | return nil 228 | } 229 | 230 | var File_routing_table_proto protoreflect.FileDescriptor 231 | 232 | var file_routing_table_proto_rawDesc = []byte{ 233 | 0x0a, 0x13, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 234 | 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x74, 235 | 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x0b, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 236 | 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa9, 0x01, 0x0a, 0x0f, 0x43, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x65, 237 | 0x72, 0x49, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x40, 0x0a, 0x11, 0x73, 0x74, 0x61, 0x72, 238 | 0x74, 0x5f, 0x63, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 239 | 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 240 | 0x61, 0x6e, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x52, 0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, 241 | 0x43, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x0f, 0x65, 0x6e, 242 | 0x64, 0x5f, 0x63, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 243 | 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 244 | 0x61, 0x6e, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x52, 0x0d, 0x65, 0x6e, 0x64, 0x43, 0x61, 245 | 0x6e, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 246 | 0x08, 0x02, 0x10, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x52, 0x03, 0x65, 0x6e, 0x64, 247 | 0x22, 0x4d, 0x0a, 0x10, 0x43, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x52, 0x61, 248 | 0x6e, 0x67, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x06, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x01, 249 | 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x74, 250 | 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x65, 0x72, 251 | 0x49, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x06, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 252 | 0xc1, 0x01, 0x0a, 0x0c, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 253 | 0x12, 0x3e, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 254 | 0x0b, 0x32, 0x24, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x62, 0x6c, 255 | 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x62, 0x6c, 256 | 0x65, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 257 | 0x1a, 0x71, 0x0a, 0x05, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x37, 0x0a, 0x05, 0x72, 0x61, 0x6e, 258 | 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x69, 259 | 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x69, 260 | 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x05, 0x72, 0x61, 0x6e, 261 | 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 262 | 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 263 | 0x2e, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x49, 0x64, 0x52, 0x08, 0x73, 0x75, 0x62, 0x6e, 0x65, 264 | 0x74, 0x49, 0x64, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 265 | 0x74, 0x6f, 0x33, 266 | } 267 | 268 | var ( 269 | file_routing_table_proto_rawDescOnce sync.Once 270 | file_routing_table_proto_rawDescData = file_routing_table_proto_rawDesc 271 | ) 272 | 273 | func file_routing_table_proto_rawDescGZIP() []byte { 274 | file_routing_table_proto_rawDescOnce.Do(func() { 275 | file_routing_table_proto_rawDescData = protoimpl.X.CompressGZIP(file_routing_table_proto_rawDescData) 276 | }) 277 | return file_routing_table_proto_rawDescData 278 | } 279 | 280 | var file_routing_table_proto_msgTypes = make([]protoimpl.MessageInfo, 4) 281 | var file_routing_table_proto_goTypes = []interface{}{ 282 | (*CanisterIdRange)(nil), // 0: routing_table.v1.CanisterIdRange 283 | (*CanisterIdRanges)(nil), // 1: routing_table.v1.CanisterIdRanges 284 | (*RoutingTable)(nil), // 2: routing_table.v1.RoutingTable 285 | (*RoutingTable_Entry)(nil), // 3: routing_table.v1.RoutingTable.Entry 286 | (*CanisterId)(nil), // 4: types.v1.CanisterId 287 | (*SubnetId)(nil), // 5: types.v1.SubnetId 288 | } 289 | var file_routing_table_proto_depIdxs = []int32{ 290 | 4, // 0: routing_table.v1.CanisterIdRange.start_canister_id:type_name -> types.v1.CanisterId 291 | 4, // 1: routing_table.v1.CanisterIdRange.end_canister_id:type_name -> types.v1.CanisterId 292 | 0, // 2: routing_table.v1.CanisterIdRanges.ranges:type_name -> routing_table.v1.CanisterIdRange 293 | 3, // 3: routing_table.v1.RoutingTable.entries:type_name -> routing_table.v1.RoutingTable.Entry 294 | 0, // 4: routing_table.v1.RoutingTable.Entry.range:type_name -> routing_table.v1.CanisterIdRange 295 | 5, // 5: routing_table.v1.RoutingTable.Entry.subnet_id:type_name -> types.v1.SubnetId 296 | 6, // [6:6] is the sub-list for method output_type 297 | 6, // [6:6] is the sub-list for method input_type 298 | 6, // [6:6] is the sub-list for extension type_name 299 | 6, // [6:6] is the sub-list for extension extendee 300 | 0, // [0:6] is the sub-list for field type_name 301 | } 302 | 303 | func init() { file_routing_table_proto_init() } 304 | func file_routing_table_proto_init() { 305 | if File_routing_table_proto != nil { 306 | return 307 | } 308 | file_types_proto_init() 309 | if !protoimpl.UnsafeEnabled { 310 | file_routing_table_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 311 | switch v := v.(*CanisterIdRange); i { 312 | case 0: 313 | return &v.state 314 | case 1: 315 | return &v.sizeCache 316 | case 2: 317 | return &v.unknownFields 318 | default: 319 | return nil 320 | } 321 | } 322 | file_routing_table_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 323 | switch v := v.(*CanisterIdRanges); i { 324 | case 0: 325 | return &v.state 326 | case 1: 327 | return &v.sizeCache 328 | case 2: 329 | return &v.unknownFields 330 | default: 331 | return nil 332 | } 333 | } 334 | file_routing_table_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { 335 | switch v := v.(*RoutingTable); i { 336 | case 0: 337 | return &v.state 338 | case 1: 339 | return &v.sizeCache 340 | case 2: 341 | return &v.unknownFields 342 | default: 343 | return nil 344 | } 345 | } 346 | file_routing_table_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { 347 | switch v := v.(*RoutingTable_Entry); i { 348 | case 0: 349 | return &v.state 350 | case 1: 351 | return &v.sizeCache 352 | case 2: 353 | return &v.unknownFields 354 | default: 355 | return nil 356 | } 357 | } 358 | } 359 | type x struct{} 360 | out := protoimpl.TypeBuilder{ 361 | File: protoimpl.DescBuilder{ 362 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 363 | RawDescriptor: file_routing_table_proto_rawDesc, 364 | NumEnums: 0, 365 | NumMessages: 4, 366 | NumExtensions: 0, 367 | NumServices: 0, 368 | }, 369 | GoTypes: file_routing_table_proto_goTypes, 370 | DependencyIndexes: file_routing_table_proto_depIdxs, 371 | MessageInfos: file_routing_table_proto_msgTypes, 372 | }.Build() 373 | File_routing_table_proto = out.File 374 | file_routing_table_proto_rawDesc = nil 375 | file_routing_table_proto_goTypes = nil 376 | file_routing_table_proto_depIdxs = nil 377 | } 378 | -------------------------------------------------------------------------------- /example/registry/proto/pb/mixed_hash_tree.pb.go: -------------------------------------------------------------------------------- 1 | // Protocol buffer mirror of `ic_crypto_tree_hash::MixedHashTree`. 2 | 3 | // Code generated by protoc-gen-go. DO NOT EDIT. 4 | // versions: 5 | // protoc-gen-go v1.26.0 6 | // protoc v3.19.2 7 | // source: mixed_hash_tree.proto 8 | 9 | package pb 10 | 11 | import ( 12 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 13 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 14 | emptypb "google.golang.org/protobuf/types/known/emptypb" 15 | reflect "reflect" 16 | sync "sync" 17 | ) 18 | 19 | const ( 20 | // Verify that this generated code is sufficiently up-to-date. 21 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 22 | // Verify that runtime/protoimpl is sufficiently up-to-date. 23 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 24 | ) 25 | 26 | // A tree containing both data and merkle proofs. 27 | type MixedHashTree struct { 28 | state protoimpl.MessageState 29 | sizeCache protoimpl.SizeCache 30 | unknownFields protoimpl.UnknownFields 31 | 32 | // Types that are assignable to TreeEnum: 33 | // *MixedHashTree_Empty 34 | // *MixedHashTree_Fork_ 35 | // *MixedHashTree_Labeled_ 36 | // *MixedHashTree_LeafData 37 | // *MixedHashTree_PrunedDigest 38 | TreeEnum isMixedHashTree_TreeEnum `protobuf_oneof:"tree_enum"` 39 | } 40 | 41 | func (x *MixedHashTree) Reset() { 42 | *x = MixedHashTree{} 43 | if protoimpl.UnsafeEnabled { 44 | mi := &file_mixed_hash_tree_proto_msgTypes[0] 45 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 46 | ms.StoreMessageInfo(mi) 47 | } 48 | } 49 | 50 | func (x *MixedHashTree) String() string { 51 | return protoimpl.X.MessageStringOf(x) 52 | } 53 | 54 | func (*MixedHashTree) ProtoMessage() {} 55 | 56 | func (x *MixedHashTree) ProtoReflect() protoreflect.Message { 57 | mi := &file_mixed_hash_tree_proto_msgTypes[0] 58 | if protoimpl.UnsafeEnabled && x != nil { 59 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 60 | if ms.LoadMessageInfo() == nil { 61 | ms.StoreMessageInfo(mi) 62 | } 63 | return ms 64 | } 65 | return mi.MessageOf(x) 66 | } 67 | 68 | // Deprecated: Use MixedHashTree.ProtoReflect.Descriptor instead. 69 | func (*MixedHashTree) Descriptor() ([]byte, []int) { 70 | return file_mixed_hash_tree_proto_rawDescGZIP(), []int{0} 71 | } 72 | 73 | func (m *MixedHashTree) GetTreeEnum() isMixedHashTree_TreeEnum { 74 | if m != nil { 75 | return m.TreeEnum 76 | } 77 | return nil 78 | } 79 | 80 | func (x *MixedHashTree) GetEmpty() *emptypb.Empty { 81 | if x, ok := x.GetTreeEnum().(*MixedHashTree_Empty); ok { 82 | return x.Empty 83 | } 84 | return nil 85 | } 86 | 87 | func (x *MixedHashTree) GetFork() *MixedHashTree_Fork { 88 | if x, ok := x.GetTreeEnum().(*MixedHashTree_Fork_); ok { 89 | return x.Fork 90 | } 91 | return nil 92 | } 93 | 94 | func (x *MixedHashTree) GetLabeled() *MixedHashTree_Labeled { 95 | if x, ok := x.GetTreeEnum().(*MixedHashTree_Labeled_); ok { 96 | return x.Labeled 97 | } 98 | return nil 99 | } 100 | 101 | func (x *MixedHashTree) GetLeafData() []byte { 102 | if x, ok := x.GetTreeEnum().(*MixedHashTree_LeafData); ok { 103 | return x.LeafData 104 | } 105 | return nil 106 | } 107 | 108 | func (x *MixedHashTree) GetPrunedDigest() []byte { 109 | if x, ok := x.GetTreeEnum().(*MixedHashTree_PrunedDigest); ok { 110 | return x.PrunedDigest 111 | } 112 | return nil 113 | } 114 | 115 | type isMixedHashTree_TreeEnum interface { 116 | isMixedHashTree_TreeEnum() 117 | } 118 | 119 | type MixedHashTree_Empty struct { 120 | Empty *emptypb.Empty `protobuf:"bytes,1,opt,name=empty,proto3,oneof"` 121 | } 122 | 123 | type MixedHashTree_Fork_ struct { 124 | Fork *MixedHashTree_Fork `protobuf:"bytes,2,opt,name=fork,proto3,oneof"` 125 | } 126 | 127 | type MixedHashTree_Labeled_ struct { 128 | Labeled *MixedHashTree_Labeled `protobuf:"bytes,3,opt,name=labeled,proto3,oneof"` 129 | } 130 | 131 | type MixedHashTree_LeafData struct { 132 | LeafData []byte `protobuf:"bytes,4,opt,name=leaf_data,json=leafData,proto3,oneof"` 133 | } 134 | 135 | type MixedHashTree_PrunedDigest struct { 136 | PrunedDigest []byte `protobuf:"bytes,5,opt,name=pruned_digest,json=prunedDigest,proto3,oneof"` 137 | } 138 | 139 | func (*MixedHashTree_Empty) isMixedHashTree_TreeEnum() {} 140 | 141 | func (*MixedHashTree_Fork_) isMixedHashTree_TreeEnum() {} 142 | 143 | func (*MixedHashTree_Labeled_) isMixedHashTree_TreeEnum() {} 144 | 145 | func (*MixedHashTree_LeafData) isMixedHashTree_TreeEnum() {} 146 | 147 | func (*MixedHashTree_PrunedDigest) isMixedHashTree_TreeEnum() {} 148 | 149 | type MixedHashTree_Fork struct { 150 | state protoimpl.MessageState 151 | sizeCache protoimpl.SizeCache 152 | unknownFields protoimpl.UnknownFields 153 | 154 | LeftTree *MixedHashTree `protobuf:"bytes,1,opt,name=left_tree,json=leftTree,proto3" json:"left_tree,omitempty"` 155 | RightTree *MixedHashTree `protobuf:"bytes,2,opt,name=right_tree,json=rightTree,proto3" json:"right_tree,omitempty"` 156 | } 157 | 158 | func (x *MixedHashTree_Fork) Reset() { 159 | *x = MixedHashTree_Fork{} 160 | if protoimpl.UnsafeEnabled { 161 | mi := &file_mixed_hash_tree_proto_msgTypes[1] 162 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 163 | ms.StoreMessageInfo(mi) 164 | } 165 | } 166 | 167 | func (x *MixedHashTree_Fork) String() string { 168 | return protoimpl.X.MessageStringOf(x) 169 | } 170 | 171 | func (*MixedHashTree_Fork) ProtoMessage() {} 172 | 173 | func (x *MixedHashTree_Fork) ProtoReflect() protoreflect.Message { 174 | mi := &file_mixed_hash_tree_proto_msgTypes[1] 175 | if protoimpl.UnsafeEnabled && x != nil { 176 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 177 | if ms.LoadMessageInfo() == nil { 178 | ms.StoreMessageInfo(mi) 179 | } 180 | return ms 181 | } 182 | return mi.MessageOf(x) 183 | } 184 | 185 | // Deprecated: Use MixedHashTree_Fork.ProtoReflect.Descriptor instead. 186 | func (*MixedHashTree_Fork) Descriptor() ([]byte, []int) { 187 | return file_mixed_hash_tree_proto_rawDescGZIP(), []int{0, 0} 188 | } 189 | 190 | func (x *MixedHashTree_Fork) GetLeftTree() *MixedHashTree { 191 | if x != nil { 192 | return x.LeftTree 193 | } 194 | return nil 195 | } 196 | 197 | func (x *MixedHashTree_Fork) GetRightTree() *MixedHashTree { 198 | if x != nil { 199 | return x.RightTree 200 | } 201 | return nil 202 | } 203 | 204 | type MixedHashTree_Labeled struct { 205 | state protoimpl.MessageState 206 | sizeCache protoimpl.SizeCache 207 | unknownFields protoimpl.UnknownFields 208 | 209 | Label []byte `protobuf:"bytes,1,opt,name=label,proto3" json:"label,omitempty"` 210 | Subtree *MixedHashTree `protobuf:"bytes,2,opt,name=subtree,proto3" json:"subtree,omitempty"` 211 | } 212 | 213 | func (x *MixedHashTree_Labeled) Reset() { 214 | *x = MixedHashTree_Labeled{} 215 | if protoimpl.UnsafeEnabled { 216 | mi := &file_mixed_hash_tree_proto_msgTypes[2] 217 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 218 | ms.StoreMessageInfo(mi) 219 | } 220 | } 221 | 222 | func (x *MixedHashTree_Labeled) String() string { 223 | return protoimpl.X.MessageStringOf(x) 224 | } 225 | 226 | func (*MixedHashTree_Labeled) ProtoMessage() {} 227 | 228 | func (x *MixedHashTree_Labeled) ProtoReflect() protoreflect.Message { 229 | mi := &file_mixed_hash_tree_proto_msgTypes[2] 230 | if protoimpl.UnsafeEnabled && x != nil { 231 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 232 | if ms.LoadMessageInfo() == nil { 233 | ms.StoreMessageInfo(mi) 234 | } 235 | return ms 236 | } 237 | return mi.MessageOf(x) 238 | } 239 | 240 | // Deprecated: Use MixedHashTree_Labeled.ProtoReflect.Descriptor instead. 241 | func (*MixedHashTree_Labeled) Descriptor() ([]byte, []int) { 242 | return file_mixed_hash_tree_proto_rawDescGZIP(), []int{0, 1} 243 | } 244 | 245 | func (x *MixedHashTree_Labeled) GetLabel() []byte { 246 | if x != nil { 247 | return x.Label 248 | } 249 | return nil 250 | } 251 | 252 | func (x *MixedHashTree_Labeled) GetSubtree() *MixedHashTree { 253 | if x != nil { 254 | return x.Subtree 255 | } 256 | return nil 257 | } 258 | 259 | var File_mixed_hash_tree_proto protoreflect.FileDescriptor 260 | 261 | var file_mixed_hash_tree_proto_rawDesc = []byte{ 262 | 0x0a, 0x15, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x74, 0x72, 0x65, 263 | 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 264 | 0x6e, 0x67, 0x2e, 0x78, 0x6e, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 265 | 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 266 | 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xfb, 0x03, 0x0a, 0x0d, 0x4d, 0x69, 0x78, 0x65, 267 | 0x64, 0x48, 0x61, 0x73, 0x68, 0x54, 0x72, 0x65, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x65, 0x6d, 0x70, 268 | 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 269 | 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 270 | 0x48, 0x00, 0x52, 0x05, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3b, 0x0a, 0x04, 0x66, 0x6f, 0x72, 271 | 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 272 | 0x69, 0x6e, 0x67, 0x2e, 0x78, 0x6e, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x69, 0x78, 0x65, 273 | 0x64, 0x48, 0x61, 0x73, 0x68, 0x54, 0x72, 0x65, 0x65, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x48, 0x00, 274 | 0x52, 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x12, 0x44, 0x0a, 0x07, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x65, 275 | 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 276 | 0x69, 0x6e, 0x67, 0x2e, 0x78, 0x6e, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x69, 0x78, 0x65, 277 | 0x64, 0x48, 0x61, 0x73, 0x68, 0x54, 0x72, 0x65, 0x65, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x65, 278 | 0x64, 0x48, 0x00, 0x52, 0x07, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x09, 279 | 0x6c, 0x65, 0x61, 0x66, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x48, 280 | 0x00, 0x52, 0x08, 0x6c, 0x65, 0x61, 0x66, 0x44, 0x61, 0x74, 0x61, 0x12, 0x25, 0x0a, 0x0d, 0x70, 281 | 0x72, 0x75, 0x6e, 0x65, 0x64, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 282 | 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0c, 0x70, 0x72, 0x75, 0x6e, 0x65, 0x64, 0x44, 0x69, 0x67, 0x65, 283 | 0x73, 0x74, 0x1a, 0x86, 0x01, 0x0a, 0x04, 0x46, 0x6f, 0x72, 0x6b, 0x12, 0x3d, 0x0a, 0x09, 0x6c, 284 | 0x65, 0x66, 0x74, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 285 | 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x78, 0x6e, 0x65, 0x74, 0x2e, 286 | 0x76, 0x31, 0x2e, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x48, 0x61, 0x73, 0x68, 0x54, 0x72, 0x65, 0x65, 287 | 0x52, 0x08, 0x6c, 0x65, 0x66, 0x74, 0x54, 0x72, 0x65, 0x65, 0x12, 0x3f, 0x0a, 0x0a, 0x72, 0x69, 288 | 0x67, 0x68, 0x74, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 289 | 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x78, 0x6e, 0x65, 0x74, 0x2e, 290 | 0x76, 0x31, 0x2e, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x48, 0x61, 0x73, 0x68, 0x54, 0x72, 0x65, 0x65, 291 | 0x52, 0x09, 0x72, 0x69, 0x67, 0x68, 0x74, 0x54, 0x72, 0x65, 0x65, 0x1a, 0x5b, 0x0a, 0x07, 0x4c, 292 | 0x61, 0x62, 0x65, 0x6c, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 293 | 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x3a, 0x0a, 0x07, 294 | 0x73, 0x75, 0x62, 0x74, 0x72, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 295 | 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x2e, 0x78, 0x6e, 0x65, 0x74, 0x2e, 0x76, 296 | 0x31, 0x2e, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x48, 0x61, 0x73, 0x68, 0x54, 0x72, 0x65, 0x65, 0x52, 297 | 0x07, 0x73, 0x75, 0x62, 0x74, 0x72, 0x65, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x74, 0x72, 0x65, 0x65, 298 | 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 299 | 0x72, 0x6f, 0x74, 0x6f, 0x33, 300 | } 301 | 302 | var ( 303 | file_mixed_hash_tree_proto_rawDescOnce sync.Once 304 | file_mixed_hash_tree_proto_rawDescData = file_mixed_hash_tree_proto_rawDesc 305 | ) 306 | 307 | func file_mixed_hash_tree_proto_rawDescGZIP() []byte { 308 | file_mixed_hash_tree_proto_rawDescOnce.Do(func() { 309 | file_mixed_hash_tree_proto_rawDescData = protoimpl.X.CompressGZIP(file_mixed_hash_tree_proto_rawDescData) 310 | }) 311 | return file_mixed_hash_tree_proto_rawDescData 312 | } 313 | 314 | var file_mixed_hash_tree_proto_msgTypes = make([]protoimpl.MessageInfo, 3) 315 | var file_mixed_hash_tree_proto_goTypes = []interface{}{ 316 | (*MixedHashTree)(nil), // 0: messaging.xnet.v1.MixedHashTree 317 | (*MixedHashTree_Fork)(nil), // 1: messaging.xnet.v1.MixedHashTree.Fork 318 | (*MixedHashTree_Labeled)(nil), // 2: messaging.xnet.v1.MixedHashTree.Labeled 319 | (*emptypb.Empty)(nil), // 3: google.protobuf.Empty 320 | } 321 | var file_mixed_hash_tree_proto_depIdxs = []int32{ 322 | 3, // 0: messaging.xnet.v1.MixedHashTree.empty:type_name -> google.protobuf.Empty 323 | 1, // 1: messaging.xnet.v1.MixedHashTree.fork:type_name -> messaging.xnet.v1.MixedHashTree.Fork 324 | 2, // 2: messaging.xnet.v1.MixedHashTree.labeled:type_name -> messaging.xnet.v1.MixedHashTree.Labeled 325 | 0, // 3: messaging.xnet.v1.MixedHashTree.Fork.left_tree:type_name -> messaging.xnet.v1.MixedHashTree 326 | 0, // 4: messaging.xnet.v1.MixedHashTree.Fork.right_tree:type_name -> messaging.xnet.v1.MixedHashTree 327 | 0, // 5: messaging.xnet.v1.MixedHashTree.Labeled.subtree:type_name -> messaging.xnet.v1.MixedHashTree 328 | 6, // [6:6] is the sub-list for method output_type 329 | 6, // [6:6] is the sub-list for method input_type 330 | 6, // [6:6] is the sub-list for extension type_name 331 | 6, // [6:6] is the sub-list for extension extendee 332 | 0, // [0:6] is the sub-list for field type_name 333 | } 334 | 335 | func init() { file_mixed_hash_tree_proto_init() } 336 | func file_mixed_hash_tree_proto_init() { 337 | if File_mixed_hash_tree_proto != nil { 338 | return 339 | } 340 | if !protoimpl.UnsafeEnabled { 341 | file_mixed_hash_tree_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 342 | switch v := v.(*MixedHashTree); i { 343 | case 0: 344 | return &v.state 345 | case 1: 346 | return &v.sizeCache 347 | case 2: 348 | return &v.unknownFields 349 | default: 350 | return nil 351 | } 352 | } 353 | file_mixed_hash_tree_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 354 | switch v := v.(*MixedHashTree_Fork); i { 355 | case 0: 356 | return &v.state 357 | case 1: 358 | return &v.sizeCache 359 | case 2: 360 | return &v.unknownFields 361 | default: 362 | return nil 363 | } 364 | } 365 | file_mixed_hash_tree_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { 366 | switch v := v.(*MixedHashTree_Labeled); i { 367 | case 0: 368 | return &v.state 369 | case 1: 370 | return &v.sizeCache 371 | case 2: 372 | return &v.unknownFields 373 | default: 374 | return nil 375 | } 376 | } 377 | } 378 | file_mixed_hash_tree_proto_msgTypes[0].OneofWrappers = []interface{}{ 379 | (*MixedHashTree_Empty)(nil), 380 | (*MixedHashTree_Fork_)(nil), 381 | (*MixedHashTree_Labeled_)(nil), 382 | (*MixedHashTree_LeafData)(nil), 383 | (*MixedHashTree_PrunedDigest)(nil), 384 | } 385 | type x struct{} 386 | out := protoimpl.TypeBuilder{ 387 | File: protoimpl.DescBuilder{ 388 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 389 | RawDescriptor: file_mixed_hash_tree_proto_rawDesc, 390 | NumEnums: 0, 391 | NumMessages: 3, 392 | NumExtensions: 0, 393 | NumServices: 0, 394 | }, 395 | GoTypes: file_mixed_hash_tree_proto_goTypes, 396 | DependencyIndexes: file_mixed_hash_tree_proto_depIdxs, 397 | MessageInfos: file_mixed_hash_tree_proto_msgTypes, 398 | }.Build() 399 | File_mixed_hash_tree_proto = out.File 400 | file_mixed_hash_tree_proto_rawDesc = nil 401 | file_mixed_hash_tree_proto_goTypes = nil 402 | file_mixed_hash_tree_proto_depIdxs = nil 403 | } 404 | --------------------------------------------------------------------------------