ブロックチェヌン䞊のRSAランダム

問題がありたす。分散型ネットワヌクでは乱数を生成するのが困難です。 ほがすべおのブロックチェヌンがすでにこの問題に遭遇しおいたす。 実際、ナヌザヌ間に信頌関係がないネットワヌクでは、吊定できない乱数を䜜成するこずで倚くの問題が解決されたす。

この蚘事では、ゲヌムを䟋ずしお、どのように問題を解決できたかを説明したす。 そのうちの最初のものは、 りェヌブスのクリスマスツリヌ。 開発には乱数発生噚が必芁でした。

ブロックチェヌン䞊のRSAランダム

圓初、私たちはブロックチェヌンからの情報に基づいお番号を生成するこずを蚈画しおいたした。 しかし、数倀は操䜜できる可胜性があり、この゜リュヌションは適切ではないこずが明らかになりたした。

私たちは、commit-expand スキヌムを䜿甚するずいう回避策を考え出したした。 サヌバヌは 1 から 5 たでの数倀を掚枬し、それに゜ルトを远加し、その結果を次を䜿甚しおハッシュしたす。 ケチャック関数。 サヌバヌは、事前に保存枈みの番号を䜿甚しおスマヌト コントラクトをデプロむしたした。 ゲヌムの芁点は、ナヌザヌがハッシュに隠された数字を掚枬するこずであるこずが刀明したした。

プレヌダヌが賭けをするず、サヌバヌは隠された数字ず「゜ルト」をスマヌト コントラクトに送信したす。 簡単に蚀えば、圌はカヌドを公開したした。 その埌、サヌバヌは数字を確認し、ナヌザヌが勝ったか負けたかを決定したす。

サヌバヌが怜蚌のために数字たたは「゜ルト」を送信しなかった堎合、ナヌザヌが勝ちたす。 この堎合、ゲヌムごずに事前にスマヌト コントラクトを展開し、その䞭に朜圚的な賞金を含める必芁がありたした。 それは䞍䟿で、時間ず費甚がかかるこずが刀明したした。 圓時、他に安党な解決策はありたせんでした。

最近、Tradisys チヌムは Waves プロトコルに機胜を远加するこずを提案したした。 rsaVerify()。 公開キヌず秘密キヌに基づいお RSA 眲名の有効性をチェックしたす。 その結果、機胜が远加されたした。

私たちは XNUMX ぀のゲヌムを開発したした。 ダむスロヌラヌ, Coin Flip О 波に乗っお。 それぞれに乱数テクノロゞヌが実装されおいたす。 それがどのように機胜するかを芋おみたしょう。

ブロックチェヌン䞊のRSAランダム

Ride on Waves を䟋ずしお乱数の生成を芋おみたしょう。 スマヌトコントラクトが芋぀かる ここで.

タブに移動 スクリプト 遞択したす 逆コンパむル枈み。 スマヌト コントラクト コヌド (別名スクリプト) が衚瀺されたす。

ブロックチェヌン䞊のRSAランダム

スマヌト コントラクト コヌドには䞀連の関数が含たれおいたす。 @Callable ずしおマヌクされたものは、次を䜿甚しお起動できたす。 呌び出しトランザクション。 私たちは XNUMX ぀の関数に興味がありたす: 賭ける О 撀退する:

  • ファンクベット (プレむダヌ遞択)
  • funcdraw(gameId,rsaSign)

1. ナヌザヌはセグメントの長さず賭け金のサむズを遞択したす。

ブロックチェヌン䞊のRSAランダム

2. クラむアントはベット関数を䜜成したす。 䞊の画像の堎合は次のようになりたす ベット("50").

3. クラむアントは、スマヌト コントラクト アドレス (ブロヌドキャスト InvocationTx) に呌び出しトランザクションを送信したす。 トランザクションにはコヌルパラメヌタずしおベット関数が含たれおいたす。 これは、呌び出しトランザクションがスマヌト コントラクト䞊のベット関数 (遞択肢: 文字列) の実行をトリガヌするこずを意味したす。

ブロックチェヌン䞊のRSAランダム

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)
  • 公開鍵
  • 朜圚的な賞金 (プレむダヌの賭けに応じお)

ブロックチェヌン䞊のRSAランダム

ブロックチェヌン内のデヌタ レコヌドは次のようになりたす (キヌず倀)。

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

「鍵」キヌ – ゲヌムID 新しいゲヌム。 残りのデヌタは「倀」フィヌルドの行に含たれたす。 これらの゚ントリはタブに保存されたす 䞔぀ スマヌトコントラクト:

ブロックチェヌン䞊のRSAランダム

ブロックチェヌン䞊のRSAランダム

5. サヌバヌはスマヌト コントラクトを「調べ」、ブロックチェヌン API を䜿甚しお送信されたトランザクション (新しいゲヌム) を芋぀けたす。 新しいゲヌムのゲヌム ID はすでにブロックチェヌンに蚘録されおいるため、倉曎したり圱響を䞎えたりするこずはできたせん

6. サヌバヌは匕き出し関数 (gameId、rsaSign) を生成したす。 たずえば、次のようになりたす。

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

7. サヌバヌは、呌び出しトランザクションをスマヌト コントラクトに送信したす (ブロヌドキャスト InvocationTx)。 トランザクションには、圢成されたdrawal関数(gameId、rsaSign)ぞの呌び出しが含たれおいたす。

ブロックチェヌン䞊のRSAランダム

関数には以䞋が含たれたす ゲヌムID 新しいゲヌムず、秘密キヌを䜿甚した䞀意の識別子の RSA 眲名の結果。 眲名結果は倉わりたせん。

これはどういう意味ですか

同じ倀 (ゲヌム ID) を取埗し、それに RSA 眲名メ゜ッドを適甚したす。 垞に同じ結果が埗られたす。 これが RSA アルゎリズムの仕組みです。 ゲヌム ID ず RSA の適甚結果が䞍明なため、最終的な数倀を操䜜するこずはできたせん。 数字を遞ぶのも無意味です。

8. ブロックチェヌンがトランザクションを受け入れたす。 匕き出し関数 (gameId、rsaSign) を実行したす。

9. 匕き出し関数内で匕き出しが発生したす RandInt 関数の生成 (ゲヌムID、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")
    }

ランド - そしお乱数がありたす。

たず、RSA 眲名の結果である文字列が取埗されたす。 ゲヌム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 に眲名し、有効な Rsa 眲名を 2880 ブロック以内に送信する必芁がありたす。 パラメヌタヌは、スマヌト コントラクトのデプロむ時に構成されたす。 割り圓おられた時間内に䜕も起こらなければ、ナヌザヌの勝ちです。 この堎合、賞品はご自身の䜏所に送付しおいただく必芁がありたす。 これは損倱に぀ながるため、「サヌバヌにずっお䞍正行為は利益にならない」こずがわかりたす。 以䞋に䟋を瀺したす。

ブロックチェヌン䞊のRSAランダム

ナヌザヌがプレむしおいたす ダむスロヌラヌ。 私は立方䜓の 2 ぀の面のうち 6 ぀を遞びたした。賭け金は 14 WAVES です。 サヌバヌが指定された時間 (2880 ブロック) 内に有効な RSA 眲名をスマヌト コントラクトに送信しない堎合、ナヌザヌは 34.44 WAVE かかりたす。

ゲヌムで数倀を生成するには、倖郚の非ブロックチェヌン システムであるオラクルを䜿甚したす。 サヌバヌはゲヌム ID の RSA 眲名を実行したす。 スマヌト コントラクトは眲名の有効性をチェックし、勝者を決定したす。 サヌバヌが䜕も送信しない堎合は、ナヌザヌが自動的に勝ちたす。

操䜜は技術的に䞍可胜なので、これは正盎な生成方法です。 すべおの Tradisys ゲヌムは、説明されおいるアルゎリズムに基づいお動䜜したす。 これがブロックチェヌンゲヌムの仕組みです。 すべおが透明で怜蚌可胜です。 他のブロックチェヌンにはこのようなシステムに類䌌したものはありたせん。 これはかなりのランダムです。

出所 habr.com

コメントを远加したす