Play the dice game on EOS---dice intelligent contract __ Block chain

Source: Internet
Author: User
Tags openssl

Dice Intelligent Contract Operation Steps, in the EOS GitHub, here no longer repeat, here is mainly about dice intelligent contract implementation.
Dice in Chinese is the dice. Smart you've guessed that this could be a dice game, yes, this is a double dice game.
Now we follow the steps to see how it is implemented: the first step: Recharge (as in the casino to change chips):

Cleos Push Action dice deposit ' ["Wang", "100.0000 EOS"] '-p Wang
cleos push action dice deposit ' ["Zhao", "100.000 0 EOS "] '-P Zhao

Wang and Zhao were created in advance, each with 1000 eos.
Tips: Before you recharge, you need to obtain authorization for the DICE Smart contract.

Now let's look at the deposit function:

void Deposit (const account_name from, const asset& quantity) {

 Eosio_assert (quantity.is_valid (), invalid Quant ity ");
 Eosio_assert (Quantity.amount > 0, "must deposit positive quantity");

 Auto ITR = Accounts.find (from);
 if (ITR = = Accounts.end ()) {
    //If there is no account in the dice contract, create a
    ITR = Accounts.emplace (_self, [ampersand] (auto& acnt) {
  acnt.owner = from;}

 Transfer to dice, as the use of EOS token, the transfer through the Eosio.token contract Execution
 Action (
    permission_level{from, N (Active)},
    N ( Eosio.token), N (transfer),
    std::make_tuple (from, _self, quantity, std::string (""))
 . Send ();

Modify the balance of the account in the dice contract
 accounts.modify (ITR, 0, [ampersand] (auto& acnt) {
    acnt.eos_balance = quantity;
 });
}

Deposit function is relatively simple, is to dice recharge, and recorded. Step two: Bet

$ OpenSSL rand 32-hex
271261da3bedbf0196d43dad5a73abc309e2d40750f09096c01e09b2ee0f91d5

$ Echo-n ' 271261da3bedbf0196d43dad5a73abc309e2d40750f09096c01e09b2ee0f91d5 ' | Xxd-r-P | Sha256sum-b | awk ' {print $} '
921e0c66a8866ca0037fbb628acd5f63f3ba119962c9f5ca68d54b5a70292f36

$ cleos Push action Dice Offerbet ' ["3.0000 EOS", "Wang", "921e0c66a8866ca0037fbb628acd5f63f3ba119962c9f5ca68d54b5a70292f36"] '-P Wang
Executed transaction:77ff114b6c80bd09e453b113531eb213a555fca888451d94f703ae0dfa512b65  280 bytes  109568 Cycles
#        dice <= dice::offerbet             {"bet": "3.0000 EOS", "Player": "Wang", "commitment": " 921e0c66a8866ca0037fbb628acd5f63f3ba119962c9f5ca68 ...

The first is to use OpenSSL to generate a random number, and then to find its hash, and finally use this hash to bet.

Now let's look at the deposit function, which is also the longest member function of the dice contract.

void Offerbet (const asset& BET, const account_name player, const checksum256& commitment) {Eosio_assert (bet.sy
 Mbol = = S (4,eos), "only EOS token allowed");
 Eosio_assert (Bet.is_valid (), "Invalid Bet");

 Eosio_assert (Bet.amount > 0, "must bet positive quantity");
 Eosio_assert (!has_offer (Commitment), "offer with this commitment already exist");

 Require_auth (player);
 Auto Cur_player_itr = accounts.find (player);

 Eosio_assert (Cur_player_itr!= accounts.end (), "Unknown Account"); Store new offer Auto New_offer_itr = Offers.emplace (_self, [Ampersand] (auto& offer) {offer.id = Offers.ava
    Ilable_primary_key ();
    Offer.bet = bet;
    Offer.owner = player;
    Offer.commitment = commitment;
 Offer.gameid = 0;

 });
 Try to find a matching bet auto idx = offers.template get_index<n (bet) > ();

 Auto Matched_offer_itr = Idx.lower_bound ((uint64_t) new_offer_itr->bet.amount); if (Matched_offer_itr = = Idx.end () | |Matched_offer_itr->bet!= New_offer_itr->bet | | Matched_offer_itr->owner = = New_offer_itr->owner) {//No matching bet found, update player ' s account acco Unts.modify (cur_player_itr, 0, [ampersand] (auto& acnt) {Eosio_assert (acnt.eos_balance >= bet, insufficient B
       Alance ");
       Acnt.eos_balance-= bet;
    acnt.open_offers++;

 });
    else {//Create Global game counter if not exists auto Gdice_itr = Global_dices.begin ();
          if (Gdice_itr = = Global_dices.end ()) {Gdice_itr = Global_dices.emplace (_self, [ampersand] (auto& gdice) {
       Gdice.nextgameid=0;
    }); }//Increment Global Game Counter global_dices.modify (gdice_itr, 0, [ampersand] (auto& gdice) {GDICE.NEXTG
    ameid++;

    }); Create a new game auto Game_itr = Games.emplace (_self, [ampersand] (auto& new_game) {new_game.id = Gdic
       e_itr->nextgameid;
       New_game.bet = new_offer_itr->bet; New_game.deAdline = 0;
       New_game.player1.commitment = matched_offer_itr->commitment;

       memset (&new_game.player1.reveal, 0, sizeof (checksum256));
       New_game.player2.commitment = new_offer_itr->commitment;
    memset (&new_game.player2.reveal, 0, sizeof (checksum256));

    });
       Update player ' s offers idx.modify (MATCHED_OFFER_ITR, 0, [Ampersand] (auto& offer) {offer.bet.amount = 0;
    Offer.gameid = game_itr->id;

    });
       Offers.modify (new_offer_itr, 0, [Ampersand] (auto& offer) {offer.bet.amount = 0;
    Offer.gameid = game_itr->id;

    }); Update player ' s accounts accounts.modify (Accounts.find (Matched_offer_itr->owner), 0, [ampersand] (auto& acnt)
       {acnt.open_offers--;
    acnt.open_games++;

    }); Accounts.modify (cur_player_itr, 0, [ampersand] (auto& acnt) {Eosio_assert (acnt.eos_balance >= bet, "Insufficie
       NT Balance ");
       Acnt.eos_balance-= bet;
   acnt.open_games++; }); }
}

When you bet, if you can't find a matching order, it will be saved; If you find a matching order, the game begins. The third step: Open the cup

Cleos push action dice reveal ' ["921e0c66a8866ca0037fbb628acd5f63f3ba119962c9f5ca68d54b5a70292f36", " 271261da3bedbf0196d43dad5a73abc309e2d40750f09096c01e09b2ee0f91d5 "] '-p Wang

Here you need to pass the random number generated by the second step and its hash.

Now let's look at the reveal function:

void reveal (const checksum256& Commitment, const checksum256& source) {assert_sha256 ((char *) &source, si

 Zeof (source), (const checksum256 *) &commitment);
 Auto idx = offers.template get_index<n (commitment) > ();

 Auto Curr_revealer_offer = Idx.find (offer::get_commitment (commitment));
 Eosio_assert (Curr_revealer_offer!= idx.end (), "offer not Found");

 Eosio_assert (Curr_revealer_offer->gameid > 0, "Unable to reveal");

 Auto Game_itr = Games.find (Curr_revealer_offer->gameid);
 Player Curr_reveal = game_itr->player1;

 Player Prev_reveal = game_itr->player2;
 if (!is_equal (curr_reveal.commitment, Commitment)) {Std::swap (curr_reveal, prev_reveal);

} eosio_assert (Is_zero (curr_reveal.reveal) = = True, "player already revealed"); Under normal circumstances need two people open Cup, if one side open Cup, the other side is delayed, then calculate the Open Cup of that party win if (!is_zero (prev_reveal.reveal)) {//The last player to uncover, the 2 player source and commitment as a
    The whole, and find out its hash checksum256 result; SHA256 (char *) &game_itr->player1, sizEOF (player) *2, &result);

    Auto Prev_revealer_offer = Idx.find (offer::get_commitment (prev_reveal.commitment));
    Determines the outcome by comparing the size of the No. 0 byte and the 1th byte of the hash. Different data, the hash is not the same, this data by the Player 1 and Player 2 submitted data composition, so player 1 and player 2 can affect the result of the game int winner = Result.hash[1] < result.hash[0]?

    0:1;
    if (winner) {Pay_and_clean (*game_itr, *curr_revealer_offer, *prev_revealer_offer);
    else {Pay_and_clean (*game_itr, *prev_revealer_offer, *curr_revealer_offer);
    } else {//The first player opens the Cup, notes the source, and starts the 5-minute countdown, if the second player does not open the cup within 5 minutes, the first player wins the game. 
          Games.modify (game_itr, 0, [Ampersand] (auto& game) {if (Is_equal (Curr_reveal.commitment, game.player1.commitment))
       Game.player1.reveal = source;

       else game.player2.reveal = source;
    Game.deadline = Now () + five_minutes;
 }); }
}

The source and commitment above correspond to the random number and its hash.

The above three steps are the main functions of the dice contract, and many technical details need to be explored. In rewriting the dice intelligent contract, I learned a lot of C + + 11 programming skills.
For example, Dawn 3.0 uses Eosio::multi_index as a container, which greatly facilitates development.
Such as:

struct Account {account
 (account_name o = account_name ()): Owner (o) {}

 account_name owner;
 Asset        Eos_balance;
 uint32_t     open_offers = 0;
 uint32_t     open_games = 0;

 BOOL Is_empty () const {return! (Eos_balance.amount | open_offers | open_games);}

 uint64_t Primary_key () const {return owner;}

 Eoslib_serialize (account, (owner) (eos_balance) (open_offers) (open_games)
};

typedef eosio::multi_index< N (account), account> Account_index;

Account_index     accounts;

With Eosio::multi_index, we can use Emplace to insert data, use Modify to modify the data, and use erase to delete the data.

There are more subtle examples:

struct offer {uint64_t ID;
 Account_name owner;
 Asset Bet;
 CHECKSUM256 Commitment;

 uint64_t GameID = 0;

 uint64_t Primary_key () const {return ID;}

 uint64_t By_bet () const {return (uint64_t) Bet.amount;}

 KEY256 by_commitment () const {return get_commitment (commitment);} Static key256 get_commitment (const checksum256& Commitment) {const uint64_t *P64 = reinterpret_cast<const UINT
    64_t *> (&commitment);
 Return key256::make_from_word_sequence<uint64_t> (P64[0], p64[1], p64[2], p64[3]);

Eoslib_serialize (offer, (ID) (owner) (BET) (commitment) (GameID)}; typedef eosio::multi_index< N (offer), Offer, indexed_by< N (BET), Const_mem_fun<offer, uint64_t, &offer::  By_bet >, indexed_by< N (commitment), Const_mem_fun<offer, key256, &offer::by_commitment> > >

Offer_index; Offer_index offers; 

The Offer_index type can be indexed either by bet or by commitment.
For example, in the Offerbet function above, use BET to index

Auto idx = offers.template get_index<n (bet) > ();
Auto Matched_offer_itr = Idx.lower_bound ((uint64_t) new_offer_itr->bet.amount);

In the reveal function above, the commitment is used to index

Auto idx = offers.template get_index<n (commitment) > ();
 Auto Curr_revealer_offer = Idx.find (offer::get_commitment (commitment)  );

Learning block chain of the road is still very long, this article is here.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.