提交 0f1c7217 编写于 作者: D Daniel Larimer

Add sha256 crypto functions to C API

Stub out simple dice contract.
上级 5773dad9
namespace dice {
void apply_offer( const OfferBet& offer ) {
assert( offer.amount > 0, "insufficient bet" );
assert( !hasOffer( offer.commitment ), "offer with this commitment already exist" );
requireAuth( offer.player );
auto acnt = getAccount( offer.player );
acnt.balance -= offer.amount;
acnt.open_offers++;
save( acnt );
/**
* 1. Lookup lowerbound on offer's by OfferPrimaryKey
* if lowerbound.primary.bet == offer.bet
* GlobalDice.nextgameid++ (load and save to DB)
* create new Game and set game.bet == offer.bet
* set player1 == lowerbound player
* set player2 == offer.player
* update lowerbound.primary.bet = 0 and lwoerbound.gameid = GlobalDice.nextgameid
* Create Offer entry in Offers table with bet = 0 and gameid == --^
* else
* Create Offer entry in Offers table with bet = offer.bet and gameid = 0
*/
}
void apply_cancel( const CancelOffer& offer ) {
/**
* Lookup Offer in Offer's table and assert that gameid == 0
* Lookup account and increment balance by bet
* Deelte offer from offers table
*/
}
/**
* No authority required on this message so long as it is properly revealed
*/
void apply_reveal( const Reveal& offer ) {
assert_sha256( &offer.source, sizeof(offer.source), &offer.commitment );
/**
* assert offer already exists
* assert offer has a gameid > 0
*
* Lookup Game by gameid
* assert Game.player[x].reveal is 0 hasn't already been revealed
* set Game.player[x].reveal to revealed
*
* if( Game.player[!x].reveal != 0 ) {
* uint256_t result;
* sha256( &game.player1, sizeof(Player)*2, result);
* if( result.words[1] < result.words[0] ) {
* payPlayer1 by incrementing account by bet and decrement open games
* }
* else
* payPlayer2 by incrmenting account by bet and decrement open games
* delete game, and both offers
* }
* else {
* set Game.deadline = now() + timeout (5 minutes)
* }
*
*/
}
/**
* No authority required by this so long as
*/
void apply_claim( const ClaimExpired& claim ) {
/// lookup Game by id, assert now() > deadline and deadline != 0
/// pay the player that revealed
/// delete game and open offers
}
}
namespace dice {
struct OfferBet {
eos::Tokens amount;
AccountName player;
uint256 commitment;
};
struct CancelOffer {
uint256 commitment;
};
struct Reveal {
uint256 commitment;
uint256 source;
};
struct ClaimExpired {
uint64_t gameid = 0;
};
using EosTokens = eos::Tokens;
struct OfferPrimaryKey {
EosTokens bet;
AccountName owner;
};
/**
* This struct is used with i128xi128 index which allows us to lookup and
* iterate over offers by either {bet,owner,commitment} or {commitment,bet,owner}
*
* Only the first 128 bits of commitment ID are used in the index, but there will
* be a requirement that these first 128 bits be unique and any collisions will
* be rejected.
*
* If there is no existing offer of equal bet size then gameid is set as 0, if it is
* matched then a new Game record is created and the Offer is modified so that bet
* goes to 0 (and therefore moves to end of queue and not matched with other bets) and
* the gameid of both offers are updated.
*/
struct PACKED( Offer ) {
OfferPrimaryKey primary;
uint256 commitment;
uint32_t gameid = 0;
};
struct Player {
uint256 commitment;
uint256 reveal;
};
/**
*
*/
struct PACKED( Game ) {
uint32_t gameid;
EosTokens bet;
Time deadline;
Player player1;
Player player2;
};
struct Packed( GlobalDice ) {
uint32_t nextgameid = 0;
};
struct PACKED( Account ) {
Account( AccountName o = AccountName() ):owner(o){}
AccountName owner;
EosTokens eos_balance;
uint32_t open_offers = 0;
bool isEmpty()const { return ! ( bool(eos_balance) | open_offers); }
};
using Accounts = Table<N(dice),N(dice),N(account),Account,uint64_t>;
using GlobalDice = Table<N(dice),N(dice),N(global),GlobalDice,uint64_t>;
using Offers = Table<N(dice),N(dice),N(global),GlobalDice,OfferPrimaryKey,uint128_t>;
inline Account getAccount( AccountName owner ) {
Account account(owner);
Accounts::get( account );
return account;
}
};
#pragma once
#include <eoslib/types.h>
/**
* This method is implemented as:
*
* uint256 calc_hash;
* sha256( data, length, &calc_hash );
* assert( calc_hash == hash, "invalid hash" );
*
* This method is optimized to a NO-OP when in fast evaluation mode
*/
void assert_sha256( char* data, uint32_t length, const uint256* hash );
/**
* Calculates sha256( data,length) and stores result in memory pointed to by hash
*/
void sha256( char* data, uint32_t length, uint256* hash );
......@@ -22,4 +22,8 @@ typedef uint32_t Time;
#define PACKED(X) __attribute((packed)) X
struct uint256 {
uint64_t words[4];
};
} /// extern "C"
......@@ -58,6 +58,29 @@ DEFINE_INTRINSIC_FUNCTION0(env,checktime,checktime,none) {
if(res > 0) res += keylen;
return res;
}
DEFINE_INTRINSIC_FUNCTION3(env, assert_sha256,assert_sha256,none,i32,dataptr,i32,datalen,i32,hash) {
FC_ASSERT( datalen > 0 );
auto& wasm = wasm_interface::get();
auto mem = wasm.current_memory;
char* data = memoryArrayPtr<char>( mem, dataptr, datalen );
const auto& v = memoryRef<fc::sha256>( mem, hash );
auto result = fc::sha256::hash( data, datalen );
FC_ASSERT( result == v, "hash miss match" );
}
DEFINE_INTRINSIC_FUNCTION3(env,sha256,sha256,none,i32,dataptr,i32,datalen,i32,hash) {
FC_ASSERT( datalen > 0 );
auto& wasm = wasm_interface::get();
auto mem = wasm.current_memory;
char* data = memoryArrayPtr<char>( mem, dataptr, datalen );
auto& v = memoryRef<fc::sha256>( mem, hash );
v = fc::sha256::hash( data, datalen );
}
DEFINE_INTRINSIC_FUNCTION2(env,multeq_i128,multeq_i128,none,i32,self,i32,other) {
auto& wasm = wasm_interface::get();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册