zoukankan      html  css  js  c++  java
  • EOS dice移到1.8版本的修改汇总

    EOS dice移到1.8版本的修改汇总

    1. CORE_SYMBOL 被去掉了,需要自己在文件中声明
    eg:

     1 uint64_t string_to_symbol_c(uint8_t precision, const char* str) {
     2          uint32_t len = 0;
     3          while (str[len]) ++len;
     4 
     5          uint64_t result = 0;
     6          // No validation is done at compile time
     7          for (uint32_t i = 0; i < len; ++i) {
     8             result |= (uint64_t(str[i]) << (8*(1+i)));
     9          }
    10 
    11          result |= uint64_t(precision);
    12          return result;
    13       }
    14 
    15 #define CORE_SYMBOL string_to_symbol_c(4,"SYS")


    2. account_name 替换成了 name 结构

    3. 合约contract的声明改成了下面结构
    contract( name receiver, name code, datastream<const char*> ds )

    dice合约变为:dice(name s, name code, eosio::datastream<const char*> ds):eosio::contract(s,code,ds)

    4. 因为account_name变为了name结构,多索引结构的初始化改为:
    offers(_self, _self.value),
    games(_self, _self.value),
    global_dices(_self, _self.value),
    accounts(_self, _self.value)

    5. 宏N变为了_n
    eg:N(commitment) 改为 "commitment"_n

    6. checksum256 改成 capi_checksum256

    7. key256 改成 fixed_bytes<32>

    8. find函数后面跟的name类型,需要添加.value,以供查找

    9. modify函数三个参数中间的0,改成_self账户或者相应的账户

    10. EOSIO_ABI 改成 EOSIO_DISPATCH

    11. 添加相应的头文件,修改为新的合约格式 [[eosio::action]],[[eosio::contract("dice")]],[[eosio::table]]等

    12. 该合约不支持除了EOS的其他资产,因此自己做了一点修改以支持测试的自定义资产,供自己测试

    完整修改代码如下:

      1 /**
      2  *  @file
      3  *  @copyright defined in eos/LICENSE.txt
      4  */
      5 #include <utility>
      6 #include <vector>
      7 #include <string>
      8 #include <eosiolib/eosio.hpp>
      9 #include <eosiolib/time.hpp>
     10 #include <eosiolib/asset.hpp>
     11 #include <eosiolib/contract.hpp>
     12 #include <eosiolib/crypto.h>
     13 #include <eosiolib/fixed_bytes.hpp>
     14 #include <eosiolib/symbol.hpp>
     15 
     16 using eosio::fixed_bytes;
     17 using eosio::indexed_by;
     18 using eosio::const_mem_fun;
     19 using eosio::asset;
     20 using eosio::permission_level;
     21 using eosio::action;
     22 using eosio::print;
     23 using eosio::name;
     24 using eosio::symbol;
     25 
     26 uint64_t string_to_symbol_c(uint8_t precision, const char* str) {
     27          uint32_t len = 0;
     28          while (str[len]) ++len;
     29 
     30          uint64_t result = 0;
     31          // No validation is done at compile time
     32          for (uint32_t i = 0; i < len; ++i) {
     33             result |= (uint64_t(str[i]) << (8*(1+i)));
     34          }
     35 
     36          result |= uint64_t(precision);
     37          return result;
     38       }
     39 
     40 #define CORE_SYMBOL string_to_symbol_c(4,"SYS")
     41 
     42 
     43 class [[eosio::contract("dice")]] dice : public eosio::contract {
     44    public:
     45       using contract::contract;
     46          
     47       const uint32_t FIVE_MINUTES = 5*60;
     48 
     49       dice(name s, name code, eosio::datastream<const char*> ds):eosio::contract(s,code,ds),
     50        offers(_self, _self.value),
     51        games(_self, _self.value),
     52        global_dices(_self, _self.value),
     53        accounts(_self, _self.value)
     54       {}
     55 
     56       [[eosio::action]]
     57       void offerbet(const asset& bet, const name player, const capi_checksum256& commitment) {
     58 
     59          //eosio_assert( bet.symbol == symbol(CORE_SYMBOL), "only core token allowed" );
     60          eosio_assert( bet.is_valid(), "invalid bet" );
     61          eosio_assert( bet.amount > 0, "must bet positive quantity" );
     62 
     63          eosio_assert( !has_offer( commitment ), "offer with this commitment already exist" );
     64          require_auth( player );
     65 
     66          auto cur_player_itr = accounts.find( player.value );
     67          eosio_assert(cur_player_itr != accounts.end(), "unknown account");
     68 
     69          // Store new offer
     70          auto new_offer_itr = offers.emplace(_self, [&](auto& offer){
     71             offer.id         = offers.available_primary_key();
     72             offer.bet        = bet;
     73             offer.owner      = player;
     74             offer.commitment = commitment;
     75             offer.gameid     = 0;
     76          });
     77 
     78          // Try to find a matching bet
     79          auto idx = offers.template get_index<"bet"_n>();
     80          auto matched_offer_itr = idx.lower_bound( (uint64_t)new_offer_itr->bet.amount );
     81 
     82          if( matched_offer_itr == idx.end()
     83             || matched_offer_itr->bet != new_offer_itr->bet
     84             || matched_offer_itr->owner == new_offer_itr->owner ) {
     85 
     86             // No matching bet found, update player's account
     87             accounts.modify( cur_player_itr, player, [&](auto& acnt) {
     88                //eosio_assert( acnt.eos_balance >= bet, "insufficient balance" );
     89                //acnt.eos_balance -= bet;
     90                for(auto iter = acnt.eos_balance.begin(); iter != acnt.eos_balance.end(); iter++){
     91                if(iter->symbol == bet.symbol){
     92                   eosio_assert( (*iter) >= bet, "insufficient balance" );
     93                   (*iter) -= bet;
     94                   print( "offerbet1 : ", asset{bet} );
     95                   break;
     96                }
     97                }
     98                acnt.open_offers++;
     99             });
    100 
    101          } else {
    102             // Create global game counter if not exists
    103             auto gdice_itr = global_dices.begin();
    104             if( gdice_itr == global_dices.end() ) {
    105                gdice_itr = global_dices.emplace(_self, [&](auto& gdice){
    106                   gdice.nextgameid=0;
    107                });
    108             }
    109 
    110             // Increment global game counter
    111             global_dices.modify(gdice_itr, _self, [&](auto& gdice){
    112                gdice.nextgameid++;
    113             });
    114 
    115             // Create a new game
    116             auto game_itr = games.emplace(_self, [&](auto& new_game){
    117                new_game.id       = gdice_itr->nextgameid;
    118                new_game.bet      = new_offer_itr->bet;
    119                new_game.deadline = eosio::time_point_sec(0);
    120 
    121                new_game.player1.commitment = matched_offer_itr->commitment;
    122                memset(&new_game.player1.reveal, 0, sizeof(capi_checksum256));
    123 
    124                new_game.player2.commitment = new_offer_itr->commitment;
    125                memset(&new_game.player2.reveal, 0, sizeof(capi_checksum256));
    126             });
    127 
    128             // Update player's offers
    129             idx.modify(matched_offer_itr, _self, [&](auto& offer){
    130                offer.bet.amount = 0;
    131                offer.gameid = game_itr->id;
    132             });
    133 
    134             offers.modify(new_offer_itr, _self, [&](auto& offer){
    135                offer.bet.amount = 0;
    136                offer.gameid = game_itr->id;
    137             });
    138 
    139             // Update player's accounts
    140             accounts.modify( accounts.find( matched_offer_itr->owner.value ), matched_offer_itr->owner, [&](auto& acnt) {
    141                acnt.open_offers--;
    142                acnt.open_games++;
    143             });
    144 
    145             accounts.modify( cur_player_itr, player, [&](auto& acnt) {
    146                //eosio_assert( acnt.eos_balance >= bet, "insufficient balance" );
    147                // acnt.eos_balance -= bet;
    148                for(auto iter = acnt.eos_balance.begin(); iter != acnt.eos_balance.end(); iter++){
    149                if(iter->symbol == bet.symbol){
    150                   eosio_assert( (*iter) >= bet, "insufficient balance" );
    151                   (*iter) -= bet;
    152                   print( "offerbet2 : ", asset{bet} );
    153                   break;
    154                }
    155                }
    156                acnt.open_games++;
    157             });
    158          }
    159       }
    160 
    161       [[eosio::action]]
    162       void canceloffer( const capi_checksum256& commitment ) {
    163 
    164          auto idx = offers.template get_index<"commitment"_n>();
    165          auto offer_itr = idx.find( offer::get_commitment(commitment) );
    166 
    167          eosio_assert( offer_itr != idx.end(), "offer does not exists" );
    168          eosio_assert( offer_itr->gameid == 0, "unable to cancel offer" );
    169          require_auth( offer_itr->owner );
    170 
    171          auto acnt_itr = accounts.find(offer_itr->owner.value);
    172          accounts.modify(acnt_itr, offer_itr->owner, [&](auto& acnt){
    173             acnt.open_offers--;
    174             // acnt.eos_balance += offer_itr->bet;
    175 
    176             for(auto iter = acnt.eos_balance.begin(); iter != acnt.eos_balance.end(); iter++){
    177                if(iter->symbol == offer_itr->bet.symbol){
    178                   (*iter) += offer_itr->bet;
    179                   print( "canceloffer : ", asset{offer_itr->bet} );
    180                   break;
    181                }
    182             }
    183          });
    184 
    185          idx.erase(offer_itr);
    186       }
    187 
    188       [[eosio::action]]
    189       void reveal( const capi_checksum256& commitment, const capi_checksum256& source ) {
    190 
    191          assert_sha256( (char *)&source, sizeof(source), (const capi_checksum256 *)&commitment );
    192 
    193          auto idx = offers.template get_index<"commitment"_n>();
    194          auto curr_revealer_offer = idx.find( offer::get_commitment(commitment)  );
    195 
    196          eosio_assert(curr_revealer_offer != idx.end(), "offer not found");
    197          eosio_assert(curr_revealer_offer->gameid > 0, "unable to reveal");
    198 
    199          auto game_itr = games.find( curr_revealer_offer->gameid );
    200 
    201          player curr_reveal = game_itr->player1;
    202          player prev_reveal = game_itr->player2;
    203 
    204          if( !is_equal(curr_reveal.commitment, commitment) ) {
    205             std::swap(curr_reveal, prev_reveal);
    206          }
    207 
    208          eosio_assert( is_zero(curr_reveal.reveal) == true, "player already revealed");
    209 
    210          if( !is_zero(prev_reveal.reveal) ) {
    211 
    212             capi_checksum256 result;
    213             sha256( (char *)&game_itr->player1, sizeof(player)*2, &result);
    214 
    215             auto prev_revealer_offer = idx.find( offer::get_commitment(prev_reveal.commitment) );
    216 
    217             int winner = result.hash[1] < result.hash[0] ? 0 : 1;
    218 
    219             if( winner ) {
    220                pay_and_clean(*game_itr, *curr_revealer_offer, *prev_revealer_offer);
    221             } else {
    222                pay_and_clean(*game_itr, *prev_revealer_offer, *curr_revealer_offer);
    223             }
    224 
    225          } else {
    226             games.modify(game_itr, _self, [&](auto& game){
    227 
    228                if( is_equal(curr_reveal.commitment, game.player1.commitment) )
    229                   game.player1.reveal = source;
    230                else
    231                   game.player2.reveal = source;
    232 
    233                game.deadline = eosio::time_point_sec(now() + FIVE_MINUTES);
    234             });
    235          }
    236       }
    237 
    238       [[eosio::action]]
    239       void claimexpired( const uint64_t gameid ) {
    240 
    241          auto game_itr = games.find(gameid);
    242 
    243          eosio_assert(game_itr != games.end(), "game not found");
    244          eosio_assert(game_itr->deadline != eosio::time_point_sec(0) && eosio::time_point_sec(now()) > game_itr->deadline, "game not expired");
    245 
    246          auto idx = offers.template get_index<"commitment"_n>();
    247          auto player1_offer = idx.find( offer::get_commitment(game_itr->player1.commitment) );
    248          auto player2_offer = idx.find( offer::get_commitment(game_itr->player2.commitment) );
    249 
    250          if( !is_zero(game_itr->player1.reveal) ) {
    251             eosio_assert( is_zero(game_itr->player2.reveal), "game error");
    252             pay_and_clean(*game_itr, *player1_offer, *player2_offer);
    253          } else {
    254             eosio_assert( is_zero(game_itr->player1.reveal), "game error");
    255             pay_and_clean(*game_itr, *player2_offer, *player1_offer);
    256          }
    257 
    258       }
    259 
    260       [[eosio::action]]
    261       void deposit( const name from, const asset& quantity ) {
    262          
    263          eosio_assert( quantity.is_valid(), "invalid quantity" );
    264          eosio_assert( quantity.amount > 0, "must deposit positive quantity" );
    265 
    266          auto itr = accounts.find(from.value);
    267          if( itr == accounts.end() ) {
    268             itr = accounts.emplace(_self, [&](auto& acnt){
    269                acnt.owner = from;
    270             });
    271          }
    272 
    273          action(
    274             permission_level{ from, "active"_n },
    275             "eosio.token"_n, "transfer"_n,
    276             std::make_tuple(from, _self, quantity, std::string(""))
    277          ).send();
    278 
    279          accounts.modify( itr, from, [&]( auto& acnt ) {
    280             //acnt.eos_balance += quantity;
    281             bool isfound = false;
    282             for(auto iter = acnt.eos_balance.begin(); iter != acnt.eos_balance.end(); iter++){
    283                if(iter->symbol == quantity.symbol){
    284                   (*iter) += quantity;
    285                   isfound = true;
    286                   print( "deposit more : ", asset{quantity} );
    287                   break;
    288                }
    289             }
    290             if(!isfound){
    291                acnt.eos_balance.emplace_back(quantity);
    292                print( "deposit add : ", asset{quantity} );
    293             }
    294          });
    295 
    296       }
    297 
    298       [[eosio::action]]
    299       void withdraw( const name to, const asset& quantity ) {
    300          require_auth( to );
    301 
    302          eosio_assert( quantity.is_valid(), "invalid quantity" );
    303          eosio_assert( quantity.amount > 0, "must withdraw positive quantity" );
    304 
    305          auto itr = accounts.find( to.value );
    306          eosio_assert(itr != accounts.end(), "unknown account");
    307 
    308          accounts.modify( itr, to, [&]( auto& acnt ) {
    309             // eosio_assert( acnt.eos_balance >= quantity, "insufficient balance" );
    310             // acnt.eos_balance -= quantity;
    311 
    312             for(auto iter = acnt.eos_balance.begin(); iter != acnt.eos_balance.end(); iter++){
    313                if(iter->symbol == quantity.symbol){
    314                   eosio_assert( (*iter) >= quantity, "insufficient balance" );
    315                   (*iter) -= quantity;
    316                   print( "withdraw : ", asset{quantity} );
    317                   break;
    318                }
    319             }
    320          });
    321 
    322          action(
    323             permission_level{ _self, "active"_n },
    324             "eosio.token"_n, "transfer"_n,
    325             std::make_tuple(_self, to, quantity, std::string(""))
    326          ).send();
    327 
    328          if( itr->is_empty() ) {
    329             accounts.erase(itr);
    330          }
    331       }
    332 
    333    private:
    334       //@abi table offer i64
    335       struct [[eosio::table]] offer {
    336          uint64_t          id;
    337          name              owner;
    338          asset             bet;
    339          capi_checksum256  commitment;
    340          uint64_t          gameid = 0;
    341 
    342          uint64_t primary_key()const { return id; }
    343 
    344          uint64_t by_bet()const { return (uint64_t)bet.amount; }
    345 
    346          fixed_bytes<32> by_commitment()const { return get_commitment(commitment); }
    347 
    348          static fixed_bytes<32> get_commitment(const capi_checksum256& commitment) {
    349             const uint64_t *p64 = reinterpret_cast<const uint64_t *>(&commitment);
    350             return fixed_bytes<32>::make_from_word_sequence<uint64_t>(p64[0], p64[1], p64[2], p64[3]);
    351          }
    352 
    353          EOSLIB_SERIALIZE( offer, (id)(owner)(bet)(commitment)(gameid) )
    354       };
    355 
    356       // typedef eosio::multi_index< N(offer), offer,
    357       //    indexed_by< N(bet), const_mem_fun<offer, uint64_t, &offer::by_bet > >,
    358       //    indexed_by< N(commitment), const_mem_fun<offer, fixed_bytes<32>,  &offer::by_commitment> >
    359       // > offer_index;
    360 
    361       typedef eosio::multi_index< "offers"_n, offer,
    362          indexed_by< "bet"_n, const_mem_fun<offer, uint64_t, &offer::by_bet > >,
    363          indexed_by< "commitment"_n, const_mem_fun<offer, fixed_bytes<32>,  &offer::by_commitment> >
    364       > offer_index_table;
    365 
    366 
    367 
    368       struct [[eosio::table]] player {
    369          capi_checksum256 commitment;
    370          capi_checksum256 reveal;
    371 
    372          EOSLIB_SERIALIZE( player, (commitment)(reveal) )
    373       };
    374 
    375       //@abi table game i64
    376       struct [[eosio::table]] game {
    377          uint64_t id;
    378          asset    bet;
    379          eosio::time_point_sec deadline;
    380          player   player1;
    381          player   player2;
    382 
    383          uint64_t primary_key()const { return id; }
    384 
    385          EOSLIB_SERIALIZE( game, (id)(bet)(deadline)(player1)(player2) )
    386       };
    387 
    388       // typedef eosio::multi_index< N(game), game> game_index;
    389       typedef eosio::multi_index< "games"_n, game> game_index_table;
    390 
    391       //@abi table global i64
    392       struct [[eosio::table]] global_dice {
    393          uint64_t id = 0;
    394          uint64_t nextgameid = 0;
    395 
    396          uint64_t primary_key()const { return id; }
    397 
    398          EOSLIB_SERIALIZE( global_dice, (id)(nextgameid) )
    399       };
    400 
    401       // typedef eosio::multi_index< N(global), global_dice> global_dice_index;
    402       typedef eosio::multi_index< "globals"_n, global_dice> global_dice_index_table;
    403 
    404       //@abi table account i64
    405       struct [[eosio::table]] account {
    406          account( name o = name() ):owner(o){}
    407 
    408          name         owner;
    409          // asset        eos_balance;
    410          std::vector<asset> eos_balance;
    411          uint32_t     open_offers = 0;
    412          uint32_t     open_games = 0;
    413 
    414          // bool is_empty()const { return !( eos_balance.amount | open_offers | open_games ); }
    415          bool is_empty()const { return !( !eos_balance.empty() | open_offers | open_games ); }
    416 
    417          uint64_t primary_key()const { return owner.value; }
    418 
    419          EOSLIB_SERIALIZE( account, (owner)(eos_balance)(open_offers)(open_games) )
    420       };
    421 
    422       // typedef eosio::multi_index< N(account), account> account_index;
    423       typedef eosio::multi_index< "accounts"_n, account> account_index_table;
    424 
    425       offer_index_table       offers;
    426       game_index_table        games;
    427       global_dice_index_table global_dices;
    428       account_index_table     accounts;
    429 
    430       bool has_offer( const capi_checksum256& commitment )const {
    431          auto idx = offers.template get_index<"commitment"_n>();
    432          auto itr = idx.find( offer::get_commitment(commitment) );
    433          return itr != idx.end();
    434       }
    435 
    436       bool is_equal(const capi_checksum256& a, const capi_checksum256& b)const {
    437          return memcmp((void *)&a, (const void *)&b, sizeof(capi_checksum256)) == 0;
    438       }
    439 
    440       bool is_zero(const capi_checksum256& a)const {
    441          const uint64_t *p64 = reinterpret_cast<const uint64_t*>(&a);
    442          return p64[0] == 0 && p64[1] == 0 && p64[2] == 0 && p64[3] == 0;
    443       }
    444 
    445       void pay_and_clean(const game& g, const offer& winner_offer,
    446           const offer& loser_offer) {
    447 
    448          // Update winner account balance and game count
    449          auto winner_account = accounts.find(winner_offer.owner.value);
    450          accounts.modify( winner_account, winner_offer.owner, [&]( auto& acnt ) {
    451             for(auto iter = acnt.eos_balance.begin(); iter != acnt.eos_balance.end(); iter++){
    452                if(iter->symbol == g.bet.symbol){
    453                   (*iter) += 2*g.bet;
    454                   print( "pay_and_clean : ", asset{2*g.bet} );
    455                   break;
    456                }
    457             }
    458             // acnt.eos_balance += 2*g.bet;
    459             acnt.open_games--;
    460          });
    461 
    462          // Update losser account game count
    463          auto loser_account = accounts.find(loser_offer.owner.value);
    464          accounts.modify( loser_account, loser_offer.owner, [&]( auto& acnt ) {
    465             acnt.open_games--;
    466          });
    467 
    468          if( loser_account->is_empty() ) {
    469             accounts.erase(loser_account);
    470          }
    471 
    472          games.erase(g);
    473          offers.erase(winner_offer);
    474          offers.erase(loser_offer);
    475       }
    476 };
    477 
    478 EOSIO_DISPATCH( dice, (offerbet)(canceloffer)(reveal)(claimexpired)(deposit)(withdraw) )
  • 相关阅读:
    Serialize and Deserialize Binary Tree
    sliding window substring problem汇总贴
    10. Regular Expression Matching
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第七章 链接
    程序员如何写一份合格的简历?(附简历模版)
    9个提高代码运行效率的小技巧你知道几个?
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第六章 存储器层次结构
    24张图7000字详解计算机中的高速缓存
    《深入理解计算机系统》(CSAPP)实验四 —— Attack Lab
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第五章 优化程序性能
  • 原文地址:https://www.cnblogs.com/tyche116/p/11533593.html
Copyright © 2011-2022 走看看