未验证 提交 0da28bb5 编写于 作者: K Kevin Heifner 提交者: GitHub

Merge pull request #6044 from brianjohnson5972/6041-contract-tests-cleanup

Remove unused contracts and cleanup tests
......@@ -7,7 +7,6 @@ set(STANDARD_INCLUDE_FOLDERS ${CMAKE_SOURCE_DIR}/contracts ${CMAKE_BINARY_DIR}/c
add_subdirectory(eosiolib)
add_subdirectory(musl)
add_subdirectory(libc++)
add_subdirectory(simple.token)
add_subdirectory(eosio.token)
add_subdirectory(eosio.msig)
add_subdirectory(eosio.sudo)
......@@ -18,17 +17,14 @@ add_subdirectory(identity)
add_subdirectory(stltest)
add_subdirectory(test.inline)
#add_subdirectory(bancor)
add_subdirectory(hello)
add_subdirectory(asserter)
add_subdirectory(infinite)
add_subdirectory(proxy)
add_subdirectory(test_api)
add_subdirectory(test_api_mem)
add_subdirectory(test_api_db)
add_subdirectory(test_api_multi_index)
add_subdirectory(test_ram_limit)
#add_subdirectory(social)
add_subdirectory(eosio.bios)
add_subdirectory(noop)
add_subdirectory(tic_tac_toe)
......
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_executable(TARGET bancor
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES libc libc++ eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <bancor/bancor.hpp>
namespace bancor {
extern "C" {
/// The apply method implements the dispatch of events to this contract
void apply( uint64_t r, uint64_t c, uint64_t a ) {
bancor::example_converter::apply( c, a );
}
}
}
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <eosiolib/eosio.hpp>
#include <eosiolib/token.hpp>
#include <eosiolib/reflect.hpp>
#include <eosiolib/generic_currency.hpp>
#include <bancor/converter.hpp>
#include <currency/currency.hpp>
namespace bancor {
typedef eosio::generic_currency< eosio::token<N(other),S(4,OTHER)> > other_currency;
typedef eosio::generic_currency< eosio::token<N(bancor),S(4,RELAY)> > relay_currency;
typedef eosio::generic_currency< eosio::token<N(currency),S(4,CUR)> > cur_currency;
typedef converter<relay_currency, other_currency, cur_currency > example_converter;
} /// bancor
#pragma once
namespace bancor {
template<typename ConverterCurrency, typename FirstCurrency, typename SecondCurrency>
class converter_contract {
public:
typedef ConverterCurrency converter_currency;
typedef FirstCurrency first_currency;
typedef SecondCurrency second_currency;
static const account_name converter_account = converter_currency::code;
struct converter_state {
typename converter_currency::token_type supply; /// total supply held by all users
typename converter_currency::token_type balance; /// supply held by converter in its own balance
};
struct converter_args {
eosio::account_name to_currency_account;
eosio::symbol_name to_currency_symbol;
uint64_t min_return_currency;
};
template<typename CurrencyType, uint32_t Weight=500000, uint32_t Base=1000000>
struct connector {
typedef CurrencyType currency_type;
typedef typename converter_currency::token_type converter_token_type;
typedef typename currency_type::token_type in_token_type;
converter_token_type convert_to_converter( in_token_type in, converter_state& state ) {
in_token_type balance = currency_type::get_balance( converter_account );
/// balance already changed when transfer executed, get pre-transfer balance
in_token_type previous_balance = balance - in;
auto init_price = (previous_balance * Base) / (Weight * state.supply);
auto init_out = init_price * in;
auto out_price = (balance*Base) / (Weight * (state.supply+init_out) );
auto final_out = out_price * in;
state.balance += final_out;
state.supply += final_out;
return final_out;
}
in_token_type convert_from_converter( converter_token_type converter_in, converter_state& state ) {
in_token_type to_balance = CurrencyType::get_balance( converter_account );
auto init_price = (to_balance * Base) / (Weight * state.supply);
in_token_type init_out = init_price * converter_in;
state.supply -= converter_in;
state.balance -= converter_in;
auto out_price = ((to_balance-init_out) * Base) / ( Weight * (state.supply) );
return out_price * converter_in;
}
};
/**
* This is called when we receive RELAY tokens from user and wish to
* convert to one of the connector currencies.
*/
static void on_convert( const typename converter_currency::transfer& trans,
const converter_args& args,
converter_state& state ) {
if( args.to_currency_type == first_currency ) {
auto output = first_connector::convert_from_converter( trans.quantity, state );
save_and_send( trans.from, state, output, args.min_return );
}
else if( args.to_currency_type == second_currency ) {
auto output = second_connector::convert_from_converter( trans.quantity, state );
save_and_send( trans.from, state, output, args.min_return );
}
else {
eosio_assert( false, "invalid to currency" );
}
}
/**
* This is called when the converter receives one of the connector currencies and it
* will send either converter tokens or a different connector currency in response.
*/
template<typename ConnectorType>
static void on_convert( const typename ConnectorType::currency_type::transfer& trans,
const converter_args& args,
converter_state& state )
{
/// convert to converter
auto converter_out = ConnectorType::convert_to_converter( trans.quantity, state );
if( args.to_currency_type == converter_currency )
{
save_and_send( trans.from, state, converter_out, args.min_return );
}
else
{
auto output = ConnectorType::convert_from_converter( converter_out, state );
save_and_send( trans.from, state, output, args.min_return );
}
}
/**
* This method factors out the boiler plate for parsing args and loading the
* initial state before dispatching to the proper on_convert case
*/
template<typename CurrencyType>
static void start_convert( const typename CurrencyType::transfer_memo& trans ) {
auto args = unpack<converter_args>( trans.memo );
eosio_assert( args.to_currency_type != trans.quantity.token_type(), "cannot convert to self" );
auto state = read_converter_state();
on_convert( trans, args, state );
}
/**
* converter_account first needs to call the currency handler to perform
* user-to-user transfers of the converter token, then if a transfer is sending
* the token back to the converter contract, it should convert like everything else.
*
* This method should be called from apply( code, action ) for each of the
* transfer types that we support (for each currency)
*/
static void on( const typename converter_currency::transfer_memo& trans ) {
converter_currency::on( trans );
if( trans.to == converter_account ) {
start_convert( trans );
}
}
/**
* All other currencies simply call start_convert if to == converter_account
*/
template<typename Currency>
static void on( const typename Currency::transfer_memo& trans ) {
if( trans.to == converter_account ) {
start_convert( trans );
} else {
eosio_assert( trans.from == converter_account,
"received unexpected notification of transfer" );
}
}
static void apply( account_name code, action_name action ) {
if( !dispatch( converter_contract,
converter_currency::transfer,
converter_currency::issue,
first_currency::transfer,
second_currency::transfer ) {
eosio_assert( false, "received unexpected action" );
}
}
}; /// converter_contract
} /// namespace bancor
{
"types": [{
"new_type_name": "account_name",
"type": "name"
}
],
"structs": [{
"name": "transfer",
"base": "",
"fields": [
{"name":"from", "type":"account_name"},
{"name":"to", "type":"account_name"},
{"name":"quantity", "type":"uint64"}
]
},{
"name": "account",
"base": "",
"fields": [
{"name":"key", "type":"name"},
{"name":"balance", "type":"uint64"}
]
}
],
"actions": [{
"name": "transfer",
"type": "transfer"
}
],
"tables": [{
"name": "account",
"type": "account",
"index_type": "i64",
"key_names" : ["key"],
"key_types" : ["name"]
}
]
}
\ No newline at end of file
#pragma once
#include <eosiolib/eosio.hpp>
#include <eosiolib/asset.hpp>
#include <eosiolib/multi_index.hpp>
namespace eosio {
using std::string;
using std::array;
/**
* This contract enables the creation, issuance, and transfering of many different tokens.
* @deprecated This class is deprecated in favor of eosio.token in Dawn 3.0
*/
class currency {
public:
currency( account_name contract )
:_contract(contract)
{ }
struct create {
account_name issuer;
asset maximum_supply;
// array<char,32> issuer_agreement_hash;
uint8_t issuer_can_freeze = true;
uint8_t issuer_can_recall = true;
uint8_t issuer_can_whitelist = true;
/*(issuer_agreement_hash)*/
EOSLIB_SERIALIZE( create, (issuer)(maximum_supply)(issuer_can_freeze)(issuer_can_recall)(issuer_can_whitelist) )
};
struct transfer
{
account_name from;
account_name to;
asset quantity;
string memo;
EOSLIB_SERIALIZE( transfer, (from)(to)(quantity)(memo) )
};
struct issue {
account_name to;
asset quantity;
string memo;
EOSLIB_SERIALIZE( issue, (to)(quantity)(memo) )
};
struct fee_schedule {
uint64_t primary_key()const { return 0; }
array<extended_asset,7> fee_per_length;
EOSLIB_SERIALIZE( fee_schedule, (fee_per_length) )
};
struct account {
asset balance;
bool frozen = false;
bool whitelist = true;
uint64_t primary_key()const { return balance.symbol.name(); }
EOSLIB_SERIALIZE( account, (balance)(frozen)(whitelist) )
};
struct currency_stats {
asset supply;
asset max_supply;
account_name issuer;
bool can_freeze = true;
bool can_recall = true;
bool can_whitelist = true;
bool is_frozen = false;
bool enforce_whitelist = false;
uint64_t primary_key()const { return supply.symbol.name(); }
EOSLIB_SERIALIZE( currency_stats, (supply)(max_supply)(issuer)(can_freeze)(can_recall)(can_whitelist)(is_frozen)(enforce_whitelist) )
};
typedef eosio::multi_index<N(accounts), account> accounts;
typedef eosio::multi_index<N(stat), currency_stats> stats;
asset get_balance( account_name owner, symbol_name symbol )const {
accounts t( _contract, owner );
return t.get(symbol).balance;
}
asset get_supply( symbol_name symbol )const {
accounts t( _contract, symbol );
return t.get(symbol).balance;
}
static void inline_transfer( account_name from, account_name to, extended_asset amount, string memo = string(), permission_name perm = N(active) ) {
action act( permission_level( from, perm ), amount.contract, N(transfer), transfer{from,to,amount,memo} );
act.send();
}
void inline_transfer( account_name from, account_name to, asset amount, string memo = string(), permission_name perm = N(active) ) {
action act( permission_level( from, perm ), _contract, N(transfer), transfer{from,to,amount,memo} );
act.send();
}
bool apply( account_name contract, action_name act ) {
if( contract != _contract )
return false;
switch( act ) {
case N(issue):
print( "issue\n");
on( unpack_action_data<issue>() );
return true;
case N(transfer):
print( "transfer\n");
on( unpack_action_data<transfer>() );
return true;
case N(create):
print( "create\n");
on( unpack_action_data<create>() );
return true;
}
return false;
}
/**
* This is factored out so it can be used as a building block
*/
void create_currency( const create& c ) {
auto sym = c.maximum_supply.symbol;
eosio_assert( sym.is_valid(), "invalid symbol name" );
stats statstable( _contract, sym.name() );
auto existing = statstable.find( sym.name() );
eosio_assert( existing == statstable.end(), "token with symbol already exists" );
statstable.emplace( c.issuer, [&]( auto& s ) {
s.supply.symbol = c.maximum_supply.symbol;
s.max_supply = c.maximum_supply;
s.issuer = c.issuer;
s.can_freeze = c.issuer_can_freeze;
s.can_recall = c.issuer_can_recall;
s.can_whitelist = c.issuer_can_whitelist;
});
}
void issue_currency( const issue& i ) {
auto sym = i.quantity.symbol.name();
stats statstable( _contract, sym );
const auto& st = statstable.get( sym );
statstable.modify( st, 0, [&]( auto& s ) {
s.supply.amount += i.quantity.amount;
eosio_assert( s.supply.amount >= 0, "underflow" );
});
add_balance( st.issuer, i.quantity, st, st.issuer );
}
void on( const create& c ) {
require_auth( c.issuer );
create_currency( c );
/*
auto fee = get_fee_schedule()[c.maximum_supply.name_length()];
if( fee.amount > 0 ) {
inline_transfer( c.issuer, _contract, fee, "symbol registration fee" );
}
*/
}
void on( const issue& i ) {
auto sym = i.quantity.symbol.name();
stats statstable( _contract, sym );
const auto& st = statstable.get( sym );
require_auth( st.issuer );
eosio_assert( i.quantity.is_valid(), "invalid quantity" );
eosio_assert( i.quantity.amount > 0, "must issue positive quantity" );
statstable.modify( st, 0, [&]( auto& s ) {
s.supply.amount += i.quantity.amount;
});
add_balance( st.issuer, i.quantity, st, st.issuer );
if( i.to != st.issuer )
{
inline_transfer( st.issuer, i.to, i.quantity, i.memo );
}
}
void on( const transfer& t ) {
require_auth(t.from);
auto sym = t.quantity.symbol.name();
stats statstable( _contract, sym );
const auto& st = statstable.get( sym );
require_recipient( t.to );
eosio_assert( t.quantity.is_valid(), "invalid quantity" );
eosio_assert( t.quantity.amount > 0, "must transfer positive quantity" );
sub_balance( t.from, t.quantity, st );
add_balance( t.to, t.quantity, st, t.from );
}
private:
void sub_balance( account_name owner, asset value, const currency_stats& st ) {
accounts from_acnts( _contract, owner );
const auto& from = from_acnts.get( value.symbol.name() );
eosio_assert( from.balance.amount >= value.amount, "overdrawn balance" );
if( has_auth( owner ) ) {
eosio_assert( !st.can_freeze || !from.frozen, "account is frozen by issuer" );
eosio_assert( !st.can_freeze || !st.is_frozen, "all transfers are frozen by issuer" );
eosio_assert( !st.enforce_whitelist || from.whitelist, "account is not white listed" );
} else if( has_auth( st.issuer ) ) {
eosio_assert( st.can_recall, "issuer may not recall token" );
} else {
eosio_assert( false, "insufficient authority" );
}
from_acnts.modify( from, owner, [&]( auto& a ) {
a.balance.amount -= value.amount;
});
}
void add_balance( account_name owner, asset value, const currency_stats& st, account_name ram_payer )
{
accounts to_acnts( _contract, owner );
auto to = to_acnts.find( value.symbol.name() );
if( to == to_acnts.end() ) {
eosio_assert( !st.enforce_whitelist, "can only transfer to white listed accounts" );
to_acnts.emplace( ram_payer, [&]( auto& a ){
a.balance = value;
});
} else {
eosio_assert( !st.enforce_whitelist || to->whitelist, "receiver requires whitelist by issuer" );
to_acnts.modify( to, 0, [&]( auto& a ) {
a.balance.amount += value.amount;
});
}
}
private:
account_name _contract;
};
}
add_wast_executable(TARGET infinite
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES libc++ libc eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <eosiolib/print.hpp> /// defines transfer struct (abi)
extern "C" {
/// The apply method just prints forever
void apply( uint64_t, uint64_t, uint64_t ) {
int idx = 0;
while(true) {
eosio::print(idx++);
}
}
}
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_executable(TARGET simple.token
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES libc++ libc eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
#include <eosiolib/eosio.hpp>
class simpletoken : public eosio::contract {
public:
simpletoken( account_name self )
:contract(self),_accounts( _self, _self){}
void transfer( account_name from, account_name to, uint64_t quantity ) {
require_auth( from );
const auto& fromacnt = _accounts.get( from );
eosio_assert( fromacnt.balance >= quantity, "overdrawn balance" );
_accounts.modify( fromacnt, from, [&]( auto& a ){ a.balance -= quantity; } );
add_balance( from, to, quantity );
}
void issue( account_name to, uint64_t quantity ) {
require_auth( _self );
add_balance( _self, to, quantity );
}
private:
struct account {
account_name owner;
uint64_t balance;
uint64_t primary_key()const { return owner; }
};
eosio::multi_index<N(accounts), account> _accounts;
void add_balance( account_name payer, account_name to, uint64_t q ) {
auto toitr = _accounts.find( to );
if( toitr == _accounts.end() ) {
_accounts.emplace( payer, [&]( auto& a ) {
a.owner = to;
a.balance = q;
});
} else {
_accounts.modify( toitr, 0, [&]( auto& a ) {
a.balance += q;
eosio_assert( a.balance >= q, "overflow detected" );
});
}
}
};
EOSIO_ABI( simpletoken, (transfer)(issue) )
add_wast_executable(TARGET social
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <eos.hpp>
/**
* The purpose of this contract is to implement something like Steem on EOS, this
* means this contract defines its own currency, allows people to create posts, vote
* on posts, and stake their voting power.
*
* Unlike Steem, the goal is to enable maximum parallelism and enable the currency to
* be easily integrated with an exchange contract.
*/
struct post_action {
account_name author;
post_name postid;
account_name reply_to_author;
int32_t reply_to_id;
uint8_t author; /// index in notify list
char[] data; /// ignored, title is embedded within
account_name get_author()const { return get_notify(author); }
};
struct vote_action {
account_name voter;
account_name author;
post_name postid;
int32_t vote_power;
};
struct post_record {
uint64_t total_votes = 0;
uint64_t claimed_votes = 0;
uint32_t created;
post_record( uint32_t c = now() ):created(c){}
static Name table_id() { return Name("post"); }
};
struct account {
uint64_t social = 0;
uint64_t social_power = 0;
int32_t vote_power = 0;
uint32_t last_vote = 0;
static Name table_id() { return Name("account"); }
};
/**
* When a user posts we create a record that tracks the total votes and the time it
* was created. A user can submit this action multiple times, but subsequent calls do
* nothing.
*
* This method only does something when called in the context of the author, if
* any other contexts are notified
*/
void apply_social_post() {
const auto& post = current_action<post_action>();
require_auth( post.author );
eosio_assert( current_context() == post.author, "cannot call from any other context" );
static post_record& existing;
if( !Db::get( post.postid, existing ) )
Db::store( post.postid, post_record( now() ) );
}
/**
* This action is called when a user casts a vote, it requires that this code is executed
* in the context of both the voter and the author. When executed in the author's context it
* updates the vote total. When executed
*/
void apply_social_vote() {
const auto& vote = current_action<vote_action>();
require_recipient( vote.voter, vote.author );
disable_context_code( vote.author() ); /// prevent the author's code from rejecting the potentially negative vote
auto context = current_context();
auto voter = vote.getVoter();
if( context == vote.author ) {
static post_record post;
eosio_assert( Db::get( vote.postid, post ) > 0, "unable to find post" );
eosio_assert( now() - post.created < days(7), "cannot vote after 7 days" );
post.votes += vote.vote_power;
Db::store( vote.postid, post );
}
else if( context == vote.voter ) {
static account vote_account;
Db::get( "account", vote_account );
auto abs_vote = abs(vote.vote_power);
vote_account.vote_power = min( vote_account.social_power,
vote_account.vote_power + (vote_account.social_power * (now()-last_vote)) / days(7));
eosio_assert( abs_vote <= vote_account.vote_power, "insufficient vote power" );
post.votes += vote.vote_power;
vote_account.vote_power -= abs_vote;
vote_account.last_vote = now();
Db::store( "account", vote_account );
} else {
eosio_assert( false, "invalid context for execution of this vote" );
}
}
......@@ -21,7 +21,6 @@ target_link_libraries( plugin_test eosio_testing eosio_chain chainbase eos_utili
target_include_directories( plugin_test PUBLIC
${CMAKE_SOURCE_DIR}/plugins/net_plugin/include
${CMAKE_SOURCE_DIR}/plugins/chain_plugin/include )
add_dependencies(plugin_test asserter test_api test_api_mem test_api_db test_api_multi_index proxy identity identity_test stltest infinite eosio.system eosio.token eosio.bios test.inline multi_index_test noop eosio.msig)
#
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/core_symbol.py.in ${CMAKE_CURRENT_BINARY_DIR}/core_symbol.py)
......
......@@ -12,15 +12,6 @@
#include <asserter/asserter.wast.hpp>
#include <asserter/asserter.abi.hpp>
#include <stltest/stltest.wast.hpp>
#include <stltest/stltest.abi.hpp>
#include <noop/noop.wast.hpp>
#include <noop/noop.abi.hpp>
#include <eosio.system/eosio.system.wast.hpp>
#include <eosio.system/eosio.system.abi.hpp>
#include <fc/io/fstream.hpp>
#include <Runtime/Runtime.h>
......
#include <boost/test/unit_test.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/chain/merkle.hpp>
#include <fc/io/json.hpp>
#ifdef NON_VALIDATING_TEST
#define TESTER tester
#else
#define TESTER validating_tester
#endif
using namespace eosio;
using namespace eosio::chain;
using namespace eosio::testing;
struct action_proof_data {
account_name receiver;
scope_name scope;
action_name name;
bytes data;
uint64_t region_id;
uint64_t cycle_index;
vector<data_access_info> data_access;
};
FC_REFLECT(action_proof_data, (receiver)(scope)(name)(data)(region_id)(cycle_index)(data_access));
struct merkle_node {
digest_type digest;
optional<size_t> left;
optional<size_t> right;
optional<size_t> parent;
};
digest_type process_merkle(vector<merkle_node>& nodes, vector<size_t> leaf_indices) {
size_t num_nodes = leaf_indices.size();
size_t base = 0;
if (num_nodes == 0) {
return digest_type();
} else if (num_nodes == 1) {
return nodes[leaf_indices.front()].digest;
}
while (num_nodes > 1) {
size_t new_nodes = (num_nodes / 2) + (num_nodes % 2);
for(size_t idx = 0; idx < new_nodes; idx++) {
size_t l_idx = idx * 2;
size_t r_idx = l_idx + 1;
size_t left = leaf_indices.at(base + l_idx);
if (r_idx >= num_nodes) {
nodes.emplace_back(
merkle_node{
digest_type::hash(make_canonical_pair(nodes[left].digest, nodes[left].digest)),
left
});
nodes[left].parent.emplace(nodes.size() - 1);
} else {
size_t right = leaf_indices.at(base + r_idx);
nodes.emplace_back(
merkle_node{
digest_type::hash(make_canonical_pair(nodes[left].digest, nodes[right].digest)),
left,
right
});
nodes[left].parent.emplace(nodes.size() - 1);
nodes[right].parent.emplace(nodes.size() - 1);
}
leaf_indices.emplace_back(nodes.size() - 1);
}
base += num_nodes;
num_nodes = new_nodes;
}
return nodes.back().digest;
}
auto get_proof_path(const vector<merkle_node>& nodes, size_t leaf) {
vector<digest_type> path;
digest_type current = nodes[leaf].digest;
while (nodes[leaf].parent.valid()) {
size_t parent = *nodes[leaf].parent;
if (leaf == *nodes[parent].left) {
if (nodes[parent].right.valid()) {
size_t right = *nodes[parent].right;
path.emplace_back(make_canonical_right(nodes[right].digest));
current = digest_type::hash(make_canonical_pair(nodes[leaf].digest, nodes[right].digest));
} else {
path.emplace_back(make_canonical_right(nodes[leaf].digest));
current = digest_type::hash(make_canonical_pair(nodes[leaf].digest, nodes[leaf].digest));
}
} else {
size_t left = *nodes[parent].left;
path.emplace_back(make_canonical_left(nodes[left].digest));
current = digest_type::hash(make_canonical_pair(nodes[left].digest, nodes[leaf].digest));
}
leaf = parent;
}
return path;
}
digest_type apply_path(const digest_type& digest, const vector<digest_type>& path) {
digest_type current = digest;
for (const auto& p: path ) {
if (is_canonical_left(p)) {
current = digest_type::hash(make_canonical_pair(p, current));
} else {
current = digest_type::hash(make_canonical_pair(current, p));
}
}
return current;
}
bool proof_is_valid(const digest_type& digest, const vector<digest_type>& path, const digest_type& expected_root) {
return apply_path(digest, path) == expected_root;
}
BOOST_AUTO_TEST_SUITE(proof_tests)
BOOST_FIXTURE_TEST_CASE( prove_block_in_chain, validating_tester ) { try {
vector<block_id_type> known_blocks;
known_blocks.reserve(100);
block_header last_block_header;
// register a callback on new blocks to record block information
validating_node->applied_block.connect([&](const block_trace& bt){
known_blocks.emplace_back(bt.block.id());
last_block_header = bt.block;
});
produce_blocks(100);
return;
vector<merkle_node> nodes;
vector<digest_type> ids;
vector<size_t> block_leaves;
nodes.reserve(100);
ids.reserve(100);
for (const auto& blk_id: known_blocks) {
nodes.emplace_back(merkle_node{blk_id});
ids.push_back(blk_id);
block_leaves.push_back(nodes.size() - 1);
}
digest_type block_mroot = process_merkle(nodes, move(block_leaves));
BOOST_REQUIRE_EQUAL((std::string)block_mroot, (std::string)merkle(ids));
produce_block();
BOOST_REQUIRE_EQUAL((std::string)block_mroot, (std::string)last_block_header.block_mroot);
for (int idx = 0; idx < 100; idx++) {
vector<digest_type> path = get_proof_path(nodes, idx);
BOOST_REQUIRE_EQUAL(true, proof_is_valid(nodes[idx].digest, path, last_block_header.block_mroot));
/** UNCOMMENT TO PRODUCE PROOFS TO STD OUT
std::cout << idx << ":" << std::string(known_blocks.at(idx)) << " = ";
for (const auto& e: path) {
std::cout << std::string(e) << " ";
}
std::cout << "-> " << std::string(last_block_header.block_mroot) << std::endl;
*/
}
} FC_LOG_AND_RETHROW() } /// transfer_test
struct action_proof_info {
action_trace trace;
size_t action_leaf;
size_t block_leaf;
uint32_t cycle_index;
uint32_t region_id;
};
/**
* This test case will attempt to allow one account to transfer on behalf
* of another account by updating the active authority.
*/
BOOST_FIXTURE_TEST_CASE( prove_action_in_block, validating_tester ) { try {
vector<merkle_node> nodes;
vector<size_t> block_leaves;
vector<action_proof_info> known_actions;
map<digest_type, digest_type> block_action_mroots;
block_header last_block_header;
block_id_type last_block_id;
// register a callback on new blocks to record block information
validating_node->applied_block.connect([&](const block_trace& bt){
nodes.emplace_back(merkle_node{bt.block.id()});
size_t block_leaf = nodes.size() - 1;
block_leaves.push_back(block_leaf);
vector<size_t> region_leaves;
for (uint32_t r_idx = 0; r_idx < bt.region_traces.size(); r_idx++) {
const auto& rt = bt.region_traces.at(r_idx);
vector<size_t> shard_leaves;
for (uint32_t c_idx = 0; c_idx < rt.cycle_traces.size(); c_idx++) {
const auto& ct = rt.cycle_traces.at(c_idx);
for (const auto& st: ct.shard_traces) {
vector<size_t> action_leaves;
for (const auto& tt: st.transaction_traces) {
for (const auto& at: tt.action_traces) {
digest_type::encoder enc;
auto a_data = action_proof_data {
at.receiver,
at.act.account,
at.act.name,
at.act.data,
tt.region_id,
tt.cycle_index,
at.data_access
};
fc::raw::pack(enc, a_data);
nodes.emplace_back(merkle_node{enc.result()});
size_t action_leaf = nodes.size() - 1;
known_actions.emplace_back(action_proof_info{at, action_leaf, block_leaf, c_idx, r_idx });
action_leaves.emplace_back(action_leaf);
}
}
if (action_leaves.size() > 0) {
process_merkle(nodes, move(action_leaves));
} else {
nodes.emplace_back(merkle_node{digest_type()});
}
shard_leaves.emplace_back(nodes.size() - 1);
}
}
if (shard_leaves.size() > 0) {
process_merkle(nodes, move(shard_leaves));
} else {
nodes.emplace_back(merkle_node{digest_type()});
}
region_leaves.emplace_back(nodes.size() - 1);
}
digest_type action_mroot = process_merkle(nodes, move(region_leaves));
BOOST_REQUIRE_EQUAL((std::string)bt.block.action_mroot, (std::string)action_mroot);
last_block_header = bt.block;
last_block_id = bt.block.id();
block_action_mroots[bt.block.id()] = bt.block.action_mroot;
});
create_accounts( { N(alice), N(bob), N(carol), N(david), N(elvis) });
produce_blocks(50);
push_dummy(N(alice), "AB");
push_dummy(N(bob), "BC");
push_dummy(N(carol), "CD");
push_dummy(N(david), "DE");
push_dummy(N(elvis), "EF");
produce_blocks(50);
digest_type block_mroot = process_merkle(nodes, move(block_leaves));
produce_block();
BOOST_REQUIRE_EQUAL((std::string)block_mroot, (std::string)last_block_header.block_mroot);
/* UNCOMMENT TO PRODUCE PROOFS TO STDOUT
std::cout << "Best Block ID: " << (std::string)last_block_id << std::endl;
std::cout << " Merkle Root: " << (std::string)last_block_header.block_mroot << std::endl;
for(const auto& ai : known_actions) {
auto block_path = get_proof_path(nodes, ai.action_leaf);
auto chain_path = get_proof_path(nodes, ai.block_leaf);
// prove action in block
auto shard_root = apply_path(nodes[ai.action_leaf].digest, block_path);
BOOST_REQUIRE_EQUAL((std::string)shard_root, (std::string)block_action_mroots[nodes[ai.block_leaf].digest]);
// prove that block is part of the chain
auto expected_block_mroot = apply_path(nodes[ai.block_leaf].digest, chain_path);
BOOST_REQUIRE_EQUAL((std::string)expected_block_mroot, (std::string)last_block_header.block_mroot);
std::cout << "Proof for Action:" << std::endl;
std::cout << std::setw(14) << "reciever" << ":" << (std::string) ai.trace.receiver << std::endl;
std::cout << std::setw(14) << "scope" << ":" << (std::string) ai.trace.act.scope << std::endl;
std::cout << std::setw(14) << "name" << ":" << (std::string) ai.trace.act.name << std::endl;
std::cout << std::setw(14) << "data" << ":" << fc::json::to_string(ai.trace.act.as<contracts::transfer>()) << std::endl;
std::cout << std::setw(14) << "data_access" << ":" << fc::json::to_string(ai.trace.data_access) << std::endl;
std::cout << std::setw(14) << "region" << ":" << ai.region_id << std::endl;
std::cout << std::setw(14) << "cycle" << ":" << ai.cycle_index << std::endl;
std::cout << std::setw(14) << "block" << ":" << (std::string)nodes[ai.block_leaf].digest << std::endl;
std::cout << std::setw(14) << "am_root" << ":" << (std::string)block_action_mroots[nodes[ai.block_leaf].digest] << std::endl;
std::cout << std::endl;
auto a_data = action_proof_data {
ai.trace.receiver,
ai.trace.act.scope,
ai.trace.act.name,
ai.trace.act.data,
ai.trace.region_id,
ai.trace.cycle_index,
ai.trace.data_access
};
auto action_data = fc::raw::pack(a_data);
std::cout << "Action Hex: " << fc::to_hex(action_data) << std::endl;
std::cout << "Action Hash: " << (std::string)nodes[ai.action_leaf].digest << std::endl;
std::cout << "Action Path: ";
for (const auto& p: block_path) {
std::cout << (std::string)p << " ";
}
std::cout << std::endl;
std::cout << "Block Path: ";
for (const auto& p: chain_path) {
std::cout << (std::string)p << " ";
}
std::cout << std::endl;
}*/
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_SUITE_END()
......@@ -12,12 +12,6 @@
#include <asserter/asserter.wast.hpp>
#include <asserter/asserter.abi.hpp>
#include <stltest/stltest.wast.hpp>
#include <stltest/stltest.abi.hpp>
#include <eosio.system/eosio.system.wast.hpp>
#include <eosio.system/eosio.system.abi.hpp>
#include <eosio.token/eosio.token.wast.hpp>
#include <eosio.token/eosio.token.abi.hpp>
......
#!/usr/bin/env bash
#
# This script captures the generic fuzz testing to which
# net_plugin has been subjected. It typically results in
# message buffers in excess of 1 gigabyte.
#
if ! pgrep nodeos > /dev/null; then
echo "Run nodeos with net_plugin configured for port 9876."
exit 1
fi
for i in `seq 1 10000`; do netcat localhost 9876 < /dev/urandom; done
#!/usr/bin/perl
use strict;
use Getopt::Long;
use Env;
use File::Basename;
use File::copy;
use File::Spec;
use File::Path;
use Cwd;
my $eos_home = defined $ENV{EOS_HOME} ? $ENV{EOS_HOME} : getcwd;
my $eosd = $eos_home . "/programs/eosd/eosd";
my $eosc = $eos_home . "/programs/eosc/eosc";
my $nodes = defined $ENV{EOS_TEST_RING} ? $ENV{EOS_TEST_RING} : "1";
my $pnodes = defined $ENV{EOS_TEST_PRODUCERS} ? $ENV{EOS_TEST_PRODUCERS} : "1";
my $prods = 21;
my $genesis = "$eos_home/genesis.json";
my $http_port_base = 8888;
my $p2p_port_base = 9876;
my $data_dir_base = "tdn";
my $hostname = "127.0.0.1";
my $first_pause = 0;
my $launch_pause = 0;
my $run_duration = 60;
my $topo = "ring";
my $override_gts = "";
my $no_delay=0;
my $test=1;
if (!GetOptions("nodes=i" => \$nodes,
"first-pause=i" => \$first_pause,
"launch-pause=i" => \$launch_pause,
"duration=i" => \$run_duration,
"topo=s" => \$topo,
"test=i" => \$test,
"time-stamp=s" => \$override_gts,
"pnodes=i" => \$pnodes)) {
print "usage: $ARGV[0] [--nodes=<n>] [--pnodes=<n>] [--topo=<ring|star>] [--first-pause=<n>] [--launch-pause=<n>] [--duration=<n>] [--time-stamp=<time> \n";
print "where:\n";
print "--nodes=n (default = 1) sets the number of eosd instances to launch\n";
print "--pnodes=n (default = 1) sets the number nodes that will also be producers\n";
print "--topo=s (default = ring) sets the network topology to either a ring shape or a star shape\n";
print "--first-pause=n (default = 0) sets the seconds delay after starting the first instance\n";
print "--launch-pause=n (default = 0) sets the seconds delay after starting subsequent nodes\n";
print "--duration=n (default = 60) sets the seconds delay after starting the last node before shutting down the test\n";
print "--time-stamp=s (default \"\") sets the timestamp in UTC for the genesis block. use \"now\" to mean the current time.\n";
print "\nproducer count currently fixed at $prods\n";
exit
}
die "pnodes value must be between 1 and $prods\n" if ($pnodes < 1 || $pnodes > $prods);
$nodes = $pnodes if ($nodes < $pnodes);
my $per_node = int ($prods / $pnodes);
my $extra = $prods - ($per_node * $pnodes);
my @pcount;
for (my $p = 0; $p < $pnodes; $p++) {
$pcount[$p] = $per_node;
if ($extra) {
$pcount[$p]++;
$extra--;
}
}
my @pid;
my @data_dir;
my @p2p_port;
my @http_port;
my @peers;
$launch_pause = 0 if ($no_delay);
$first_pause = 0 if ($no_delay);
my $rhost = $hostname; # from a list for multihost tests
for (my $i = 0; $i < $nodes; $i++) {
$p2p_port[$i] = $p2p_port_base + $i;
$http_port[$i] = $http_port_base + $i;
$data_dir[$i] = "$data_dir_base-$i";
}
opendir(DIR, ".") or die $!;
while (my $d = readdir(DIR)) {
if ($d =~ $data_dir_base) {
rmtree ($d) or die $!;
}
}
closedir(DIR);
sub write_config {
my $i = shift;
my $producer = shift;
mkdir ($data_dir[$i]);
mkdir ($data_dir[$i]."/blocks");
mkdir ($data_dir[$i]."/blockchain");
open (my $cfg, '>', "$config_dir[$i]/config.ini") ;
print $cfg "genesis-json = \"$genesis\"\n";
print $cfg "block-log-dir = blocks\n";
print $cfg "readonly = 0\n";
print $cfg "shared-file-dir = blockchain\n";
print $cfg "shared-file-size = 64\n";
print $cfg "http-server-address = 127.0.0.1:$http_port[$i]\n";
print $cfg "p2p-listen-endpoint = 0.0.0.0:$p2p_port[$i]\n";
print $cfg "p2p-server-address = $hostname:$p2p_port[$i]\n";
foreach my $peer (@peers) {
print $cfg "p2p-peer-address = $peer\n";
}
if (defined $producer) {
print $cfg "enable-stale-production = true\n";
print $cfg "required-participation = true\n";
print $cfg "private-key = [\"EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV\",\"5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3\"]\n";
print $cfg "plugin = eosio::producer_plugin\n";
print $cfg "plugin = eosio::chain_api_plugin\n";
my $prod_ndx = ord('a') + $producer;
my $num_prod = $pcount[$producer];
for (my $p = 0; $p < $num_prod; $p++) {
print $cfg "producer-name = init" . chr($prod_ndx) . "\n";
$prod_ndx += $pnodes; # ($p < $per_node-1) ? $pnodes : 1;
}
}
close $cfg;
}
#connect each producer to the one ahead in the list, last to the first
#if bidir set then double connect to the one behind as well
sub make_ring_topology {
my $bidir = shift;
if ($nodes == 1) {
write_config (0,0);
return 1;
}
for (my $i = 0; $i < $nodes; $i++) {
my $pi = $i if ($i < $pnodes);
my $rport = ($i == $nodes - 1) ? $p2p_port_base : $p2p_port[$i] + 1;
$peers[0] = "$rhost:$rport";
if ($nodes > 2 && $bidir) {
$rport = $p2p_port[$i] - 1;
$rport += $nodes if ($i == 0);
$peers[1] = "$rhost:$rport";
}
write_config ($i, $pi);
}
return 1;
}
#connect each producer to three others, index+1, index + 1 + delta, index + 2(1 + delta)
#delta determined by total number of producer nodes. between 4 and 7, delta = pnodes-4
sub make_star_topology {
if ($pnodes < 4) {
return make_ring_topology(0);
}
my $numconn = 3;
my @ports;
my $delta = $pnodes > 6 ? 4 : $pnodes - $numconn;
for (my $i = 0; $i < $nodes; $i++) {
my $pi = $i if ($i < $pnodes);
$ports[0] = $p2p_port[$i];
for (my $d = 1; $d <= $numconn; $d++) {
my $rind = ($i + ($d) * ($delta)) % $nodes;
$rind++ if ($rind == $i);
my $rport = $p2p_port[$rind];
for (my $chk = 0; $chk < $d; $chk++) {
if ($rport == $ports[$chk]) {
$rport++;
$chk = -1;
}
}
$ports[$d] = $rport;
$peers[$d-1] = "$rhost:$rport";
}
write_config ($i, $pi);
}
return 1;
}
sub launch_nodes {
my $gtsarg;
if ($override_gts) {
my $GTS = $override_gts;
print "override gts = $override_gts\n";
if ($override_gts =~ "now" ) {
chomp ($GTS = `date -u "+%Y-%m-%dT%H:%M:%S"`);
my @s = split (':',$GTS);
$s[2] = substr ((100 + (int ($s[2]/3) * 3)),1);
$GTS = join (':', @s);
print "using genesis time stamp $GTS\n";
}
$gtsarg = "--genesis-timestamp=$GTS";
}
for (my $i = 0; $i < $nodes; $i++) {
my @cmdline = ($eosd,
$gtsarg,
"--data-dir=$data_dir[$i]",
"--verbose-http-errors",
"--http-validate-host=false");
$pid[$i] = fork;
if ($pid[$i] > 0) {
my $pause = $i == 0 ? $first_pause : $launch_pause;
print "parent process looping, child pid = $pid[$i]";
if ($i < $nodes - 1) {
print ", pausing $pause seconds\n";
sleep ($pause);
}
else {
print "\n";
}
}
elsif (defined ($pid[$i])) {
print "child execing now, pid = $$\n";
open OUTPUT, '>', "$data_dir[$i]/stdout.txt" or die $!;
open ERROR, '>', "$data_dir[$i]/stderr.txt" or die $!;
STDOUT->fdopen ( \*OUTPUT, 'w') or die $!;
STDERR->fdopen ( \*ERROR, 'w') or die $!;
print "$cmdline[0], $cmdline[1], $cmdline[2]\n";
exec @cmdline;
print "child terminating now\n";
exit;
}
else {
print "fork failed\n";
exit;
}
}
}
sub perform_work {
my $mode = shift;
sleep (5);
print "all nodes launched, network running for $run_duration seconds\n";
if ($mode == 0) {
sleep ($run_duration);
}
elsif ($mode == 1) {
my $stoptime = time () + $run_duration;
my $counter = 0;
while (time () < $stoptime) {
`$eosc transfer eos inita 10 >> eosc.out 2>> eosc.err`;
$counter++;
if ($counter % 1000 == 0) {
print "$counter client iterations\n";
}
}
print "minimal contract ran $counter times.\n";
}
else {
print "test mode $mode not defined\n";
}
}
sub kill_nodes {
foreach my $pp (@pid) {
print "killing $pp\n";
if (kill (2, $pp) != 0) {
sleep (1);
kill 9, $pp;
}
}
}
###################################################
# main
if ( $topo =~ "ring" ) { make_ring_topology (1) or die; }
elsif ( $topo =~ "star" ) { make_star_topology () or die; }
else { print "$topo is not a known topology" and die; }
launch_nodes ();
perform_work ($test);
kill_nodes () if ($run_duration > 0);
......@@ -28,7 +28,7 @@ target_include_directories( unit_test PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/contracts
${CMAKE_CURRENT_BINARY_DIR}/contracts
${CMAKE_CURRENT_BINARY_DIR}/include )
add_dependencies(unit_test asserter test_api test_api_mem test_api_db test_ram_limit test_api_multi_index eosio.token proxy identity identity_test stltest infinite eosio.system eosio.token eosio.bios test.inline multi_index_test noop eosio.msig payloadless tic_tac_toe deferred_test snapshot_test)
add_dependencies(unit_test asserter test_api test_api_mem test_api_db test_ram_limit test_api_multi_index eosio.token proxy identity identity_test stltest eosio.system eosio.token eosio.bios multi_index_test noop eosio.msig payloadless tic_tac_toe deferred_test snapshot_test)
#Manually run unit_test for all supported runtimes
#To run unit_test with all log from blockchain displayed, put --verbose after --, i.e. unit_test -- --verbose
......
......@@ -9,8 +9,6 @@
#include <eosio.sudo/eosio.sudo.wast.hpp>
#include <eosio.sudo/eosio.sudo.abi.hpp>
#include <test_api/test_api.wast.hpp>
#include <Runtime/Runtime.h>
#include <fc/variant_object.hpp>
......
......@@ -114,9 +114,6 @@ public:
);
}
asset get_balance( const account_name& act ) {
//return get_currency_balance( config::system_account_name, symbol(CORE_SYMBOL), act );
//temporary code. current get_currency_balancy uses table name N(accounts) from currency.h
//generic_currency table name is N(account).
const auto& db = control->db();
const auto* tbl = db.find<table_id_object, by_code_scope_table>(boost::make_tuple(N(eosio.token), act, N(accounts)));
share_type result = 0;
......
......@@ -19,9 +19,6 @@
#include <test_ram_limit/test_ram_limit.abi.hpp>
#include <test_ram_limit/test_ram_limit.wast.hpp>
#define DISABLE_EOSLIB_SERIALIZE
#include <test_api/test_api_common.hpp>
/*
* register test suite `ram_tests`
*/
......
......@@ -11,9 +11,6 @@
#include <eosio.system/eosio.system.wast.hpp>
#include <eosio.system/eosio.system.abi.hpp>
#include <proxy/proxy.wast.hpp>
#include <proxy/proxy.abi.hpp>
#include <Runtime/Runtime.h>
#include <fc/variant_object.hpp>
......
......@@ -517,76 +517,6 @@ BOOST_FIXTURE_TEST_CASE(misaligned_tests, tester ) try {
check_aligned(misaligned_const_ref_wast);
} FC_LOG_AND_RETHROW()
// test cpu usage
/* Comment out this test due to not being robust to changes
BOOST_FIXTURE_TEST_CASE(cpu_usage_tests, tester ) try {
#warning This test does not appear to be very robust.
create_accounts( {N(f_tests)} );
bool pass = false;
std::string code = R"=====(
(module
(import "env" "require_auth" (func $require_auth (param i64)))
(import "env" "eosio_assert" (func $eosio_assert (param i32 i32)))
(table 0 anyfunc)
(memory $0 1)
(export "apply" (func $apply))
(func $test1 (param $0 i64))
(func $test2 (param $0 i64) (result i64) (i64.add (get_local $0) (i64.const 32)))
(func $apply (param $0 i64)(param $1 i64)(param $2 i64)
)=====";
for (int i = 0; i < 1024; ++i) {
code += "(call $test1 (call $test2(i64.const 1)))\n";
}
code += "))";
produce_blocks(1);
set_code(N(f_tests), code.c_str());
produce_blocks(10);
uint32_t start = config::default_per_signature_cpu_usage + config::default_base_per_transaction_cpu_usage;
start += 100 * ( config::default_base_per_action_cpu_usage
+ config::determine_payers_cpu_overhead_per_authorization
+ config::base_check_authorization_cpu_per_authorization );
start += config::resource_processing_cpu_overhead_per_billed_account;
start /= 1024;
start += 3077; // injected checktime amount
--start;
wdump((start));
uint32_t end = start + 5;
uint32_t limit = start;
for( limit = start; limit < end; ++limit ) {
signed_transaction trx;
for (int i = 0; i < 100; ++i) {
action act;
act.account = N(f_tests);
act.name = N() + (i * 16);
act.authorization = vector<permission_level>{{N(f_tests),config::active_name}};
trx.actions.push_back(act);
}
set_transaction_headers(trx);
trx.max_cpu_usage_ms = limit++;
trx.sign(get_private_key( N(f_tests), "active" ), control->get_chain_id());
try {
push_transaction(trx);
produce_blocks(1);
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
break;
} catch (eosio::chain::tx_cpu_usage_exceeded &) {
}
BOOST_REQUIRE_EQUAL(true, validate());
}
wdump((limit));
BOOST_CHECK_EQUAL(true, start < limit && limit < end);
} FC_LOG_AND_RETHROW()
*/
// test weighted cpu limit
BOOST_FIXTURE_TEST_CASE(weighted_cpu_limit_tests, tester ) try {
// TODO Increase the robustness of this test.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册