基于RSA的区块链随机

在开发游戏的过程中,我们需要解决一个问题。 在分布式网络中生成随机数很复杂。 几乎所有的区块链都已经面临这个问题。 确实,在任何人之间都不信任的网络中,创建随机数可以解决许多问题。

在本文中,我们解释了如何解决游戏中的问题。 其中第一个是Waves Xmas Tree





最初,我们计划使用来自区块链的信息生成一个数字。 但是,在进一步调查中,很明显可以操纵这种以数字方式创建号码的过程。 我们不得不放弃这个解决方案。

我们提出了一种解决方法,即采用“提交披露”方案。 服务器建议从1到5的数字,并在其中添加“盐”,然后使用Keccak函数对结果进行哈希处理 。 服务器使用已保存的号码预调试了智能合约。 结果是游戏被有效地简化为用户猜测哈希隐藏的数字。

玩家下注,服务器向智能合约发送了一个隐藏的数字和“盐”。 换句话说,显示了卡片。 之后,服务器验证数字并确定用户是赢还是输。

如果服务器未发送数字和“盐”进行验证,则用户赢了。 在这种情况下,有必要提前部署智能合约并为每场比赛安排潜在的获胜机会。 这是不方便,昂贵和费时的。 但是,那时还没有其他安全解决方案。

此后不久,Tradisys团队建议将rsaVerify()函数添加到Waves协议中。 这将根据公钥和私钥检查RSA签名的有效性。 根据我们的建议,该功能已添加。

我们构建了三个新游戏: 骰子滚轴投币翻转乘风破浪 。 在它们每个中,都实现了新的随机数技术。 让我们仔细看看它是如何工作的。



首先让我们看一下随机数的生成。 您可以在此处找到智能合约。

转到脚本选项卡,然后选择反编译 。 您将看到智能合约的代码(或脚本)。



智能合约代码由功能列表组成。 可以通过调用事务运行@Callable。 我们对其中两个感兴趣: 下注下注
  • 功能投注(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(游戏ID)
  • 游戏状态=已提交
  • 玩家选择(范围为50)
  • 公钥
  • 潜在奖励(取决于玩家的投注)




这就是键值数据库在区块链上的外观:

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


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




5.服务器通过区块链API查找发送的交易(新游戏)。 游戏ID已记录在区块链中,因此无法更改或删除它。

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

撤回(«FwsuaaShC6DMWdSWQ5osGWtYkVbTEZrsnxqDbVx5oUpq»,«BASE64:Gy69dKdmXUEsAmUrpoWxDLTQOGj5 / qO8COA + QjyPVYTAjxXYvEESJbSiCSBRRCOAliqCWwaS161nWqoTL / TltiIvw3nKyd4RJIBNSIgEWGM1tEtNwwnRwSVHs7ToNfZ2Dvk / GgPUqLFDSjnRQpTHdHUPj9mQ8erWw0r6cJXrzfcagKg3yY / 0wJ6AyIrflR35mUCK4cO7KumdvC9Mx0hr / ojlHhN732nuG8ps4CUlRw3CkNjNIajBUlyKQwpBKmmiy3yJa / QM5PLxqdppmfFS9y0sxgSlfLOgZ51xRDYuS8NViOA7c1JssH48ZtDbBT5yqzRJXs3RnmZcMDr / q0x6Bg ==»)

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



该功能包含游戏ID和唯一ID的RSA签名。 签名结果不可更改。

这是什么意思?


我们采用相同的值(游戏ID),并对其应用RSA签名方法。 RSA算法就是这样工作的。 由于游戏ID和RSA算法的结果未知,因此无法操纵最终数字。 尝试猜测一个数字也毫无意义。

8.区块链收到运行提现功能的交易(gameId,rsaSign)。

9.在撤回函数(gameId,rsaSign)内部调用了GenerateRandIn函数。 这是一个随机数生成器。

 # @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是一个随机数

首先,使用作为RSA签名结果的字符串。 然后,它通过SHA-256( sha256(rsaSign) )进行哈希处理

我们无法预测签名结果和后续的哈希。 因此,不可能影响其生成。 为了获得特定范围内的数字(例如1到100),将转换函数转换为Int和%100( 模拟)。

在本文的开头,我们提到了rsaVerify()函数,该函数允许通过私钥针对公共密钥检查RSA签名的有效性。 这是GenerateRandInt(gameId,rsaSign)的一部分:

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

首先,使用RSAPUBLIC公钥和rsaSign字符串。 检查签名的有效性。 如果检查成功,则生成数字。 否则,系统认为签名无效(无效的RSA签名)。

服务器必须使用私钥对游戏ID进行签名,并在2880个块内发送有效的RSA签名。 在部署智能合约时管理该选项。 如果在规定时间内没有任何反应,则用户获胜。 在这种情况下,奖励必须由用户独立发送。 事实证明,作弊对服务器无利可图,因为这会导致损失。 下面有一个例子。



用户玩骰子滚轮 。 他从6个立方体面中选择2个,并下注14个WAVES。 如果服务器未在设定的时间(2,880块)内向智能合约发送有效的RSA签名,则用户将收到34.44 WAVES。

为了生成数字,我们使用Oracle,即外部系统而不是区块链。 服务器为游戏ID实现RSA签名。 智能合约检查签名的有效性并确定获胜者。 如果服务器什么都不发送,则用户将自动获胜。

该方法确保了操作在技术上是不可能的。 所有Tradisys游戏均基于上述算法-确保我们的游戏公平,透明。 一切都可以公开审核以确保诚实。

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


All Articles