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) )
原文地址:https://www.cnblogs.com/tyche116/p/11533593.html