RChain Powerbox Summary

Darryl Neudorf
RChain-China
Published in
7 min readNov 13, 2020

RChain Powerbox Summary

August 11, 2020 — Originally posted in Chinese here by Dimworm.

The Powerbox is the RChain system-level channel through which Rholang smart contract developers can invoke system resources. the Powerbox layer sits between the system’s physical resources and the Rholang code, and is used to handle requests such as disk IO and network, and access requests to RSpace via the The Powerbox layer.

The Powerbox model is borrowed from the Object Capability (“OCaps”) Security Model, where the Powerbox acts as an arbiter of privilege transfer and combines multiple privilege management in one place. When a subsystem needs a new permission, the Powerbox decides whether to grant it or not.

There are 29 Powerboxes in this article for developers to use.

First category, screen IO related
Includes the following five.

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

The other three are similar. stdout outputs to the screen, and stdoutAck generates an acknowledgement signal to trigger other events.

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

Category 2, Deploy related

Includes the following five.

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

Smart Contracts can get information from the system during the deployment of Smart Contracts and out of blocks.

rho:rchain:deployId returns the current deployable smart contract’s deployId.

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

rho:rchain:deployerId can return the deployerId of the current smart contract deployer.

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

rho:rchain:deployerId:ops Receives a deployerId, which returns the public key of the deployer. The following example returns the address of the REV wallet corresponding to the current smart contract deployer.

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) | | DeployerIdOps!
for (@deployerPubKeyBytes <- deployerPubKeyBytesCh) {
RevAddress!("fromPublicKey", deployerPubKeyBytes, *revAddrCh) | | RevAddress!
for (@deployerRevAddress <- revAddrCh) {
stdout!(deployerRevAddress)
}
}
}

rho:block:data can return the BlockNumber, timestamp, and deployerId of the block that the smart contract is currently deployed.

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

rho:deploy:params This parameter was used in some version of PoS.rhox and has been removed in anticipation of discovering related information.

The third type, currency related
Including the following four.

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

REV differs from ETH in that ETH is a native coin on ethereum and there is no coin on RChain, REV is generated by way of a smart contract and should be called a token. The advantage of REV is that it has the same business logic as other tokens on the RChain mainnet and can be interoperated through smart contracts, whereas ETH is There is no such capability. That’s why tokens like WETH exist on ethereum.

rho:rchain:makeMint This smart contract can cast the token for you, and REV is cast by this smart contract.

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

To understand the basic concepts of Vault and Purse you can see here: https://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

Note: REV can be accurate to 8 decimal places. REV can only be expressed as an integer on the chain, and the REV balance should be divided by 10⁸.

rho:rchain:revVault interacts with REV’s smart contract to initiate activities such as creating new wallets, transferring funds, etc.
The following code is used to query the wallet address balance.

rho:rchain:revVault
rl(rho:registry:lookup), RevVaultCh,
vaultCh, balanceCh,
stdout(rho:io:stdout)
in {

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

}

}

Other operations, such as transfers, can be found at https://github.com/rchain/rchain/blob/0a6ffe0826e56707d32b6b7348b3d29c345692ed/casper/src/main/resources/RevVault. .rho

rho:rev:address can generate REV addresses from both the public key and Unforgeable name.

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

rho:rchain:multiSigRevVault Used to generate multi-signature wallets, we will write an article specifically about this code, multi-signature wallet smart contract code.
https://github.com/rchain/rchain/blob/d581015a2ed5c81aa92f1f31e8efcef14e0c4fff/casper/src/main/resources/MultiSigRevVault.rho

Category IV, Competence-related
Including the following three.

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

rho:rchain:authKey AuthKey is used to create an authorized token, AuthKey provides make and check methods. make method formulates the unforgeable name as “shape” to ensure no leakage. unforgeable name.
We will write an article about AuthKey.
AuthKey’s code: https://github.com/rchain/rchain/blob/d0a3dd737828eca8ec9320b7d590d5421567879f/casper/src/main/resources/AuthKey.rho

sys:authToken:ops This application is found in the PoS.rhox code and should be used to check if the call is from the system. See also.
https://github.com/rchain/rchain/blob/0a6ffe0826e56707d32b6b7348b3d29c345692ed/casper/src/main/resources/PoS.rhox


sysAuthTokenOps!(“check”, sysAuthToken, *isValidTokenCh) | sysAuthTokenOps!
for (@isValid <- isValidTokenCh) {
if (isValid) {

}

rho:rchain:pos makes a call to the PoS smart contract.
The following example is from https://github.com/rchain/rchain/blob/e70f4c1d3660b155718a9d084993f25a64c9a76a/rholang/examples/bond/bond.rho successfully completed once Validator’s Binding.

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

Category V, Data Structures
Including the following four.

rho:lang:either

rho:lang:listOps

rho:lang:nonNegativeNumber

rho:lang:treeHashMap

Either Either is a data type borrowed from scala, and is used in scenarios where there are two possible outcomes. Eitehr is also more complex, and we are preparing an article to explain it.
https://github.com/rchain/rchain/blob/0a6ffe0826e56707d32b6b7348b3d29c345692ed/casper/src/main/resources/Either.rho

rho:lang:listOps for arrays of operations on chains
https://github.com/rchain/rchain/blob/582247cf1e2e4c93f8bae59cb040168ae2c38021/casper/src/main/resources/ListOps.rho

rho:lang:nonNegativeNumber
Add and multiply non-negative numbers to prevent overflow.

rho:lang:treeHashMap TreeHashMap TreeHashMap is also a data type borrowed from scala, used to improve the speed of data insertion or query on the chain. We specialize in preparing an article about TreeHashMap. TreeHashMapr related code: https://github.com/rchain/rchain/blob/582247cf1e2e4c93f8bae59cb040168ae2c38021/casper/ src/main/resources/TreeHashMap.rho

Category VI, registration-related
Including the following four.

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

rho:registry:insertArbitrary The following example registers a newContract on the chain:

new newContract, uriChan,
insertArbitrary(rho:registry:insertArbitrary),
stdout(rho:io:stdout)
in {
contract newContract(@a) = {

}|
insertArbitrary!(bundle+{*newContract} , *uriChan) | insertArbitrary!
for(@uri <- uriChan) {
stdout!(uri)
}
}

rho:registry:lookup The following example finds the contract for newContract from the chain and triggers.

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

rho:registry:ops The following example uses a string to generate rho:id.

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

Category VII, test-related
Including the following four.

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

We don’t usually use test classes, we’ll introduce them when we get a chance.

Welcome to “Rholang Chinese Community” public website.

Developers are welcome to join “RChain Developers” WeChat group. Please add lowbird WeChat to join the group. Non-developers please do not join, there will be a round of testing, and only those who pass will be admitted.

愁虫

愁虫

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的基本概念可以看这里:https://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⁸。

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 用于生成多重签名钱包,我们会专门写文章介绍这部分代码,多重签名钱包智能合约的代码:

https://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的代码:https://github.com/rchain/rchain/blob/d0a3dd737828eca8ec9320b7d590d5421567879f/casper/src/main/resources/AuthKey.rho

sys:authToken:ops 这个应用是在PoS.rhox的代码里发现的,应该是用于检查是否是来自系统的调用。请参见:
https://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情况也比较复杂,我们专门准备一篇文章讲解。

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

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

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

rho:lang:treeHashMap TreeHashMap也是借鉴于scala的一个数据类型,用于提高链上数据插入或查询的速度。我们专门做准备一篇文章介绍TreeHashMap。TreeHashMapr的相关代码:https://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微信,拉你入群。非开发者请勿加,会有一轮测试,通过者方可入群

--

--