• 2020年8月10日 20:22

    Powerbox 是RChain系统级的channel,通过Powerbox,Rholang智能合约开发者可以调用系统资源。Powerbox层位于系统物理资源和Rholang代码之间,用于处理磁盘IO和网络等请求,对RSpace的访问请求也要通过Powerbox层。

    Powerbox 模式是从 Object Capability ("OCaps") Security Model 借鉴过来的,Powerbox 作为权限转移的仲裁者, 将多样化的权限管理集于一身。 当子系统需要新的权限时,由Powerbox决定是否授予。

    本文整理了29个Powerbox,方便开发者调用,如有遗漏请指出。

    第一类,屏幕IO相关
    包括以下5个:

    `rho:io:stdout`
    `rho:io:stdlog`
    `rho:io:stdoutAck`
    `rho:io:stderr`
    `rho:io:stderrAck`
    

    stdoutstdoutAck 为例简单介绍使用方法,其它三个类似。stdout向屏幕输出;stdoutAck向屏幕输出的同时产生一个确认信号,用以触发其它事件。

    new myAckChannel,
    stdout(`rho:io:stdout`),
    stdoutAck(`rho:io:stdoutAck`) in {
      stdoutAck!("Print some words.", *myAckChannel)|
      for (acknowledgement <- myAckChannel) {
        stdout!("Received an acknowledgement.")
      }
    }
    

    第二类,deploy相关

    包括以下5个:

    `rho:rchain:deployId`
    `rho:rchain:deployerId`
    `rho:rchain:deployerId:ops`
    `rho:block:data`
    `rho:deploy:params`
    
    

    在部署智能合约和出块的过程中,智能合约可以从系统得到相应信息。

    rho:rchain:deployId 能够返回当前部署的智能合约的deployId.

    new deployId(`rho:rchain:deployId`),
      stdout(`rho:io:stdout`) 
    in {
      stdout!(*deployId)
      }  
    
    

    rho:rchain:deployerId 能够返回当前智能合约的部署者的deployerId.

    new deployerId(`rho:rchain:deployerId`),
      stdout(`rho:io:stdout`) 
    in {
      stdout!(*deployerId)
      }  
    

    rho:rchain:deployerId:ops 接收一个deployerId, 返回部署者的公钥。下面的例子返回了当前智能合约部署者对应的REV钱包地址。

    new RevAddress(`rho:rev:address`), DeployerIdOps(`rho:rchain:deployerId:ops`),
      deployerId(`rho:rchain:deployerId`), stdout(`rho:io:stdout`),
      revAddrCh, deployerPubKeyBytesCh
    in {
      DeployerIdOps!("pubKeyBytes", *deployerId, *deployerPubKeyBytesCh) |
      for (@deployerPubKeyBytes <- deployerPubKeyBytesCh) {
        RevAddress!("fromPublicKey", deployerPubKeyBytes, *revAddrCh) |
        for (@deployerRevAddress <- revAddrCh) {
          stdout!(deployerRevAddress)
        }
      }
    }  
    

    rho:block:data 能够返回当前智能合约部署的区块的BlockNumber, 时间戳和deployerId.

    new retCh, getBlockData(`rho:block:data`), stdout(`rho:io:stdout`) in {
      getBlockData!(*retCh) |
      for (@blockNumber, @timestamp, @sender <- retCh) {
        stdout!((blockNumber, timestamp, sender))
      }
    }  
    

    rho:deploy:params 该参数曾用于PoS.rhox的某个版本,现已去掉,期待能发现相关资料。

    第三类,货币相关
    包括以下4个:

    `rho:rchain:makeMint`
    `rho:rchain:revVault`
    `rho:rev:address`
    `rho:rchain:multiSigRevVault`
    

    REV与ETH不同的地方在于,ETH是以太坊上原生的coin,而在RChain上没有coin,REV是通过智能合约的方式生成的,应该称为Token。 REV的好处是与其它RChain主网上的Token拥有相同的业务逻辑,通过智能合约可以进行互操作,而ETH就没有这个能力。这也是为什么以太坊上会存在WETH这样的Token.

    rho:rchain:makeMint 这个智能合约可以帮你铸造Token,REV就是通过这个智能合约铸造的。

    new MakeMintCh, stdout(`rho:io:stdout`),
      rl(`rho:registry:lookup`)
    in {
      rl!(`rho:rchain:makeMint`, *MakeMintCh) |
      for (@(_, MakeMint) <- MakeMintCh){
        new mintCh in {
          @MakeMint!(*mintCh) |
          for (mint <- mintCh) {
            new purseCh in {
              mint!("makePurse", 9999999999999, *purseCh) |
              for (purse <- purseCh) {
                stdout!(*purse)
              }
            }
          }
        }    
      }
    }  
    

    想要了解Vault和Purse的基本概念可以看这里:rchain.atlassian.net/wiki/spaces/CORE/pages/652640311/Wallet+proposal+Note+we+decided+to+rename+terms+such+that+wallet+is+not+used+for+on-chain+components

    注:REV可精确到小数点后8位。REV在链上只能以整数表示,REV余额要除以10^8。

    rho:rchain:revVault 与REV的智能合约互动,发起创建新钱包,转账等活动。
    下面的代码用于查询钱包地址余额。

    new
      rl(`rho:registry:lookup`), RevVaultCh,
      vaultCh, balanceCh,
      stdout(`rho:io:stdout`)
    in {
    
      rl!(`rho:rchain:revVault`, *RevVaultCh) |
      for (@(_, RevVault) <- RevVaultCh) {
        match "%REV_ADDR" {
          revAddress => {
            stdout!(("Accessing vault at RevAddress", revAddress)) |
            @RevVault!("findOrCreate", revAddress, *vaultCh) |
            for (@(true, vault) <- vaultCh) {
              @vault!("balance", *balanceCh) |
              for (@balance <- balanceCh) {
                stdout!(("Balance is", balance))
              }
            }
          }
        }
    
      }
    
    }
    

    其它诸如转账等操作,详细信息可参考https://github.com/rchain/rchain/blob/0a6ffe0826e56707d32b6b7348b3d29c345692ed/casper/src/main/resources/RevVault.rho

    rho:rev:address 可以从公钥和Unforgeable name两种形式生成REV地址。

    new a, RevAddress(`rho:rev:address`), revAddr1Ch, revAddr2Ch,
    stdout(`rho:io:stdout`) in {
      RevAddress!("fromUnforgeable", *a, *revAddr1Ch) |
      RevAddress!("fromPublicKey", "xxx", *revAddr2Ch) |
      for (@unforgeableRevAddress <- revAddr1Ch) {
        stdout!(("Rev address from Unforgeable name: ", unforgeableRevAddress))
      }|
      for (@deployerRevAddress <- revAddr2Ch) {
        stdout!(("Rev address from pub key: ", deployerRevAddress))  
      }
    }  
    

    rho:rchain:multiSigRevVault 用于生成多重签名钱包,我们会专门写文章介绍这部分代码,多重签名钱包智能合约的代码:

    github.com/rchain/rchain/blob/d581015a2ed5c81aa92f1f31e8efcef14e0c4fff/casper/src/main/resources/MultiSigRevVault.rho

    第四类,权限相关
    包括以下3个:

    `rho:rchain:authKey`
    `sys:authToken:ops`
    `rho:rchain:pos`
    
    

    rho:rchain:authKey AuthKey用于创建一个授权token,AuthKey提供make和check两个方法,make方法将unforgeable name配制成“shape”,以保证不会泄漏unforgeable name。
    我们会专门写一篇文章讲解AuthKey。
    AuthKey的代码:github.com/rchain/rchain/blob/d0a3dd737828eca8ec9320b7d590d5421567879f/casper/src/main/resources/AuthKey.rho

    sys:authToken:ops 这个应用是在PoS.rhox的代码里发现的,应该是用于检查是否是来自系统的调用。请参见:
    github.com/rchain/rchain/blob/0a6ffe0826e56707d32b6b7348b3d29c345692ed/casper/src/main/resources/PoS.rhox

    ...
    sysAuthTokenOps!("check", sysAuthToken, *isValidTokenCh) |
    for (@isValid <- isValidTokenCh) {
        if (isValid) {
            ...
        } 
    ...    
    

    rho:rchain:pos 对PoS智能合约进行调用,
    下面这个例子来自于https://github.com/rchain/rchain/blob/e70f4c1d3660b155718a9d084993f25a64c9a76a/rholang/examples/bond/bond.rho 成功完成一次Validator的绑定:

    new retCh, PoSCh, rl(`rho:registry:lookup`), stdout(`rho:io:stdout`) in {
      stdout!("About to lookup pos contract...") |
      rl!(`rho:rchain:pos`, *PoSCh) |
      for(@(_, PoS) <- PoSCh) {
        stdout!("About to bond...") |
        new deployerId(`rho:rchain:deployerId`) in {
          @PoS!("bond", *deployerId, 100, *retCh) |
          for ( @(true, message) <- retCh) {
            stdout!("Successfully bonded!")
          }
        }
      }
    }
    

    第五类,数据结构类
    包括以下4个:

    #`rho:lang:either`
    #`rho:lang:listOps`
    #`rho:lang:nonNegativeNumber`
    #`rho:lang:treeHashMap`
    

    rho:lang:either Either是借鉴自scala的数据类型,适用于可能会出现两种结果的场景。有Left, Right两个子类型。Eitehr情况也比较复杂,我们专门准备一篇文章讲解。

    github.com/rchain/rchain/blob/0a6ffe0826e56707d32b6b7348b3d29c345692ed/casper/src/main/resources/Either.rho

    rho:lang:listOps 用于链上的数组操作
    github.com/rchain/rchain/blob/582247cf1e2e4c93f8bae59cb040168ae2c38021/casper/src/main/resources/ListOps.rho

    rho:lang:nonNegativeNumber
    用于非负数的加法和乘法,防止overflow

    rho:lang:treeHashMap TreeHashMap也是借鉴于scala的一个数据类型,用于提高链上数据插入或查询的速度。我们专门做准备一篇文章介绍TreeHashMap。TreeHashMapr的相关代码:github.com/rchain/rchain/blob/582247cf1e2e4c93f8bae59cb040168ae2c38021/casper/src/main/resources/TreeHashMap.rho

    第六类,注册相关
    包括以下4个:

    `rho:registry:insertArbitrary`
    `rho:registry:insertSigned:secp256k1`
    `rho:registry:lookup`
    `rho:registry:ops`
    

    rho:registry:insertArbitrary 下面例子在链上注册newContract:

    new newContract, uriChan, 
      insertArbitrary(`rho:registry:insertArbitrary`),
      stdout(`rho:io:stdout`) 
    in {
      contract newContract(@a) = {
        ...
      }|
      insertArbitrary!(bundle+{*newContract}  , *uriChan) |
      for(@uri <- uriChan) {
        stdout!(uri)
      }
    }
    

    rho:registry:lookup 下面例子从链上找到newContract的合约并触发:

    new newContractCh,
      rl(`rho:registry:lookup`), 
      stdout(`rho:io:stdout`)
    in {
      rl!(`rho:id:xxx`, *newContractCh) |
      for (newContract <- newContractCh) {
        newContract!("123")
      }
    }    
    

    rho:registry:ops 下面的例子是用字符串生成rho:id :

    new registryOps(`rho:registry:ops`), retCh,
      stdout(`rho:io:stdout`)
    in {
      registryOps!("buildUri", "foo".toByteArray(), *retCh) |
      for (@ret <- retCh){
        stdout!(ret)
      }
    }
    

    第七类,测试相关
    包括以下4个:

    `rho:test:deploy:set`
    `rho:test:assertAck`
    `rho:test:testSuiteCompleted`
    `rho:test:deployerId:make`
    

    测试类我们一般用不到,找机会再介绍。


    欢迎关注 “Rholang中文社区” 公众号

    欢迎开发者加入 “RChain开发者” 微信群。加群请加lowbird微信,拉你入群。非开发者请勿加,会有一轮测试,通过者方可入群。