提交 a51bb3b5 编写于 作者: A Anton Perkov

Merge branch 'master' into system-contract-new-style

......@@ -77,7 +77,7 @@ steps:
echo "--- :m: Starting MongoDB" && \
$(which mongod) --fork --logpath "$(pwd)"/mongod.log && \
echo "+++ :microscope: Running tests" && \
ln -s "$(pwd)" /data/job && cd /data/job/build && make test
ln -s "$(pwd)" /data/job && cd /data/job/build && ctest --output-on-failure
retry:
automatic:
limit: 1
......@@ -87,9 +87,7 @@ steps:
artifact_paths:
- "mongod.log"
- "build/genesis.json"
- "build/etc/eosio/node_00/config.ini"
- "build/var/lib/node_00/stderr.txt"
- "build/test_walletd_output.log"
- "build/config.ini"
timeout: 30
- command: |
......@@ -99,7 +97,7 @@ steps:
echo "--- :m: Starting MongoDB" && \
$(which mongod) --fork --logpath "$(pwd)"/mongod.log && \
echo "+++ :microscope: Running tests" && \
cd /data/job/build && make test
cd /data/job/build && ctest --output-on-failure
retry:
automatic:
limit: 1
......@@ -109,9 +107,7 @@ steps:
artifact_paths:
- "mongod.log"
- "build/genesis.json"
- "build/etc/eosio/node_00/config.ini"
- "build/var/lib/node_00/stderr.txt"
- "build/test_walletd_output.log"
- "build/config.ini"
plugins:
docker#v1.1.1:
image: "eosio/ci:ubuntu"
......@@ -124,7 +120,7 @@ steps:
echo "--- :m: Starting MongoDB" && \
$(which mongod) --fork --logpath "$(pwd)"/mongod.log && \
echo "+++ :microscope: Running tests" && \
cd /data/job/build && make test
cd /data/job/build && ctest --output-on-failure
retry:
automatic:
limit: 1
......@@ -134,9 +130,7 @@ steps:
artifact_paths:
- "mongod.log"
- "build/genesis.json"
- "build/etc/eosio/node_00/config.ini"
- "build/var/lib/node_00/stderr.txt"
- "build/test_walletd_output.log"
- "build/config.ini"
plugins:
docker#v1.1.1:
image: "eosio/ci:fedora"
......@@ -149,7 +143,7 @@ steps:
echo "--- :m: Starting MongoDB" && \
$(which mongod) --fork --logpath "$(pwd)"/mongod.log && \
echo "+++ :microscope: Running tests" && \
cd /data/job/build && make test
cd /data/job/build && ctest --output-on-failure
retry:
automatic:
limit: 1
......@@ -159,9 +153,7 @@ steps:
artifact_paths:
- "mongod.log"
- "build/genesis.json"
- "build/etc/eosio/node_00/config.ini"
- "build/var/lib/node_00/stderr.txt"
- "build/test_walletd_output.log"
- "build/config.ini"
plugins:
docker#v1.1.1:
image: "eosio/ci:centos"
......@@ -174,7 +166,7 @@ steps:
echo "--- :m: Starting MongoDB" && \
$(which mongod) --fork --logpath "$(pwd)"/mongod.log && \
echo "+++ :microscope: Running tests" && \
cd /data/job/build && make test
cd /data/job/build && ctest --output-on-failure
retry:
automatic:
limit: 1
......@@ -184,9 +176,7 @@ steps:
artifact_paths:
- "mongod.log"
- "build/genesis.json"
- "build/etc/eosio/node_00/config.ini"
- "build/var/lib/node_00/stderr.txt"
- "build/test_walletd_output.log"
- "build/config.ini"
plugins:
docker#v1.1.1:
image: "eosio/ci:amazonlinux"
......
......@@ -160,10 +160,11 @@ docker pull eosio/eos:dawn3x
docker volume create --name=nodeos-data-volume
docker volume create --name=keosd-data-volume
# start containers
docker-compose -f docker-compose-dawn3.0.yml up -d
docker-compose -f docker-compose-dawn3.0.yaml up -d
# get chain info
curl http://127.0.0.1:8888/v1/chain/get_info
# get logs
docker-compose logs nodeosd
```
The `blocks` data are stored under `--data-dir` by default, and the wallet files are stored under `--wallet-dir` by default, of course you can change these as you want.
......@@ -3,7 +3,7 @@ version: "3"
services:
nodeosd:
image: eosio/eos:dawn3x
command: /opt/eosio/bin/nodeosd.sh
command: /opt/eosio/bin/nodeosd.sh --data-dir /opt/eosio/bin/data-dir
hostname: nodeosd
ports:
- 8888:8888
......@@ -15,7 +15,7 @@ services:
keosd:
image: eosio/eos:dawn3x
command: /opt/eosio/bin/keosd
command: /opt/eosio/bin/keosd --wallet-dir /opt/eosio/bin/data-dir
hostname: keosd
links:
- nodeosd
......
......@@ -10,7 +10,7 @@ services:
build:
context: .
image: eosio/eos
command: /opt/eosio/bin/nodeosd.sh
command: /opt/eosio/bin/nodeosd.sh --data-dir /opt/eosio/bin/data-dir
hostname: nodeosd
ports:
- 8888:8888
......@@ -22,7 +22,7 @@ services:
keosd:
image: eosio/eos
command: /opt/eosio/bin/keosd
command: /opt/eosio/bin/keosd --wallet-dir /opt/eosio/bin/data-dir
hostname: keosd
links:
- nodeosd
......
......@@ -91,11 +91,7 @@ namespace eosiosystem {
if ( 0 < stake_storage_quantity.amount ) {
global_state_singleton gs( _self, _self );
auto parameters = gs.exists() ? gs.get() : get_default_parameters();
eosio::symbol_name sym = eosio::symbol_type(S(4,EOS)).name();
eosio::token::stats stats_tbl(N(eosio.token), sym);
const auto& st = stats_tbl.get(sym);
const eosio::asset token_supply = st.supply;
const eosio::asset token_supply = eosio::token(N(eosio.token)).get_supply(eosio::symbol_type(system_token_symbol).name());
//make sure that there is no posibility of overflow here
int64_t storage_bytes_estimated = int64_t( parameters.max_storage_size - parameters.total_storage_bytes_reserved )
* int64_t(parameters.storage_reserve_ratio) * stake_storage_quantity
......@@ -153,9 +149,9 @@ namespace eosiosystem {
}
//set_resource_limits( tot_itr->owner, tot_itr->storage_bytes, tot_itr->net_weight.quantity, tot_itr->cpu_weight.quantity );
eosio::inline_transfer(eosio::permission_level{from,N(active)}, N(eosio.token),
{ from, N(eosio), total_stake, std::string("stake bandwidth") } );
INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {from,N(active)},
{ from, N(eosio), total_stake, std::string("stake bandwidth") } );
if ( asset(0) < stake_net_quantity + stake_cpu_quantity ) {
increase_voting_power( from, stake_net_quantity + stake_cpu_quantity );
......@@ -181,11 +177,11 @@ namespace eosiosystem {
eosio_assert( dbw.cpu_weight >= unstake_cpu_quantity, "insufficient staked cpu bandwidth" );
eosio_assert( dbw.storage_bytes >= unstake_storage_bytes, "insufficient staked storage" );
eosio::asset storage_stake_decrease(0, S(4,EOS));
eosio::asset storage_stake_decrease(0, system_token_symbol);
if ( 0 < unstake_storage_bytes ) {
storage_stake_decrease = 0 < dbw.storage_bytes ?
dbw.storage_stake * int64_t(unstake_storage_bytes) / int64_t(dbw.storage_bytes)
: eosio::asset(0, S(4,EOS));
: eosio::asset(0, system_token_symbol);
global_state_singleton gs( _self, _self );
auto parameters = gs.get(); //it should exist if user staked for bandwith
parameters.total_storage_bytes_reserved -= unstake_storage_bytes;
......@@ -257,8 +253,8 @@ namespace eosiosystem {
// allow people to get their tokens earlier than the 3 day delay if the unstake happened immediately after many
// consecutive missed blocks.
eosio::inline_transfer( eosio::permission_level{N(eosio),N(active)}, N(eosio.token),
{ N(eosio), req->owner, req->amount, std::string("unstake") });
INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {N(eosio),N(active)},
{ N(eosio), req->owner, req->amount, std::string("unstake") } );
refunds_tbl.erase( req );
}
......
......@@ -84,7 +84,8 @@ namespace eosiosystem {
static constexpr uint32_t max_inflation_rate = 5; // 5% annual inflation
static constexpr uint32_t seconds_per_day = 24 * 3600;
static constexpr uint64_t system_token_symbol = S(4,EOS);
class system_contract : public native, private eosio::contract {
public:
......
......@@ -107,8 +107,8 @@ void system_contract::claimrewards(const account_name& owner) {
p.per_block_payments.amount = 0;
});
eosio::inline_transfer(eosio::permission_level{N(eosio),N(active)}, N(eosio.token),
{ N(eosio), owner, rewards, std::string("producer claiming rewards") } );
INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {N(eosio),N(active)},
{ N(eosio), owner, rewards, std::string("producer claiming rewards") } );
}
} //namespace eosiosystem
......@@ -189,14 +189,11 @@ namespace eosiosystem {
}
eosio::asset system_contract::payment_per_block(uint32_t percent_of_max_inflation_rate) {
eosio::symbol_name sym = eosio::symbol_type(S(4,EOS)).name();
eosio::token::stats stats_tbl(N(eosio.token), sym);
const auto& st = stats_tbl.get(sym);
const eosio::asset token_supply = st.supply;
const eosio::asset token_supply = eosio::token(N(eosio.token)).get_supply(eosio::symbol_type(system_token_symbol).name());
const double annual_rate = double(max_inflation_rate * percent_of_max_inflation_rate) / double(10000);
double continuous_rate = std::log1p(annual_rate);
const double continuous_rate = std::log1p(annual_rate);
int64_t payment = static_cast<int64_t>((continuous_rate * double(token_supply.amount)) / double(blocks_per_year));
return eosio::asset(payment, S(4,EOS));
return eosio::asset(payment, system_token_symbol);
}
void system_contract::update_elected_producers(time cycle_time) {
......@@ -340,8 +337,8 @@ namespace eosiosystem {
}
auto issue_quantity = parameters.blocks_per_cycle * (parameters.payment_per_block + parameters.payment_to_eos_bucket);
eosio::inline_issue(eosio::permission_level{N(eosio),N(active)}, N(eosio.token),
{ N(eosio), issue_quantity, std::string("producer pay") });
INLINE_ACTION_SENDER(eosio::token, issue)( N(eosio.token), {{N(eosio),N(active)}},
{N(eosio), issue_quantity, std::string("producer pay")} );
set_blockchain_parameters( parameters );
gs.set( parameters, _self );
......
......@@ -10,8 +10,8 @@ namespace eosio {
void token::create( account_name issuer,
asset maximum_supply,
uint8_t issuer_can_freeze,
uint8_t issuer_can_recall,
uint8_t issuer_can_whitelist )
uint8_t issuer_can_recall,
uint8_t issuer_can_whitelist )
{
require_auth( _self );
......@@ -35,7 +35,7 @@ void token::create( account_name issuer,
}
void token::issue( account_name to, asset quantity, string memo )
void token::issue( account_name to, asset quantity, string memo )
{
print( "issue" );
auto sym = quantity.symbol.name();
......@@ -55,14 +55,14 @@ void token::issue( account_name to, asset quantity, string memo )
if( to != st.issuer )
{
dispatch_inline( permission_level{st.issuer,N(active)}, _self, N(transfer), &token::transfer, { st.issuer, to, quantity, memo } );
SEND_INLINE_ACTION( *this, transfer, {st.issuer,N(active)}, {st.issuer, to, quantity, memo} );
}
}
void token::transfer( account_name from,
void token::transfer( account_name from,
account_name to,
asset quantity,
string /*memo*/ )
string /*memo*/ )
{
print( "transfer" );
require_auth( from );
......
......@@ -40,6 +40,11 @@ namespace eosio {
friend eosiosystem::system_contract;
inline asset get_supply( symbol_name sym )const;
inline asset get_balance( account_name owner, symbol_name sym )const;
private:
struct account {
asset balance;
bool frozen = false;
......@@ -69,18 +74,18 @@ namespace eosio {
account_name ram_payer );
};
typedef std::tuple<account_name, account_name, asset, string> transfer_args;
void inline_transfer( permission_level permissions, account_name code, transfer_args args )
asset token::get_supply( symbol_name sym )const
{
action act( permissions, code, N(transfer), args );
act.send();
stats statstable( _self, sym );
const auto& st = statstable.get( sym );
return st.supply;
}
typedef std::tuple<account_name, asset, string> issue_args;
void inline_issue( permission_level permissions, account_name code, issue_args args )
asset token::get_balance( account_name owner, symbol_name sym )const
{
action act( permissions, code, N(issue), args );
act.send();
accounts accountstable( _self, owner );
const auto& ac = accountstable.get( sym );
return ac.balance;
}
} /// namespace eosio
......@@ -7,6 +7,11 @@
#include <eosiolib/datastream.hpp>
#include <eosiolib/serialize.hpp>
#include <boost/preprocessor/variadic/size.hpp>
#include <boost/preprocessor/variadic/to_tuple.hpp>
#include <boost/preprocessor/tuple/enum.hpp>
#include <boost/preprocessor/facilities/overload.hpp>
namespace eosio {
/**
......@@ -24,7 +29,7 @@ namespace eosio {
* This method unpacks the current action at type T.
*
* @brief Interpret the action body as type T
*
*
* Example:
* @code
* struct dummy_action {
......@@ -134,16 +139,26 @@ namespace eosio {
}
/**
* @tparam Action - a type derived from action_meta<Scope,Name>
* @tparam T - the type of the action data
* @param auth - a single permission_level to be used as the authorization of the action
* @param a - name of the contract account
* @param n - name of the action
* @param value - will be serialized via pack into data
*/
template<typename Action>
action( const permission_level& auth, account_name a, action_name n, const Action& value )
:authorization(1,auth) {
account = a;
name = n;
data = pack(value);
}
template<typename T>
action( const permission_level& auth, account_name a, action_name n, T&& value )
:account(a), name(n), authorization(1,auth), data(pack(std::forward<T>(value))) {}
/**
* @tparam T - the type of the action data
* @param auths - vector permission_levels defining the authorizations of the action
* @param a - name of the contract account
* @param n - name of the action
* @param value - will be serialized via pack into data
*/
template<typename T>
action( vector<permission_level> auths, account_name a, action_name n, T&& value )
:account(a), name(n), authorization(std::move(auths)), data(pack(std::forward<T>(value))) {}
EOSLIB_SERIALIZE( action, (account)(name)(authorization)(data) )
......@@ -178,18 +193,41 @@ namespace eosio {
static uint64_t get_name() { return Name; }
};
template<typename T, typename... Args>
void dispatch_inline( permission_level perm,
account_name code, action_name act,
void (T::*)(Args...), std::tuple<Args...> args ) {
action( perm, code, act, args ).send();
template<typename... Args>
void dispatch_inline( account_name code, action_name act,
vector<permission_level> perms,
std::tuple<Args...> args ) {
action( perms, code, act, std::move(args) ).send();
}
template<typename, uint64_t>
struct inline_dispatcher;
template<typename T, uint64_t Name, typename... Args>
struct inline_dispatcher<void(T::*)(Args...), Name> {
static void call(account_name code, const permission_level& perm, std::tuple<Args...> args) {
dispatch_inline(code, Name, vector<permission_level>(1, perm), std::move(args));
}
static void call(account_name code, vector<permission_level> perms, std::tuple<Args...> args) {
dispatch_inline(code, Name, std::move(perms), std::move(args));
}
};
///@} actioncpp api
} // namespace eosio
#define INLINE_ACTION_SENDER3( CONTRACT_CLASS, FUNCTION_NAME, ACTION_NAME )\
::eosio::inline_dispatcher<decltype(&CONTRACT_CLASS::FUNCTION_NAME), ACTION_NAME>::call
#define INLINE_ACTION_SENDER2( CONTRACT_CLASS, NAME )\
INLINE_ACTION_SENDER3( CONTRACT_CLASS, NAME, ::eosio::string_to_name(#NAME) )
#define INLINE_ACTION_SENDER(...) BOOST_PP_OVERLOAD(INLINE_ACTION_SENDER,__VA_ARGS__)(__VA_ARGS__)
#define SEND_INLINE_ACTION( CONTRACT, NAME, ... )\
INLINE_ACTION_SENDER(std::decay_t<decltype(CONTRACT)>, NAME)( (CONTRACT).get_self(),\
BOOST_PP_TUPLE_ENUM(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__)) );
#define ACTION( CODE, NAME ) struct NAME : ::eosio::action_meta<CODE, ::eosio::string_to_name(#NAME) >
......@@ -60,7 +60,7 @@ namespace eosio {
symbol_name value;
symbol_type() { }
symbol_type(const symbol_name& s): value(s) { }
symbol_type(symbol_name s): value(s) { }
bool is_valid()const { return is_valid_symbol( value ); }
uint64_t precision()const { return value & 0xff; }
uint64_t name()const { return value >> 8; }
......
......@@ -2,9 +2,14 @@
namespace eosio {
struct contract {
contract( account_name n ):_self(n){}
account_name _self;
class contract {
public:
contract( account_name n ):_self(n){}
inline account_name get_self()const { return _self; }
protected:
account_name _self;
};
} /// namespace eosio
......@@ -255,10 +255,31 @@ DataStream& operator >> ( DataStream& ds, std::array<T,N>& v ) {
return ds;
}
namespace _datastream_detail {
template<typename T>
constexpr bool is_pointer() {
return std::is_pointer<T>::value ||
std::is_null_pointer<T>::value ||
std::is_member_pointer<T>::value;
}
template<typename T>
constexpr bool is_primitive() {
return std::is_arithmetic<T>::value ||
std::is_enum<T>::value;
}
}
template<typename DataStream, typename T, std::enable_if_t<_datastream_detail::is_pointer<T>()>* = nullptr>
DataStream& operator >> ( DataStream& ds, T ) {
static_assert(!_datastream_detail::is_pointer<T>(), "Pointers should not be serialized" );
return ds;
}
template<typename DataStream, typename T, std::size_t N,
std::enable_if_t<std::is_scalar<T>::value == false || std::is_pointer<T>::value == true, int> = 0>
std::enable_if_t<!_datastream_detail::is_primitive<T>() &&
!_datastream_detail::is_pointer<T>()>* = nullptr>
DataStream& operator << ( DataStream& ds, const T (&v)[N] ) {
static_assert(!std::is_pointer<T>::value, "Pointers should not be serialized" );
ds << unsigned_int( N );
for( uint32_t i = 0; i < N; ++i )
ds << v[i];
......@@ -266,7 +287,7 @@ DataStream& operator << ( DataStream& ds, const T (&v)[N] ) {
}
template<typename DataStream, typename T, std::size_t N,
std::enable_if_t<std::is_scalar<T>::value == true && std::is_pointer<T>::value == false, int> = 0>
std::enable_if_t<_datastream_detail::is_primitive<T>()>* = nullptr>
DataStream& operator << ( DataStream& ds, const T (&v)[N] ) {
ds << unsigned_int( N );
ds.write((char*)&v[0], sizeof(v));
......@@ -274,9 +295,9 @@ DataStream& operator << ( DataStream& ds, const T (&v)[N] ) {
}
template<typename DataStream, typename T, std::size_t N,
std::enable_if_t<std::is_scalar<T>::value == false || std::is_pointer<T>::value == true, int> = 0>
std::enable_if_t<!_datastream_detail::is_primitive<T>() &&
!_datastream_detail::is_pointer<T>()>* = nullptr>
DataStream& operator >> ( DataStream& ds, T (&v)[N] ) {
static_assert(!std::is_pointer<T>::value, "Pointers should not be serialized" );
unsigned_int s;
ds >> s;
eosio_assert( N == s.value, "T[] size and unpacked size don't match");
......@@ -286,7 +307,7 @@ DataStream& operator >> ( DataStream& ds, T (&v)[N] ) {
}
template<typename DataStream, typename T, std::size_t N,
std::enable_if_t<std::is_scalar<T>::value == true && std::is_pointer<T>::value == false, int> = 0>
std::enable_if_t<_datastream_detail::is_primitive<T>()>* = nullptr>
DataStream& operator >> ( DataStream& ds, T (&v)[N] ) {
unsigned_int s;
ds >> s;
......@@ -388,33 +409,29 @@ DataStream& operator>>( DataStream& ds, std::tuple<Args...>& t ) {
return ds;
}
template<typename DataStream, typename T, std::enable_if_t<std::is_scalar<T>::value == false, int> = 0>
template<typename DataStream, typename T, std::enable_if_t<std::is_class<T>::value>* = nullptr>
DataStream& operator<<( DataStream& ds, const T& v ) {
static_assert(!std::is_pointer<T>::value, "Pointers should not be serialized" );
boost::pfr::for_each_field(v, [&](const auto& field) {
ds << field;
});
return ds;
}
template<typename DataStream, typename T, std::enable_if_t<std::is_scalar<T>::value == false, int> = 0>
template<typename DataStream, typename T, std::enable_if_t<std::is_class<T>::value>* = nullptr>
DataStream& operator>>( DataStream& ds, T& v ) {
static_assert(!std::is_pointer<T>::value, "Pointers should not be serialized" );
boost::pfr::for_each_field(v, [&](auto& field) {
ds >> field;
});
return ds;
}
template<typename DataStream, typename T, std::enable_if_t<std::is_scalar<T>::value == true, int> = 0>
template<typename DataStream, typename T, std::enable_if_t<_datastream_detail::is_primitive<T>()>* = nullptr>
DataStream& operator<<( DataStream& ds, const T& v ) {
static_assert(!std::is_pointer<T>::value, "Pointers should not be serialized" );
ds.write( (const char*)&v, sizeof(T) );
return ds;
}
template<typename DataStream, typename T, std::enable_if_t<std::is_scalar<T>::value == true, int> = 0>
template<typename DataStream, typename T, std::enable_if_t<_datastream_detail::is_primitive<T>()>* = nullptr>
DataStream& operator>>( DataStream& ds, T& v ) {
static_assert(!std::is_pointer<T>::value, "Pointers should not be serialized" );
ds.read( (char*)&v, sizeof(T) );
return ds;
}
......
......@@ -88,15 +88,15 @@ int32_t db_idx256_lowerbound(account_name code, account_name scope, table_name t
int32_t db_idx256_upperbound(account_name code, account_name scope, table_name table, void* data, uint32_t data_len, uint64_t* primary);
int32_t db_idx256_end(account_name code, account_name scope, table_name table);
int32_t db_idx_double_store(account_name scope, table_name table, account_name payer, uint64_t id, const uint64_t* secondary);
void db_idx_double_update(int32_t iterator, account_name payer, const uint64_t* secondary);
int32_t db_idx_double_store(account_name scope, table_name table, account_name payer, uint64_t id, const double* secondary);
void db_idx_double_update(int32_t iterator, account_name payer, const double* secondary);
void db_idx_double_remove(int32_t iterator);
int32_t db_idx_double_next(int32_t iterator, uint64_t* primary);
int32_t db_idx_double_previous(int32_t iterator, uint64_t* primary);
int32_t db_idx_double_find_primary(account_name code, account_name scope, table_name table, uint64_t* secondary, uint64_t primary);
int32_t db_idx_double_find_secondary(account_name code, account_name scope, table_name table, const uint64_t* secondary, uint64_t* primary);
int32_t db_idx_double_lowerbound(account_name code, account_name scope, table_name table, uint64_t* secondary, uint64_t* primary);
int32_t db_idx_double_upperbound(account_name code, account_name scope, table_name table, uint64_t* secondary, uint64_t* primary);
int32_t db_idx_double_find_primary(account_name code, account_name scope, table_name table, double* secondary, uint64_t primary);
int32_t db_idx_double_find_secondary(account_name code, account_name scope, table_name table, const double* secondary, uint64_t* primary);
int32_t db_idx_double_lowerbound(account_name code, account_name scope, table_name table, double* secondary, uint64_t* primary);
int32_t db_idx_double_upperbound(account_name code, account_name scope, table_name table, double* secondary, uint64_t* primary);
int32_t db_idx_double_end(account_name code, account_name scope, table_name table);
}
......@@ -83,7 +83,7 @@ namespace eosio {
*
* @details Default constructor to fixed_key object which initializes all bytes to zero
*/
fixed_key() : _data() {}
constexpr fixed_key() : _data() {}
/**
* @brief Constructor to fixed_key object from std::array of num_words() words
......
......@@ -27,12 +27,6 @@ namespace eosio {
using boost::multi_index::const_mem_fun;
namespace hana = boost::hana;
template<typename T>
struct secondary_index_db_functions;
#define WRAP_SECONDARY_SIMPLE_TYPE(IDX, TYPE)\
template<>\
struct secondary_index_db_functions<TYPE> {\
......@@ -85,55 +79,40 @@ struct secondary_index_db_functions<TYPE> {\
static int32_t db_idx_upperbound( uint64_t code, uint64_t scope, uint64_t table, TYPE& secondary, uint64_t& primary ) {\
return db_##IDX##_upperbound( code, scope, table, secondary.data(), TYPE::num_words(), &primary );\
}\
};\
WRAP_SECONDARY_SIMPLE_TYPE(idx64, uint64_t)
WRAP_SECONDARY_SIMPLE_TYPE(idx128, uint128_t)
WRAP_SECONDARY_ARRAY_TYPE(idx256, key256)
template<>
struct secondary_index_db_functions<double> {
static int32_t db_idx_next( int32_t iterator, uint64_t* primary ) { return db_idx_double_next( iterator, primary ); }
static int32_t db_idx_previous( int32_t iterator, uint64_t* primary ) { return db_idx_double_previous( iterator, primary ); }
static void db_idx_remove( int32_t iterator ) { db_idx_double_remove( iterator ); }
static int32_t db_idx_end( uint64_t code, uint64_t scope, uint64_t table ) { return db_idx_double_end( code, scope, table ); }
static int32_t db_idx_store( uint64_t scope, uint64_t table, uint64_t payer, uint64_t id, double secondary ) {
uint64_t val = *(uint64_t*)(&secondary); // Get uint64_t representation of double secondary
return db_idx_double_store( scope, table, payer, id, &val );
}
static void db_idx_update( int32_t iterator, uint64_t payer, double secondary ) {
uint64_t val = *(uint64_t*)(&secondary); // Get uint64_t representation of double secondary
db_idx_double_update( iterator, payer, &val );
}
static int32_t db_idx_find_primary( uint64_t code, uint64_t scope, uint64_t table, uint64_t primary, double& secondary ) {
uint64_t val = 0;
auto itr = db_idx_double_find_primary( code, scope, table, &val, primary );
if( itr >= 0 )
secondary = *(double*)(&val); // Store double secondary from uint64_t representation stored in val
return itr;
}
static int32_t db_idx_find_secondary( uint64_t code, uint64_t scope, uint64_t table, double secondary, uint64_t& primary ) {
uint64_t val = *(uint64_t*)(&secondary);
return db_idx_double_find_secondary( code, scope, table, &val, &primary );
}
static int32_t db_idx_lowerbound( uint64_t code, uint64_t scope, uint64_t table, double& secondary, uint64_t& primary ) {
uint64_t val = *(uint64_t*)(&secondary); // Get uint64_t representation of double secondary
auto itr = db_idx_double_lowerbound( code, scope, table, &val, &primary );
if( itr >= 0 )
secondary = *(double*)(&val); // Store double secondary from uint64_t representation stored in val
return itr;
}
static int32_t db_idx_upperbound( uint64_t code, uint64_t scope, uint64_t table, double& secondary, uint64_t& primary ) {
uint64_t val = *(uint64_t*)(&secondary); // Get uint64_t representation of double secondary
auto itr = db_idx_double_upperbound( code, scope, table, &val, &primary );
if( itr >= 0 )
secondary = *(double*)(&val); // Store double secondary from uint64_t representation stored in val
return itr;
}
};
template<uint64_t TableName, typename T, typename... Indices>
class multi_index;
#define MAKE_TRAITS_FOR_ARITHMETIC_SECONDARY_KEY(TYPE)\
template<>\
struct secondary_key_traits<TYPE> {\
static constexpr TYPE lowest() { return std::numeric_limits<TYPE>::lowest(); }\
};
namespace _multi_index_detail {
namespace hana = boost::hana;
template<typename T>
struct secondary_index_db_functions;
template<typename T>
struct secondary_key_traits;
WRAP_SECONDARY_SIMPLE_TYPE(idx64, uint64_t)
MAKE_TRAITS_FOR_ARITHMETIC_SECONDARY_KEY(uint64_t)
WRAP_SECONDARY_SIMPLE_TYPE(idx128, uint128_t)
MAKE_TRAITS_FOR_ARITHMETIC_SECONDARY_KEY(uint128_t)
WRAP_SECONDARY_SIMPLE_TYPE(idx_double, double)
MAKE_TRAITS_FOR_ARITHMETIC_SECONDARY_KEY(double)
WRAP_SECONDARY_ARRAY_TYPE(idx256, key256)
template<>
struct secondary_key_traits<key256> {
static constexpr key256 lowest() { return key256(); }
};
}
template<uint64_t IndexName, typename Extractor>
struct indexed_by {
......@@ -235,6 +214,8 @@ class multi_index
}
const_iterator& operator++() {
using namespace _multi_index_detail;
eosio_assert( _item != nullptr, "cannot increment end iterator" );
if( _item->__iters[Number] == -1 ) {
......@@ -260,6 +241,8 @@ class multi_index
}
const_iterator& operator--() {
using namespace _multi_index_detail;
uint64_t prev_pk = 0;
int32_t prev_itr = -1;
......@@ -300,7 +283,8 @@ class multi_index
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
const_iterator cbegin()const {
return lower_bound(std::numeric_limits<secondary_key_type>::lowest());
using namespace _multi_index_detail;
return lower_bound( secondary_key_traits<secondary_key_type>::lowest() );
}
const_iterator begin()const { return cbegin(); }
......@@ -314,6 +298,10 @@ class multi_index
const_reverse_iterator rend()const { return crend(); }
const_iterator find( secondary_key_type&& secondary )const {
return find( secondary );
}
const_iterator find( const secondary_key_type& secondary )const {
auto lb = lower_bound( secondary );
auto e = cend();
if( lb == e ) return e;
......@@ -323,10 +311,23 @@ class multi_index
return lb;
}
const T& get( secondary_key_type&& secondary )const {
return get( secondary );
}
// Gets the object with the smallest primary key in the case where the secondary key is not unique.
const T& get( const secondary_key_type& secondary )const {
auto result = find( secondary );
eosio_assert( result != cend(), "unable to find secondary key" );
return *result;
}
const_iterator lower_bound( secondary_key_type&& secondary )const {
return lower_bound( secondary );
}
const_iterator lower_bound( const secondary_key_type& secondary )const {
using namespace _multi_index_detail;
uint64_t primary = 0;
secondary_key_type secondary_copy(secondary);
auto itr = secondary_index_db_functions<secondary_key_type>::db_idx_lowerbound( get_code(), get_scope(), name(), secondary_copy, primary );
......@@ -343,6 +344,8 @@ class multi_index
return upper_bound( secondary );
}
const_iterator upper_bound( const secondary_key_type& secondary )const {
using namespace _multi_index_detail;
uint64_t primary = 0;
secondary_key_type secondary_copy(secondary);
auto itr = secondary_index_db_functions<secondary_key_type>::db_idx_upperbound( get_code(), get_scope(), name(), secondary_copy, primary );
......@@ -356,6 +359,8 @@ class multi_index
}
const_iterator iterator_to( const T& obj ) {
using namespace _multi_index_detail;
const auto& objitem = static_cast<const item&>(obj);
eosio_assert( objitem.__idx == _multidx, "object passed to iterator_to is not in multi_index" );
......@@ -405,6 +410,8 @@ class multi_index
struct intc { enum e{ value = I }; operator uint64_t()const{ return I; } };
static constexpr auto transform_indices( ) {
using namespace _multi_index_detail;
typedef decltype( hana::zip_shortest(
hana::make_tuple( intc<0>(), intc<1>(), intc<2>(), intc<3>(), intc<4>(), intc<5>(),
intc<6>(), intc<7>(), intc<8>(), intc<9>(), intc<10>(), intc<11>(),
......@@ -429,6 +436,8 @@ class multi_index
indices_type _indices;
const item& load_object_by_primary_iterator( int32_t itr )const {
using namespace _multi_index_detail;
auto itr2 = std::find_if(_items_vector.rbegin(), _items_vector.rend(), [&](const item_ptr& ptr) {
return ptr._primary_itr == itr;
});
......@@ -454,7 +463,7 @@ class multi_index
ds >> val;
i.__primary_itr = itr;
boost::hana::for_each( _indices, [&]( auto& idx ) {
hana::for_each( _indices, [&]( auto& idx ) {
typedef typename decltype(+hana::at_c<1>(idx))::type index_type;
i.__iters[ index_type::number() ] = -1;
......@@ -591,24 +600,28 @@ class multi_index
template<uint64_t IndexName>
auto get_index() {
auto res = boost::hana::find_if( _indices, []( auto&& in ) {
using namespace _multi_index_detail;
auto res = hana::find_if( _indices, []( auto&& in ) {
return std::integral_constant<bool, std::decay<typename decltype(+hana::at_c<0>(in))::type>::type::index_name == IndexName>();
});
});
static_assert( res != hana::nothing, "name provided is not the name of any secondary index within multi_index" );
static_assert( res != hana::nothing, "name provided is not the name of any secondary index within multi_index" );
return typename decltype(+hana::at_c<0>(res.value()))::type(this);
return typename decltype(+hana::at_c<0>(res.value()))::type(this);
}
template<uint64_t IndexName>
auto get_index()const {
auto res = boost::hana::find_if( _indices, []( auto&& in ) {
using namespace _multi_index_detail;
auto res = hana::find_if( _indices, []( auto&& in ) {
return std::integral_constant<bool, std::decay<typename decltype(+hana::at_c<1>(in))::type>::type::index_name == IndexName>();
});
});
static_assert( res != hana::nothing, "name provided is not the name of any secondary index within multi_index" );
static_assert( res != hana::nothing, "name provided is not the name of any secondary index within multi_index" );
return typename decltype(+hana::at_c<1>(res.value()))::type(this);
return typename decltype(+hana::at_c<1>(res.value()))::type(this);
}
const_iterator iterator_to( const T& obj )const {
......@@ -619,6 +632,8 @@ class multi_index
template<typename Lambda>
const_iterator emplace( uint64_t payer, Lambda&& constructor ) {
using namespace _multi_index_detail;
eosio_assert( _code == current_receiver(), "cannot create objects in table of another contract" ); // Quick fix for mutating db using multi_index that shouldn't allow mutation. Real fix can come in RC2.
auto itm = std::make_unique<item>( this, [&]( auto& i ){
......@@ -644,7 +659,7 @@ class multi_index
if( pk >= _next_primary_key )
_next_primary_key = (pk >= no_available_primary_key) ? no_available_primary_key : (pk + 1);
boost::hana::for_each( _indices, [&]( auto& idx ) {
hana::for_each( _indices, [&]( auto& idx ) {
typedef typename decltype(+hana::at_c<0>(idx))::type index_type;
i.__iters[index_type::number()] = secondary_index_db_functions<typename index_type::secondary_key_type>::db_idx_store( _scope, index_type::name(), payer, obj.primary_key(), index_type::extract_secondary_key(obj) );
......@@ -669,12 +684,14 @@ class multi_index
template<typename Lambda>
void modify( const T& obj, uint64_t payer, Lambda&& updater ) {
using namespace _multi_index_detail;
const auto& objitem = static_cast<const item&>(obj);
eosio_assert( objitem.__idx == this, "object passed to modify is not in multi_index" );
auto& mutableitem = const_cast<item&>(objitem);
eosio_assert( _code == current_receiver(), "cannot modify objects in table of another contract" ); // Quick fix for mutating db using multi_index that shouldn't allow mutation. Real fix can come in RC2.
auto secondary_keys = boost::hana::transform( _indices, [&]( auto&& idx ) {
auto secondary_keys = hana::transform( _indices, [&]( auto&& idx ) {
typedef typename decltype(+hana::at_c<0>(idx))::type index_type;
return index_type::extract_secondary_key( obj );
......@@ -703,7 +720,7 @@ class multi_index
if( pk >= _next_primary_key )
_next_primary_key = (pk >= no_available_primary_key) ? no_available_primary_key : (pk + 1);
boost::hana::for_each( _indices, [&]( auto& idx ) {
hana::for_each( _indices, [&]( auto& idx ) {
typedef typename decltype(+hana::at_c<0>(idx))::type index_type;
auto secondary = index_type::extract_secondary_key( obj );
......@@ -723,7 +740,7 @@ class multi_index
const T& get( uint64_t primary )const {
auto result = find( primary );
eosio_assert( result != end(), "unable to find key" );
eosio_assert( result != cend(), "unable to find key" );
return *result;
}
......@@ -753,6 +770,8 @@ class multi_index
}
void erase( const T& obj ) {
using namespace _multi_index_detail;
const auto& objitem = static_cast<const item&>(obj);
eosio_assert( objitem.__idx == this, "object passed to erase is not in multi_index" );
eosio_assert( _code == current_receiver(), "cannot erase objects in table of another contract" ); // Quick fix for mutating db using multi_index that shouldn't allow mutation. Real fix can come in RC2.
......@@ -768,7 +787,7 @@ class multi_index
db_remove_i64( objitem.__primary_itr );
boost::hana::for_each( _indices, [&]( auto& idx ) {
hana::for_each( _indices, [&]( auto& idx ) {
typedef typename decltype(+hana::at_c<0>(idx))::type index_type;
auto i = objitem.__iters[index_type::number()];
......
/**
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
......@@ -98,6 +98,11 @@ namespace eosio {
printhex(static_cast<const void*>(arr.data()), arr.size());
}
template<size_t Size>
inline void print( fixed_key<Size>& val ) {
print(static_cast<const fixed_key<Size>&>(val));
}
/**
* Prints a 64 bit names as base32 encoded string
* @brief Prints a 64 bit names as base32 encoded string
......
......@@ -14,7 +14,9 @@ namespace eosio {
void forward( action_name reqauth, account_name forward_code, account_name forward_auth ) {
require_auth( reqauth );
dispatch_inline( permission_level{forward_auth,N(active)}, forward_code, N(reqauth), &testinline::reqauth, { forward_auth } );
INLINE_ACTION_SENDER(testinline, reqauth)( forward_code, {forward_auth,N(active)}, {forward_auth} );
//SEND_INLINE_ACTION( testinline(forward_code), reqauth, {forward_auth,N(active)}, {forward_auth} );
//eosio::dispatch_inline<account_name>( N(forward_code), N(reqauth), {{forward_auth, N(active)}}, {forward_auth} );
}
};
......
......@@ -90,6 +90,10 @@ struct test_db {
static void idx64_upperbound(uint64_t receiver, uint64_t code, uint64_t action);
static void test_invalid_access(uint64_t receiver, uint64_t code, uint64_t action);
static void idx_double_nan_create_fail(uint64_t receiver, uint64_t code, uint64_t action);
static void idx_double_nan_modify_fail(uint64_t receiver, uint64_t code, uint64_t action);
static void idx_double_nan_lookup_fail(uint64_t receiver, uint64_t code, uint64_t action);
};
struct test_multi_index {
......
......@@ -17,6 +17,9 @@ extern "C" {
WASM_TEST_HANDLER_EX(test_db, idx64_lowerbound);
WASM_TEST_HANDLER_EX(test_db, idx64_upperbound);
WASM_TEST_HANDLER_EX(test_db, test_invalid_access);
WASM_TEST_HANDLER_EX(test_db, idx_double_nan_create_fail);
WASM_TEST_HANDLER_EX(test_db, idx_double_nan_modify_fail);
WASM_TEST_HANDLER_EX(test_db, idx_double_nan_lookup_fail);
//unhandled test call
eosio_assert(false, "Unknown Test");
......
......@@ -495,3 +495,41 @@ void test_db::test_invalid_access(uint64_t receiver, uint64_t code, uint64_t act
eosio_assert( value == ia.val, "test_invalid_access: value did not match" );
}
}
void test_db::idx_double_nan_create_fail(uint64_t receiver, uint64_t, uint64_t) {
double x = 0.0;
x = x / x; // create a NaN
db_idx_double_store( N(nan), N(nan), receiver, 0, &x); // should fail
}
void test_db::idx_double_nan_modify_fail(uint64_t receiver, uint64_t, uint64_t) {
double x = 0.0;
db_idx_double_store( N(nan), N(nan), receiver, 0, &x);
auto itr = db_idx_double_find_primary(receiver, N(nan), N(nan), &x, 0);
x = 0.0;
x = x / x; // create a NaN
db_idx_double_update(itr, 0, &x); // should fail
}
void test_db::idx_double_nan_lookup_fail(uint64_t receiver, uint64_t, uint64_t) {
auto act = eosio::get_action(1, 0);
auto lookup_type = eosio::unpack<uint32_t>(act.data);
uint64_t pk;
double x = 0.0;
db_idx_double_store( N(nan), N(nan), receiver, 0, &x);
x = x / x; // create a NaN
switch( lookup_type ) {
case 0: // find
db_idx_double_find_secondary(receiver, N(nan), N(nan), &x, &pk);
break;
case 1: // lower bound
db_idx_double_lowerbound(receiver, N(nan), N(nan), &x, &pk);
break;
case 2: // upper bound
db_idx_double_upperbound(receiver, N(nan), N(nan), &x, &pk);
break;
default:
eosio_assert( false, "idx_double_nan_lookup_fail: unexpected lookup_type" );
}
}
......@@ -9,7 +9,7 @@
#include "test_memory.cpp"
extern "C" {
void apply( uint64_t receiver, uint64_t code, uint64_t action ) {
void apply( uint64_t /*receiver*/, uint64_t code, uint64_t action ) {
require_auth(code);
//test_extended_memory
......
......@@ -344,6 +344,7 @@ template <typename T>
void test_memory_load() {
T *ptr = (T *)(8192 * 1024 - 1);
volatile T tmp = ptr[0];
(void)tmp;
}
void test_memory::test_outofbound_4()
......@@ -391,4 +392,5 @@ void test_memory::test_outofbound_13()
volatile unsigned int a = 0xffffffff;
double *ptr = (double *)a; // load with memory wrap
volatile double tmp = ptr[0];
(void)tmp;
}
......@@ -512,6 +512,7 @@ void test_multi_index::idx256_general(uint64_t receiver, uint64_t code, uint64_t
print("First entry with a secondary key greater than 42 has ID=", upper->id, ".\n");
eosio_assert( upper->id == 2, "idx256_general - upper_bound" );
eosio_assert( upper->id == secidx.get(onetwothreefour).id, "idx256_general - secondary index get" );
print("Removed entry with ID=", lower1->id, ".\n");
secidx.erase( lower1 );
......@@ -769,4 +770,3 @@ void test_multi_index::idx64_pk_cache_sk_lookup(uint64_t receiver, uint64_t code
}
#pragma GCC diagnostic pop
......@@ -19,8 +19,8 @@ struct impl {
/**
* @brief Check for valid movement
* @detail Movement is considered valid if it is inside the board and done on empty cell
* @param movement - the movement made by the player
* @param game - the game on which the movement is being made
* @param mvt - the movement made by the player
* @param game_for_movement - the game on which the movement is being made
* @return true if movement is valid
*/
bool is_valid_movement(const movement& mvt, const game& game_for_movement) {
......@@ -33,7 +33,7 @@ struct impl {
/**
* @brief Get winner of the game
* @detail Winner of the game is the first player who made three consecutive aligned movement
* @param game - the game which we want to determine the winner of
* @param current_game - the game which we want to determine the winner of
* @return winner of the game (can be either none/ draw/ account name of host/ account name of challenger)
*/
account_name get_winner(const game& current_game) {
......@@ -86,7 +86,7 @@ struct impl {
/**
* @brief Apply create action
* @param create - action to be applied
* @param c - action to be applied
*/
void on(const create& c) {
require_auth(c.host);
......@@ -106,7 +106,7 @@ struct impl {
/**
* @brief Apply restart action
* @param restart - action to be applied
* @param r - action to be applied
*/
void on(const restart& r) {
require_auth(r.by);
......@@ -127,7 +127,7 @@ struct impl {
/**
* @brief Apply close action
* @param close - action to be applied
* @param c - action to be applied
*/
void on(const close& c) {
require_auth(c.host);
......@@ -143,7 +143,7 @@ struct impl {
/**
* @brief Apply move action
* @param move - action to be applied
* @param m - action to be applied
*/
void on(const move& m) {
require_auth(m.by);
......@@ -165,7 +165,7 @@ struct impl {
eosio_assert(is_valid_movement(m.mvt, *itr), "not a valid movement!");
// Fill the cell, 1 for host, 2 for challenger
const auto cell_value = itr->turn == itr->host ? 1 : 2;
const uint8_t cell_value = itr->turn == itr->host ? 1 : 2;
const auto turn = itr->turn == itr->host ? itr->challenger : itr->host;
existing_host_games.modify(itr, itr->host, [&]( auto& g ) {
g.board[m.mvt.row * 3 + m.mvt.column] = cell_value;
......@@ -177,7 +177,7 @@ struct impl {
}
/// The apply method implements the dispatch of events to this contract
void apply( uint64_t receiver, uint64_t code, uint64_t action ) {
void apply( uint64_t /*receiver*/, uint64_t code, uint64_t action ) {
if (code == code_account) {
if (action == N(create)) {
......
......@@ -10,7 +10,6 @@
* @ingroup examplecontract
*
* @details
*
* For the following tic-tac-toe game:
* - Each pair of player can have 2 unique game, one where player_1 become host and player_2 become challenger and vice versa
* - The game data is stored in the "host" scope and use the "challenger" as the key
......@@ -53,7 +52,8 @@ namespace tic_tac_toe {
static const uint32_t board_len = 9;
struct game {
game() { initialize_board(); }
game(account_name challenger, account_name host):challenger(challenger), host(host), turn(host) {
game(account_name challenger_account, account_name host_account)
: challenger(challenger_account), host(host_account), turn(host_account) {
// Initialize board
initialize_board();
}
......
......@@ -180,9 +180,15 @@ bool chain_controller::_push_block(const signed_block& new_block)
{ try {
uint32_t skip = _skip_flags;
if (!(skip&skip_fork_db)) {
/// TODO: if the block is greater than the head block and before the next maintenance interval
// verify that the block signer is in the current set of active producers.
if(new_block.block_num() > head_block_num()) {
if(!is_start_of_round(new_block.block_num())) {
auto schedule = get_global_properties().active_producers.producers;
if(std::find(schedule.begin(), schedule.end(),
producer_key{new_block.producer, new_block.signee()}) == schedule.end()) {
return false; // Not forking and not pushing block with unexpected signature
}
}
}
shared_ptr<fork_item> new_head = _fork_db.push_block(new_block);
//If the head block from the longest chain does not build off of the current head, we need to switch forks.
if (new_head->data.previous != head_block_id()) {
......@@ -1556,7 +1562,7 @@ const producer_object& chain_controller::validate_block_header(uint32_t skip, co
}
auto expected_schedule_version = get_global_properties().active_producers.version;
EOS_ASSERT( next_block.schedule_version == expected_schedule_version , block_validate_exception,"wrong producer schedule version specified ${x} expectd ${y}",
EOS_ASSERT( next_block.schedule_version == expected_schedule_version , block_validate_exception,"wrong producer schedule version specified ${x} expected ${y}",
("x", next_block.schedule_version)("y",expected_schedule_version) );
return producer;
......@@ -2072,7 +2078,7 @@ uint32_t chain_controller::get_slot_at_time( block_timestamp_type when )const
auto first_slot_time = get_slot_time(1);
if( when < first_slot_time )
return 0;
return block_timestamp_type(when).slot - first_slot_time.slot + 1;
return when.slot - first_slot_time.slot + 1;
}
uint32_t chain_controller::producer_participation_rate()const
......
......@@ -133,10 +133,8 @@ namespace eosio { namespace chain { namespace contracts {
typedef secondary_index<key256_t,index256_object_type>::index_index index256_index;
struct soft_double_less {
bool operator()( uint64_t a, uint64_t b )const {
float64_t x; x.v = a;
float64_t y; y.v = b;
return f64_lt(x, y);
bool operator()( const float64_t& lhs, const float64_t& rhs )const {
return f64_lt(lhs, rhs);
}
};
......@@ -145,8 +143,8 @@ namespace eosio { namespace chain { namespace contracts {
*
* The software double implementation is using the Berkeley softfloat library (release 3).
*/
typedef secondary_index<uint64_t,index_double_object_type,soft_double_less>::index_object index_double_object;
typedef secondary_index<uint64_t,index_double_object_type,soft_double_less>::index_index index_double_index;
typedef secondary_index<float64_t,index_double_object_type,soft_double_less>::index_object index_double_object;
typedef secondary_index<float64_t,index_double_object_type,soft_double_less>::index_index index_double_index;
} // ::contracts
......
......@@ -53,6 +53,8 @@ namespace eosio {
struct symbol_code {
uint64_t value;
operator uint64_t()const { return value; }
};
class symbol {
......
......@@ -641,31 +641,35 @@ class softfloat_api : public context_aware_api {
return from_softfloat64(ui64_to_f64( a ));
}
private:
inline float32_t to_softfloat32( float f ) {
static bool is_nan( const float32_t f ) {
return ((f.v & 0x7FFFFFFF) > 0x7F800000);
}
static bool is_nan( const float64_t f ) {
return ((f.v & 0x7FFFFFFFFFFFFFFF) > 0x7FF0000000000000);
}
static bool is_nan( const float128_t& f ) {
const uint32_t* iptr = (const uint32_t*)&f;
return softfloat_isNaNF128M( iptr );
}
static float32_t to_softfloat32( float f ) {
return *reinterpret_cast<float32_t*>(&f);
}
inline float64_t to_softfloat64( double d ) {
static float64_t to_softfloat64( double d ) {
return *reinterpret_cast<float64_t*>(&d);
}
inline float from_softfloat32( float32_t f ) {
static float from_softfloat32( float32_t f ) {
return *reinterpret_cast<float*>(&f);
}
inline double from_softfloat64( float64_t d ) {
static double from_softfloat64( float64_t d ) {
return *reinterpret_cast<double*>(&d);
}
static constexpr uint32_t inv_float_eps = 0x4B000000;
static constexpr uint64_t inv_double_eps = 0x4330000000000000;
inline bool sign_bit( float32_t f ) { return f.v >> 31; }
inline bool sign_bit( float64_t f ) { return f.v >> 63; }
inline bool is_nan( float32_t f ) {
return ((f.v & 0x7FFFFFFF) > 0x7F800000);
}
inline bool is_nan( float64_t f ) {
return ((f.v & 0x7FFFFFFFFFFFFFFF) > 0x7FF0000000000000);
}
static bool sign_bit( float32_t f ) { return f.v >> 31; }
static bool sign_bit( float64_t f ) { return f.v >> 63; }
};
class producer_api : public context_aware_api {
......@@ -973,6 +977,42 @@ class console_api : public context_aware_api {
return context.IDX.previous_secondary(iterator, primary);\
}
#define DB_API_METHOD_WRAPPERS_FLOAT_SECONDARY(IDX, TYPE)\
int db_##IDX##_store( uint64_t scope, uint64_t table, uint64_t payer, uint64_t id, const TYPE& secondary ) {\
EOS_ASSERT( !softfloat_api::is_nan( secondary ), transaction_exception, "NaN is not an allowed value for a secondary key" );\
return context.IDX.store( scope, table, payer, id, secondary );\
}\
void db_##IDX##_update( int iterator, uint64_t payer, const TYPE& secondary ) {\
EOS_ASSERT( !softfloat_api::is_nan( secondary ), transaction_exception, "NaN is not an allowed value for a secondary key" );\
return context.IDX.update( iterator, payer, secondary );\
}\
void db_##IDX##_remove( int iterator ) {\
return context.IDX.remove( iterator );\
}\
int db_##IDX##_find_secondary( uint64_t code, uint64_t scope, uint64_t table, const TYPE& secondary, uint64_t& primary ) {\
EOS_ASSERT( !softfloat_api::is_nan( secondary ), transaction_exception, "NaN is not an allowed value for a secondary key" );\
return context.IDX.find_secondary(code, scope, table, secondary, primary);\
}\
int db_##IDX##_find_primary( uint64_t code, uint64_t scope, uint64_t table, TYPE& secondary, uint64_t primary ) {\
return context.IDX.find_primary(code, scope, table, secondary, primary);\
}\
int db_##IDX##_lowerbound( uint64_t code, uint64_t scope, uint64_t table, TYPE& secondary, uint64_t& primary ) {\
EOS_ASSERT( !softfloat_api::is_nan( secondary ), transaction_exception, "NaN is not an allowed value for a secondary key" );\
return context.IDX.lowerbound_secondary(code, scope, table, secondary, primary);\
}\
int db_##IDX##_upperbound( uint64_t code, uint64_t scope, uint64_t table, TYPE& secondary, uint64_t& primary ) {\
EOS_ASSERT( !softfloat_api::is_nan( secondary ), transaction_exception, "NaN is not an allowed value for a secondary key" );\
return context.IDX.upperbound_secondary(code, scope, table, secondary, primary);\
}\
int db_##IDX##_end( uint64_t code, uint64_t scope, uint64_t table ) {\
return context.IDX.end_secondary(code, scope, table);\
}\
int db_##IDX##_next( int iterator, uint64_t& primary ) {\
return context.IDX.next_secondary(iterator, primary);\
}\
int db_##IDX##_previous( int iterator, uint64_t& primary ) {\
return context.IDX.previous_secondary(iterator, primary);\
}
class database_api : public context_aware_api {
public:
......@@ -1012,7 +1052,7 @@ class database_api : public context_aware_api {
DB_API_METHOD_WRAPPERS_SIMPLE_SECONDARY(idx64, uint64_t)
DB_API_METHOD_WRAPPERS_SIMPLE_SECONDARY(idx128, uint128_t)
DB_API_METHOD_WRAPPERS_ARRAY_SECONDARY(idx256, 2, uint128_t)
DB_API_METHOD_WRAPPERS_SIMPLE_SECONDARY(idx_double, uint64_t)
DB_API_METHOD_WRAPPERS_FLOAT_SECONDARY(idx_double, float64_t)
};
class memory_api : public context_aware_api {
......@@ -1247,37 +1287,37 @@ class compiler_builtins : public context_aware_api {
}
int __eqtf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
float128_t a = {{ la, ha }};
float128_t b = {{ la, ha }};
float128_t b = {{ lb, hb }};
return f128_eq( a, b );
}
int __netf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
float128_t a = {{ la, ha }};
float128_t b = {{ la, ha }};
float128_t b = {{ lb, hb }};
return !f128_eq( a, b );
}
int __getf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
float128_t a = {{ la, ha }};
float128_t b = {{ la, ha }};
float128_t b = {{ lb, hb }};
return !f128_lt( a, b );
}
int __gttf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
float128_t a = {{ la, ha }};
float128_t b = {{ la, ha }};
float128_t b = {{ lb, hb }};
return !f128_lt( a, b ) && !f128_eq( a, b );
}
int __letf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
float128_t a = {{ la, ha }};
float128_t b = {{ la, ha }};
float128_t b = {{ lb, hb }};
return f128_le( a, b );
}
int __lttf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
float128_t a = {{ la, ha }};
float128_t b = {{ la, ha }};
float128_t b = {{ lb, hb }};
return f128_lt( a, b );
}
int __cmptf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
float128_t a = {{ la, ha }};
float128_t b = {{ la, ha }};
float128_t b = {{ lb, hb }};
if ( f128_lt( a, b ) )
return -1;
if ( f128_eq( a, b ) )
......@@ -1286,7 +1326,7 @@ class compiler_builtins : public context_aware_api {
}
int __unordtf2( uint64_t la, uint64_t ha, uint64_t lb, uint64_t hb ) {
float128_t a = {{ la, ha }};
float128_t b = {{ la, ha }};
float128_t b = {{ lb, hb }};
if ( f128_isSignalingNaN( a ) || f128_isSignalingNaN( b ) )
return 1;
return 0;
......@@ -1302,6 +1342,12 @@ class compiler_builtins : public context_aware_api {
void __floatunsitf( float128_t& ret, uint32_t i ) {
ret = ui32_to_f128(i); /// TODO: should be 128
}
void __floatditf( float128_t& ret, uint64_t a ) {
ret = i64_to_f128( a );
}
void __floatunditf( float128_t& ret, uint64_t a ) {
ret = ui64_to_f128( a );
}
void __extendsftf2( float128_t& ret, uint32_t f ) {
float32_t in = { f };
ret = f32_to_f128( in );
......@@ -1443,10 +1489,13 @@ REGISTER_INTRINSICS(compiler_builtins,
(__getf2, int(int64_t, int64_t, int64_t, int64_t) )
(__gttf2, int(int64_t, int64_t, int64_t, int64_t) )
(__lttf2, int(int64_t, int64_t, int64_t, int64_t) )
(__letf2, int(int64_t, int64_t, int64_t, int64_t) )
(__cmptf2, int(int64_t, int64_t, int64_t, int64_t) )
(__unordtf2, int(int64_t, int64_t, int64_t, int64_t) )
(__floatsitf, void (int, int) )
(__floatunsitf, void (int, int) )
(__floatditf, void (int, int64_t) )
(__floatunditf, void (int, int64_t) )
(__floatsidf, double(int) )
(__extendsftf2, void(int, int) )
(__extenddftf2, void(int, double) )
......
......@@ -52,6 +52,7 @@ namespace fc
SSL_TYPE(ecdsa_sig, ECDSA_SIG, ECDSA_SIG_free)
SSL_TYPE(bn_ctx, BN_CTX, BN_CTX_free)
SSL_TYPE(evp_cipher_ctx, EVP_CIPHER_CTX, EVP_CIPHER_CTX_free )
SSL_TYPE(ec_key, EC_KEY, EC_KEY_free)
/** allocates a bignum by default.. */
struct ssl_bignum : public ssl_wrapper<BIGNUM>
......
......@@ -116,7 +116,12 @@ namespace fc
gelf_message["host"] = my->cfg.host;
gelf_message["short_message"] = format_string(message.get_format(), message.get_data());
gelf_message["timestamp"] = context.get_timestamp().time_since_epoch().count() / 1000000.;
const auto time_ns = context.get_timestamp().time_since_epoch().count();
gelf_message["timestamp"] = time_ns / 1000000.;
gelf_message["_timestamp_ns"] = time_ns;
static unsigned long gelf_log_counter;
gelf_message["_log_id"] = fc::to_string(++gelf_log_counter);
switch (context.get_log_level())
{
......
Subproject commit 4f0bb0ded7a5024d20d53827a81fe92473bf6058
Subproject commit 72f025ba240d49a6531d40148ca229a358404f78
......@@ -133,8 +133,15 @@ namespace eosio { namespace testing {
return control->get_database().find<ObjectType,IndexBy>( forward<Args>(args)... );
}
public_key_type get_public_key( name keyname, string role = "owner" ) const;
private_key_type get_private_key( name keyname, string role = "owner" ) const;
template< typename KeyType = fc::ecc::private_key_shim >
private_key_type get_private_key( name keyname, string role = "owner" ) const {
return private_key_type::regenerate<KeyType>(fc::sha256::hash(string(keyname)+role));
}
template< typename KeyType = fc::ecc::private_key_shim >
public_key_type get_public_key( name keyname, string role = "owner" ) const {
return get_private_key<KeyType>( keyname, role ).get_public_key();
}
void set_code( account_name name, const char* wast );
void set_code( account_name name, const vector<uint8_t> wasm );
......@@ -142,6 +149,7 @@ namespace eosio { namespace testing {
unique_ptr<chain_controller> control;
std::map<chain::public_key_type, chain::private_key_type> block_signing_private_keys;
bool chain_has_transaction( const transaction_id_type& txid ) const;
const transaction_receipt& get_transaction_receipt( const transaction_id_type& txid ) const;
......
......@@ -12,6 +12,7 @@
#include <fc/utility.hpp>
#include <fc/io/json.hpp>
#include <eosio/chain/producer_object.hpp>
#include "WAST/WAST.h"
#include "WASM/WASM.h"
......@@ -71,16 +72,6 @@ namespace eosio { namespace testing {
}
public_key_type base_tester::get_public_key( name keyname, string role ) const {
return get_private_key( keyname, role ).get_public_key();
}
private_key_type base_tester::get_private_key( name keyname, string role ) const {
return private_key_type::regenerate<fc::ecc::private_key_shim>(fc::sha256::hash(string(keyname)+role));
}
void base_tester::close() {
control.reset();
chain_transactions.clear();
......@@ -112,8 +103,18 @@ namespace eosio { namespace testing {
auto head_time = control->head_block_time();
auto next_time = head_time + skip_time;
uint32_t slot = control->get_slot_at_time( next_time );
auto sch_pro = control->get_scheduled_producer(slot);
auto priv_key = get_private_key( sch_pro, "active" );
auto sch_pro = control->get_scheduled_producer(slot);
const auto& sch_pro_signing_key = control->get_producer(sch_pro).signing_key;
private_key_type priv_key;
// Check if signing private key exist in the list
auto private_key_itr = block_signing_private_keys.find( sch_pro_signing_key );
if( private_key_itr == block_signing_private_keys.end() ) {
// If it's not found, default to active k1 key
priv_key = get_private_key( sch_pro, "active" );
} else {
priv_key = private_key_itr->second;
}
return control->generate_block( next_time, sch_pro, priv_key, skip_flag );
}
......@@ -536,7 +537,7 @@ namespace eosio { namespace testing {
if (tbl) {
const auto *obj = db.template find<contracts::key_value_object, contracts::by_scope_primary>(boost::make_tuple(tbl->id, asset_symbol.to_symbol_code().value));
if (obj) {
//balance is the second field after symbol, so skip the symbol
//balance is the first field in the serialization
fc::datastream<const char *> ds(obj->value.data(), obj->value.size());
fc::raw::unpack(ds, result);
}
......
......@@ -319,19 +319,27 @@ read_only::get_table_rows_result read_only::get_table_rows( const read_only::get
}
vector<asset> read_only::get_currency_balance( const read_only::get_currency_balance_params& p )const {
const abi_def abi = get_abi( db, p.code );
auto table_type = get_table_type( abi, "accounts" );
vector<asset> results;
walk_table<contracts::key_value_index, contracts::by_scope_primary>(p.code, p.account, N(accounts), [&](const contracts::key_value_object& obj){
share_type balance;
EOS_ASSERT( obj.value.size() >= sizeof(asset), chain::asset_type_exception, "Invalid data on table");
asset cursor;
fc::datastream<const char *> ds(obj.value.data(), obj.value.size());
fc::raw::unpack(ds, balance);
auto cursor = asset(balance, symbol(obj.primary_key));
fc::raw::unpack(ds, cursor);
EOS_ASSERT( cursor.get_symbol().valid(), chain::asset_type_exception, "Invalid asset");
if( !p.symbol || cursor.symbol_name().compare(*p.symbol) == 0 ) {
results.emplace_back(balance, symbol(obj.primary_key));
if( !p.symbol || boost::iequals(cursor.symbol_name(), *p.symbol) ) {
results.emplace_back(cursor);
}
// return false if we are looking for one and found it, true otherwise
return !p.symbol || cursor.symbol_name().compare(*p.symbol) != 0;
return !(p.symbol && boost::iequals(cursor.symbol_name(), *p.symbol));
});
return results;
......@@ -339,15 +347,24 @@ vector<asset> read_only::get_currency_balance( const read_only::get_currency_bal
fc::variant read_only::get_currency_stats( const read_only::get_currency_stats_params& p )const {
fc::mutable_variant_object results;
walk_table<contracts::key_value_index, contracts::by_scope_primary>(p.code, p.code, N(stat), [&](const contracts::key_value_object& obj){
share_type balance;
fc::datastream<const char *> ds(obj.value.data(), obj.value.size());
fc::raw::unpack(ds, balance);
auto cursor = asset(balance, symbol(obj.primary_key));
const abi_def abi = get_abi( db, p.code );
auto table_type = get_table_type( abi, "stat" );
uint64_t scope = ( eosio::chain::string_to_symbol( 0, boost::algorithm::to_upper_copy(p.symbol).c_str() ) >> 8 );
walk_table<contracts::key_value_index, contracts::by_scope_primary>(p.code, scope, N(stat), [&](const contracts::key_value_object& obj){
EOS_ASSERT( obj.value.size() >= sizeof(read_only::get_currency_stats_result), chain::asset_type_exception, "Invalid data on table");
fc::datastream<const char *> ds(obj.value.data(), obj.value.size());
read_only::get_currency_stats_result result;
result.supply = cursor;
results[cursor.symbol_name()] = result;
fc::raw::unpack(ds, result.supply);
fc::raw::unpack(ds, result.max_supply);
fc::raw::unpack(ds, result.issuer);
results[result.supply.symbol_name()] = result;
return true;
});
......
......@@ -172,12 +172,15 @@ public:
vector<asset> get_currency_balance( const get_currency_balance_params& params )const;
struct get_currency_stats_params {
name code;
optional<string> symbol;
name code;
string symbol;
};
struct get_currency_stats_result {
asset supply;
asset supply;
asset max_supply;
account_name issuer;
};
fc::variant get_currency_stats( const get_currency_stats_params& params )const;
......@@ -359,7 +362,7 @@ FC_REFLECT( eosio::chain_apis::read_only::get_table_rows_result, (rows)(more) );
FC_REFLECT( eosio::chain_apis::read_only::get_currency_balance_params, (code)(account)(symbol));
FC_REFLECT( eosio::chain_apis::read_only::get_currency_stats_params, (code)(symbol));
FC_REFLECT( eosio::chain_apis::read_only::get_currency_stats_result, (supply));
FC_REFLECT( eosio::chain_apis::read_only::get_currency_stats_result, (supply)(max_supply)(issuer));
FC_REFLECT( eosio::chain_apis::read_only::get_account_results, (account_name)(permissions) )
FC_REFLECT( eosio::chain_apis::read_only::get_code_results, (account_name)(code_hash)(wast)(abi) )
......
......@@ -8,6 +8,7 @@
#include <fc/log/logger_config.hpp>
#include <fc/reflect/variant.hpp>
#include <fc/io/json.hpp>
#include <fc/crypto/openssl.hpp>
#include <boost/asio.hpp>
#include <boost/optional.hpp>
......@@ -38,6 +39,7 @@ namespace eosio {
namespace detail {
template<class T>
struct asio_with_stub_log : public websocketpp::config::asio {
typedef asio_with_stub_log type;
typedef asio base;
......@@ -51,14 +53,6 @@ namespace eosio {
typedef base::con_msg_manager_type con_msg_manager_type;
typedef base::endpoint_msg_manager_type endpoint_msg_manager_type;
/// Custom Logging policies
/*typedef websocketpp::log::syslog<concurrency_type,
websocketpp::log::elevel> elog_type;
typedef websocketpp::log::syslog<concurrency_type,
websocketpp::log::alevel> alog_type;
*/
//typedef base::alog_type alog_type;
//typedef base::elog_type elog_type;
typedef websocketpp::log::stub elog_type;
typedef websocketpp::log::stub alog_type;
......@@ -70,8 +64,7 @@ namespace eosio {
typedef type::elog_type elog_type;
typedef type::request_type request_type;
typedef type::response_type response_type;
typedef websocketpp::transport::asio::basic_socket::endpoint
socket_type;
typedef T socket_type;
};
typedef websocketpp::transport::asio::endpoint<transport_config>
......@@ -81,12 +74,12 @@ namespace eosio {
};
}
using websocket_server_type = websocketpp::server<detail::asio_with_stub_log>;
using websocket_server_type = websocketpp::server<detail::asio_with_stub_log<websocketpp::transport::asio::basic_socket::endpoint>>;
using websocket_server_tls_type = websocketpp::server<detail::asio_with_stub_log<websocketpp::transport::asio::tls_socket::endpoint>>;
using ssl_context_ptr = websocketpp::lib::shared_ptr<websocketpp::lib::asio::ssl::context>;
class http_plugin_impl {
public:
//shared_ptr<std::thread> http_thread;
//asio::io_service http_ios;
map<string,url_handler> url_handlers;
optional<tcp::endpoint> listen_endpoint;
string access_control_allow_origin;
......@@ -94,6 +87,114 @@ namespace eosio {
bool access_control_allow_credentials = false;
websocket_server_type server;
optional<tcp::endpoint> https_listen_endpoint;
string https_cert_chain;
string https_key;
websocket_server_tls_type https_server;
ssl_context_ptr on_tls_init(websocketpp::connection_hdl hdl) {
ssl_context_ptr ctx = websocketpp::lib::make_shared<websocketpp::lib::asio::ssl::context>(asio::ssl::context::sslv23_server);
try {
ctx->set_options(asio::ssl::context::default_workarounds |
asio::ssl::context::no_sslv2 |
asio::ssl::context::no_sslv3 |
asio::ssl::context::no_tlsv1 |
asio::ssl::context::no_tlsv1_1 |
asio::ssl::context::single_dh_use);
ctx->use_certificate_chain_file(https_cert_chain);
ctx->use_private_key_file(https_key, asio::ssl::context::pem);
//going for the A+! Do a few more things on the native context to get ECDH in use
fc::ec_key ecdh = EC_KEY_new_by_curve_name(NID_secp384r1);
if (!ecdh)
FC_THROW("Failed to set NID_secp384r1");
if(SSL_CTX_set_tmp_ecdh(ctx->native_handle(), (EC_KEY*)ecdh) != 1)
FC_THROW("Failed to set ECDH PFS");
if(SSL_CTX_set_cipher_list(ctx->native_handle(), \
"EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:AES256:" \
"!DHE:!RSA:!AES128:!RC4:!DES:!3DES:!DSS:!SRP:!PSK:!EXP:!MD5:!LOW:!aNULL:!eNULL") != 1)
FC_THROW("Failed to set HTTPS cipher list");
} catch (const fc::exception& e) {
elog("https server initialization error: ${w}", ("w", e.to_detail_string()));
} catch(std::exception& e) {
elog("https server initialization error: ${w}", ("w", e.what()));
}
return ctx;
}
template<class T>
void handle_http_request(typename websocketpp::server<detail::asio_with_stub_log<T>>::connection_ptr con) {
try {
if (!access_control_allow_origin.empty()) {
con->append_header("Access-Control-Allow-Origin", access_control_allow_origin);
}
if (!access_control_allow_headers.empty()) {
con->append_header("Access-Control-Allow-Headers", access_control_allow_headers);
}
if (access_control_allow_credentials) {
con->append_header("Access-Control-Allow-Credentials", "true");
}
con->append_header("Content-type", "application/json");
auto body = con->get_request_body();
auto resource = con->get_uri()->get_resource();
auto handler_itr = url_handlers.find(resource);
if(handler_itr != url_handlers.end()) {
handler_itr->second(resource, body, [con](int code, string body) {
con->set_body(body);
con->set_status(websocketpp::http::status_code::value(code));
});
} else {
wlog("404 - not found: ${ep}", ("ep",resource));
error_results results{websocketpp::http::status_code::not_found,
"Not Found", fc::exception(FC_LOG_MESSAGE(error, "Unknown Endpoint"))};
con->set_body(fc::json::to_string(results));
con->set_status(websocketpp::http::status_code::not_found);
}
} catch( const fc::exception& e ) {
elog( "http: ${e}", ("e",e.to_detail_string()));
error_results results{websocketpp::http::status_code::internal_server_error,
"Internal Service Error", e};
con->set_body(fc::json::to_string(results));
con->set_status(websocketpp::http::status_code::internal_server_error);
} catch( const std::exception& e ) {
elog( "http: ${e}", ("e",e.what()));
error_results results{websocketpp::http::status_code::internal_server_error,
"Internal Service Error", fc::exception(FC_LOG_MESSAGE(error, e.what()))};
con->set_body(fc::json::to_string(results));
con->set_status(websocketpp::http::status_code::internal_server_error);
} catch( ... ) {
error_results results{websocketpp::http::status_code::internal_server_error,
"Internal Service Error", fc::exception(FC_LOG_MESSAGE(error, "Unknown Exception"))};
con->set_body(fc::json::to_string(results));
con->set_status(websocketpp::http::status_code::internal_server_error);
}
}
template<class T>
void create_server_for_endpoint(const tcp::endpoint& ep, websocketpp::server<detail::asio_with_stub_log<T>>& ws) {
try {
ws.clear_access_channels(websocketpp::log::alevel::all);
ws.init_asio(&app().get_io_service());
ws.set_reuse_addr(true);
ws.set_http_handler([&](connection_hdl hdl) {
handle_http_request<T>(ws.get_con_from_hdl(hdl));
});
} catch ( const fc::exception& e ){
elog( "http: ${e}", ("e",e.to_detail_string()));
} catch ( const std::exception& e ){
elog( "http: ${e}", ("e",e.what()));
} catch (...) {
elog("error thrown from http io service");
}
}
};
http_plugin::http_plugin():my(new http_plugin_impl()){}
......@@ -102,7 +203,16 @@ namespace eosio {
void http_plugin::set_program_options(options_description&, options_description& cfg) {
cfg.add_options()
("http-server-address", bpo::value<string>()->default_value("127.0.0.1:8888"),
"The local IP and port to listen for incoming http connections.")
"The local IP and port to listen for incoming http connections; set blank to disable.")
("https-server-address", bpo::value<string>(),
"The local IP and port to listen for incoming https connections; leave blank to disable.")
("https-certificate-chain-file", bpo::value<string>(),
"Filename with the certificate chain to present on https connections. PEM format. Required for https.")
("https-private-key-file", bpo::value<string>(),
"Filename with https private key in PEM format. Required for https")
("access-control-allow-origin", bpo::value<string>()->notifier([this](const string& v) {
my->access_control_allow_origin = v;
......@@ -110,7 +220,6 @@ namespace eosio {
}),
"Specify the Access-Control-Allow-Origin to be returned on each request.")
("access-control-allow-headers", bpo::value<string>()->notifier([this](const string& v) {
my->access_control_allow_headers = v;
ilog("configured http with Access-Control-Allow-Headers : ${o}", ("o", my->access_control_allow_headers));
......@@ -127,115 +236,89 @@ namespace eosio {
}
void http_plugin::plugin_initialize(const variables_map& options) {
if(options.count("http-server-address")) {
#if 0
auto lipstr = options.at("http-server-address").as< string >();
auto fcep = fc::ip::endpoint::from_string(lipstr);
my->listen_endpoint = tcp::endpoint(boost::asio::ip::address_v4::from_string((string)fcep.get_address()), fcep.port());
#endif
auto resolver = std::make_shared<tcp::resolver>( std::ref( app().get_io_service() ) );
if( options.count( "http-server-address" ) ) {
auto lipstr = options.at("http-server-address").as< string >();
auto host = lipstr.substr( 0, lipstr.find(':') );
auto port = lipstr.substr( host.size()+1, lipstr.size() );
idump((host)(port));
tcp::resolver::query query( tcp::v4(), host.c_str(), port.c_str() );
my->listen_endpoint = *resolver->resolve( query);
ilog("configured http to listen on ${h}:${p}", ("h",host)("p",port));
tcp::resolver resolver(app().get_io_service());
if(options.count("http-server-address") && options.at("http-server-address").as<string>().length()) {
string lipstr = options.at("http-server-address").as<string>();
string host = lipstr.substr(0, lipstr.find(':'));
string port = lipstr.substr(host.size()+1, lipstr.size());
tcp::resolver::query query( tcp::v4(), host.c_str(), port.c_str() );
try {
my->listen_endpoint = *resolver.resolve(query);
ilog("configured http to listen on ${h}:${p}", ("h",host)("p",port));
} catch(const boost::system::system_error& ec) {
elog("failed to configure http to listen on ${h}:${p} (${m})", ("h",host)("p",port)("m", ec.what()));
}
}
if(options.count("https-server-address") && options.at("https-server-address").as<string>().length()) {
if(!options.count("https-certificate-chain-file") || options.at("https-certificate-chain-file").as<string>().empty()) {
elog("https-certificate-chain-file is required for HTTPS");
return;
}
if(!options.count("https-private-key-file") || options.at("https-private-key-file").as<string>().empty()) {
elog("https-private-key-file is required for HTTPS");
return;
}
// uint32_t addr = my->listen_endpoint->address().to_v4().to_ulong();
// auto fcep = fc::ip::endpoint (addr,my->listen_endpoint->port());
string lipstr = options.at("https-server-address").as<string>();
string host = lipstr.substr(0, lipstr.find(':'));
string port = lipstr.substr(host.size()+1, lipstr.size());
tcp::resolver::query query(tcp::v4(), host.c_str(), port.c_str());
try {
my->https_listen_endpoint = *resolver.resolve(query);
ilog("configured https to listen on ${h}:${p} (TLS configuration will be validated momentarily)", ("h",host)("p",port));
my->https_cert_chain = options.at("https-certificate-chain-file").as<string>();
my->https_key = options.at("https-private-key-file").as<string>();
} catch(const boost::system::system_error& ec) {
elog("failed to configure https to listen on ${h}:${p} (${m})", ("h",host)("p",port)("m", ec.what()));
}
}
//watch out for the returns above when adding new code here
}
void http_plugin::plugin_startup() {
if(my->listen_endpoint) {
try {
my->create_server_for_endpoint(*my->listen_endpoint, my->server);
ilog("start listening for http requests");
my->server.listen(*my->listen_endpoint);
my->server.start_accept();
} catch ( const fc::exception& e ){
elog( "http: ${e}", ("e",e.to_detail_string()));
} catch ( const std::exception& e ){
elog( "http: ${e}", ("e",e.what()));
} catch (...) {
elog("error thrown from http io service");
}
}
//my->http_thread = std::make_shared<std::thread>([&](){
//ilog("start processing http thread");
try {
my->server.clear_access_channels(websocketpp::log::alevel::all);
my->server.init_asio(&app().get_io_service()); //&my->http_ios);
my->server.set_reuse_addr(true);
my->server.set_http_handler([&](connection_hdl hdl) {
auto con = my->server.get_con_from_hdl(hdl);
try {
//ilog("handle http request: ${url}", ("url",con->get_uri()->str()));
//ilog("${body}", ("body", con->get_request_body()));
if (!my->access_control_allow_origin.empty()) {
con->append_header("Access-Control-Allow-Origin", my->access_control_allow_origin);
}
if (!my->access_control_allow_headers.empty()) {
con->append_header("Access-Control-Allow-Headers", my->access_control_allow_headers);
}
if (my->access_control_allow_credentials) {
con->append_header("Access-Control-Allow-Credentials", "true");
}
con->append_header("Content-type", "application/json");
auto body = con->get_request_body();
auto resource = con->get_uri()->get_resource();
auto handler_itr = my->url_handlers.find(resource);
if(handler_itr != my->url_handlers.end()) {
handler_itr->second(resource, body, [con,this](int code, string body) {
con->set_body(body);
con->set_status(websocketpp::http::status_code::value(code));
});
} else {
wlog("404 - not found: ${ep}", ("ep",resource));
error_results results{websocketpp::http::status_code::not_found,
"Not Found", fc::exception(FC_LOG_MESSAGE(error, "Unknown Endpoint"))};
con->set_body(fc::json::to_string(results));
con->set_status(websocketpp::http::status_code::not_found);
}
} catch( const fc::exception& e ) {
elog( "http: ${e}", ("e",e.to_detail_string()));
error_results results{websocketpp::http::status_code::internal_server_error,
"Internal Service Error", e};
con->set_body(fc::json::to_string(results));
con->set_status(websocketpp::http::status_code::internal_server_error);
} catch( const std::exception& e ) {
elog( "http: ${e}", ("e",e.what()));
error_results results{websocketpp::http::status_code::internal_server_error,
"Internal Service Error", fc::exception(FC_LOG_MESSAGE(error, e.what()))};
con->set_body(fc::json::to_string(results));
con->set_status(websocketpp::http::status_code::internal_server_error);
} catch( ... ) {
error_results results{websocketpp::http::status_code::internal_server_error,
"Internal Service Error", fc::exception(FC_LOG_MESSAGE(error, "Unknown Exception"))};
con->set_body(fc::json::to_string(results));
con->set_status(websocketpp::http::status_code::internal_server_error);
}
});
ilog("start listening for http requests");
my->server.listen(*my->listen_endpoint);
my->server.start_accept();
// my->http_ios.run();
// ilog("http io service exit");
} catch ( const fc::exception& e ){
elog( "http: ${e}", ("e",e.to_detail_string()));
} catch ( const std::exception& e ){
elog( "http: ${e}", ("e",e.what()));
} catch (...) {
elog("error thrown from http io service");
}
//});
if(my->https_listen_endpoint) {
try {
my->create_server_for_endpoint(*my->https_listen_endpoint, my->https_server);
my->https_server.set_tls_init_handler([this](websocketpp::connection_hdl hdl) -> ssl_context_ptr{
return my->on_tls_init(hdl);
});
ilog("start listening for https requests");
my->https_server.listen(*my->https_listen_endpoint);
my->https_server.start_accept();
} catch ( const fc::exception& e ){
elog( "https: ${e}", ("e",e.to_detail_string()));
} catch ( const std::exception& e ){
elog( "https: ${e}", ("e",e.what()));
} catch (...) {
elog("error thrown from https io service");
}
}
}
void http_plugin::plugin_shutdown() {
// if(my->http_thread) {
if(my->server.is_listening())
my->server.stop_listening();
// my->http_ios.stop();
// my->http_thread->join();
// my->http_thread.reset();
// }
if(my->server.is_listening())
my->server.stop_listening();
if(my->https_server.is_listening())
my->https_server.stop_listening();
}
void http_plugin::add_handler(const string& url, const url_handler& handler) {
......
......@@ -28,7 +28,6 @@
#include <boost/asio/steady_timer.hpp>
#include <boost/intrusive/set.hpp>
#include "old_versions.hpp"
namespace fc {
extern std::unordered_map<std::string,logger>& get_logger_map();
}
......@@ -272,7 +271,7 @@ namespace eosio {
*/
chain::signature_type sign_compact(const chain::public_key_type& signer, const fc::sha256& digest) const;
bool is_old_version (uint16_t v);
int16_t to_net_version(int16_t v);
};
const fc::string logger_name("net_plugin_impl");
......@@ -297,11 +296,31 @@ namespace eosio {
constexpr auto def_txn_expire_wait = std::chrono::seconds(3);
constexpr auto def_resp_expected_wait = std::chrono::seconds(5);
constexpr auto def_sync_fetch_span = 100;
constexpr auto def_max_just_send = 1500; // "mtu" * 1
constexpr uint32_t def_max_just_send = 0xFFFFFFFF; //1500; // "mtu" * 1
constexpr auto def_send_whole_blocks = true;
constexpr auto message_header_size = 4;
/**
* For a while, network version was a 16 bit value equal to the second set of 16 bits
* of the current build's git commit id. We are now replacing that with an integer protocol
* identifier. Based on historical analysis of all git commit identifiers, the larges gap
* between ajacent commit id values is shown below.
* these numbers were found with the following commands on the master branch:
*
* git log | grep "^commit" | awk '{print substr($2,4,4)}' | sort -u > sorted.txt
* rm -f gap.txt; prev=0; for a in $(cat sorted.txt); do echo $prev $((0x$a - 0x$prev)) $a >> gap.txt; prev=$a; done; sort -k2 -n gap.txt | tail
*
* DO NOT EDIT net_version_base OR net_version_range!
*/
constexpr int16_t net_version_base = 0xb1d4;
constexpr int16_t net_version_range = 133;
/**
* If there is a change to network protocol or behavior, increment net version to identify
* the need for compatibility hooks
*/
constexpr int16_t net_version = 1;
/**
* Index by id
* Index by is_known, block_num, validated_time, this is the order we will broadcast
......@@ -2015,15 +2034,16 @@ namespace eosio {
return;
}
if( msg.network_version != network_version) {
c->backwards_compatibility = is_old_version (msg.network_version);
int16_t mnv = to_net_version(msg.network_version);
c->backwards_compatibility = mnv < net_version;
if (network_version_match) {
elog("Peer network version does not match expected ${nv} but got ${mnv}",
("nv", network_version)("mnv", msg.network_version));
("nv", net_version)("mnv", mnv));
c->enqueue(go_away_message(wrong_version));
return;
} else {
ilog("Local network version: ${nv} Remote version: ${mnv}",
("nv", eosio::itoh(network_version))("mnv", eosio::itoh(msg.network_version)));
("nv", net_version)("mnv", mnv));
}
}
......@@ -2678,6 +2698,7 @@ namespace eosio {
( "network-version-match", bpo::value<bool>()->default_value(false),
"True to require exact match of peer network version.")
( "sync-fetch-span", bpo::value<uint32_t>()->default_value(def_sync_fetch_span), "number of blocks to retrieve in a chunk from any individual peer during synchronization")
( "max-implicit-request", bpo::value<uint32_t>()->default_value(def_max_just_send), "maximum sizes of transaction or block messages that are set wothout first sending a notice")
;
}
......@@ -2689,7 +2710,7 @@ namespace eosio {
void net_plugin::plugin_initialize( const variables_map& options ) {
ilog("Initialize net plugin");
my->network_version = static_cast<uint16_t>(app().version());
my->network_version = net_version_base + net_version;
my->network_version_match = options.at("network-version-match").as<bool>();
my->send_whole_blocks = def_send_whole_blocks;
......@@ -2699,7 +2720,7 @@ namespace eosio {
my->connector_period = std::chrono::seconds(options.at("connection-cleanup-period").as<int>());
my->txn_exp_period = def_txn_expire_wait;
my->resp_expected_period = def_resp_expected_wait;
my->big_msg_master->just_send_it_max = def_max_just_send;
my->big_msg_master->just_send_it_max = options.at("max-implicit-request").as<uint32_t>();
my->max_client_count = options.at("max-clients").as<int>();
my->num_clients = 0;
......@@ -2891,32 +2912,11 @@ namespace eosio {
return connection_ptr();
}
/*
* this really should be in apputils
*/
std::set<uint16_t> known_old;
std::set<uint16_t> known_new;
bool net_plugin_impl::is_old_version (uint16_t v) {
if (known_old.find (v) != known_old.end()) {
fc_dlog (logger,"version ${v} is known to be old",("v",v));
return true;
}
if (known_new.find (v) != known_new.end()) {
fc_dlog (logger,"version ${v} is known to be new",("v",v));
return false;
int16_t net_plugin_impl::to_net_version (int16_t v) {
if (v >= net_version_base) {
v -= net_version_base;
return (v > net_version_range) ? 0 : v;
}
for (auto old: old_versions) {
if (v == (uint16_t)old) {
fc_dlog (logger,"adding version ${v} to the known old set",("v",v));
known_old.insert(v);
return true;
}
}
fc_dlog (logger,"adding version ${v} to the known new set",("v",v));
known_new.insert(v);
return false;
return 0;
}
}
此差异已折叠。
......@@ -689,45 +689,30 @@ int main( int argc, char** argv ) {
get_balance->add_option( "account", accountName, localized("The account to query balances for") )->required();
get_balance->add_option( "symbol", symbol, localized("The symbol for the currency if the contract operates multiple currencies") );
get_balance->set_callback([&] {
auto result = call(get_currency_balance_func, fc::mutable_variant_object("json", false)
auto result = call(get_currency_balance_func, fc::mutable_variant_object
("account", accountName)
("code", code)
("symbol", symbol=="*" ? fc::variant(symbol) : fc::variant() )
("symbol", symbol.empty() ? fc::variant() : symbol)
);
const auto& rows = result.get_array();
if (symbol.empty()) {
for( const auto& r : rows ) {
std::cout << r.as_string()
<< std::endl;
}
/*
std::cout << fc::json::to_pretty_string(rows)
<< std::endl;
*/
} else if ( rows.size() > 0 ){
std::cout << rows[0].as_string()
for( const auto& r : rows ) {
std::cout << r.as_string()
<< std::endl;
}
});
auto get_currency_stats = get_currency->add_subcommand( "stats", localized("Retrieve the stats of for a given currency"), false);
get_currency_stats->add_option( "contract", code, localized("The contract that operates the currency") )->required();
get_currency_stats->add_option( "symbol", symbol, localized("The symbol for the currency if the contract operates multiple currencies") );
get_currency_stats->add_option( "symbol", symbol, localized("The symbol for the currency if the contract operates multiple currencies") )->required();
get_currency_stats->set_callback([&] {
auto result = call(get_currency_stats_func, fc::mutable_variant_object("json", false)
("code", code)
("symbol", symbol)
);
if (symbol.empty()) {
std::cout << fc::json::to_pretty_string(result)
<< std::endl;
} else {
const auto& mapping = result.get_object();
std::cout << fc::json::to_pretty_string(mapping[symbol])
<< std::endl;
}
std::cout << fc::json::to_pretty_string(result)
<< std::endl;
});
// get accounts
......
......@@ -76,8 +76,6 @@ err:
return ret;
}
SSL_TYPE(ec_key, EC_KEY, EC_KEY_free)
fc::crypto::r1::compact_signature compact_r1(fc::crypto::r1::public_key_data& pubkey, fc::ecdsa_sig& sig, fc::sha256& digest) {
fc::crypto::r1::compact_signature csig;
ec_key key = EC_KEY_new_by_curve_name( NID_X9_62_prime256v1 );
......
......@@ -109,6 +109,44 @@
printf "\n\tNo required YUM dependencies to install.\n"
fi
if [[ $ENABLE_CODE_COVERAGE == true ]]; then
printf "\n\tChecking perl installation."
perl_bin=$( which perl 2>/dev/null )
if [ $? -ne 0 ]; then
printf "\n\tInstalling perl."
yum -y install perl
if [ $? -ne 0 ]; then
printf "\n\tUnable to install perl at this time.\n"
printf "\n\tExiting now.\n"
fi
else
printf "\n\tPerl installation found at ${perl_bin}."
fi
printf "\n\tChecking LCOV installation."
if [ ! -e /usr/local/bin/lcov ]; then
printf "\n\tLCOV installation not found.\n"
printf "\tInstalling LCOV.\n"
cd ${TEMP_DIR}
git clone https://github.com/linux-test-project/lcov.git
if [ $? -ne 0 ]; then
printf "\tUnable to clone LCOV at this time.\n"
printf "\tExiting now.\n\n"
exit;
fi
cd lcov
sudo make install
if [ $? -ne 0 ]; then
printf "\tUnable to install LCOV at this time.\n"
printf "\tExiting now.\n\n"
exit;
fi
rm -rf ${TEMP_DIR}/lcov
printf "\tSuccessfully installed LCOV.\n"
else
printf "\n\tLCOV installation found @ /usr/local/bin/lcov.\n"
fi
fi
printf "\n\tChecking boost library installation.\n"
BVERSION=`cat "${BOOST_ROOT}/include/boost/version.hpp" 2>/dev/null | grep BOOST_LIB_VERSION \
| tail -1 | tr -s ' ' | cut -d\ -f3 | sed 's/[^0-9\._]//gI'`
......
......@@ -31,8 +31,6 @@ target_include_directories( chain_test PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/includ
add_dependencies(chain_test asserter test_api test_api_mem test_api_db test_api_multi_index exchange currency proxy identity identity_test stltest infinite eosio.system eosio.token eosio.bios test.inline multi_index_test noop dice eosio.msig)
#
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/llvm-gcov.sh ${CMAKE_CURRENT_BINARY_DIR}/../llvm-gcov.sh COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/p2p_tests/sync/test.sh ${CMAKE_CURRENT_BINARY_DIR}/p2p_tests/sync/test.sh COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/p2p_tests/dawn_515/test.sh ${CMAKE_CURRENT_BINARY_DIR}/p2p_tests/dawn_515/test.sh COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/trans_sync_across_mixed_cluster_test.sh ${CMAKE_CURRENT_BINARY_DIR}/trans_sync_across_mixed_cluster_test.sh COPYONLY)
......@@ -63,8 +61,8 @@ endif()
# TODO: add_test(NAME trans_sync_across_mixed_cluster_test COMMAND tests/trans_sync_across_mixed_cluster_test.sh -p 1 -n 2 WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_test(NAME distributed-transactions-test COMMAND tests/distributed-transactions-test.py -p 1 -n 4 -v --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_test(NAME distributed-transactions-remote-test COMMAND tests/distributed-transactions-remote-test.py -v --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
# TODO: add_test(NAME restart-scenarios-test_resync COMMAND tests/restart-scenarios-test.py -c resync -p3 --dump-error-details WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
# TODO: add_test(NAME restart-scenarios-test_replay COMMAND tests/restart-scenarios-test.py -c replay -p3 --dump-error-details WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_test(NAME restart-scenarios-test_resync COMMAND tests/restart-scenarios-test.py -c resync -p4 -v --dump-error-details WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
# add_test(NAME restart-scenarios-test_replay COMMAND tests/restart-scenarios-test.py -c replay -p4 -v --dump-error-details WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
# TODO: add_test(NAME consensus-validation-malicious-producers COMMAND tests/consensus-validation-malicious-producers.py -w 80 --dump-error-details WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
if(ENABLE_COVERAGE_TESTING)
......@@ -84,8 +82,8 @@ if(ENABLE_COVERAGE_TESTING)
endif() # NOT GENHTML_PATH
# no spaces allowed within tests list
set(ctest_tests 'chain_test_binaryen|chain_test_wavm|p2p_dawn515_test')
set(ctest_exclude_tests 'nodeos_run_test|nodeos_run_remote_test|nodeos_run_test-mongodb|distributed-transactions-test|distributed-transactions-remote-test')
set(ctest_tests 'chain_test_binaryen|chain_test_wavm|p2p_dawn515_test|nodeos_run_test|distributed-transactions-test|restart-scenarios-test_resync')
set(ctest_exclude_tests 'nodeos_run_remote_test|nodeos_run_test-mongodb|distributed-transactions-remote-test|restart-scenarios-test_replay')
# Setup target
add_custom_target(${Coverage_NAME}
......@@ -95,7 +93,7 @@ if(ENABLE_COVERAGE_TESTING)
COMMAND ctest -R ${ctest_tests} -E ${ctest_exclude_tests}
COMMENT "Capturing lcov counters and generating report"
COMMAND ${LCOV_PATH} --directory . --capture --gcov-tool ./tests/llvm-gcov.sh --output-file ${Coverage_NAME}.info
COMMAND ${LCOV_PATH} --directory . --capture --gcov-tool ./tools/llvm-gcov.sh --output-file ${Coverage_NAME}.info
COMMENT "Processing code coverage counters and generating report."
COMMAND ${GENHTML_PATH} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info
......
......@@ -945,6 +945,21 @@ BOOST_FIXTURE_TEST_CASE(db_tests, TESTER) { try {
N(testapi) );
BOOST_CHECK_EQUAL( res, success() );
CALL_TEST_FUNCTION_AND_CHECK_EXCEPTION( *this, "test_db", "idx_double_nan_create_fail", {},
transaction_exception, "NaN is not an allowed value for a secondary key");
CALL_TEST_FUNCTION_AND_CHECK_EXCEPTION( *this, "test_db", "idx_double_nan_modify_fail", {},
transaction_exception, "NaN is not an allowed value for a secondary key");
uint32_t lookup_type = 0; // 0 for find, 1 for lower bound, and 2 for upper bound;
CALL_TEST_FUNCTION_AND_CHECK_EXCEPTION( *this, "test_db", "idx_double_nan_lookup_fail", fc::raw::pack(lookup_type),
transaction_exception, "NaN is not an allowed value for a secondary key");
lookup_type = 1;
CALL_TEST_FUNCTION_AND_CHECK_EXCEPTION( *this, "test_db", "idx_double_nan_lookup_fail", fc::raw::pack(lookup_type),
transaction_exception, "NaN is not an allowed value for a secondary key");
lookup_type = 2;
CALL_TEST_FUNCTION_AND_CHECK_EXCEPTION( *this, "test_db", "idx_double_nan_lookup_fail", fc::raw::pack(lookup_type),
transaction_exception, "NaN is not an allowed value for a secondary key");
BOOST_REQUIRE_EQUAL( validate(), true );
} FC_LOG_AND_RETHROW() }
......
......@@ -231,6 +231,34 @@ BOOST_AUTO_TEST_CASE( push_invalid_block ) { try {
BOOST_REQUIRE_THROW(chain.control->push_block(new_block), tx_empty_shard);
} FC_LOG_AND_RETHROW() }/// push_invalid_block
BOOST_AUTO_TEST_CASE( push_unexpected_signature_block ) { try {
vector<tester> producers(5);
char a = 'a';
vector<account_name> producer_names;
for( ; a <= 'a'+producers.size()-1; ++a) {
producer_names.emplace_back(std::string("init")+a);
}
producers[0].create_accounts(producer_names);
producers[0].set_producers(producer_names);
auto block = producers[0].produce_block();
producers[0].push_block(block);
block = producers[1].produce_block();
producers[1].push_block(block);
auto head_id = producers[0].control->head_block_num();
tester unscheduled_producer;
block = unscheduled_producer.produce_block();
unscheduled_producer.push_block(block);
BOOST_CHECK_EQUAL(head_id, producers[0].control->head_block_num());
block = producers[2].produce_block();
producers[2].push_block(block);
BOOST_CHECK_PREDICATE(std::not_equal_to<decltype(head_id)>(),
(head_id)(producers[3].control->head_block_num()));
} FC_LOG_AND_RETHROW() }/// push_unexpected_signature_block
// Utility function to check expected irreversible block
uint32_t calc_exp_last_irr_block_num(const base_tester& chain, const uint32_t& head_block_num) {
......@@ -1175,11 +1203,11 @@ BOOST_AUTO_TEST_CASE(account_ram_limit) { try {
transaction_trace trace = chain.create_account(N(acc2), acc1);
chain.produce_block();
BOOST_ASSERT(trace.status == transaction_trace::executed);
BOOST_REQUIRE_EQUAL(trace.status, transaction_trace::executed);
trace = chain.create_account(N(acc3), acc1);
chain.produce_block();
BOOST_ASSERT(trace.status == transaction_trace::executed);
BOOST_REQUIRE_EQUAL(trace.status, transaction_trace::executed);
BOOST_REQUIRE_EXCEPTION(
chain.create_account(N(acc4), acc1),
......@@ -1192,4 +1220,29 @@ BOOST_AUTO_TEST_CASE(account_ram_limit) { try {
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_CASE(producer_r1_key) { try {
// Use validating_tester to check that the block is synced properly
validating_tester chain;
// Set new producer
account_name tester_producer_name = "tester";
chain.create_account(tester_producer_name);
auto producer_r1_priv_key = chain.get_private_key<fc::crypto::r1::private_key_shim>( tester_producer_name, "active" );
auto producer_r1_pub_key = producer_r1_priv_key.get_public_key();
chain.push_action(N(eosio), N(setprods), N(eosio),
fc::mutable_variant_object()("version", 1)("producers", vector<producer_key>{{ tester_producer_name, producer_r1_pub_key }}));
// Add signing key to the tester object, so it can sign with the correct key
chain.block_signing_private_keys[producer_r1_pub_key] = producer_r1_priv_key;
// Wait until the current round ends
chain.produce_blocks_until_end_of_round();
// The next set of producers will be producing starting in the middle of next round
// This round should not throw any exception
BOOST_CHECK_NO_THROW(chain.produce_blocks_until_end_of_round());
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_SUITE_END()
......@@ -923,6 +923,21 @@ BOOST_AUTO_TEST_CASE( link_delay_link_change_test ) { try {
liquid_balance = get_currency_balance(chain, N(tester2));
BOOST_REQUIRE_EQUAL(asset::from_string("0.0000 CUR"), liquid_balance);
BOOST_REQUIRE_EXCEPTION(
chain.push_action(config::system_account_name, contracts::linkauth::get_name(), tester_account, fc::mutable_variant_object()
("account", "tester")
("code", "currency")
("type", "transfer")
("requirement", "second"),
30, 3),
transaction_exception,
[] (const transaction_exception &e)->bool {
std::string check_str = "3030000 transaction_exception: transaction validation exception\nauthorization imposes a delay (10 sec) greater than the delay specified in transaction header (3 sec)";
BOOST_REQUIRE_EQUAL(check_str, e.to_detail_string().substr(0, check_str.length()));
return true;
}
);
// this transaction will be delayed 20 blocks
chain.push_action(config::system_account_name, contracts::linkauth::get_name(), tester_account, fc::mutable_variant_object()
("account", "tester")
......@@ -1024,6 +1039,207 @@ BOOST_AUTO_TEST_CASE( link_delay_link_change_test ) { try {
} FC_LOG_AND_RETHROW() }/// schedule_test
// test link with unlink
BOOST_AUTO_TEST_CASE( link_delay_unlink_test ) { try {
TESTER chain;
const auto& tester_account = N(tester);
chain.set_code(config::system_account_name, eosio_system_wast);
chain.set_abi(config::system_account_name, eosio_system_abi);
chain.produce_blocks();
chain.create_account(N(currency));
chain.produce_blocks(10);
chain.set_code(N(currency), currency_wast);
chain.set_abi(N(currency), currency_abi);
chain.produce_blocks();
chain.create_account(N(tester));
chain.create_account(N(tester2));
chain.produce_blocks(10);
chain.push_action(config::system_account_name, contracts::updateauth::get_name(), tester_account, fc::mutable_variant_object()
("account", "tester")
("permission", "first")
("parent", "active")
("data", authority(chain.get_public_key(tester_account, "first")))
("delay", 10));
chain.push_action(config::system_account_name, contracts::linkauth::get_name(), tester_account, fc::mutable_variant_object()
("account", "tester")
("code", "currency")
("type", "transfer")
("requirement", "first"));
chain.produce_blocks();
chain.push_action(N(currency), N(create), N(currency), mutable_variant_object()
("issuer", "currency" )
("maximum_supply", "9000000.0000 CUR" )
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0)
);
chain.push_action(N(currency), name("issue"), N(currency), fc::mutable_variant_object()
("to", "currency")
("quantity", "1000000.0000 CUR")
("memo", "for stuff")
);
auto trace = chain.push_action(N(currency), name("transfer"), N(currency), fc::mutable_variant_object()
("from", "currency")
("to", "tester")
("quantity", "100.0000 CUR")
("memo", "hi" )
);
BOOST_REQUIRE_EQUAL(transaction_receipt::executed, trace.status);
BOOST_REQUIRE_EQUAL(0, trace.deferred_transaction_requests.size());
chain.produce_blocks();
auto liquid_balance = get_currency_balance(chain, N(currency));
BOOST_REQUIRE_EQUAL(asset::from_string("999900.0000 CUR"), liquid_balance);
liquid_balance = get_currency_balance(chain, N(tester));
BOOST_REQUIRE_EQUAL(asset::from_string("100.0000 CUR"), liquid_balance);
// this transaction will be delayed 20 blocks
trace = chain.push_action(N(currency), name("transfer"), N(tester), fc::mutable_variant_object()
("from", "tester")
("to", "tester2")
("quantity", "1.0000 CUR")
("memo", "hi" ),
30, 10
);
BOOST_REQUIRE_EQUAL(transaction_receipt::delayed, trace.status);
BOOST_REQUIRE_EQUAL(1, trace.deferred_transaction_requests.size());
BOOST_REQUIRE_EQUAL(0, trace.action_traces.size());
chain.produce_blocks();
liquid_balance = get_currency_balance(chain, N(currency));
BOOST_REQUIRE_EQUAL(asset::from_string("999900.0000 CUR"), liquid_balance);
liquid_balance = get_currency_balance(chain, N(tester));
BOOST_REQUIRE_EQUAL(asset::from_string("100.0000 CUR"), liquid_balance);
liquid_balance = get_currency_balance(chain, N(tester2));
BOOST_REQUIRE_EQUAL(asset::from_string("0.0000 CUR"), liquid_balance);
BOOST_REQUIRE_EXCEPTION(
chain.push_action(config::system_account_name, contracts::unlinkauth::get_name(), tester_account, fc::mutable_variant_object()
("account", "tester")
("code", "currency")
("type", "transfer"),
30, 7),
transaction_exception,
[] (const transaction_exception &e)->bool {
std::string check_str = "3030000 transaction_exception: transaction validation exception\nauthorization imposes a delay (10 sec) greater than the delay specified in transaction header (7 sec)";
BOOST_REQUIRE_EQUAL(check_str, e.to_detail_string().substr(0, check_str.length()));
return true;
}
);
// this transaction will be delayed 20 blocks
chain.push_action(config::system_account_name, contracts::unlinkauth::get_name(), tester_account, fc::mutable_variant_object()
("account", "tester")
("code", "currency")
("type", "transfer"),
30, 10
);
BOOST_REQUIRE_EQUAL(transaction_receipt::delayed, trace.status);
BOOST_REQUIRE_EQUAL(1, trace.deferred_transaction_requests.size());
BOOST_REQUIRE_EQUAL(0, trace.action_traces.size());
chain.produce_blocks();
liquid_balance = get_currency_balance(chain, N(tester));
BOOST_REQUIRE_EQUAL(asset::from_string("100.0000 CUR"), liquid_balance);
liquid_balance = get_currency_balance(chain, N(tester2));
BOOST_REQUIRE_EQUAL(asset::from_string("0.0000 CUR"), liquid_balance);
chain.produce_blocks(16);
liquid_balance = get_currency_balance(chain, N(tester));
BOOST_REQUIRE_EQUAL(asset::from_string("100.0000 CUR"), liquid_balance);
liquid_balance = get_currency_balance(chain, N(tester2));
BOOST_REQUIRE_EQUAL(asset::from_string("0.0000 CUR"), liquid_balance);
// this transaction will be delayed 20 blocks
trace = chain.push_action(N(currency), name("transfer"), N(tester), fc::mutable_variant_object()
("from", "tester")
("to", "tester2")
("quantity", "5.0000 CUR")
("memo", "hi" ),
30, 10
);
BOOST_REQUIRE_EQUAL(transaction_receipt::delayed, trace.status);
BOOST_REQUIRE_EQUAL(1, trace.deferred_transaction_requests.size());
BOOST_REQUIRE_EQUAL(0, trace.action_traces.size());
chain.produce_blocks();
liquid_balance = get_currency_balance(chain, N(tester));
BOOST_REQUIRE_EQUAL(asset::from_string("100.0000 CUR"), liquid_balance);
liquid_balance = get_currency_balance(chain, N(tester2));
BOOST_REQUIRE_EQUAL(asset::from_string("0.0000 CUR"), liquid_balance);
chain.produce_blocks();
liquid_balance = get_currency_balance(chain, N(tester));
BOOST_REQUIRE_EQUAL(asset::from_string("100.0000 CUR"), liquid_balance);
liquid_balance = get_currency_balance(chain, N(tester2));
BOOST_REQUIRE_EQUAL(asset::from_string("0.0000 CUR"), liquid_balance);
// first transfer will finally be performed
chain.produce_blocks();
liquid_balance = get_currency_balance(chain, N(tester));
BOOST_REQUIRE_EQUAL(asset::from_string("99.0000 CUR"), liquid_balance);
liquid_balance = get_currency_balance(chain, N(tester2));
BOOST_REQUIRE_EQUAL(asset::from_string("1.0000 CUR"), liquid_balance);
// this transfer is performed right away since delay is removed
trace = chain.push_action(N(currency), name("transfer"), N(tester), fc::mutable_variant_object()
("from", "tester")
("to", "tester2")
("quantity", "10.0000 CUR")
("memo", "hi" )
);
BOOST_REQUIRE_EQUAL(transaction_receipt::executed, trace.status);
BOOST_REQUIRE_EQUAL(0, trace.deferred_transaction_requests.size());
chain.produce_blocks();
liquid_balance = get_currency_balance(chain, N(tester));
BOOST_REQUIRE_EQUAL(asset::from_string("89.0000 CUR"), liquid_balance);
liquid_balance = get_currency_balance(chain, N(tester2));
BOOST_REQUIRE_EQUAL(asset::from_string("11.0000 CUR"), liquid_balance);
chain.produce_blocks(15);
liquid_balance = get_currency_balance(chain, N(tester));
BOOST_REQUIRE_EQUAL(asset::from_string("89.0000 CUR"), liquid_balance);
liquid_balance = get_currency_balance(chain, N(tester2));
BOOST_REQUIRE_EQUAL(asset::from_string("11.0000 CUR"), liquid_balance);
chain.produce_blocks();
liquid_balance = get_currency_balance(chain, N(tester));
BOOST_REQUIRE_EQUAL(asset::from_string("89.0000 CUR"), liquid_balance);
liquid_balance = get_currency_balance(chain, N(tester2));
BOOST_REQUIRE_EQUAL(asset::from_string("11.0000 CUR"), liquid_balance);
// second transfer finally is performed
chain.produce_blocks();
liquid_balance = get_currency_balance(chain, N(tester));
BOOST_REQUIRE_EQUAL(asset::from_string("84.0000 CUR"), liquid_balance);
liquid_balance = get_currency_balance(chain, N(tester2));
BOOST_REQUIRE_EQUAL(asset::from_string("16.0000 CUR"), liquid_balance);
} FC_LOG_AND_RETHROW() }/// link_delay_unlink_test
// test moving link with delay on permission's parent
BOOST_AUTO_TEST_CASE( link_delay_link_change_heirarchy_test ) { try {
TESTER chain;
......@@ -1444,6 +1660,23 @@ BOOST_AUTO_TEST_CASE( canceldelay_test ) { try {
liquid_balance = get_currency_balance(chain, N(tester2));
BOOST_REQUIRE_EQUAL(asset::from_string("0.0000 CUR"), liquid_balance);
BOOST_REQUIRE_EXCEPTION(
chain.push_action(config::system_account_name, contracts::updateauth::get_name(), tester_account, fc::mutable_variant_object()
("account", "tester")
("permission", "first")
("parent", "active")
("data", authority(chain.get_public_key(tester_account, "first")))
("delay", 0),
30, 7
),
transaction_exception,
[] (const transaction_exception &e)->bool {
std::string check_str = "3030000 transaction_exception: transaction validation exception\nauthorization imposes a delay (10 sec) greater than the delay specified in transaction header (7 sec)";
BOOST_REQUIRE_EQUAL(check_str, e.to_detail_string().substr(0, check_str.length()));
return true;
}
);
// this transaction will be delayed 20 blocks
trace = chain.push_action(config::system_account_name, contracts::updateauth::get_name(), tester_account, fc::mutable_variant_object()
("account", "tester")
......
......@@ -21,7 +21,6 @@ parser.add_argument("-s", type=str, help="topology", default="mesh")
parser.add_argument("-v", help="verbose", action='store_true')
parser.add_argument("--nodes-file", type=str, help="File containing nodes info in JSON format.")
parser.add_argument("--seed", type=int, help="random seed", default=seed)
parser.add_argument("--not-noon", help="This is not the Noon branch.", action='store_true')
parser.add_argument("--dont-kill", help="Leave cluster running after test finishes", action='store_true')
parser.add_argument("--dump-error-details",
help="Upon error print etc/eosio/node_*/config.ini and var/lib/node_*/stderr.log to stdout",
......@@ -35,7 +34,6 @@ total_nodes = pnodes if args.n == 0 else args.n
debug=args.v
nodesFile=args.nodes_file
seed=args.seed
amINoon=not args.not_noon
dontKill=args.dont_kill
dumpErrorDetails=args.dump_error_details
......@@ -47,9 +45,6 @@ if nodesFile is not None:
testUtils.Utils.Debug=debug
testSuccessful=False
if not amINoon:
testUtils.Utils.iAmNotNoon()
random.seed(seed) # Use a fixed seed for repeatability.
cluster=testUtils.Cluster(walletd=True)
walletMgr=testUtils.WalletMgr(True)
......@@ -106,7 +101,7 @@ try:
if not cluster.createAccounts(initaAccount):
errorExit("Accounts creation failed.")
# TDB: Known issue (Issue 2043) that 'get currency balance' doesn't return balance.
# TBD: Known issue (Issue 2043) that 'get currency balance' doesn't return balance.
# Uncomment when functional
# Print("Spread funds and validate")
# if not cluster.spreadFundsAndValidate(10):
......
......@@ -237,7 +237,7 @@ try:
errorExit("Failed to transfer funds %d from account %s to %s" % (
transferAmount, initaAccount.name, testeraAccount.name))
# TDB: Known issue (Issue 2043) that 'get currency balance' doesn't return balance.
# TBD: Known issue (Issue 2043) that 'get currency balance' doesn't return balance.
# Uncomment when functional
# expectedAmount=transferAmount
# Print("Verify transfer, Expected: %d" % (expectedAmount))
......@@ -254,7 +254,7 @@ try:
errorExit("Failed to force transfer funds %d from account %s to %s" % (
transferAmount, initaAccount.name, testeraAccount.name))
# TDB: Known issue (Issue 2043) that 'get currency balance' doesn't return balance.
# TBD: Known issue (Issue 2043) that 'get currency balance' doesn't return balance.
# Uncomment when functional
# expectedAmount=975421
# Print("Verify transfer, Expected: %d" % (expectedAmount))
......@@ -295,7 +295,7 @@ try:
transferAmount, initaAccount.name, testeraAccount.name))
transId=testUtils.Node.getTransId(trans)
# TDB: Known issue (Issue 2043) that 'get currency balance' doesn't return balance.
# TBD: Known issue (Issue 2043) that 'get currency balance' doesn't return balance.
# Uncomment when functional
# expectedAmount=975311+5000 # 5000 initial deposit
# Print("Verify transfer, Expected: %d" % (expectedAmount))
......@@ -418,7 +418,7 @@ try:
abiActionName=account["abi"]["actions"][0]["name"]
abiType=account["abi"]["actions"][0]["type"]
if abiName != "transfer" or abiActionName != "transfer" or abiType != "transfer":
errorExit("FAILURE - get table currency account failed", raw=True)
errorExit("FAILURE - get EOS account failed", raw=True)
Print("push create action to currency contract")
contract="currency"
......@@ -437,35 +437,37 @@ try:
if trans is None or not trans[0]:
errorExit("FAILURE - issue action to currency contract failed", raw=True)
# TODO need to update eosio.system contract to use new currency and update cleos and chain_plugin for interaction
# Print("Verify currency contract has proper initial balance (via get table)")
# contract="currency"
# table="accounts"
# row0=node.getTableRow(currencyAccount.name, contract, table, 0)
# if row0 is None:
# cmdError("%s get table currency account" % (ClientName))
# errorExit("Failed to retrieve contract %s table %s" % (contract, table))
#
# balanceKey="balance"
# keyKey="key"
# if row0[balanceKey] != 1000000000:
# errorExit("FAILURE - get table currency account failed", raw=True)
#
# Print("Verify currency contract has proper initial balance (via get currency balance)")
# res=node.getCurrencyBalance(contract, currencyAccount.name, "CUR")
# if res is None:
# cmdError("%s get currency balance" % (ClientName))
# errorExit("Failed to retrieve CUR balance from contract %s account %s" % (contract, currencyAccount.name))
#
# if res.strip()[1:-1] != "100000.0000 CUR":
# errorExit("FAILURE - get currency balance failed", raw=True)
#
Print("Verify currency contract has proper initial balance (via get table)")
contract="currency"
table="accounts"
row0=node.getTableRow(contract, currencyAccount.name, table, 0)
if row0 is None:
cmdError("%s get currency table currency account" % (ClientName))
errorExit("Failed to retrieve contract %s table %s" % (contract, table))
balanceKey="balance"
keyKey="key"
if row0[balanceKey] != "100000.0000 CUR":
errorExit("FAILURE - Wrong currency balance", raw=True)
Print("Verify currency contract has proper initial balance (via get currency balance)")
res=node.getCurrencyBalance(contract, currencyAccount.name, "CUR")
if res is None:
cmdError("%s get currency balance" % (ClientName))
errorExit("Failed to retrieve CUR balance from contract %s account %s" % (contract, currencyAccount.name))
expected="100000.0000 CUR"
actual=res.strip()
if actual != expected:
errorExit("FAILURE - get currency balance failed. Recieved response: <%s>" % (res), raw=True)
# TBD: "get currency stats is still not working. Enable when ready.
# Print("Verify currency contract has proper total supply of CUR (via get currency stats)")
# res=node.getCurrencyStats(contract, "CUR")
# if res is None or not ("supply" in res):
# cmdError("%s get currency stats" % (ClientName))
# errorExit("Failed to retrieve CUR stats from contract" % (contract))
#
# errorExit("Failed to retrieve CUR stats from contract %s" % (contract))
# if res["supply"] != "100000.0000 CUR":
# errorExit("FAILURE - get currency stats failed", raw=True)
......@@ -487,26 +489,30 @@ try:
errorExit("Failed to verify push message transaction id.")
# TODO need to update eosio.system contract to use new currency and update cleos and chain_plugin for interaction
# Print("read current contract balance")
# contract="currency"
# table="accounts"
# row0=node.getTableRow(initaAccount.name, contract, table, 0)
# if row0 is None:
# cmdError("%s get table currency account" % (ClientName))
# errorExit("Failed to retrieve contract %s table %s" % (contract, table))
#
# balanceKey="balance"
# keyKey="key"
# if row0[balanceKey] != 50:
# errorExit("FAILURE - get table currency account failed", raw=True)
#
# row0=node.getTableRow(currencyAccount.name, contract, table, 0)
# if row0 is None:
# cmdError("%s get table currency account" % (ClientName))
# errorExit("Failed to retrieve contract %s table %s" % (contract, table))
#
# if row0[balanceKey] != 999999950:
# errorExit("FAILURE - get table currency account failed", raw=True)
Print("read current contract balance")
contract="currency"
table="accounts"
row0=node.getTableRow(contract, initaAccount.name, table, 0)
if row0 is None:
cmdError("%s get currency table inita account" % (ClientName))
errorExit("Failed to retrieve contract %s table %s" % (contract, table))
balanceKey="balance"
keyKey="key"
expected="0.0050 CUR"
actual=row0[balanceKey]
if actual != expected:
errorExit("FAILURE - Wrong currency balance (expected=%s, actual=%s)" % (str(expected), str(actual)), raw=True)
row0=node.getTableRow(contract, currencyAccount.name, table, 0)
if row0 is None:
cmdError("%s get currency table currency account" % (ClientName))
errorExit("Failed to retrieve contract %s table %s" % (contract, table))
expected="99999.9950 CUR"
actual=row0[balanceKey]
if actual != expected:
errorExit("FAILURE - Wrong currency balance (expected=%s, actual=%s)" % (str(expected), str(actual)), raw=True)
Print("Exchange Contract Tests")
Print("upload exchange contract")
......@@ -577,7 +583,7 @@ try:
for blockNum in range(1, currentBlockNum+1):
block=node.getBlock(blockNum, retry=False, silentErrors=True)
if block is None:
# TDB: Known issue (Issue 2099) that the block containing setprods isn't retrievable.
# TBD: Known issue (Issue 2099) that the block containing setprods isn't retrievable.
# Enable errorExit() once that is resolved.
Print("WARNING: Failed to get block %d (probably issue 2099). Report and keep going..." % (blockNum))
# cmdError("%s get block" % (ClientName))
......
......@@ -7,7 +7,7 @@ import random
import signal
###############################################################
# Test for different test scenarios.
# Test for different nodes restart scenarios.
# Nodes can be producing or non-producing.
# -p <producing nodes count>
# -c <chain strategy[replay|resync|none]>
......@@ -22,7 +22,6 @@ import signal
###############################################################
DefaultKillPercent=25
Print=testUtils.Utils.Print
def errorExit(msg="", errorCode=1):
......@@ -41,7 +40,6 @@ parser.add_argument("--kill-sig", type=str, help="kill signal[%s|%s]" %
parser.add_argument("--kill-count", type=int, help="nodeos instances to kill", default=-1)
parser.add_argument("-v", help="verbose logging", action='store_true')
parser.add_argument("--dont-kill", help="Leave cluster running after test finishes", action='store_true')
parser.add_argument("--not-noon", help="This is not the Noon branch.", action='store_true')
parser.add_argument("--dump-error-details",
help="Upon error print etc/eosio/node_*/config.ini and var/lib/node_*/stderr.log to stdout",
action='store_true')
......@@ -55,33 +53,33 @@ delay=args.d
chainSyncStrategyStr=args.c
debug=args.v
total_nodes = pnodes
killCount=args.kill_count if args.kill_count > 0 else int(round((DefaultKillPercent/100.0)*total_nodes))
killCount=args.kill_count if args.kill_count > 0 else 1
killSignal=args.kill_sig
killEosInstances= not args.dont_kill
dumpErrorDetails=args.dump_error_details
keepLogs=args.keep_logs
amINoon=not args.not_noon
seed=1
testUtils.Utils.Debug=debug
testSuccessful=False
if not amINoon:
testUtils.Utils.iAmNotNoon()
Print ("producing nodes: %d, topology: %s, delay between nodes launch(seconds): %d, chain sync strategy: %s" % (
pnodes, topo, delay, chainSyncStrategyStr))
random.seed(seed) # Use a fixed seed for repeatability.
cluster=testUtils.Cluster()
walletMgr=testUtils.WalletMgr(False)
cluster.killall()
cluster.cleanup()
random.seed(1) # Use a fixed seed for repeatability.
testSuccessful=False
try:
cluster.setChainStrategy(chainSyncStrategyStr)
cluster.setWalletMgr(walletMgr)
cluster.killall()
cluster.cleanup()
Print ("producing nodes: %d, topology: %s, delay between nodes launch(seconds): %d, chain sync strategy: %s" % (
pnodes, topo, delay, chainSyncStrategyStr))
Print("Stand up cluster")
if cluster.launch(pnodes, total_nodes, topo, delay) is False:
if cluster.launch(pnodes, total_nodes, topo=topo, delay=delay) is False:
errorExit("Failed to stand up eos cluster.")
Print ("Wait for Cluster stabilization")
......@@ -96,22 +94,30 @@ try:
if wallet is None:
errorExit("Failed to create wallet %s" % (walletName))
Print ("Create wallet.")
Print ("Populate wallet with %d accounts." % (accountsCount))
if not cluster.populateWallet(accountsCount, wallet):
errorExit("Wallet initialization failed.")
initaAccount=cluster.initaAccount
Print("Importing keys for account %s into wallet %s." % (initaAccount.name, wallet.name))
if not walletMgr.importKey(initaAccount, wallet):
errorExit("Failed to import key for account %s" % (initaAccount.name))
Print("Create accounts.")
#if not cluster.createAccounts(wallet):
if not cluster.createAccounts(testUtils.Cluster.initaAccount):
if not cluster.createAccounts(initaAccount):
errorExit("Accounts creation failed.")
Print("Wait on cluster sync.")
if not cluster.waitOnClusterSync():
errorExit("Cluster sync wait failed.")
Print("Spread funds and validate")
if not cluster.spreadFundsAndValidate(10):
errorExit("Failed to spread and validate funds.")
# TBD: Known issue (Issue 2043) that 'get currency balance' doesn't return balance.
# Uncomment when functional
# Print("Spread funds and validate")
# if not cluster.spreadFundsAndValidate(10):
# errorExit("Failed to spread and validate funds.")
Print("Wait on cluster sync.")
if not cluster.waitOnClusterSync():
......@@ -122,9 +128,11 @@ try:
errorExit("Failed to kill Eos instances")
Print("nodeos instances killed.")
Print("Spread funds and validate")
if not cluster.spreadFundsAndValidate(10):
errorExit("Failed to spread and validate funds.")
# TBD: Known issue (Issue 2043) that 'get currency balance' doesn't return balance.
# Uncomment when functional
# Print("Spread funds and validate")
# if not cluster.spreadFundsAndValidate(10):
# errorExit("Failed to spread and validate funds.")
Print("Wait on cluster sync.")
if not cluster.waitOnClusterSync():
......@@ -140,9 +148,11 @@ try:
errorExit("Cluster never synchronized")
Print ("Cluster synched")
Print("Spread funds and validate")
if not cluster.spreadFundsAndValidate(10):
errorExit("Failed to spread and validate funds.")
# TBD: Known issue (Issue 2043) that 'get currency balance' doesn't return balance.
# Uncomment when functional
# Print("Spread funds and validate")
# if not cluster.spreadFundsAndValidate(10):
# errorExit("Failed to spread and validate funds.")
Print("Wait on cluster sync.")
if not cluster.waitOnClusterSync():
......
此差异已折叠。
......@@ -151,9 +151,9 @@ public:
// the balance is implied to be 0 if either the table or row does not exist
if (tbl) {
const auto *obj = db.find<contracts::key_value_object, contracts::by_scope_primary>(boost::make_tuple(tbl->id, symbol(SY(4,EOS)).value() >> 8));
const auto *obj = db.find<contracts::key_value_object, contracts::by_scope_primary>(boost::make_tuple(tbl->id, symbol(SY(4,EOS)).to_symbol_code()));
if (obj) {
//balance is the second field after symbol, so skip the symbol
// balance is the first field in the serialization
fc::datastream<const char *> ds(obj->value.data(), obj->value.size());
fc::raw::unpack(ds, result);
}
......@@ -183,7 +183,7 @@ public:
("can_freeze", 0)
("can_recall", 0)
("can_whitelist", 0);
base_tester::push_action(contract, N(create), contract, act );
}
......@@ -1107,14 +1107,14 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, eosio_system_tester) try {
vector<char> key = fc::raw::pack(get_public_key(N(alice), "active"));
// 1 block produced
BOOST_REQUIRE_EQUAL(success(), push_action(N(alice), N(regproducer), mvo()
("producer", "alice")
("producer_key", key )
("prefs", params)
)
);
auto prod = get_producer_info( N(alice) );
BOOST_REQUIRE_EQUAL("alice", prod["owner"].as_string());
......@@ -1130,7 +1130,7 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, eosio_system_tester) try {
// 1 block produced
BOOST_REQUIRE_EQUAL(success(), stake("bob", "11.0000 EOS", "10.1111 EOS", "10.1111 EOS"));
// bob votes for alice
// 1 block produced
BOOST_REQUIRE_EQUAL(success(), push_action(N(bob), N(voteproducer), mvo()
......
......@@ -573,7 +573,7 @@ BOOST_FIXTURE_TEST_CASE(weighted_cpu_limit_tests, tester ) try {
pass = true;
count++;
} catch (eosio::chain::tx_resource_exhausted &) {
BOOST_ASSERT(count == 10);
BOOST_REQUIRE_EQUAL(count, 3);
break;
}
BOOST_REQUIRE_EQUAL(true, validate());
......@@ -582,7 +582,7 @@ BOOST_FIXTURE_TEST_CASE(weighted_cpu_limit_tests, tester ) try {
mgr.set_account_limits(N(acc2), -1, -1, 1000);
}
}
BOOST_ASSERT(count == 2);
BOOST_REQUIRE_EQUAL(count, 3);
} FC_LOG_AND_RETHROW()
/**
......
configure_file( eosiocpp.in eosiocpp @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/llvm-gcov.sh ${CMAKE_CURRENT_BINARY_DIR}/llvm-gcov.sh COPYONLY)
install( FILES ${CMAKE_CURRENT_BINARY_DIR}/eosiocpp DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}
PERMISSIONS OWNER_READ
OWNER_WRITE
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册