dfinity开发——动态创建Canister与Canister的控制器管理

前言

这是dfinity中动态创建Canister例子,就是在A.mo 的actor中动态创建B.mo中的actor类。

项目

1.首先创建一个项目

dfx new CanisterMGT

2.启动项目

cd CanisterMGT
dfx start --clean

3.在项目下创建types.mo 和 sub.mo文件
在这里插入图片描述

4.types.mo是canister所需要的类型和属性,添加如下代码:

module{

    public type canister_settings =
     {
        freezing_threshold : ?Nat;
        controllers : ?[Principal];
        memory_allocation : ?Nat;
        compute_allocation : ?Nat;
    };

    public type definite_canister_settings = 
    {
        freezing_threshold : Nat;
        controllers : [Principal];
        memory_allocation : Nat;
        compute_allocation : Nat;
    };

    public type user_id = Principal;
    
    public type wasm_module = [Nat8];
    public type canister_id = Principal;
    public type ICActor = actor 
    {
        canister_status : shared { canister_id : canister_id } -> async 
        {
            // status : { #stopped; #stopping; #running };
            // memory_size : Nat;
            // cycles : Nat;
            settings : { controllers : [Principal] };
            //module_hash : ?[Nat8];
        };

        create_canister : shared { settings : ?canister_settings } -> async 
        {
            canister_id : canister_id;
        };
        
        delete_canister : shared { canister_id : canister_id } -> async ();
        
        deposit_cycles : shared { canister_id : canister_id } -> async ();
        
        install_code : shared 
        {
            arg : [Nat8];wasm_module : wasm_module;mode : { #reinstall; #upgrade; #install };canister_id : canister_id;
        } -> async ();
        
        provisional_create_canister_with_cycles : shared 
        {
            settings : ?canister_settings;
            amount : ?Nat;
        } -> async { canister_id : canister_id };
        
        provisional_top_up_canister : shared 
        {
            canister_id : canister_id;
            amount : Nat;
        } -> async ();
        
        raw_rand : shared () -> async [Nat8];
        start_canister : shared { canister_id : canister_id } -> async ();
        stop_canister : shared { canister_id : canister_id } -> async ();
        uninstall_code : shared { canister_id : canister_id } -> async ();
        
        update_settings : shared 
        {
            canister_id : Principal;
            settings : canister_settings;
        } -> async ();
    };
}

5.sub.mo是接下要在main.mo里面创建的canistet,sub.mo里面的代码就是它自身要实现的代码,但cycleBalance() 和wallet_receive()这两个属性是必须要添加在里面的,有必要也添加下canister的升级代码。

import Cycles "mo:base/ExperimentalCycles"; 
import Nat "mo:base/Nat";

shared({caller}) actor class Sub(installer : Principal) = this
{

    public query({caller}) func cycleBalance() : async Nat
    {
        Cycles.balance()
    };

    public shared({caller}) func wallet_receive() : async Nat 
    {
        Cycles.accept(Cycles.available())
    };

    public shared query ({caller}) func whoami() : async Principal 
    {
        caller
    };

     stable var counter = 0;

    public query func get() : async Nat
    {
        return counter;
    };

    public func inc() : async () 
    {
        counter += 1;
    };
}

6.main.mo是创建canister的代码

import Types "./types";
import Cycles "mo:base/ExperimentalCycles"; 
import RBT "mo:base/RBTree";
import Nat "mo:base/Nat";
import Principal "mo:base/Principal";
import Sub "./sub";
import Array "mo:base/Array";


actor Self
{

    public type canister_info = 
    {
        canister_id : Principal;
        id:Nat;
    };

	//获取当前pid
    public shared query ({caller}) func whoami() : async Principal 
    {
        caller
    };
	
	//获取当前canister id
    public shared query ({caller}) func getCanisterId() : async Principal
    {
        Principal.fromActor(Self);
    };

	//记录创建的canister个数
    private stable var subs_index : Nat = 0;
    private let subs = RBT.RBTree<Nat, Principal>(Nat.compare); //存储创建的sub canister

    private let IC : Types.ICActor = actor "aaaaa-aa"; 
    private let CYCLE_LIMIT = 50; //创建canister要分配的cycle

    //动态创建canister的函数,返回创建的canisister id
    public shared({caller}) func createSub() : async canister_info
    {
        Cycles.add(CYCLE_LIMIT);
        let sub = await Sub.Sub(caller);
        let principal = Principal.fromActor(sub);
        await IC.update_settings({
            canister_id = principal;
            settings = 
            {
                freezing_threshold = ?20;
                controllers = ?[principal]; //控制器是它自身
                memory_allocation = ?0;
                compute_allocation = ?0;
            }
        });
        subs.put(b_index, principal);
        subs_index += 1;
        let canister_info = {canister_id = principal;id = subs_index;}
    };

    //获取canister的控制器
    public func get_controllers(canister_id : Principal) : async [Principal] 
    {
        let status = await IC.canister_status({ canister_id = canister_id });
        return status.settings.controllers;
    };
};

7.运行项目

dfx deploy

8.调用创建canister的接口

dfx canister call CanisterMGT createSub

动态创建第一个canister

(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call CanisterMGT createSub
(record { id = 1 : nat; canister_id = principal "r7inp-6aaaa-aaaaa-aaabq-cai" })

9.现在来访问新创建的这个canister里面的属性
查看cycles,这50个是刚刚转进去的

(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call r7inp-6aaaa-aaaaa-aaabq-cai cycleBalance
(50 : nat)

计数

base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call r7inp-6aaaa-aaaaa-aaabq-cai get         
(0 : nat)
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call r7inp-6aaaa-aaaaa-aaabq-cai inc
()
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call r7inp-6aaaa-aaaaa-aaabq-cai get
(1 : nat)
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call r7inp-6aaaa-aaaaa-aaabq-cai inc
()
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call r7inp-6aaaa-aaaaa-aaabq-cai get
(2 : nat)

然后再创建一个canister

(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call CanisterMGT createSub                   
(record { id = 2 : nat; canister_id = principal "rkp4c-7iaaa-aaaaa-aaaca-cai" })

访问里面的属性

(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call rkp4c-7iaaa-aaaaa-aaaca-cai get
(0 : nat)
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call rkp4c-7iaaa-aaaaa-aaaca-cai inc
()
(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call rkp4c-7iaaa-aaaaa-aaaca-cai get
(1 : nat)
(base) dalao@dalaodeMacBook-Pro CanisterMGT % 

10.查看控制状态

如果canister当前只有一个控制器,它是拒绝外部访问它的控制器

(base) dalao@dalaodeMacBook-Pro CanisterMGT % dfx canister call CanisterMGT get_controllers '(principal "r7inp-6aaaa-aaaaa-aaabq-cai")'
Error: The Replica returned an error: code 4, message: "Only the controllers of the canister r7inp-6aaaa-aaaaa-aaabq-cai can control it.
Canister's controllers: r7inp-6aaaa-aaaaa-aaabq-cai
Sender's ID: rrkah-fqaaa-aaaaa-aaaaq-cai"

11.创建canister分配过去的cycle记得回收,我在测试的时创建一堆canister之后,退出环境之后才记得没有回收cycle,现在还在找办法找回来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知来者逆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值