EOS智能合约开发系列(九): 高级权限设置

这是介绍EOS账户与权限的第二篇。上篇文章中,我们介绍了EOS的账户和权限这些概念,并介绍了一些权限设置的基本命令,包括如何自定义简单的权限。然而,EOS还有更为强大和灵活的权限自定义功能,还可以实现多重签名,本文就来介绍一下。

更灵活的自定义格式

还记得我们上篇文章中,自定义许可权限的命令吗?

cleos set account permission     -p accountname@active

这个命令中,我们使用的key,其实可以换成更多的东西,比如用一个JSON来描述的权限:

{
  "threshold"       : 100,    /*An integer that defines cumulative signature weight required for authorization*/
  "keys"            : [],     /*An array made up of individual permissions defined with an EOSIO-style PUBLIC KEY*/
  "accounts"        : []      /*An array made up of individual permissions defined with an EOSIO-style ACCOUNT*/
}

我们可以在其中指定多个keys,并给予不同的权重,我们也可以指定多个accounts,也同样可以设置不同的权重。注意threshold的值可以是任意整数值,具体设多少,可以自己随意设置,只要满足自己的需求就行;怎么样知道是否满足需求呢?继续往下阅读,读懂了你就明白了。

使用多个keys授权的例子

cleos set account permission tester trans '{"threshold": 2, "keys":[
  {"key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
  "weight":2},
  {"key":"EOS83sN8bfKGk3jTBezN41UN7LfXSVFa1w3YQcGApE67J26t3HLcr",
  "weight":2}
]}' active -p tester@active

这里我们使用的授权JSON是:

{
  "threshold": 2,
  "keys": [{
    "key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
    "weight": 2
  }, {
    "key": "EOS83sN8bfKGk3jTBezN41UN7LfXSVFa1w3YQcGApE67J26t3HLcr",
    "weight": 2
  }]
}

意思是,如果我把这里设定的许可权限授予了两个人,那么他们中的任何一个都可以以trans许可来签名交易。如果我们把trans许可关联了transfer action,那么也就意味这两个人中,任何一个人都可以进行转账交易。

如果你还没有把trans许可与eosio.token合约的 transfer action 关联起来,可以这么做(在执行下面命令以前,需要打开tester的key所在的钱包,如果你是跟着本系列文章来的,那么tester的key在default钱包里):

cleos set action permission tester eosio.token transfer trans

使用key固然挺好,但有一个缺点,就是太长了,太难记了。有没有更好的办法呢?有的,那就是用account,而且用account还有额外的好处。

使用多个账户名授权的例子

除了直接使用key以外,我们还可以使用多个账户名共同授权。使用账户名好处多,一方面,账户名要好记的多;另一方面,我们就不用关心key了,即便账户修改了active或者owner的许可,也对我们这个自定义的许可不会产生影响。

为了演示方便,以及为了后面演示多重签名的方便,我们先创建两个的钱包:bobwallet 和 carlwallet:

~ cleos wallet create -n bobwallet
Creating wallet: bobwallet
Save password to use in the future to unlock this wallet.
Without password imported keys will not be retrievable.
"PW5KKCuhViVgaP9MXLswpwDKPsXzcqfgeCuZHaHM8HuaUEV57fPHw"

~ cleos wallet create -n carlwallet
Creating wallet: carlwallet
Save password to use in the future to unlock this wallet.
Without password imported keys will not be retrievable.
"PW5KQyCcZp5QoMzp3kKSFkmizLe4mbG5vNBaG2VeD2815g2sp1DEG"

保存好钱包密码,我们创建两组key,并导入test钱包

~ cleos create key
Private key: 5KGnBSEAxmuhSJTLzsjTZie4hewMyToh4Mzq85pGDuzFRMQd9Yx
Public key: EOS8UTyktNUn4afScvYqMJ9JumGA27X7qmwgYpscwDoEHeFVYjDgb
~ cleos create key
Private key: 5KGhaQFuvPQjvKTR1VB1xpk8zUemgA2bXFL7hPVLx7PawNBUuKE
Public key: EOS7ufpQne6oXmanxvdoadmPkmfCT9rmtncML1tLRb7emgMrHgMBL


~ cleos wallet import --private-key 5KGnBSEAxmuhSJTLzsjTZie4hewMyToh4Mzq85pGDuzFRMQd9Yx -n carlwallet
imported private key for: EOS8UTyktNUn4afScvYqMJ9JumGA27X7qmwgYpscwDoEHeFVYjDgb
 ~ cleos wallet import --private-key 5KGhaQFuvPQjvKTR1VB1xpk8zUemgA2bXFL7hPVLx7PawNBUuKE -n bobwallet
imported private key for: EOS7ufpQne6oXmanxvdoadmPkmfCT9rmtncML1tLRb7emgMrHgMBL

如你所见,我们创建了两个key,一个导入了bobwallet钱包,一个导入了carlwallet钱包。

我们再创建两个账户bob和carl,他们分别拥有这两个key:

cleos create account user carl EOS8UTyktNUn4afScvYqMJ9JumGA27X7qmwgYpscwDoEHeFVYjDgb EOS8UTyktNUn4afScvYqMJ9JumGA27X7qmwgYpscwDoEHeFVYjDgb

cleos create account user bob EOS7ufpQne6oXmanxvdoadmPkmfCT9rmtncML1tLRb7emgMrHgMBL EOS7ufpQne6oXmanxvdoadmPkmfCT9rmtncML1tLRb7emgMrHgMBL

bob使用的是bobwallet钱包里的key,carl使用的是carlwallet钱包里的key。
我们这样做,是为了模拟这种情形:bob和carl这两个人有不同的钱包,并且他们都互相不知道对方的key。

现在我们考虑这么一个需求场景:tester用户拥有把自己账户的资金转出的权限。这不用说了,这是tester账户在被创建时就被赋予的权限;那么假如tester想把转账的权利赋予bob和carl呢?仅仅是转账的权力,其他的权力他想保留。那么它该怎么办呢?

你应该想到了本文开始时的例子了,我们当时用的key,很类似,对吧?我们现在可以直接用账户名了,可以这么做:

cleos set account permission tester trans '{"threshold": 2, "accounts":[
  {
    "permission":
      {"actor":"bob","permission":"active"},
      "weight":2
  },
  {"permission":
      {"actor":"carl","permission":"owner"},
      "weight":2}
]}' active -p tester@active

执行完成之后,我们看一下tester的账户情况:

~ cleos get account tester
permissions:
     owner     1:    1 EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
        active     1:    1 EOS83sN8bfKGk3jTBezN41UN7LfXSVFa1w3YQcGApE67J26t3HLcr
           trans     2:    2 bob@active, 2 carl@owner,
           vote     4:    3 EOS7LVbDSU3hMewm8F2sxXUNDFPCUmqNvpYJe4TCg58GJ9UW8bo3M, 1 EOS83sN8bfKGk3jTBezN41UN7LfXSVFa1w3YQcGApE67J26t3HLcr

可以看到trans许可的阀值(threshold)是2, bob@activecarl@owner这两个权限的权重也都是2,也就是说,他们中的任何一个都可以让执行trans权限,我们前面给trans关联的是eosio.token合约的transfer action,也就是说,bob和carl任何一个人都可以签名转账交易。刚好满足了tester想下放转账权限的需求。

我们来验证一下,我们先把所有的钱包都锁住。然后只解锁bobwallet,然后用bob@active对tester账户进行转账,可参考上一篇内容:

~ cleos wallet lock_all
Locked All Wallets
~ cleos wallet unlock -n bobwallet
password: Unlocked: bobwallet

~ cleos push action eosio.token transfer \
        '[ "tester", "user", "0.5000 SYS", "2 you know how much i love you" ]' -p tester@trans
executed transaction: 052dd5ee257b1760a48e906e8fe1b345cbcc6b1dbadcd1c29cf85936c252f220  160 bytes  7942 us
#   eosio.token <= eosio.token::transfer        {"from":"tester","to":"user","quantity":"0.5000 SYS","memo":"2 you know how much i love you"}
#        tester <= eosio.token::transfer        {"from":"tester","to":"user","quantity":"0.5000 SYS","memo":"2 you know how much i love you"}
#          user <= eosio.token::transfer        {"from":"tester","to":"user","quantity":"0.5000 SYS","memo":"2 you know how much i love you"}

如你所见,成功了。你可以试试把所有的钱包都关闭,然后打开carlwallet,然后再执行上面的转账操作,你会发现也是成功的。
不知道你有没有发现,这个转账命令,其实无需指定你用那个钱包或者用哪个key签名,cleos自动从已经解锁的钱包里找出符合条件的key对交易进行签名,所以我们只需要打开拥有相应key的钱包就可以了。

你可能会说,感觉这个东西太复杂,用处也不是很大,不就是可以把账户的某些操作放权嘛。其实,这里的放权,只是其中一个功能;我想你应该也想到了一些,比如,如果我把每个用户的权重改的小一些,小于threshold,会怎么样?
你能想到这一点,说明你很聪明,这就是多重签名了,我们后面继续讲解。

简介:不羁,一名程序员;专研EOS技术,玩转EOS智能合约开发。
微信公众号:know_it_well
知识星球地址:https://t.zsxq.com/QvbuzFM

你可能感兴趣的:(EOS智能合约开发系列(九): 高级权限设置)