2019-05-15
#include <eosio/eosio.hpp>
#include <eosio/asset.hpp>
#include <eosio/transaction.hpp>
#include <eosio/crypto.hpp>
#include <eosio/time.hpp>
#include <eosio/system.hpp>
#include <eosio/print.hpp>
using namespace eosio;
using namespace std;
CONTRACT pvpbetwallet : public contract {
public:
using contract::contract;
pvpbetwallet( name receiver, name code, datastream<const char*> ds )
: contract(receiver, code, ds), boardtable(receiver, receiver.value), bettable(receiver, receiver.value) {}
ACTION transfer(name from, name to, asset quantity, string memo);
ACTION reveal(const uint64_t &table_id, const checksum256 &seed);
ACTION send(const int &index, const name &winner, const uint64_t &table_id);
// EOSIO network
const string symbol_name = "EOS";
// Contract network
const symbol network_symbol = symbol(symbol_name, 4);
const name & lord = name("suwzhaoihuan");
const name & wallet = name("pvpbetwallet");
const int values[16][3] = {
{1000, 1960, 40},
{1960, 3840, 80},
{3840, 7520, 160},
{7520, 14720, 320},
{14720, 28800, 640},
{28800, 56320, 1280},
{56320, 110080, 2560},
{110080, 215040, 5120},
{215040, 419840, 10240},
{419840, 819200, 20480},
{819200, 1597440, 40960},
{1597440, 3112960, 81920},
{3112960, 6062080, 163840},
{6062080, 11796480, 327680},
{11796480, 22937600, 655360},
{22937600, 44564480, 1310720}
};
time_point next(){
return current_time_point() + seconds(360);
}
int findIndex(asset quantity){
for (int i = 0; i < 16; i++){
if (quantity.amount == values[i][0]){
return i;
}
}
check(false, "quantity index not found");
}
void split(const std::string &s, vector<std::string> &v, const std::string &c){
std::string::size_type pos1, pos2;
pos2 = s.find(c);
pos1 = 0;
while (std::string::npos != pos2){
v.push_back(s.substr(pos1, pos2 - pos1));
pos1 = pos2 + c.size();
pos2 = s.find(c, pos1);
}
if (pos1 != s.length()){
v.push_back(s.substr(pos1));
}
}
TABLE board_table {
// 仅有一条记录
uint64_t id;
// 登顶时间
time_point top_time;
// 目前积累的奖赏
asset pool;
// 当前头部用户
name player_name;
// 头部用户投注额分红后进行减半操作
asset quantity;
// 进行下次分红的时间。
time_point next_time;
uint64_t primary_key() const { return id; }
};
// typedef eosio::multi_index<N(表名),表的对象类型> 实例化变量名
typedef eosio::multi_index<"boardtablea"_n, board_table> board_tables;
TABLE bet_table {
// 桌子的标识
uint64_t id;
// 有效时间
time_point valid_time;
// 投注额
asset quantity;
// 桌子的哈希
checksum256 table_hash;
// 玩家1名称
name p1_name;
// 玩家2名称
name p2_name;
// 玩家1哈希
checksum256 p1_hash;
// 玩家2哈希
checksum256 p2_hash;
// 桌子的种子
checksum256 table_seed;
// 玩家1种子
checksum256 p1_seed;
// 玩家2种子
checksum256 p2_seed;
uint64_t primary_key() const { return id; }
};
typedef eosio::multi_index<"bettablea"_n, bet_table> bet_tables;
using transfer_action = action_wrapper<"transfer"_n, &pvpbetwallet::transfer>;
using reveal_action = action_wrapper<"reveal"_n, &pvpbetwallet::reveal>;
using send_action = action_wrapper<"send"_n, &pvpbetwallet::send>;
board_tables boardtable;
bet_tables bettable;
};
ACTION pvpbetwallet::transfer(name from, name to, asset quantity, std::string memo){
if (from == lord){
// 补充能量
return;
}
require_auth(_self);
eosio::check(from != to, "cannot transfer to self");
eosio::check(_self == to, "must transfer to this contract");
eosio::check(memo.size() <= 256, "memo must smaller than 256");
eosio::check(quantity.symbol == eosio::symbol("EOS", 4), "only accepts EOS");
eosio::check(quantity.is_valid(), "invalid token transfer");
int index = pvpbetwallet::findIndex(quantity);
eosio::check(-1 != index, "quantity not found");
// composed by user_id-table_hash-user_hash-user_seed-player_hash
std::vector<std::string> memos;
pvpbetwallet::split(memo, memos, "-");
std::string user_id = memos[0];
std::string table_hash = memos[1];
std::string user_hash = memos[2];
std::string user_seed = memos[3];
std::string player_hash = memos[4];
// 调试
eosio::print("user_id:" + memos[0]);
eosio::print("table_hash:" + memos[1]);
eosio::print("user_hash:" + memos[2]);
eosio::print("user_seed:" + memos[3]);
eosio::print("player_hash:" + memos[4]);
// 验证给定数据和其sha256哈希值是否匹配
//void assert_sha256( const char* data, uint32_t length, const eosio::checksum256& hash );
// 选手需要检查user_hash为user_seed生成。
//const char* seed_sha256 = const_cast<char*>(user_seed.c_str());
eosio::assert_sha256(user_seed.c_str, std::strlen(user_seed), user_hash);
auto player_id = atoi(user_id.c_str);
auto table_id = player_id / 2;
// bet_tables bets(_code, _code.value);
auto bet = bets.find(table_id);
if (bet == bets.end()){
bets.emplace(_self, [&](auto &bet) {
bet.id = table_id;
bet.valid_time = eosio::current_time_point() + 180000;
bet.quantity = quantity;
bet.table_hash = table_hash;
bet.p1_name = from;
bet.p1_hash = user_hash;
bet.p2_hash = player_hash;
bet.p1_seed = user_seed;
});
}else{
// 选手需要检查user_hash为user_seed生成,
// 同时检查p1_hash与player_hash相等,同时检查p2_hash与user_hash相等,
// 同时检查table_hash与数据库的table_hash相等,同时检查数量相等。
eosio::check(bet->valid_time >= eosio::current_time_point(), "time expired");
eosio::check(quantity.amount == bet->quantity.amount, "must equal quantity");
eosio::check(player_hash == bet->p1_hash, "must match player hash");
eosio::check(user_hash == bet->p2_hash, "must match user hash");
eosio::check(table_hash == bet->table_hash, "must match table hash");
bets.modify(bet, _self, [&](auto &bet) {
bet.p2_name = from;
bet.p2_seed = user_seed;
});
}
}
ACTION pvpbetwallet::reveal(const uint64_t &table_id, const eosio::checksum256 &seed){
}
ACTION pvpbetwallet::send(const int &index, const name &winner, const uint64_t &table_id){
}