RSA随机区块链

有一个问题-在分散的网络中很难生成随机数。 几乎所有的区块链都已经遇到了这种情况。 实际上,在用户之间没有信任的网络中,创建不可否认的随机数可以解决许多问题。

本文介绍了如何以游戏为例解决问题。 其中第一个是Waves Xmas Tree 。 为了进行开发,我们需要一个随机数生成器。



最初,我们计划根据来自区块链的信息生成一个数字。 但是,事情变得很清楚:可以操纵该数字,这意味着解决方案不合适。

我们想出一种解决方法:使用提交披露方案。 服务器“猜测”一个从1到5的数字,并在其中添加“盐”,然后使用Keccak函数对结果进行哈希处理 。 服务器预先部署了一个已保存编号的智能合约。 事实证明,该游戏被简化为用户猜测哈希隐藏的数字的事实。

玩家下注,服务器将请求的号码和“盐”发送到智能合约。 他用通俗的语言透露了卡片。 之后,服务器验证数字并确定用户是赢还是输。

如果服务器未发送数字或“盐”进行验证,则用户将获胜。 在这种情况下,对于每款游戏,必须事先部署智能合约并在其中赢得潜在收益。 事实证明,这是不便的,漫长且昂贵的。 当时,没有其他安全的解决方案。

最近,Tradisys团队建议将rsaVerify()函数添加到Waves协议中。 它根据公钥和私钥验证RSA签名的有效性。 结果,增加了功能。

我们开发了三款游戏: 骰子滚轮投币翻转乘风破浪 。 每种都实现了随机数技术。 让我们看看它是如何工作的。



考虑使用“乘波”生成随机数。 可以在这里找到智能合约。

转到“ 脚本”标签,然后选择“ 反编译” 。 请参阅智能合约的代码(又名脚本)。



智能合约代码包含一组功能。 那些标记为@Callable的变量可以使用调用事务触发。 我们对以下两个功能感兴趣: betwithdraw

  • 功能投注(playerChoice)
  • 功能撤回(gameId,rsaSign)

1.用户选择分段的长度和下注的大小。



2.客户形成下注功能。 对于上面的图像,这将是下注(“ 50”)

3.客户端将调用事务发送到智能合约的地址(广播InvocationTx)。 作为Call参数的交易包含bet函数。 这意味着调用事务开始在智能合约上执行下注功能(选择:字符串)。



4.考虑下注功能:

@Callable(i) func bet (playerChoice) = { let newGameNum = IncrementGameNum() let gameId = toBase58String(i.transactionId) let pmt = extract(i.payment) let betNotInWaves = isDefined(pmt.assetId) let feeNotInWaves = isDefined(pmt.assetId) let winAmt = ValidateBetAndDefineWinAmt(pmt.amount, playerChoice) let txIdUsed = isDefined(getString(this, gameId)) if (betNotInWaves) then throw ("Bet amount must be in Waves") else if (feeNotInWaves) then throw ("Transaction's fee must be in Waves") else if (txIdUsed) then throw ("Passed txId had been used before. Game aborted.") else { let playerPubKey58 = toBase58String(i.callerPublicKey) let gameDataStr = FormatGameDataStr(STATESUBMITTED, playerChoice, playerPubKey58, height, winAmt, "") ScriptResult(WriteSet(cons(DataEntry(RESERVATIONKEY, ValidateAndIncreaseReservedAmt(winAmt)), cons(DataEntry(GAMESCOUNTERKEY, newGameNum), cons(DataEntry(gameId, gameDataStr), nil)))), TransferSet(cons(ScriptTransfer(SERVER, COMMISSION, unit), nil))) } } 

该功能将新游戏写入智能合约状态。 即:

  • 新游戏的唯一标识符(游戏ID)
  • 游戏状态=已提交
  • 球员选择(线长50)
  • 公钥
  • 潜在的奖金(取决于玩家的赌注)



这就是区块链中数据记录的样子(键值):

 { "type": "string", "value": "03WON_0283_448t8Jn9P3717UnXFEVD5VWjfeGE5gBNeWg58H2aJeQEgJ_06574069_09116020000_0229", "key": "2GKTX6NLTgUrE4iy9HtpSSHpZ3G8W4cMfdjyvvnc21dx" } 

“键”(键)-新游戏的游戏ID 。 其余数据包含在“值”(值)字段的行中。 这些条目存储在智能合约的“ 数据”选项卡中:





5.服务器“查看”智能合约,并使用区块链Api查找发送的交易(新游戏)。 新游戏的游戏ID已记录在区块链上,这意味着不再可能更改或影响它

6.服务器形成一个撤回功能(gameId,rsaSign)。 例如,这:

 withdraw ("FwsuaaShC6DMWdSWQ5osGWtYkVbTEZrsnxqDbVx5oUpq", "base64:Gy69dKdmXUEsAmUrpoWxDLTQOGj5/qO8COA+QjyPVYTAjxXYvEESJbSiCSBRRCOAliqCWwaS161nWqoTL/TltiIvw3nKyd4RJIBNSIgEWGM1tEtNwwnRwSVHs7ToNfZ2Dvk/GgPUqLFDSjnRQpTHdHUPj9mQ8erWw0r6cJXrzfcagKg3yY/0wJ6AyIrflR35mUCK4cO7KumdvC9Mx0hr/ojlHhN732nuG8ps4CUlRw3CkNjNIajBUlyKQwpBKmmiy3yJa/QM5PLxqdppmfFS9y0sxgSlfLOgZ51xRDYuS8NViOA7c1JssH48ZtDbBT5yqzRJXs3RnmZcMDr/q0x6Bg==") 

7.服务器将调用事务发送到智能合约(广播的InvocationTx)。 交易包含对生成的提现函数(gameId,rsaSign)的调用:



该函数包含新游戏的游戏ID和带有私钥的唯一标识符的RSA签名结果。 签名的结果不变。

这是什么意思?

我们采用相同的值(游戏ID),并对其应用RSA签名方法。 我们将始终获得相同的结果。 RSA算法就是这样工作的。 您无法操纵最终号码,因为游戏ID和使用RSA的结果未知。 匹配数字也没有意义。

8.区块链接受交易。 运行撤回功能(gameId,rsaSign)

9.在提现函数中, GenerateRandInt函数 (gameId,rsaSign)被导出。 这是一个随机数生成器


 # @return 1 ... 100 func GenerateRandInt (gameId,rsaSign) = { # verify RSA signature to proof random let rsaSigValid = rsaVerify (SHA256, toBytes(gameId), rsaSign, RSAPUBLIC) if (rsaSigValid) then { let rand = (toInt(sha256(rsaSign)) % 100) if ((0 > rand)) then ((-1 * rand) + 1) else (rand + 1) } else throw ("Invalid RSA signature") } 

rand-并且有一个随机数。

首先,获取一个字符串,该字符串是使用私钥( rsaSign )对游戏ID进行 RSA签名的结果。 然后使用SHA-256( sha256(rsaSign) )对其进行哈希处理

我们无法预测签名和后续哈希的结果。 因此,不可能影响随机数的产生。 要获取一定范围内的数字(例如1到100),请使用toInt和%100转换函数(类似于mod )。

在本文的开头,我们提到了rsaVerify()函数,该函数使您可以通过公钥使用私钥来检查RSA签名的有效性。 这是GenerateRandInt(gameId,rsaSign)部分:

 rsaVerify (SHA256, toBytes(gameId), rsaSign, RSAPUBLIC) 

RSAPUBLIC公共密钥和rsaSign字符串传递到输入。 检查签名的有效性。 如果检查成功,将生成一个数字。 否则,系统认为签名无效(无效的RSA签名)。

服务器必须使用私钥对游戏ID进行签名,并在2880个块内发送有效的Rsa签名。 部署智能合约时配置该参数。 如果在分配的时间内没有任何反应,则用户获胜。 在这种情况下,奖品必须自己发送到您的地址。 事实证明,服务器“作弊不赚钱”,因为这会导致损失。 下面是一个例子。



用户玩骰子滚子 。 我从立方体的6个面中选择2个,下注为14 WAVES。 如果服务器未在设置的时间内(2880块)在智能合约上发送有效的RSA签名,则用户将进行34.44次WAVES。

为了在游戏中生成数字,我们使用了oracle-一个外部的,非阻塞的系统。 服务器实现游戏ID的RSA签名。 智能合约检查签名的有效性并确定获胜者。 如果服务器未发送任何内容,则用户将自动获胜。

所描述的方法确保了操作在技术上是不可能的。 所有Tradisys游戏都使用算法,因此它们是诚实透明的。 一切都应进行公众审查。 这样可以确保诚实。

Source: https://habr.com/ru/post/zh-CN464357/


All Articles