• 2020年9月30日 20:21

    我们来发行一个自己的币吧,我先抛个砖,一个游戏币:Bullet 子弹币。

    Bullet的发行

    如果你向Bullet的智能合约打10000个REV,你就能马上得到200个Bullet,比例是2%,这个打币的过程可以叫做质押。
    质押的时间是100天。100天后,你向智能合约发起提币,10000个REV打回到你原来的钱包里。
    目前运行在测试网上,质押时间暂定为一天。一天后可以提币。

    Bullet的使用

    Bullet有什么用呢?可以用来打游戏。前提是游戏dApp的开发者愿意选用Bullet作为自己的游戏币。
    为什么游戏开发者要选用Bullet? 因为Bullet完全由智能合约控制,并且没有后门。游戏开发者使用Bullet没有成本。

    Bullet有什么好处

    1. 对REV质押挖矿的人来说,多了一个选择。可以质押给节点挖REV,也可以打到Bullet的智能合约里挖Bullet
    2. Bullet的利率和REV的年利率7%差不多
    3. Bullet能够锁定不少REV,有助于REV的价格稳定

    Bullet的下一步规划

    目前Bullet智能合约部署在测试网上进行测试,合适的时候会转到主网。为了证明Bullet的工作原理可行,并且帮助建立Bullet的生态,我打算在锐Rui钱包里集成对Bullet的支持,包括转账、质押、提币等,甚至可能包括Bullet的交易。第二,打算把老母鸡(Oldhen)游戏跑起来,大家就可以用Bullet打游戏了。

    如何测试

    在不跑节点的情况下,目前最好的测试方法是通过RNode client testing page( tgrospic.github.io/rnode-client-js/ )。
    我还在尝试Dappy,没有成功,有一些问题没解决。

    BulletVault在测试网的地址是:
    rho:id:auz8oqkczecbiq7jmeeeoyackumqybo4pijfec3rnjccwz6mhtqr9t

    质押币的大池子地址是:11112QLdkH7gj4KmJbZSG45jLpFMd9i7pQ2YZKk6iSkPVFJGb8mUro
    不要向大池子直接打测试币,必须通过调用deposit函数才能触发Bullet铸币。

    下面开始技术讲解:

    代码库:github.com/dimworm/Bullet

    基本概念

    Purse: 是REV存放的地方,REV在purse里放着,REV不能离开Purse。 所谓REV转账,其实就是Purse的来回移动。

    Vault: 就是Purse存放的地方,可以是一个公钥,也可以是一个Unforgeable Name, 比如多重签名钱包。
    Purse和Vault不同于我们理解的钱包Wallet,Wallet是私钥存储的地方,在链下。而Purse和Vault是链上概念。

    REV Mint: 通过生成Purse的方式铸币。

    用到了哪些库

    RevAddress(`rho:rev:address`) // 生成钱包地址
    deployerId(`rho:rchain:deployerId`)  //获得调用者的deployerId
    deployId(`rho:rchain:deployId`) //获得调者的deployId,因为部署于链上的智能合约不适合使用stdout显示运行结果,故采用deployId作为信息返回通道。
    DeployerIdOps(`rho:rchain:deployerId:ops`) //用于从调用者的公钥计算出其REV钱包地址。
    blockData(`rho:block:data`) //获得调用者的出块时间戳
    insertArbitrary(`rho:registry:insertArbitrary`) //在链上注册智能合约
    rl!(`rho:rchain:makeMint`, *MakeMintCh)  //铸币智能合约
    rl!(`rho:rchain:authKey`, *AuthKeyCh) //鉴权智能合约
    rl!(`rho:lang:either`, *EitherCh) //Either是一种数据类型,用于处理异常
    rl!(`rho:lang:treeHashMap`, *TreeHashMapCh) //TreeHashMap是一种数据结构,用于提高数据的读写效率
    rl!(`rho:rchain:revVault`, *RevVaultCh) //REV的智能合约
    

    如何存储

    采用了两个TreeHashMap,一个用于存储Bullet的所有钱包账户信息,另一个用于存储打入的REV的账户信息。

              // mapstore for depositing REV
              TreeHashMap!("init", 2, *revMapStore) 
              // mapstore for bullet token
              TreeHashMap!("init", 2, *bulletMapStore)
    

    5d5d9aaf019c236642391a29fd52baeb.png

    REV大池子

    REV质押在一个智能合约大池子里,任何人没有权限动用。方法是生成一个新的Unforgeable name,基于此生成一个钱包地址。好处是该钱包地址没有对应任何私钥,所以没人能够设置后门。

     RevAddress!("fromUnforgeable", *unf, *revHouseAddrCh) |
     for (@revHouseVaultAuthKey <- authKeyCh;  @revHouseAddr <- revHouseAddrCh) {
       ...
     }
    

    如何鉴权

    采用authKey对每一个调用者的身份进行鉴权,在key的生成过程中,加入了一个“环境变量”,为了防止黑客将key偷出。

      rl!(`rho:rchain:authKey`, *AuthKeyCh) |
      for (@(_, AuthKey)  <- AuthKeyCh}
        ...
        @AuthKey!("make", (*_bulletVault, deployerRevAddress), *ret)
        ...
        @AuthKey!("check", *authKey, (*_bulletVault, ownRevAddress), *authKeyValidCh) 
        ...
     }    
    
    

    如何发行

    任何人调用deposit函数,质押一定数量的REV都可以得到Bullet。deposit函数会从用户REV账户里扣取REV,并更新revMap总账本,成功后,即打出相应数量的Bullet到用户账户。

    contract BulletVault(@"deposit", @amount, retCh) = {
      ...
    }
    

    如何提币

    100天后,目前在测试网是1天,用户可以调用withdraw函数,程序检查时间跨度是否满足要求,合格后即打回原有REV。

    contract BulletVault(@"withdraw", retCh) = {
      ...
    }
    

    智能合约如何判断时间

    在用户调用时,从blockData返回三个参数,中间的参数就是timestamp。

    new blockData(`rho:block:data`), tCh in {
      blockData!(*tCh) |
      for (@_, @t, @_ <- tCh) {
        stdout!(["Current timestamp is: ",t])
      }
    
    
    

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

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

    5d5d9aaf019c236642391a29fd52baeb.png

    PNG, 66.1 KB, 被 Dimworm上传于2020年9月30日