BCSkill (Block chain skill )
区块链中文技术社区

只讨论区块链底层技术
遵守一切相关法律政策!

EOS账户权限介绍以及增删改查

EOS一直宣传自己的账号权限机制,下面将演示针对账号bcskill三个权限组的增删改查

  • owner 账号拥有者,拥有账号全部的权限,等于超级管理员 (新建账号预设)
  • active 拥有账号大部分账户的权限,等于管理员 (新建账号预设)
  • custom 自定义添加,用于下面演示针对权限组的增删改查
    拥有哪些组的私钥,就拥有当前账号哪些权限。每个组可以有多个授权key,也可以多个授权账户。

1. 生成多组公钥私钥 (在线生成

  • 用于添加到三个权限组演示
权限名 公钥 私钥
owner EOS6fQzsc9Bn5buFbNxHgGMNh9zr2gcbHz2YaaBCfMApw3E8vADu3 5Hvpv1qkoBymEb8DA1MfrgHdcPbxGkE7Ux9DPzhRnb8kHBoAuBn
active EOS5G45ChvRSTjQJGvHX8gBEV2ZrUvbxnh6WEd1qfXKox7KqnZb7j 5Jqq6ztSk41Y6duygrFwCKKVBTaat8zLExG3owwnJSHZMKRcZC4
custom EOS5QxpwkWLAAWQqcT8teKrUceYr5Nj6PsBmCVoLaQQVqcoP2ZjF5 5JewRAyyYoNoTfwmy32CLBiyqS2DfQ8njY4ENuzqJ5Rrp7Zft2o
  • 用于演示一个权限组多个账号
账户名 公钥 私钥
temporary EOS7Yfs4kL6j9G8nmCTFt5ycLUpV4NmPaZKfuVfYC8XJbuDYPPdnA 5JnHkERVzDec7j31gAscy39mDbZvTr2XvGS7SZgwQCgNca3McL1
  • 用于演示一个权限组多个授权key
公钥 私钥
EOS7UKzLPHVUTYpex48pRZokvBNEEp5KKXFGwcb5Qv6dZTWUYHGeP 5JUhVJetKVxZ1vKPBwxKe458g7Zz3LnAz9kLhmirVs7tiSF2bGk

2.导入私钥

cleos wallet import 5Hvpv1qkoBymEb8DA1MfrgHdcPbxGkE7Ux9DPzhRnb8kHBoAuBn
cleos wallet import 5Jqq6ztSk41Y6duygrFwCKKVBTaat8zLExG3owwnJSHZMKRcZC4
cleos wallet import 5JewRAyyYoNoTfwmy32CLBiyqS2DfQ8njY4ENuzqJ5Rrp7Zft2o

3.创建账号

cleos system newaccount eosio bcskill EOS6fQzsc9Bn5buFbNxHgGMNh9zr2gcbHz2YaaBCfMApw3E8vADu3 EOS5G45ChvRSTjQJGvHX8gBEV2ZrUvbxnh6WEd1qfXKox7KqnZb7j  --stake-net '50.00 SYS' --stake-cpu '50.00 SYS' --buy-ram-kbytes 10000

创建账户时,会一同加入owner,active两个组,(两个组的公钥可以用同一个,但不建议)

4.查看账户信息

cleos get account bcskill -j

也就是只要有EOS6fQzsc9Bn5buFbNxHgGMNh9zr2gcbHz2YaaBCfMApw3E8vADu3的私钥,就拥有对账户bcskill的owner权限组的权限
拥有EOS5G45ChvRSTjQJGvHX8gBEV2ZrUvbxnh6WEd1qfXKox7KqnZb7j的私钥,就拥有对账户bcskill的active权限组的权限

5.为bcskill账号增加自定义权限组custom,基于active

cleos set account permission bcskill custom '{"threshold":1,"keys":[{"key":"EOS5QxpwkWLAAWQqcT8teKrUceYr5Nj6PsBmCVoLaQQVqcoP2ZjF5","weight":1}],"accounts":[]}' active

6.查看账户信息

cleos get account bcskill -j

7.为权限组custom更换权限key

cleos set account permission bcskill custom '{"threshold": 1, "keys": [{"key": "EOS7UKzLPHVUTYpex48pRZokvBNEEp5KKXFGwcb5Qv6dZTWUYHGeP", "weight": 1}], "accounts": []}' active

8.查看账户信息

cleos get account bcskill -j

custom授权key已更新

9.为custom添加多个授权key

cleos set account permission bcskill custom '{"threshold":1,"keys":[{"key":"EOS5QxpwkWLAAWQqcT8teKrUceYr5Nj6PsBmCVoLaQQVqcoP2ZjF5","weight":1},{"key":"EOS7UKzLPHVUTYpex48pRZokvBNEEp5KKXFGwcb5Qv6dZTWUYHGeP","weight":1}],"accounts":[]}' active

10.查看账户信息

cleos get account bcskill -j

custom已有两个授权key

11.创建账号temporary

cleos system newaccount eosio temporary EOS7Yfs4kL6j9G8nmCTFt5ycLUpV4NmPaZKfuVfYC8XJbuDYPPdnA EOS7Yfs4kL6j9G8nmCTFt5ycLUpV4NmPaZKfuVfYC8XJbuDYPPdnA  --stake-net '50.00 SYS' --stake-cpu '50.00 SYS' --buy-ram-kbytes 10000

12.为custom添加其他授权账号temporary

cleos set account permission bcskill custom '{"threshold":2,"keys":[{"key":"EOS5QxpwkWLAAWQqcT8teKrUceYr5Nj6PsBmCVoLaQQVqcoP2ZjF5","weight":1}],"accounts":[{"permission":{"actor":"temporary","permission":"active"},"weight":1}]}' active

13.查看账户信息

cleos get account bcskill -j

custom已有授权账号temporary

14.删除custom权限组

cleos set account permission bcskill custom 'NULL' active

15.查看账户信息

cleos get account bcskill -j

custom权限组已被删除

下一篇将讲解EOS账户权限的使用

零基础部署测试合约(三)---合约部署

下面开始编译合约


进入合约目录 /License

  1. 生成ABI
    eosiocpp -g License.abi License.cpp
  2. 生成WAST
    eosiocpp -o License.wast License.cpp

    执行完成后


开始部署合约

部署测试合约(一)---前准备中,已经创建dapp.token,dapp.exec账号

下面开始在dapp.token账户部署合约

cleos set contract dapp.token License/ -p dapp.token


开始执行合约
  1. 执行合约setuserinfo 修改用户信息
    cleos push action dapp.token setuserinfo '["dapp.exec","区块链技能学习", "bcskill.com"]' -p dapp.exec

  2. 查看用户信息
    cleos get table dapp.token dapp.token accounts

  3. 执行合约makeproject 创建项目
    cleos push action dapp.token makeproject '["dapp.exec","testcontract"]' -p dapp.exec

  4. 查看项目信息
    cleos get table dapp.token dapp.token projecttable

  5. 执行合约 buylicense购买项目授权
    cleos push action dapp.token buylicense '["dapp.exec","testcontract"]' -p dapp.exec

  6. 查看项目信息
    cleos get table dapp.token dapp.token projecttable

零基础部署测试合约(二)---合约编译

下面演示EOS智能合约编写,实例将涉及对链上多索引(multi_index)的增删改查。

实例为License合约,主要功能为

  • 客户设置自己的信息
  • 客户创建自己的项目
  • 客户购买项目授权
  • 验证项目授权
    (由于演示二级索引,项目名称为索引唯一,所以实例为用户单项目)
    上面的权限都是基于客户自身的权限验证,创建是创建的系统子账户,可用于系统币转账

合约代码基于C++语言,源代码分为源文件(.cpp)和头文件(.hpp)
//License.hpp

#include <eosiolib/asset.hpp>
#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>

class License : public eosio::contract {
    public:
        License( account_name self )
        :eosio::contract(self)
        ,accounts(_self, _self)
        ,projecttable(_self, _self){}

        void setuserinfo(account_name owner, const std::string& company_name, const std::string& contact_info);
        void makeproject(account_name owner, const std::string& project_name);
        void buylicense(account_name owner, const std::string& project_name);
        void testlicense(account_name owner, const std::string& project_name);

    private:
        //@abi table accounts i64
        struct account{
            account_name name;
            std::string company_name;
            std::string contact_info;
            uint8_t level;
            uint64_t primary_key()const { return name; }
            EOSLIB_SERIALIZE(account, (name)(company_name)(contact_info)(level))
        };

        typedef eosio::multi_index<N(accounts),account> account_table;
        account_table accounts;

        //@abi table projecttable i64
        struct project{
            uint32_t pkey;
            account_name owner_name;
            std::string project_name;
            std::string company_name;
            std::string contact_info;
            uint8_t      status;

            uint64_t primary_key()const { return pkey; }
            uint64_t getowner_name() const{return owner_name;}
            EOSLIB_SERIALIZE(project, (pkey)(owner_name)(project_name)(company_name)(contact_info)(status))
        };
        //contracts/eosiolib/multi_index.hpp
        //multi_index用于封装智能合约对数据库的管理,增、删、改、查
        //eosio::multi_index<N(表名),数据类型> 
        //一个multi_index最多支持16个二级索引
        //定义二级索引使用eosio::indexed_by模板。N(byowner_name)为索引的名称
        //project表数据类型,uint64_t索引类型即索引函数返回的类型(只支持uint64_t,uint128_t,double,long double,key256类型),&project::getowner_name索引函数。
        typedef eosio::multi_index<N(projecttable),project, eosio::indexed_by<N(byowner_name), eosio::const_mem_fun<project, account_name, &project::getowner_name> >> projecttable_type;
        projecttable_type projecttable;
};
EOSIO_ABI(License, (setuserinfo)(makeproject)(buylicense)(testlicense))

//License.cpp

#include <License.hpp>

void License::setuserinfo(account_name owner, const std::string& company_name, const std::string& contact_info){
    eosio::print("License::setuserinfo line 4");
    require_auth(owner);
    auto account_itr = accounts.find(owner);
    if(account_itr == accounts.end()){
        account_itr = accounts.emplace(_self, [&](auto& account){
            account.name = owner;
            account.company_name = company_name;
            account.contact_info = contact_info;
        });
    }
    else{
        accounts.modify(account_itr, 0, [&](auto& account) {
            account.company_name = company_name;
            account.contact_info = contact_info;
        });
    }
}

void License::makeproject(account_name owner, const std::string& project_name){
    require_auth(owner);
    //二级索引查找
    auto customer_index = projecttable.template get_index<N(byowner_name)>();
    account_name customer_acct = owner; //如果是string 可以用 eosio::string_to_name 转换
    auto cust_itr = customer_index.find(customer_acct);
    if (cust_itr != customer_index.end() && cust_itr->owner_name == customer_acct) {
        customer_index.modify(cust_itr, 0, [&](auto& project) {
            project.project_name = project_name;
            project.status = cust_itr->status; //初始化未授权,须另购买
            auto account_itr = accounts.find(owner);
            if(account_itr != accounts.end()){
                project.project_name = project_name;
                project.company_name = account_itr->company_name;
                project.contact_info = account_itr->contact_info;

            }
        });
    } 
    else{
        auto project_itr = projecttable.emplace(_self, [&](auto& project){
                project.owner_name = owner;
                project.project_name = project_name;
                auto account_itr = accounts.find(owner);
                if(account_itr != accounts.end()){
                    project.company_name = account_itr->company_name;
                    project.contact_info = account_itr->contact_info;
                    project.status = 0; //初始化未授权,须另购买
                }
            });
    }
}

void License::buylicense(account_name owner, const std::string& project_name){
    require_auth(owner);
    bool bFind = false;
    //二级索引查找
    auto customer_index = projecttable.template get_index<N(byowner_name)>();
    account_name customer_acct = owner; //如果是string 可以用 eosio::string_to_name 转换
    auto cust_itr = customer_index.find(customer_acct);
    while (cust_itr != customer_index.end() && cust_itr->owner_name == customer_acct) {
        if(cust_itr->project_name == project_name){
            if(cust_itr->status == 0){
                //TODO 判断当前账户余额,购买转账等操作
                customer_index.modify(cust_itr, 0, [&](auto& project) {
                    project.status = 1;
                });
            }
            else{
                eosio_assert(false, "The current project is authorized" );
            }
            bFind = true;
            break;
        }
        cust_itr++;
    } 
    eosio_assert(bFind, "owner with project not exists" );
}

void License::testlicense(account_name owner, const std::string& project_name){
    require_auth(owner);
    bool bFind = false;
    for( const auto& project : projecttable ) {
        if(project.project_name == project_name && project.owner_name == owner){
            eosio_assert((project.status == 1), "The current project is not authorized" );
            bFind = true;
            break;
        }
    }
    eosio_assert(bFind, "owner with project not exists" );
}

Github

零基础部署测试合约(一)---前准备

经过前面的三步

EOS 节点部署,BP出块(一)-->前期准备
EOS 节点部署,BP出块(二)-->节点连接
EOS 节点部署,BP出块(三)-->开始部署
已经完成了EOS链服务器相关配置,下面开始部署合约相关配置

  1. 打开eosio节点终端,创建dapp.token,dapp.exec账号
账号 公钥 私钥
dapp.token EOS7STj8j1LDXBVhttRm9FiyME1fDDn77UfjsFu1XQ2ybF2sYpwAM 5J87thFoJVD9fNos9i9QvLYFxZqCWMX4xJ3gGUGkweDbEn5WY2d
dapp.exec EOS5rzFj2sd4hmpAco8ujmDMDxZwWWTSvcS5BJYWpCcen6YbtNFAN 5JC9FdRjX3c3fsB62S5Tz22LgTuRHegb1XEV16uft8u3njmm9E5
//导入私钥
cleos wallet import 5J87thFoJVD9fNos9i9QvLYFxZqCWMX4xJ3gGUGkweDbEn5WY2d
cleos wallet import 5JC9FdRjX3c3fsB62S5Tz22LgTuRHegb1XEV16uft8u3njmm9E5
//创建账号
cleos system newaccount eosio dapp.token EOS7STj8j1LDXBVhttRm9FiyME1fDDn77UfjsFu1XQ2ybF2sYpwAM EOS7STj8j1LDXBVhttRm9FiyME1fDDn77UfjsFu1XQ2ybF2sYpwAM  --stake-net '50.00 SYS' --stake-cpu '50.00 SYS' --buy-ram-kbytes 10000
cleos system newaccount eosio dapp.exec EOS5rzFj2sd4hmpAco8ujmDMDxZwWWTSvcS5BJYWpCcen6YbtNFAN EOS5rzFj2sd4hmpAco8ujmDMDxZwWWTSvcS5BJYWpCcen6YbtNFAN  --stake-net '50.00 SYS' --stake-cpu '50.00 SYS' --buy-ram-kbytes 10000
//如果提示 Error 3080001: account using more than allotted RAM usage
cleos system buyram eosio dapp.token '100000.0000 SYS' -p eosio

部署测试合约(二)---合约编译
部署测试合约(三)---合约部署

零基础EOS 节点部署,BP出块(一)-->前期准备

事前准备

  1. 部署3台主机,账户名为(eosio,eosio.bp1,eosio.bp2),系统为Ubuntu 16.04以上版本
  2. 生成15个EOS地址 (10个系统预留账户,2个节点,3个用于投票)(在线生成
eosio eosio.token eosio.bpay eosio.msig eosio.names
eosio.ram eosio.ramfee eosio.saving eosio.stake eosio.upay
eosio.bp1 eosio.bp2 voter1 voter2 voter3
账户名 私钥 公钥
eosio 5KeqsXty9Sa8GfJgNfkckYxKKGcAWE4AWmUHiw6ifDcn3jjUg2i EOS5DkKbBZnSKNSV1iu27ovnygGhoCA99eH69KyNNkSkNrrbBoiRe
eosio.token 5JvL5wbJeQdgpKDDLRFUyWmHwBpRDgvARn99cS4pXoxZt8p7p4w EOS5M2sNqDPZtQoBcRMnPQEnY1MJaVtdWWPx7A3UpcLgtzdLusFVW
eosio.bpay 5KS9q4MPwmcpEM3rX96zR4A4FvLJZC9y1BZxvidaEwqfb4MWREx EOS5iezVa6bsmvZ3HNxdqgyX6GFRMWzE7FsjS3cui8Foavxnj8CfR
eosio.msig 5HsbhVhjtzeuzxdWKQv2MWBtbHzgjxEtYKQg9XB3cxPRYaC7r4m EOS8K1wkfCzPmxAjjfqvqw6zQ1Dbc82YsQyR8MmwNFLcRHcJtth89
eosio.names 5JrEru2K7FKLrwfLQ6B55PRWj2MXVkuXrLiurfn2osSatRsEmj6 EOS5ps938c5zj6UqhdCfssyAy7WSbHgfZoraqD6HrnbpmpEwPwX7S
eosio.ram 5HqNyZgePkdSZLuhz9YTi36L7HuhxpPeEEppNaB49Z7WcJWVsed EOS7DA8jGA6HfZXYcGSGJNsWJL5Q6t5bWcvm4zNykN3Jw7tASzBCR
eosio.ramfee 5KdYWerC5XnqfDhVV5igoyjuNFrT78McrErvbUMd36Wje77t6kJ EOS7R1Ds4zLMPN6onVXjL8XGgKHHCMWjLT7wn3bHcHnQX3dVLErjE
eosio.saving 5JN3GEXZVKYWAgbfdppvGU3hSpiu9BUcpEwpqMMp1NA6gvUsGF9 EOS6BDfFaFZgvx889BQbdaGTMYSn5tUuxaynGQDhpDGD662eBGwkF
eosio.upay 5Kgqr6jB6mfMjNv4vX1Hwj3KqiCxYUhPCnuxTK1mVN118fok4oG EOS7zS7sHctU54oD6is2oPfq11duCMSWfda3HXJAghSfqqr2BZZnV
eosio.bp1 5JzWCZ9W7VNWLYroQpjYG2z6H6UjJUkKdinZpumf6Ru2xoxSrKT EOS7mcXeVUSLCZxEf8eBPm2MbmiswNovoB6rk71pPqaZoxwSAeK7b
eosio.bp2 5HragVTsSmmAg1mznNMDSeAp2ZezcNBw6SbczrNpNtUqRcx4vhh EOS6hfh1yup4tZjbjhD3oPuZwMFqL4iUVehgMsukuvx5ojTWuurtT
voter1 5Jb2DtzYFU9c3LSEP5PPAfN7Je8d8yLGdDN42n561zy34UFwzTN EOS6wLrhcEQDZJvfZSCgVkFzsKcv34XTsTTjXXQZajWaBbEhvLPMg
voter2 5JsFet6W3Xmp3DvcHJsJ6GVcksSZJunGhmjpQaE9Np2ZtK4JYbc EOS6u8i7rknHyAd7AdziWSnEsAbyJHA3U9So4R8p2z58cA1KeEDv2
voter3 5JdQRPPCXtVLKBj5qhg6QtVq5PHuKoKnrcpePG6CsryPuYkiWX6 EOS8LyieKTsMAZGp7DSEhBPEPmPXvQKT5c3EXgEvACcdRwwRwDzoy

EOS 节点部署,BP出块(二)-->节点连接
EOS 节点部署,BP出块(三)-->开始部署