提交 f038f6fa 编写于 作者: D Daniel Larimer

Fixed exchange contract so it fills bids

上级 4190d532
const char* currency_wast = R"=====(
(module
(type $FUNCSIG$ijjj (func (param i64 i64 i64) (result i32)))
(type $FUNCSIG$ijjii (func (param i64 i64 i32 i32) (result i32)))
(type $FUNCSIG$vj (func (param i64)))
(type $FUNCSIG$ijjjii (func (param i64 i64 i64 i32 i32) (result i32)))
(type $FUNCSIG$vii (func (param i32 i32)))
(type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(import "env" "assert" (func $assert (param i32 i32)))
(import "env" "load_i64" (func $load_i64 (param i64 i64 i64 i32 i32) (result i32)))
(import "env" "readMessage" (func $readMessage (param i32 i32) (result i32)))
(import "env" "remove_i64" (func $remove_i64 (param i64 i64 i64) (result i32)))
(import "env" "requireAuth" (func $requireAuth (param i64)))
(import "env" "requireNotice" (func $requireNotice (param i64)))
(import "env" "store_i64" (func $store_i64 (param i64 i64 i32 i32) (result i32)))
(table 0 anyfunc)
(memory $0 1)
(data (i32.const 4) "\90\04\00\00")
(data (i32.const 16) "integer underflow subtracting token balance\00")
(data (i32.const 64) "integer overflow adding token balance\00")
(data (i32.const 112) "message shorter than expected\00")
(export "memory" (memory $0))
(export "_ZN8currency12storeAccountEyRKNS_7AccountE" (func $_ZN8currency12storeAccountEyRKNS_7AccountE))
(export "_ZN8currency23apply_currency_transferERKNS_8TransferE" (func $_ZN8currency23apply_currency_transferERKNS_8TransferE))
(export "init" (func $init))
(export "apply" (func $apply))
(func $_ZN8currency12storeAccountEyRKNS_7AccountE (param $0 i64) (param $1 i32)
(block $label$0
(br_if $label$0
(i64.eq
(i64.load offset=8
(get_local $1)
)
(i64.const 0)
)
)
(drop
(call $store_i64
(get_local $0)
(i64.const 21967113313)
(get_local $1)
(i32.const 16)
)
)
(return)
)
(drop
(call $remove_i64
(get_local $0)
(i64.const 21967113313)
(i64.load
(get_local $1)
)
)
)
)
(func $_ZN8currency23apply_currency_transferERKNS_8TransferE (param $0 i32)
(local $1 i64)
(local $2 i32)
(i32.store offset=4
(i32.const 0)
(tee_local $2
(i32.sub
(i32.load offset=4
(i32.const 0)
)
(i32.const 32)
)
)
)
(set_local $1
(i64.load
(get_local $0)
)
)
(call $requireNotice
(i64.load offset=8
(get_local $0)
)
)
(call $requireNotice
(get_local $1)
)
(call $requireAuth
(i64.load
(get_local $0)
)
)
(i64.store offset=16
(get_local $2)
(i64.const 21967113313)
)
(i64.store offset=24
(get_local $2)
(i64.const 0)
)
(drop
(call $load_i64
(i64.load
(get_local $0)
)
(i64.const 862690298531)
(i64.const 21967113313)
(i32.add
(get_local $2)
(i32.const 16)
)
(i32.const 16)
)
)
(i64.store
(get_local $2)
(i64.const 21967113313)
)
(i64.store offset=8
(get_local $2)
(i64.const 0)
)
(drop
(call $load_i64
(i64.load offset=8
(get_local $0)
)
(i64.const 862690298531)
(i64.const 21967113313)
(get_local $2)
(i32.const 16)
)
)
(call $assert
(i64.ge_u
(i64.load offset=24
(get_local $2)
)
(i64.load offset=16
(get_local $0)
)
)
(i32.const 16)
)
(i64.store offset=24
(get_local $2)
(i64.sub
(i64.load offset=24
(get_local $2)
)
(tee_local $1
(i64.load offset=16
(get_local $0)
)
)
)
)
(call $assert
(i64.ge_u
(i64.add
(get_local $1)
(i64.load offset=8
(get_local $2)
)
)
(get_local $1)
)
(i32.const 64)
)
(i64.store offset=8
(get_local $2)
(i64.add
(i64.load offset=8
(get_local $2)
)
(i64.load offset=16
(get_local $0)
)
)
)
(set_local $1
(i64.load
(get_local $0)
)
)
(block $label$0
(block $label$1
(br_if $label$1
(i64.eq
(i64.load offset=24
(get_local $2)
)
(i64.const 0)
)
)
(drop
(call $store_i64
(get_local $1)
(i64.const 21967113313)
(i32.add
(get_local $2)
(i32.const 16)
)
(i32.const 16)
)
)
(br $label$0)
)
(drop
(call $remove_i64
(get_local $1)
(i64.const 21967113313)
(i64.load offset=16
(get_local $2)
)
)
)
)
(set_local $1
(i64.load
(i32.add
(get_local $0)
(i32.const 8)
)
)
)
(block $label$2
(block $label$3
(br_if $label$3
(i64.eq
(i64.load
(i32.add
(get_local $2)
(i32.const 8)
)
)
(i64.const 0)
)
)
(drop
(call $store_i64
(get_local $1)
(i64.const 21967113313)
(get_local $2)
(i32.const 16)
)
)
(br $label$2)
)
(drop
(call $remove_i64
(get_local $1)
(i64.const 21967113313)
(i64.load
(get_local $2)
)
)
)
)
(i32.store offset=4
(i32.const 0)
(i32.add
(get_local $2)
(i32.const 32)
)
)
)
(func $init
(local $0 i32)
(i32.store offset=4
(i32.const 0)
(tee_local $0
(i32.sub
(i32.load offset=4
(i32.const 0)
)
(i32.const 16)
)
)
)
(i64.store offset=8
(get_local $0)
(i64.const 1000000000)
)
(i64.store
(get_local $0)
(i64.const 21967113313)
)
(drop
(call $store_i64
(i64.const 862690298531)
(i64.const 21967113313)
(get_local $0)
(i32.const 16)
)
)
(i32.store offset=4
(i32.const 0)
(i32.add
(get_local $0)
(i32.const 16)
)
)
)
(func $apply (param $0 i64) (param $1 i64)
(local $2 i32)
(i32.store offset=4
(i32.const 0)
(tee_local $2
(i32.sub
(i32.load offset=4
(i32.const 0)
)
(i32.const 32)
)
)
)
(block $label$0
(br_if $label$0
(i64.ne
(get_local $0)
(i64.const 862690298531)
)
)
(br_if $label$0
(i64.ne
(get_local $1)
(i64.const 624065709652)
)
)
(i64.store offset=24
(get_local $2)
(i64.const 0)
)
(call $assert
(i32.gt_u
(call $readMessage
(i32.add
(get_local $2)
(i32.const 8)
)
(i32.const 24)
)
(i32.const 23)
)
(i32.const 112)
)
(call $_ZN8currency23apply_currency_transferERKNS_8TransferE
(i32.add
(get_local $2)
(i32.const 8)
)
)
)
(i32.store offset=4
(i32.const 0)
(i32.add
(get_local $2)
(i32.const 32)
)
)
)
)
)=====";
......@@ -74,7 +74,7 @@ namespace eos {
}
private:
uint128_t value;
uint128_t value = 0;
};
/**
......
#pragma once
#include <eoslib/message.h>
#include <eoslib/print.hpp>
namespace eos {
......
......@@ -5,6 +5,7 @@
namespace eos {
static_assert( sizeof(long) == sizeof(int), "unexpected size difference" );
inline void print( const char* ptr ) {
prints(ptr);
......@@ -19,6 +20,9 @@ namespace eos {
inline void print( int num ) {
printi(num);
}
inline void print( unsigned int num ) {
printi(num);
}
inline void print( uint128 num ) {
printi128((uint128_t*)&num);
......
......@@ -101,10 +101,13 @@ namespace eos {
}
friend QuoteToken operator / ( BaseToken b, const price& q ) {
return QuoteToken( uint64_t((uint128(b.quantity) * uint128(precision) ) / q.base_per_quote) );
eos::print( "operator/ ", uint128(b.quantity), " * ", uint128( precision ), " / ", q.base_per_quote, "\n" );
return QuoteToken( uint64_t((uint128(b.quantity) * uint128(precision) / q.base_per_quote)) );
}
friend BaseToken operator * ( QuoteToken b, const price& q ) {
friend BaseToken operator * ( const QuoteToken& b, const price& q ) {
eos::print( "b: ", b, " \n" );
eos::print( "operator* ", uint128(b.quantity), " * ", uint128( q.base_per_quote ), " / ", precision, "\n" );
//return QuoteToken( uint64_t( mult_div_i128( b.quantity, q.base_per_quote, precision ) ) );
return BaseToken( uint64_t((b.quantity * q.base_per_quote) / precision) );
}
......
......@@ -20,4 +20,6 @@ typedef uint64_t TokenName;
typedef uint64_t TableName;
typedef uint32_t Time;
#define PACKED(X) __attribute((packed)) X
} /// extern "C"
......@@ -99,6 +99,8 @@ void apply_eos_transfer( const eos::Transfer& transfer ) {
}
void match( Bid& bid, Account& buyer, Ask& ask, Account& seller ) {
print( "match bid: ", bid, "\nmatch ask: ", ask, "\n");
eos::Tokens ask_eos = ask.quantity * ask.price;
EosTokens fill_amount_eos = min<eos::Tokens>( ask_eos, bid.quantity );
......@@ -150,7 +152,8 @@ void apply_exchange_buy( BuyOrder order ) {
return;
}
print( "asks found, lets see what matches\n" );
print( "ask: ", lowest_ask, "\n" );
print( "bid: ", bid, "\n" );
auto seller_account = getAccount( lowest_ask.seller.name );
......
......@@ -12,21 +12,31 @@ namespace exchange {
typedef eos::price<EosTokens,CurrencyTokens> Price;
struct Bid {
struct PACKED( Bid ) {
OrderID buyer;
Price price;
eos::Tokens quantity;
Time expiration;
void print() {
eos::print( "{ quantity: ", quantity, ", price: ", price, " }" );
}
};
static_assert( sizeof(Bid) == 32+12, "unexpected padding" );
struct Ask {
struct PACKED( Ask ) {
OrderID seller;
Price price;
CurrencyTokens quantity;
Time expiration;
void print() {
eos::print( "{ quantity: ", quantity, ", price: ", price, " }" );
}
};
static_assert( sizeof(Ask) == 32+12, "unexpected padding" );
struct Account {
struct PACKED( Account ) {
Account( AccountName o = AccountName() ):owner(o){}
AccountName owner;
......
此差异已折叠。
......@@ -29,6 +29,13 @@ struct Message : public types::Message {
}
Message(const types::Message& m) : types::Message(m) {}
template<typename T>
void set_packed(const types::FuncName& t, const T& value) {
type = t;
data.resize(sizeof(value));
memcpy( data.data(), &value, sizeof(value) );
}
template<typename T>
void set(const types::FuncName& t, const T& value) {
type = t;
......
......@@ -82,6 +82,7 @@ class apply_context : public precondition_validate_context {
int32_t store_i64( Name scope, Name table, Name key, const char* data, uint32_t len);
int32_t remove_i64( Name scope, Name table, Name key );
int32_t remove_i128i128( Name scope, Name table, uint128_t primary, uint128_t secondary );
int32_t store_i128i128( Name scope, Name table, uint128_t primary, uint128_t secondary,
const char* data, uint32_t len );
......
......@@ -259,6 +259,21 @@ int32_t message_validate_context::lowerbound_secondary_i128i128( Name scope, Nam
return copylen;
}
int32_t apply_context::remove_i128i128( Name scope, Name table, uint128_t primary, uint128_t secondary ) {
require_scope( scope );
const auto* obj = db.find<key128x128_value_object,by_scope_primary>( boost::make_tuple(
AccountName(scope),
AccountName(code),
AccountName(table),
primary, secondary) );
if( obj ) {
mutable_db.remove( *obj );
return 1;
}
return 0;
}
int32_t apply_context::remove_i64( Name scope, Name table, Name key ) {
require_scope( scope );
......
......@@ -21,8 +21,8 @@ namespace eos { namespace chain {
DEFINE_INTRINSIC_FUNCTION2(env,multeq_i128,multeq_i128,none,i32,self,i32,other) {
auto& wasm = wasm_interface::get();
auto mem = wasm.current_memory;
uint128_t& v = memoryRef<uint128_t>( mem, self );
const uint128_t& o= memoryRef<const uint128_t>( mem, other );
auto& v = memoryRef<unsigned __int128>( mem, self );
const auto& o = memoryRef<const unsigned __int128>( mem, other );
v *= o;
}
......@@ -30,8 +30,8 @@ DEFINE_INTRINSIC_FUNCTION2(env,multeq_i128,multeq_i128,none,i32,self,i32,other)
DEFINE_INTRINSIC_FUNCTION2(env,diveq_i128,diveq_i128,none,i32,self,i32,other) {
auto& wasm = wasm_interface::get();
auto mem = wasm.current_memory;
uint128_t& v = memoryRef<uint128_t>( mem, self );
const uint128_t& o = memoryRef<const uint128_t>( mem, other );
auto& v = memoryRef<unsigned __int128>( mem, self );
const auto& o = memoryRef<const unsigned __int128>( mem, other );
FC_ASSERT( o != 0, "divide by zero" );
v /= o;
}
......@@ -61,9 +61,17 @@ DEFINE_INTRINSIC_FUNCTION4(env,store_i128i128,store_i128i128,i32,i64,scope,i64,t
return result;
}
struct i128_keys {
uint128_t primary;
uint128_t secondary;
};
DEFINE_INTRINSIC_FUNCTION3(env,remove_i128i128,remove_i128i128,i32,i64,scope,i64,table,i32,data) {
FC_ASSERT( !"remove not implemented" );
return 0;
auto& wasm = wasm_interface::get();
FC_ASSERT( wasm.current_apply_context, "not a valid apply context" );
const i128_keys& keys = memoryRef<const i128_keys>( wasm.current_memory, data );
return wasm_interface::get().current_apply_context->remove_i128i128( Name(scope), Name(table), keys.primary, keys.secondary );
}
DEFINE_INTRINSIC_FUNCTION5(env,load_primary_i128i128,load_primary_i128i128,i32,i64,scope,i64,code,i64,table,i32,data,i32,datalen) {
......@@ -237,11 +245,14 @@ DEFINE_INTRINSIC_FUNCTION2(env,send,send,i32,i32,trx_buffer, i32,trx_buffer_size
DEFINE_INTRINSIC_FUNCTION2(env,readMessage,readMessage,i32,i32,destptr,i32,destsize) {
FC_ASSERT( destsize > 0 );
wasm_interface& wasm = wasm_interface::get();
auto mem = wasm.current_memory;
char* begin = memoryArrayPtr<char>( mem, destptr, destsize );
char* begin = memoryArrayPtr<char>( mem, destptr, uint32_t(destsize) );
int minlen = std::min<int>(wasm.current_validate_context->msg.data.size(), destsize);
wdump((destsize)(wasm.current_validate_context->msg.data.size()));
memcpy( begin, wasm.current_validate_context->msg.data.data(), minlen );
return minlen;
}
......@@ -273,8 +284,9 @@ DEFINE_INTRINSIC_FUNCTION1(env,printi,printi,none,i64,val) {
DEFINE_INTRINSIC_FUNCTION1(env,printi128,printi128,none,i32,val) {
auto& wasm = wasm_interface::get();
auto mem = wasm.current_memory;
fc::uint128_t& value = memoryRef<fc::uint128_t>( mem, val );
std::cerr << fc::variant(value).get_string();
auto& value = memoryRef<unsigned __int128>( mem, val );
fc::uint128_t v(value>>64, uint64_t(value) );
std::cerr << fc::variant(v).get_string();
}
DEFINE_INTRINSIC_FUNCTION1(env,printn,printn,none,i64,val) {
std::cerr << Name(val).toString();
......
......@@ -32,13 +32,17 @@ namespace fc
uint128( uint64_t _h, uint64_t _l )
:hi(_h),lo(_l){}
uint128( const fc::bigint& bi );
uint128( unsigned __int128 i ) {
memcpy(this, (char*)&i, sizeof(i) );
}
explicit uint128( unsigned __int128 i ):hi( i >> 64 ), lo(i){ }
operator std::string()const;
operator fc::bigint()const;
explicit operator unsigned __int128()const {
unsigned __int128 result(hi);
result <<= 64;
return result | lo;
}
bool operator == ( const uint128& o )const{ return hi == o.hi && lo == o.lo; }
bool operator != ( const uint128& o )const{ return hi != o.hi || lo != o.lo; }
bool operator < ( const uint128& o )const { return (hi == o.hi) ? lo < o.lo : hi < o.hi; }
......
......@@ -54,21 +54,23 @@ using namespace chain;
uint64_t number = 0;
};
struct Bid {
struct __attribute((packed)) Bid {
OrderID buyer;
fc::uint128_t price;
unsigned __int128 price;
uint64_t quantity;
Time expiration;
uint8_t fill_or_kill = false;
};
struct Ask {
struct __attribute((packed)) Ask {
OrderID seller;
fc::uint128_t price;
unsigned __int128 price;
uint64_t quantity;
Time expiration;
uint8_t fill_or_kill = false;
};
FC_REFLECT( OrderID, (name)(number) );
FC_REFLECT( Bid, (buyer)(price)(quantity)(expiration) );
FC_REFLECT( Ask, (seller)(price)(quantity)(expiration) );
FC_REFLECT( Bid, (buyer)(price)(quantity)(expiration)(fill_or_kill) );
FC_REFLECT( Ask, (seller)(price)(quantity)(expiration)(fill_or_kill) );
struct record {
uint64_t a = 0;
......@@ -369,9 +371,9 @@ BOOST_FIXTURE_TEST_CASE(create_script, testing_fixture)
static const uint64_t precision = 1000ll*1000ll*1000ll*1000ll*1000ll;
fc::uint128_t to_price( double p ) {
unsigned __int128 to_price( double p ) {
uint64_t pi(p);
fc::uint128_t result(pi);
unsigned __int128 result(pi);
result *= precision;
double fract = p - pi;
......@@ -393,6 +395,7 @@ void SellCurrency( testing_blockchain& chain, AccountName seller, AccountName ex
trx.emplaceMessage("exchange", sort_names( {} ),
vector<types::AccountPermission>{ {seller,"active"} },
"sell", b );
//trx.messages.back().set_packed( "sell", b);
trx.expiration = chain.head_block_time() + 100;
trx.set_reference_block(chain.head_block_id());
chain.push_transaction(trx);
......@@ -410,6 +413,7 @@ void BuyCurrency( testing_blockchain& chain, AccountName buyer, AccountName exch
trx.emplaceMessage("exchange", sort_names( {} ),
vector<types::AccountPermission>{ {buyer,"active"} },
"buy", b );
//trx.messages.back().set_packed( "buy", b);
trx.expiration = chain.head_block_time() + 100;
trx.set_reference_block(chain.head_block_id());
chain.push_transaction(trx);
......@@ -464,7 +468,8 @@ BOOST_FIXTURE_TEST_CASE(create_exchange, testing_fixture) {
//BOOST_REQUIRE_THROW( SellCurrency( chain, "initb", "exchange", 1, 100, .5 ), fc::exception ); // order id already exists
//SellCurrency( chain, "initb", "exchange", 2, 100, .75 );
BuyCurrency( chain, "initb", "exchange", 1, 50, .25 );
// BuyCurrency( chain, "initb", "exchange", 1, 50, .25 );
BuyCurrency( chain, "initb", "exchange", 1, 50, .5 );
//BOOST_REQUIRE_THROW( BuyCurrency( chain, "initb", "exchange", 1, 50, .25 ), fc::exception ); // order id already exists
/// this should buy 5 from initb order 2 at a price of .75
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册