From fb2fa941d5b5c4604ed8348b4cd3a2e138c4bdbc Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Fri, 14 Jul 2017 20:46:23 -0400 Subject: [PATCH] progress on testing exchange contract --- contracts/eoslib/db.h | 2 +- contracts/eoslib/db.hpp | 3 +- contracts/eoslib/print.hpp | 5 + contracts/eoslib/token.hpp | 14 ++- contracts/exchange/exchange.cpp | 16 +-- libraries/chain/chain_controller.cpp | 1 + .../include/eos/chain/chain_controller.hpp | 3 +- .../include/eos/chain/key_value_object.hpp | 21 ++-- libraries/chain/message_handling_contexts.cpp | 92 ++++++++++++---- libraries/chain/wasm_interface.cpp | 62 ++++++++--- libraries/fc/include/fc/uint128.hpp | 5 + libraries/fc/src/uint128.cpp | 2 + libraries/types/include/eos/types/native.hpp | 2 + tests/slow_tests/slow_tests.cpp | 102 +++++++++++++++++- 14 files changed, 264 insertions(+), 66 deletions(-) diff --git a/contracts/eoslib/db.h b/contracts/eoslib/db.h index 2ea81f6be..f378a93f3 100644 --- a/contracts/eoslib/db.h +++ b/contracts/eoslib/db.h @@ -31,7 +31,7 @@ int32_t remove_i64( AccountName scope, TableName table, uint64_t key ); * 32 bytes are the primary and secondary keys. These keys will be interpreted and sorted as unsigned * 128 bit integers. * - * @return the total number of bytes read or -1 for "not found" or "end". + * @return the total number of bytes read or -1 for "not found" or "end" where bytes read includes 32 bytes of the key */ ///@{ int32_t front_primary_i128i128( AccountName scope, AccountName code, TableName table, void* data, uint32_t len ); diff --git a/contracts/eoslib/db.hpp b/contracts/eoslib/db.hpp index c9ed0f4dc..8b46e43a5 100644 --- a/contracts/eoslib/db.hpp +++ b/contracts/eoslib/db.hpp @@ -138,7 +138,8 @@ struct Table { }; static bool store( const Record& r ) { - return impl::store( scope, table, &r, sizeof(r) ); + assert( impl::store( scope, table, &r, sizeof(r) ), "error storing record" ); + return true; } static bool remove( const Record& r ) { return impl::remove( scope, table, &r ); diff --git a/contracts/eoslib/print.hpp b/contracts/eoslib/print.hpp index 08b47274f..bda1b23be 100644 --- a/contracts/eoslib/print.hpp +++ b/contracts/eoslib/print.hpp @@ -28,6 +28,11 @@ namespace eos { printn(name.value); } + template + inline void print_native( T&& t ) { + t.print(); + } + template inline void print( Arg a ) { print_native(a); diff --git a/contracts/eoslib/token.hpp b/contracts/eoslib/token.hpp index 073c3a7cc..91ef16ec9 100644 --- a/contracts/eoslib/token.hpp +++ b/contracts/eoslib/token.hpp @@ -1,10 +1,13 @@ #pragma once #include +#include namespace eos { template struct token { + static const uint64_t currency_type = CurrencyType; + token(){} explicit token( NumberType v ):quantity(v){}; NumberType quantity = 0; @@ -41,6 +44,10 @@ namespace eos { friend bool operator != ( const token& a, const token& b ) { return a.quantity != b.quantity; } explicit operator bool()const { return quantity != 0; } + + inline void print() { + eos::print( quantity, " ", Name(CurrencyType) ); + } }; /** @@ -49,6 +56,8 @@ namespace eos { template struct price { + typedef BaseToken base_token_type; + typedef QuoteToken quote_token_type; /** * The largest base 10 integer that can be represented with 53 bits of * a double. This number keeps the math in range of JavaScript. By @@ -84,7 +93,10 @@ namespace eos { friend bool operator == ( const price& a, const price& b ) { return a.base_per_quote == b.base_per_quote; } friend bool operator != ( const price& a, const price& b ) { return a.base_per_quote != b.base_per_quote; } -// private: + inline void print() { + eos::print( base_per_quote, ".", " ", Name(base_token_type::currency_type), "/", Name(quote_token_type::currency_type) ); + } + private: /** * represented as number of base tokens to purchase 1 quote token */ diff --git a/contracts/exchange/exchange.cpp b/contracts/exchange/exchange.cpp index e719b25fa..d93e4b72b 100644 --- a/contracts/exchange/exchange.cpp +++ b/contracts/exchange/exchange.cpp @@ -65,20 +65,12 @@ inline void modifyAccount( AccountName a, Lambda&& modify ) { void apply_currency_transfer( const currency::Transfer& transfer ) { if( transfer.to == N(exchange) ) { modifyAccount( transfer.from, [&]( Account& account ){ - print( "balance: " ); - printi( account.currency_balance.quantity ); - print( "deposit: " ); - printi( transfer.quantity.quantity ); account.currency_balance += transfer.quantity; }); } else if( transfer.from == N(exchange) ) { requireAuth( transfer.to ); /// require the reciever of funds (account owner) to authorize this transfer modifyAccount( transfer.to, [&]( Account& account ){ - print( "balance: " ); - printi( account.currency_balance.quantity ); - print( "withdraw: " ); - printi( transfer.quantity.quantity ); account.currency_balance -= transfer.quantity; }); } else { @@ -140,7 +132,7 @@ void apply_exchange_buy( BuyOrder order ) { assert( bid.quantity > eos::Tokens(0), "invalid quantity" ); assert( bid.expiration > now(), "order expired" ); - print( Name(bid.buyer.name), " created bid for ", order.quantity.quantity, " currency at price: ", order.price.base_per_quote, "\n" ); + print( Name(bid.buyer.name), " created bid for ", order.quantity, " currency at price: ", order.price, "\n" ); Bid existing_bid; assert( !BidsById::get( bid.buyer, existing_bid ), "order with this id already exists" ); @@ -183,7 +175,7 @@ void apply_exchange_buy( BuyOrder order ) { save( buyer_account ); print( "saving buyer's account\n" ); if( bid.quantity ) { - print( bid.quantity.quantity, " eos left over" ); + print( bid.quantity, " eos left over" ); assert( !order.fill_or_kill, "order not completely filled" ); Bids::store( bid ); return; @@ -199,8 +191,8 @@ void apply_exchange_sell( SellOrder order ) { assert( ask.quantity > currency::Tokens(0), "invalid quantity" ); assert( ask.expiration > now(), "order expired" ); - print( "\n\n", Name(ask.seller.name), " created sell for ", order.quantity.quantity, - " currency at price: ", order.price.base_per_quote, "\n"); + print( "\n\n", Name(ask.seller.name), " created sell for ", order.quantity, + " currency at price: ", order.price, "\n"); Ask existing_ask; assert( !AsksById::get( ask.seller, existing_ask ), "order with this id already exists" ); diff --git a/libraries/chain/chain_controller.cpp b/libraries/chain/chain_controller.cpp index b605d4549..5370e1791 100644 --- a/libraries/chain/chain_controller.cpp +++ b/libraries/chain/chain_controller.cpp @@ -606,6 +606,7 @@ void chain_controller::process_message( const Transaction& trx, const Message& m apply_message(apply_ctx); for (const auto& recipient : message.recipients) { + if( recipient == message.code ) continue; /// we already ran it above try { apply_context recipient_ctx(*this,_db, trx, message, recipient); validate_message_precondition(recipient_ctx); diff --git a/libraries/chain/include/eos/chain/chain_controller.hpp b/libraries/chain/include/eos/chain/chain_controller.hpp index c60f0ef13..fb9194b5c 100644 --- a/libraries/chain/include/eos/chain/chain_controller.hpp +++ b/libraries/chain/include/eos/chain/chain_controller.hpp @@ -216,8 +216,9 @@ namespace eos { namespace chain { uint32_t last_irreversible_block_num() const; - protected: + // protected: const chainbase::database& get_database() const { return _db; } + chainbase::database& get_mutable_database() { return _db; } private: diff --git a/libraries/chain/include/eos/chain/key_value_object.hpp b/libraries/chain/include/eos/chain/key_value_object.hpp index 1d3235b42..cba97b61b 100644 --- a/libraries/chain/include/eos/chain/key_value_object.hpp +++ b/libraries/chain/include/eos/chain/key_value_object.hpp @@ -61,9 +61,9 @@ namespace eos { namespace chain { OBJECT_CTOR(key128x128_value_object, (value)) id_type id; - AccountName scope; - AccountName code; - AccountName table; + uint64_t scope; + uint64_t code; + uint64_t table; uint128_t primary_key; uint128_t secondary_key; shared_string value; @@ -77,9 +77,9 @@ namespace eos { namespace chain { ordered_unique, member>, ordered_unique, composite_key< key128x128_value_object, - member, - member, - member, + member, + member, + member, member, member >, @@ -87,13 +87,12 @@ namespace eos { namespace chain { >, ordered_unique, composite_key< key128x128_value_object, - member, - member, - member, + member, + member, + member, member, member - >, - composite_key_compare< std::less,std::less,std::less,std::less, std::less > + > > > >; diff --git a/libraries/chain/message_handling_contexts.cpp b/libraries/chain/message_handling_contexts.cpp index beb0da991..878df795d 100644 --- a/libraries/chain/message_handling_contexts.cpp +++ b/libraries/chain/message_handling_contexts.cpp @@ -61,10 +61,12 @@ int32_t message_validate_context::load_i64( Name scope, Name code, Name table, N int32_t message_validate_context::back_primary_i128i128( Name scope, Name code, Name table, uint128_t* primary, uint128_t* secondary, char* value, uint32_t valuelen ) { + return -1; + /* require_scope( scope ); const auto& idx = db.get_index(); - auto itr = idx.lower_bound( boost::make_tuple( AccountName(scope), - AccountName(code), + auto itr = idx.lower_bound( boost::make_tuple( uint64_t(scope), + uint64_t(code), table.value+1, *primary, uint128_t(0) ) ); @@ -86,11 +88,13 @@ int32_t message_validate_context::back_primary_i128i128( Name scope, Name code, itr->value.copy(value, copylen); } return copylen; + */ } int32_t message_validate_context::back_secondary_i128i128( Name scope, Name code, Name table, uint128_t* primary, uint128_t* secondary, char* value, uint32_t valuelen ) { + /* require_scope( scope ); const auto& idx = db.get_index(); auto itr = idx.lower_bound( boost::make_tuple( AccountName(scope), @@ -116,17 +120,20 @@ int32_t message_validate_context::back_secondary_i128i128( Name scope, Name code itr->value.copy(value, copylen); } return copylen; + */ + return -1; } int32_t message_validate_context::front_primary_i128i128( Name scope, Name code, Name table, uint128_t* primary, uint128_t* secondary, char* value, uint32_t valuelen ) { + /* require_scope( scope ); const auto& idx = db.get_index(); - auto itr = idx.lower_bound( boost::make_tuple( AccountName(scope), - AccountName(code), - AccountName(table), + auto itr = idx.lower_bound( boost::make_tuple( uint64_t(scope), + uint64_t(code), + uint64_t(table), *primary, uint128_t(0) ) ); if( itr == idx.end() ) @@ -147,20 +154,55 @@ int32_t message_validate_context::front_primary_i128i128( Name scope, Name code, itr->value.copy(value, copylen); } return copylen; + */ + return -1; } int32_t message_validate_context::front_secondary_i128i128( Name scope, Name code, Name table, uint128_t* primary, uint128_t* secondary, char* value, uint32_t valuelen ) { require_scope( scope ); const auto& idx = db.get_index(); + /* auto itr = idx.lower_bound( boost::make_tuple( AccountName(scope), AccountName(code), AccountName(table), - *secondary, uint128_t(0) ) ); + uint128_t(0), uint128_t(0) ) ); + */ + auto itr = idx.lower_bound( boost::make_tuple( uint64_t(0ull), + uint64_t(0ull), + uint64_t(0ull), + uint128_t(0), + uint128_t(0)) ); + + wdump((scope)(code)(table)); + idump((idx.size())); + for( const auto& item : idx ) { + auto tup = boost::make_tuple( item.scope, item.code, item.table, item.primary_key, item.secondary_key ); + auto in = boost::make_tuple( AccountName(scope), AccountName(code), AccountName(table), + uint128_t(1), uint128_t(1) ); + idump( (scope)(code)(table)(fc::uint128(*primary))(fc::uint128(*secondary)) ); + if( item.scope == uint64_t(scope) ) + if( item.code == uint64_t(code) ) + if( item.table == uint64_t(table) ) + { + ilog( "matching scope, code, table" ); + /* + if( item.secondary_key >= uint128_t(0) ) { + idump( "secondary_key >= 0" ); + if( item.primary_key >= uint128_t(0) ) + idump( "primary_key >= 0" ); + } + */ + } + + wdump( (item.scope)(item.code)(item.table)(fc::uint128(item.primary_key))(fc::uint128(item.secondary_key)) ); + } + ilog("."); if( itr == idx.end() ) return -1; + /* --itr; if( itr->scope != scope || @@ -176,6 +218,8 @@ int32_t message_validate_context::front_secondary_i128i128( Name scope, Name cod itr->value.copy(value, copylen); } return copylen; + */ + return -1; } @@ -184,15 +228,15 @@ int32_t message_validate_context::load_primary_i128i128( Name scope, Name code, require_scope( scope ); const auto& idx = db.get_index(); - auto itr = idx.lower_bound( boost::make_tuple( AccountName(scope), - AccountName(code), - AccountName(table), + auto itr = idx.lower_bound( boost::make_tuple( uint64_t(scope), + uint64_t(code), + uint64_t(table), *primary, uint128_t(0) ) ); if( itr == idx.end() || - itr->scope != scope || - itr->code != code || - itr->table != table || + itr->scope != uint64_t(scope) || + itr->code != uint64_t(code) || + itr->table != uint64_t(table) || itr->primary_key != *primary ) return -1; *secondary = itr->secondary_key; @@ -206,11 +250,12 @@ int32_t message_validate_context::load_primary_i128i128( Name scope, Name code, int32_t message_validate_context::lowerbound_primary_i128i128( Name scope, Name code, Name table, uint128_t* primary, uint128_t* secondary, char* value, uint32_t valuelen ) { + /* require_scope( scope ); const auto& idx = db.get_index(); - auto itr = idx.lower_bound( boost::make_tuple( AccountName(scope), - AccountName(code), - AccountName(table), + auto itr = idx.lower_bound( boost::make_tuple( uint64_t(scope), + uint64_t(code), + uint64_t(table), *primary, uint128_t(0) ) ); if( itr == idx.end() || @@ -226,16 +271,19 @@ int32_t message_validate_context::lowerbound_primary_i128i128( Name scope, Name itr->value.copy(value, copylen); } return copylen; + */ + return -1; } int32_t message_validate_context::lowerbound_secondary_i128i128( Name scope, Name code, Name table, uint128_t* primary, uint128_t* secondary, char* value, uint32_t valuelen ) { + /* require_scope( scope ); const auto& idx = db.get_index(); - auto itr = idx.lower_bound( boost::make_tuple( AccountName(scope), - AccountName(code), - AccountName(table), + auto itr = idx.lower_bound( boost::make_tuple( uint64_t(scope), + uint64_t(code), + uint64_t(table), uint128_t(0), *secondary ) ); if( itr == idx.end() || @@ -251,6 +299,8 @@ int32_t message_validate_context::lowerbound_secondary_i128i128( Name scope, Nam itr->value.copy(value, copylen); } return copylen; + */ + return -1; } int32_t apply_context::remove_i64( Name scope, Name table, Name key ) { @@ -300,14 +350,18 @@ int32_t apply_context::store_i128i128( Name scope, Name table, uint128_t primary AccountName(code), AccountName(table), primary, secondary ) ); + idump(( *((fc::uint128_t*)&primary)) ); + idump(( *((fc::uint128_t*)&secondary)) ); if( obj ) { + wlog( "modify" ); mutable_db.modify( *obj, [&]( auto& o ) { o.primary_key = primary; o.secondary_key = secondary; o.value.assign(value, valuelen); }); - return 0; + return valuelen; } else { + wlog( "new" ); mutable_db.create( [&](auto& o) { o.scope = scope; o.code = code; diff --git a/libraries/chain/wasm_interface.cpp b/libraries/chain/wasm_interface.cpp index 65d66caa6..c82922c64 100644 --- a/libraries/chain/wasm_interface.cpp +++ b/libraries/chain/wasm_interface.cpp @@ -41,16 +41,24 @@ DEFINE_INTRINSIC_FUNCTION0(env,now,now,i32) { } DEFINE_INTRINSIC_FUNCTION4(env,store_i128i128,store_i128i128,i32,i64,scope,i64,table,i32,data,i32,datalen) { + static const uint32_t keylen = 2*sizeof(uint128_t); + FC_ASSERT( datalen >= keylen, "insufficient data passed" ); + auto& wasm = wasm_interface::get(); FC_ASSERT( wasm.current_apply_context, "not a valid apply context" ); - char* v = &memoryRef( wasm.current_memory, data ); - uint128_t& primary = *((uint128_t*)v); - uint128_t& secondary = *(((uint128_t*)v)+1); - char* value = v + 2*sizeof(uint128_t); - return wasm_interface::get().current_apply_context->store_i128i128( + char* v = memoryArrayPtr( wasm.current_memory, data, datalen ); + + uint128_t* primary = ((uint128_t*)v); + uint128_t* secondary = primary + 1; + + char* value = (char*)(secondary+1); + uint32_t valuelen = datalen - keylen; + auto result = wasm_interface::get().current_apply_context->store_i128i128( Name(scope), Name(table), - primary, secondary, value, datalen - 2*sizeof(uint128_t) ); + *primary, *secondary, value, valuelen ) + keylen; + wdump((datalen)(valuelen)(result)); + return result; } DEFINE_INTRINSIC_FUNCTION3(env,remove_i128i128,remove_i128i128,i32,i64,scope,i64,table,i32,data) { @@ -72,31 +80,52 @@ DEFINE_INTRINSIC_FUNCTION5(env,load_secondary_i128i128,load_secondary_i128i128,i } DEFINE_INTRINSIC_FUNCTION5(env,back_primary_i128i128,back_primary_i128i128,i32,i64,scope,i64,code,i64,table,i32,data,i32,datalen) { - + wlog( "back primary" ); auto& wasm = wasm_interface::get(); char* v = &memoryRef( wasm.current_memory, data ); return wasm_interface::get().current_validate_context->back_primary_i128i128( Name(scope), Name(code), Name(table), (uint128_t*)v, (uint128_t*)(v+sizeof(uint128_t)), v, datalen-(2*sizeof(uint128_t)) ); } DEFINE_INTRINSIC_FUNCTION5(env,front_primary_i128i128,front_primary,i32,i64,scope,i64,code,i64,table,i32,data,i32,datalen) { + wlog( "front primary" ); auto& wasm = wasm_interface::get(); char* v = &memoryRef( wasm.current_memory, data ); return wasm_interface::get().current_validate_context->front_primary_i128i128( Name(scope), Name(code), Name(table), - (uint128_t*)v, (uint128_t*)(v+sizeof(uint128_t)), v, datalen-(2*sizeof(uint128_t)) ); + (uint128_t*)v, (uint128_t*)(v+sizeof(uint128_t)), + v, datalen-(2*sizeof(uint128_t)) ) + 2*sizeof(uint128_t); } DEFINE_INTRINSIC_FUNCTION5(env,back_secondary_i128i128,back_secondary_i128i128,i32,i64,scope,i64,code,i64,table,i32,data,i32,datalen) { + wlog( "back secondary" ); auto& wasm = wasm_interface::get(); - char* v = &memoryRef( wasm.current_memory, data ); + char* v = memoryArrayPtr( wasm.current_memory, data, datalen ); + + + return wasm_interface::get().current_validate_context->back_secondary_i128i128( Name(scope), Name(code), Name(table), (uint128_t*)v, (uint128_t*)(v+sizeof(uint128_t)), v, datalen-(2*sizeof(uint128_t)) ); - return 0; } DEFINE_INTRINSIC_FUNCTION5(env,front_secondary_i128i128,front_secondary_i128i128,i32,i64,scope,i64,code,i64,table,i32,data,i32,datalen) { + wlog( "front secondary" ); + FC_ASSERT( datalen >= 2*sizeof(uint128_t), "insufficient data passed" ); auto& wasm = wasm_interface::get(); - char* v = &memoryRef( wasm.current_memory, data ); - return wasm_interface::get().current_validate_context->front_secondary_i128i128( Name(scope), Name(code), Name(table), - (uint128_t*)v, (uint128_t*)(v+sizeof(uint128_t)), v, datalen-(2*sizeof(uint128_t)) ); + + char* v = memoryArrayPtr( wasm.current_memory, data, datalen ); + + uint128_t* primary = (uint128_t*)v; + uint128_t* secondary = primary+1; + const uint32_t keylen = 2*sizeof(uint128_t); + + char* value = v + keylen; + uint64_t valuelen = datalen - keylen; + + auto result = wasm_interface::get().current_validate_context->front_secondary_i128i128( Name(scope), Name(code), Name(table), + primary, secondary, value, valuelen); + if( result >= 0) { + result += keylen; + } + wdump((result)(datalen)); + return result; } DEFINE_INTRINSIC_FUNCTION0(env,currentCode,currentCode,i64) { @@ -236,7 +265,8 @@ DEFINE_INTRINSIC_FUNCTION2(env,readMessage,readMessage,i32,i32,destptr,i32,dests } DEFINE_INTRINSIC_FUNCTION2(env,assert,assert,none,i32,test,i32,msg) { - std::string message = &Runtime::memoryRef( wasm_interface::get().current_memory, msg ); + const char* m = &Runtime::memoryRef( wasm_interface::get().current_memory, msg ); + std::string message( m ); if( !test ) edump((message)); FC_ASSERT( test, "assertion failed: ${s}", ("s",message)("ptr",msg) ); } @@ -474,12 +504,12 @@ DEFINE_INTRINSIC_FUNCTION1(env,toUpper,toUpper,none,i32,charptr) { char* memstart = &memoryRef( current_memory, 0 ); // state.init_memory.resize(1<<16); /// TODO: actually get memory size - std::cerr <<"INIT MEMORY: \n"; for( uint32_t i = 0; i < 10000; ++i ) if( memstart[i] ) { - state.mem_end = i; + state.mem_end = i+1; //std::cerr << (char)memstart[i]; } + ilog( "INIT MEMORY: ${size}", ("size", state.mem_end) ); state.init_memory.resize(state.mem_end); memcpy( state.init_memory.data(), memstart, state.mem_end ); //state.init_memory.size() ); diff --git a/libraries/fc/include/fc/uint128.hpp b/libraries/fc/include/fc/uint128.hpp index 5e599dc38..fd54d7d98 100644 --- a/libraries/fc/include/fc/uint128.hpp +++ b/libraries/fc/include/fc/uint128.hpp @@ -32,6 +32,9 @@ 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) ); + } operator std::string()const; operator fc::bigint()const; @@ -122,6 +125,8 @@ namespace fc void to_variant( const uint128& var, variant& vo ); void from_variant( const variant& var, uint128& vo ); + void to_variant( const unsigned __int128& var, variant& vo ); + void from_variant( const variant& var, unsigned __int128& vo ); namespace raw { diff --git a/libraries/fc/src/uint128.cpp b/libraries/fc/src/uint128.cpp index 66128ce73..aa5a2bcb0 100644 --- a/libraries/fc/src/uint128.cpp +++ b/libraries/fc/src/uint128.cpp @@ -376,6 +376,8 @@ namespace fc void to_variant( const uint128& var, variant& vo ) { vo = std::string(var); } void from_variant( const variant& var, uint128& vo ){ vo = uint128(var.as_string()); } + void to_variant( const unsigned __int128& var, variant& vo ) { to_variant( *((uint128*)var), vo); } + void from_variant( const variant& var, unsigned __int128& vo ) { from_variant( var, *((uint128*)&vo)); } } // namespace fc diff --git a/libraries/types/include/eos/types/native.hpp b/libraries/types/include/eos/types/native.hpp index 5853360c3..09971ac74 100644 --- a/libraries/types/include/eos/types/native.hpp +++ b/libraries/types/include/eos/types/native.hpp @@ -131,7 +131,9 @@ namespace eos { namespace types { } friend bool operator < ( const Name& a, const Name& b ) { return a.value < b.value; } + friend bool operator <= ( const Name& a, const Name& b ) { return a.value <= b.value; } friend bool operator > ( const Name& a, const Name& b ) { return a.value > b.value; } + friend bool operator >=( const Name& a, const Name& b ) { return a.value >= b.value; } friend bool operator == ( const Name& a, const Name& b ) { return a.value == b.value; } friend bool operator != ( const Name& a, const Name& b ) { return a.value != b.value; } diff --git a/tests/slow_tests/slow_tests.cpp b/tests/slow_tests/slow_tests.cpp index e67ef1607..067e1729d 100644 --- a/tests/slow_tests/slow_tests.cpp +++ b/tests/slow_tests/slow_tests.cpp @@ -67,8 +67,99 @@ FC_REFLECT( OrderID, (name)(number) ); FC_REFLECT( Bid, (buyer)(price)(quantity)(expiration) ); FC_REFLECT( Ask, (seller)(price)(quantity)(expiration) ); + struct record { + uint64_t a = 0; + uint64_t b = 0; + uint64_t c = 0; + fc::uint128 d = 0; + fc::uint128 e = 0; + }; + + struct by_abcde; + struct by_abced; + using test_index = boost::multi_index_container< + record, + indexed_by< + ordered_unique, + composite_key< record, + member, + member, + member, + member, + member + > + >, + ordered_unique, + composite_key< record, + member, + member, + member, + member, + member + > + > + > + >; +// FC_REFLECT( record, (a)(b)(c)(d)(e) ); + BOOST_AUTO_TEST_SUITE(slow_tests) + +BOOST_FIXTURE_TEST_CASE(multiindex, testing_fixture) +{ + test_index idx; + idx.emplace( record{1,0,0,1,9} ); + idx.emplace( record{1,1,1,2,8} ); + idx.emplace( record{1,2,3,3,7} ); + idx.emplace( record{1,2,3,5,6} ); + idx.emplace( record{1,2,3,6,5} ); + idx.emplace( record{1,2,3,7,5} ); + idx.emplace( record{1,2,3,8,3} ); + + auto& by_de = idx.get(); + auto& by_ed = idx.get(); + + auto itr = by_de.lower_bound( boost::make_tuple(1,2,3,0,0) ); + BOOST_REQUIRE( itr != by_de.end() ); + BOOST_REQUIRE( itr->d == 3 ); + + auto itr2 = by_ed.lower_bound( boost::make_tuple(1,2,3,0,0) ); + BOOST_REQUIRE( itr2 != by_ed.end() ); + BOOST_REQUIRE( itr2->e == 3 ); + //BOOST_REQUIRE( itr2 == by_ed.begin() ); + Make_Blockchain(chain) + auto& db = chain.get_mutable_database(); + db.create( [&]( auto& obj ) { + obj.scope = 1; + obj.code = 1; + obj.table = 1; + obj.primary_key = 1; + obj.secondary_key = 2; + }); + db.create( [&]( auto& obj ) { + obj.scope = 1; + obj.code = 1; + obj.table = 1; + obj.primary_key = 2; + obj.secondary_key = 3; + }); + db.create( [&]( auto& obj ) { + obj.scope = 1; + obj.code = 1; + obj.table = 1; + obj.primary_key = 3; + obj.secondary_key = 2; + }); + { + auto& sidx = db.get_index< key128x128_value_index, by_scope_secondary> (); + auto lower = sidx.lower_bound( boost::make_tuple( 1, 1, 1, 0, 0 ) ); + BOOST_REQUIRE( lower != sidx.end() ); + BOOST_REQUIRE( lower->primary_key == 1 ); + BOOST_REQUIRE( lower->secondary_key == 2 ); + } + +} + // Test that TaPoS still works after block 65535 (See Issue #55) BOOST_FIXTURE_TEST_CASE(tapos_wrap, testing_fixture) { try { @@ -297,7 +388,7 @@ void SellCurrency( testing_blockchain& chain, AccountName seller, AccountName ex eos::chain::SignedTransaction trx; trx.scope = sort_names({"exchange"}); - trx.emplaceMessage("exchange", sort_names( {"exchange"} ), + trx.emplaceMessage("exchange", sort_names( {} ), vector{ {seller,"active"} }, "sell", b ); trx.expiration = chain.head_block_time() + 100; @@ -314,7 +405,7 @@ void BuyCurrency( testing_blockchain& chain, AccountName buyer, AccountName exch eos::chain::SignedTransaction trx; trx.scope = sort_names({"exchange"}); - trx.emplaceMessage("exchange", sort_names( {"exchange"} ), + trx.emplaceMessage("exchange", sort_names( {} ), vector{ {buyer,"active"} }, "buy", b ); trx.expiration = chain.head_block_time() + 100; @@ -366,15 +457,18 @@ BOOST_FIXTURE_TEST_CASE(create_exchange, testing_fixture) { TransferCurrency( chain, "initb", "exchange", 2000 ); chain.produce_blocks(1); + wlog( "start buy and sell" ); SellCurrency( chain, "initb", "exchange", 1, 100, .5 ); + SellCurrency( chain, "initb", "exchange", 1, 100, .75 ); + SellCurrency( chain, "initb", "exchange", 1, 100, .85 ); //BOOST_REQUIRE_THROW( SellCurrency( chain, "initb", "exchange", 1, 100, .5 ), fc::exception ); // order id already exists - SellCurrency( chain, "initb", "exchange", 2, 100, .75 ); + //SellCurrency( chain, "initb", "exchange", 2, 100, .75 ); BuyCurrency( chain, "initb", "exchange", 1, 50, .25 ); //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 - BuyCurrency( chain, "initb", "exchange", 2, 50, .8 ); + //BuyCurrency( chain, "initb", "exchange", 2, 50, .8 ); } FC_LOG_AND_RETHROW() }catch(...) { -- GitLab