提交 86124b14 编写于 作者: B Bart Wyatt

temporary checkin

上级 9977db71
......@@ -11,6 +11,7 @@ add_subdirectory(test_api)
#add_subdirectory(simpledb)
#add_subdirectory(storage)
#add_subdirectory(social)
add_subdirectory(test.system)
add_subdirectory(noop)
install( DIRECTORY eosiolib DESTINATION include/ )
......
......@@ -37,7 +37,27 @@ extern "C" {
* @return time in seconds from 1970 of the last accepted block
*/
time now();
///@ } systemcapi
/**
* @defgroup privilegedapi Privileged API
* @ingroup systemapi
* @brief Defines an API for accessing configuration of the chain that can only be done by privileged accounts
*/
/**
* @defgroup privilegedcapi Privileged C API
* @ingroup privilegedapi
* @brief Define C Privileged API
*
* @{
*/
void set_resource_limits( account_name account, int64_t ram_bytes, int64_t net_weight, int64_t cpu_weight, int64_t ignored);
void set_active_producers( char *producer_data, size_t producer_data_size );
///@ } privilegedcapi
}
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)
add_wast_target(test.system "${CMAKE_SOURCE_DIR}/contracts" ${CMAKE_CURRENT_BINARY_DIR})
{
"types": [{
"new_type_name": "account_name",
"type": "name"
}
],
"structs": [{
"name": "set_account_limits",
"base": "",
"fields": [
{"name":"account", "type":"account_name"},
{"name":"ram_bytes", "type":"int64"},
{"name":"net_weight", "type":"int64"},
{"name":"cpu_weight", "type":"int64"}
]
},{
"name": "set_global_limits",
"base": "",
"fields": [
{"name":"cpu_usec_per_period", "type":"int64"},
]
},{
"name": "producer_key",
"base": "",
"fields": [
{"name":"account", "type":"account_name"},
{"name":"public_key", "type":"string"}
]
},{
"name": "set_producers",
"base": "",
"fields": [
{"name":"version", "type":"uint32"},
{"name":"producer", "type":"producer_key[]"}
]
}],
"tables": []
}
\ No newline at end of file
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <eosiolib/action.hpp>
#include <eosiolib/types.hpp>
#include <eosiolib/serialize.hpp>
#include <eosiolib/string.hpp>
#include <eosiolib/system.h>
using namespace eosio;
namespace testsystem {
template<uint64_t Val>
struct dispatchable {
constexpr static uint64_t action_name = Val;
};
struct set_account_limits : dispatchable<N(setalimits)> {
account_name account;
int64_t ram_bytes;
int64_t net_weight;
int64_t cpu_weight;
static void process(const set_account_limits& act) {
set_resource_limits(act.account, act.ram_bytes, act.net_weight, act.cpu_weight, 0);
}
EOSLIB_SERIALIZE( set_account_limits, (account)(ram_bytes)(net_weight)(cpu_weight) );
};
struct set_global_limits : dispatchable<N(setglimits)> {
int64_t cpu_usec_per_period;
static void process(const set_global_limits& act) {
// TODO: support this
}
EOSLIB_SERIALIZE( set_global_limits, (cpu_usec_per_period) );
};
struct producer_key {
account_name account;
string public_key;
EOSLIB_SERIALIZE( producer_key, (account)(public_key) );
};
struct set_producers : dispatchable<N(setproducers)> {
uint32_t version;
vector<producer_key> producers;
static void process(const set_producers&) {
char buffer[action_size()];
read_action( buffer, sizeof(buffer) );
set_active_producers(buffer, sizeof(buffer));
}
EOSLIB_SERIALIZE( set_producers, (version)(producers) );
};
template<typename T, typename ...Rem>
struct dispatcher_impl {
static void dispatch(uint64_t action) {
if (action == T::action_name) {
T::process(current_action<T>());
} else {
dispatcher_impl<Rem...>::dispatch(action);
}
}
};
using dispatcher = dispatcher_impl<set_account_limits, set_global_limits, set_producers>;
};
extern "C" {
/// The apply method implements the dispatch of events to this contract
void apply( uint64_t code, uint64_t act ) {
if (code == current_receiver()) {
testsystem::dispatcher::dispatch(act);
}
}
} // extern "C"
file(GLOB HEADERS "include/eosio/chain/*.hpp" "include/eosio/chain/contracts/*.hpp")
file(GLOB HEADERS "include/eosio/chain/*.hpp")
## SORT .cpp by most likely to change / break compile
add_library( eosio_chain
......@@ -29,13 +29,12 @@ add_library( eosio_chain
${HEADERS}
transaction_metadata.cpp)
transaction_metadata.cpp)
target_link_libraries( eosio_chain eos_utilities fc chainbase Logging IR WAST WASM Runtime )
target_include_directories( eosio_chain
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/../wasm-jit/Include"
"${CMAKE_BINARY_DIR}/contracts"
)
if(MSVC)
......
......@@ -1094,37 +1094,9 @@ void chain_controller::_initialize_chain(contracts::chain_initializer& starter)
for (int i = 0; i < 0x10000; i++)
_db.create<block_summary_object>([&](block_summary_object&) {});
auto acts = starter.prepare_database(*this, _db);
// create a block for our genesis transaction to send to applied_irreversible_block below
signed_block block{};
block.producer = config::system_account_name;
block_trace btrace{block};
btrace.region_traces.emplace_back();
auto& rtrace = btrace.region_traces.back();
rtrace.cycle_traces.emplace_back();
auto& ctrace = rtrace.cycle_traces.back();
ctrace.shard_traces.emplace_back();
auto& strace = ctrace.shard_traces.back();
signed_transaction genesis_setup_transaction; // not actually signed, signature checking is skipped
genesis_setup_transaction.actions = move(acts);
block.input_transactions.emplace_back(genesis_setup_transaction);
ilog( "applying genesis transaction" );
with_skip_flags(skip_scope_check | skip_transaction_signatures | skip_authority_check | received_block | genesis_setup,
[&](){
transaction_metadata tmeta( packed_transaction(genesis_setup_transaction), chain_id_type(), initial_timestamp );
transaction_trace ttrace = __apply_transaction( tmeta );
strace.append(ttrace);
});
// TODO: Should we write this genesis block instead of faking it on startup?
strace.calculate_root();
applied_block(btrace);
applied_irreversible_block(block);
starter.prepare_database(*this, _db);
ilog( "done applying genesis transaction" );
ilog( "done initializing chain" );
});
}
} FC_CAPTURE_AND_RETHROW() }
......
......@@ -8,10 +8,6 @@
#include <eosio/chain/producer_object.hpp>
#include <eosio/chain/permission_object.hpp>
#include <eosio/chain/wast_to_wasm.hpp>
#include <eosio.system/eosio.system.wast.hpp>
#include <eosio.system/eosio.system.abi.hpp>
#include <fc/io/json.hpp>
......@@ -171,15 +167,6 @@ abi_def chain_initializer::eos_contract_abi()
}
});
eos_abi.tables.emplace_back( table_def {
"currency", "i64", {
"key"
}, {
"name"
},
"account"
});
eos_abi.tables.emplace_back( table_def {
"recovery", "i64", {
"account",
......@@ -193,14 +180,8 @@ abi_def chain_initializer::eos_contract_abi()
return eos_abi;
}
// forward declared method from eosio contract
void intialize_eosio_tokens(chainbase::database& db, const account_name& system_account, share_type initial_tokens);
std::vector<action> chain_initializer::prepare_database( chain_controller& chain,
void chain_initializer::prepare_database( chain_controller& chain,
chainbase::database& db) {
std::vector<action> messages_to_process;
/// Create the native contract accounts manually; sadly, we can't run their contracts to make them create themselves
auto create_native_account = [this, &db](account_name name) {
db.create<account_object>([this, &name](account_object& a) {
......@@ -239,40 +220,6 @@ std::vector<action> chain_initializer::prepare_database( chain_controller& chain
};
create_native_account(config::system_account_name);
// Queue up messages which will run contracts to create the initial accounts
auto init_eosio_sytem = genesis_state_type::initial_account_type(name(config::eosio_system_account_name).to_string(), 0, 0, genesis.eosio_system_key, genesis.eosio_system_key);
genesis.initial_accounts.emplace_back(move(init_eosio_sytem));
for (const auto& acct : genesis.initial_accounts) {
action message( {{config::system_account_name, config::active_name}},
newaccount{ config::system_account_name, acct.name,
authority(acct.owner_key),
authority(acct.active_key),
authority(acct.owner_key)
});
messages_to_process.emplace_back(move(message));
}
// Create initial contracts eosio.system
auto wasm = wast_to_wasm(eosio_system_wast);
action eosio_system_setcode({{config::eosio_system_account_name, config::active_name}},
contracts::setcode{
.account = config::eosio_system_account_name,
.vmtype = 0,
.vmversion = 0,
.code = bytes(wasm.begin(), wasm.end())
});
auto abi = fc::json::from_string(eosio_system_abi).template as<contracts::abi_def>();
action eosio_system_setabi({{config::eosio_system_account_name, config::active_name}},
contracts::setabi{
.account = config::eosio_system_account_name,
.abi = abi
});
messages_to_process.emplace_back(move(eosio_system_setcode));
messages_to_process.emplace_back(move(eosio_system_setabi));
// Create special accounts
auto create_special_account = [this, &db](account_name name, const auto& owner, const auto& active) {
db.create<account_object>([this, &name](account_object& a) {
......@@ -299,8 +246,6 @@ std::vector<action> chain_initializer::prepare_database( chain_controller& chain
create_special_account(config::nobody_account_name, empty_authority, empty_authority);
create_special_account(config::producers_account_name, empty_authority, active_producers_authority);
return messages_to_process;
}
} } } // namespace eosio::chain::contracts
......@@ -17,7 +17,6 @@ namespace eosio { namespace chain {
*/
struct chain_config {
share_type producer_pay;
uint32_t target_block_size;
uint32_t max_block_size;
......@@ -46,7 +45,6 @@ inline bool operator!=(const chain_config& a, const chain_config& b) { return !(
} } // namespace eosio::chain
FC_REFLECT(eosio::chain::chain_config,
(producer_pay)
(target_block_size)
(max_block_size)
(target_block_acts_per_scope)
......
......@@ -18,7 +18,6 @@ const static uint64_t system_account_name = N(eosio);
const static uint64_t nobody_account_name = N(nobody);
const static uint64_t anybody_account_name = N(anybody);
const static uint64_t producers_account_name = N(producers);
const static uint64_t eosio_system_account_name = N(eosio.system);
const static uint64_t eosio_auth_scope = N(eosio.auth);
const static uint64_t eosio_all_scope = N(eosio.all);
......@@ -63,9 +62,6 @@ const static uint32_t default_max_gen_trx_count = 16; ///< the number of
const static uint32_t producers_authority_threshold = 14;
const static uint32_t rate_limiting_precision = 1000*1000;
const static share_type default_elected_pay = asset(100).amount;
const static share_type default_min_eos_balance = asset(100).amount;
const static uint16_t max_recursion_depth = 6;
/**
......@@ -80,9 +76,7 @@ const static int producer_repititions = 12;
//const static int blocks_per_round = producer_count * producer_repititions;
const static int irreversible_threshold_percent= 70 * percent_1;
const static int max_producer_votes = 30;
const static auto staked_balance_cooldown_sec = fc::days(3).to_seconds();
} } } // namespace eosio::chain::config
template<typename Number>
......
......@@ -22,8 +22,7 @@ namespace eosio { namespace chain { namespace contracts {
void register_types(chain::chain_controller& chain, chainbase::database& db);
std::vector<action> prepare_database(chain::chain_controller& chain, chainbase::database& db);
void prepare_database(chain::chain_controller& chain, chainbase::database& db);
static abi_def eos_contract_abi();
......
......@@ -43,7 +43,6 @@ struct genesis_state_type {
};
chain_config initial_configuration = {
.producer_pay = config::default_elected_pay,
.target_block_size = config::default_target_block_size,
.max_block_size = config::default_max_block_size,
.target_block_acts_per_scope = config::default_target_block_acts_per_scope,
......@@ -62,10 +61,6 @@ struct genesis_state_type {
time_point initial_timestamp;
public_key_type initial_key;
public_key_type eosio_system_key;
vector<initial_account_type> initial_accounts;
vector<initial_producer_type> initial_producers;
/**
* Temporary, will be moved elsewhere.
......
......@@ -10,8 +10,11 @@ target_link_libraries( eosio_testing eosio_chain eos_utilities fc chainbase Logg
target_include_directories( eosio_testing
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/../wasm-jit/Include"
"${CMAKE_BINARY_DIR}/contracts"
)
add_dependencies( eosio_testing test.system )
if(MSVC)
set_source_files_properties( db_init.cpp db_block.cpp database.cpp block_log.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
endif(MSVC)
......
......@@ -21,7 +21,7 @@ namespace eosio { namespace testing {
void close();
void open();
void create_init_accounts();
void push_genesis_block();
signed_block produce_block( fc::microseconds skip_time = fc::milliseconds(config::block_interval_ms) );
void produce_blocks( uint32_t n = 1 );
......@@ -31,20 +31,20 @@ namespace eosio { namespace testing {
action_result push_action(action&& cert_act, uint64_t authorizer);
void set_tapos( signed_transaction& trx ) const;
void create_accounts( vector<account_name> names, asset init_bal, bool multisig = false ) {
for( auto n : names ) create_account(n, init_bal, N(inita), multisig );
void create_accounts( vector<account_name> names, bool multisig = false ) {
for( auto n : names ) create_account(n, N(inita), multisig );
}
void set_authority( account_name account, permission_name perm, authority auth,
permission_name parent = config::owner_name );
void create_account( account_name name, asset initial_balance = asset(), account_name creator = N(inita), bool multisig = false );
void create_account( account_name name, string balance = "0.0000 EOS", account_name creator = N(inita), bool multisig = false );
void create_account( account_name name, account_name creator = config::system_account_name, bool multisig = false );
void create_account( account_name name, account_name creator = config::system_account_name, bool multisig = false );
transaction_trace push_nonce( account_name from, const string& role, const string& v = "blah" );
transaction_trace transfer( account_name from, account_name to, asset amount, string memo = "", account_name currency = config::eosio_system_account_name );
transaction_trace transfer( account_name from, account_name to, string amount, string memo = "", account_name currency = config::eosio_system_account_name );
transaction_trace transfer( account_name from, account_name to, asset amount, string memo = "", account_name currency );
transaction_trace transfer( account_name from, account_name to, string amount, string memo = "", account_name currency );
template<typename ObjectType, typename IndexBy, typename... Args>
const auto& get( Args&&... args ) {
......
......@@ -6,7 +6,8 @@
#include <eosio/chain/contracts/contract_table_objects.hpp>
#include <eosio/chain/contracts/abi_serializer.hpp>
#include <eosio.system/eosio.system.abi.hpp>
#include <test.system/test.system.wast.hpp>
#include <test.system/test.system.abi.hpp>
#include <fc/utility.hpp>
#include <fc/io/json.hpp>
......@@ -25,52 +26,15 @@ namespace eosio { namespace testing {
cfg.genesis.initial_timestamp = fc::time_point::from_iso_string("2020-01-01T00:00:00.000");
cfg.genesis.initial_key = get_public_key( config::system_account_name, "active" );
cfg.genesis.eosio_system_key = get_public_key( config::eosio_system_account_name, "active");
open();
if (process_genesis)
create_init_accounts();
push_genesis_block();
}
void tester::create_init_accounts() {
contracts::abi_def eosio_system_abi_def = fc::json::from_string(eosio_system_abi).as<contracts::abi_def>();
chain::contracts::abi_serializer eosio_system_serializer(eosio_system_abi_def);
signed_transaction trx;
set_tapos(trx);
action act;
act.account = config::eosio_system_account_name;
act.name = N(issue);
act.authorization = vector<permission_level>{{config::eosio_system_account_name,config::active_name}};
act.data = eosio_system_serializer.variant_to_binary("issue", fc::json::from_string("{\"to\":\"eosio.system\",\"quantity\":\"1000000000.0000 EOS\"}"));
trx.actions.push_back(act);
set_tapos(trx);
trx.sign( get_private_key( config::eosio_system_account_name, "active" ), chain_id_type() );
push_transaction(trx);
create_account(N(inita), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initb), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initc), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initd), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(inite), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initf), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initg), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(inith), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initi), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initj), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initk), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initl), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initm), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initn), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(inito), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initp), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initq), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initr), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(inits), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initt), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initu), "1000000.0000 EOS", config::eosio_system_account_name);
void tester::push_genesis_block() {
set_code(config::eosio_system_account_name, test_system_wast);
set_abi(config::eosio_system_account_name, test_system_abi);
}
public_key_type tester::get_public_key( name keyname, string role ) const {
......
#include <boost/test/unit_test.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/chain/contracts/abi_serializer.hpp>
using namespace eosio;
using namespace eosio::chain;
using namespace eosio::chain::contracts;
using namespace eosio::testing;
struct auth_tester : tester {
transaction_trace tester::push_nonce(account_name from, std::initializer_list<permission_level> &&permissions, std::initializer_list<private_key_type> &&sign_with) {
variant pretty_trx = fc::mutable_variant_object()
("actions", fc::variants({
fc::mutable_variant_object()
("account", name(config::system_account_name))
("name", "nonce")
("authorization", vector<permission_level>(permissions))
("data", fc::mutable_variant_object()
("value", v)
)
})
);
signed_transaction trx;
auto resolve = [this](const account_name& name) -> optional<contracts::abi_serializer> {
return resolver(*this, name);
};
contracts::abi_serializer::from_variant(pretty_trx, trx, resolve);
set_tapos( trx );
for(const auto& iter = sign_with.begin(); iter != sign_with.end(); ++iter)
trx.sign( *iter );
return push_transaction( trx );
}
};
BOOST_AUTO_TEST_SUITE(auth_tests)
BOOST_FIXTURE_TEST_CASE( missing_sigs, auth_tester ) { try {
create_accounts( {N(alice)} );
produce_block();
BOOST_REQUIRE_THROW( push_nonce( N(alice), {permission_level{N(alice), config::active_name}}, {} ), tx_missing_sigs );
auto trace = push_nonce(N(alice), {permission_level{N(alice), config::active_name}}, { get_private_key(N(alice), "active", chain_id_type()) } );
produce_block();
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace.id));
} FC_LOG_AND_RETHROW() } /// missing_sigs
BOOST_FIXTURE_TEST_CASE( missing_auths, auth_tester ) { try {
create_accounts( {N(alice)} );
produce_block();
/// action not provided from authority
BOOST_REQUIRE_THROW( push_nonce( N(alice), {permission_level{N(bob), config::active_name}}, { get_private_key(N(alice), "active", chain_id_type()) } ), tx_missing_auth);
} FC_LOG_AND_RETHROW() } /// transfer_test
/**
* 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( delegate_auth, auth_tester ) { try {
test.create_accounts( {N(alice),N(bob)});
test.produce_block();
auto delegated_auth = authority( 1, {},
{
{ .permission = {N(bob),config::active_name}, .weight = 1}
});
set_authority( N(alice), config::active_name, delegated_auth );
produce_block( fc::hours(2) ); ///< skip 2 hours
/// execute nonce from alice signed by bob
auto trace = push_nonce(N(alice), {permission_level{N(alice), config::active_name}}, { get_private_key(N(bob), "active", chain_id_type()) } );
produce_block();
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace.id));
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_SUITE_END()
#include <boost/test/unit_test.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/chain/contracts/abi_serializer.hpp>
using namespace eosio;
using namespace eosio::chain;
using namespace eosio::chain::contracts;
using namespace eosio::testing;
BOOST_AUTO_TEST_SUITE(transfer_tests)
BOOST_AUTO_TEST_CASE( transfer_test ) { try {
tester test;
test.produce_blocks(1000);
test.create_accounts( {N(dan), N(bart)}, asset::from_string("100.0000 EOS") );
test.transfer( N(inita), N(dan), "10.0000 EOS", "memo" );
{
const asset dans_balance( test.get_balance( N(dan) ) );
FC_ASSERT( dans_balance == asset::from_string("110.0000 EOS") );
}
test.produce_block();
{
const asset dans_balance( test.get_balance( N(dan) ) );
FC_ASSERT( dans_balance == asset::from_string("110.0000 EOS") );
}
/// insufficient funds
BOOST_REQUIRE_THROW(test.transfer(N(dan),N(bart), "111.0000 EOS", "memo"), assert_exception);
/// this should succeed because dan has sufficient balance
test.transfer(N(dan),N(bart), "110.0000 EOS", "memo");
/// verify that bart now has 110.000 + 100.000
const asset barts_balance( test.get_balance( N(bart) ) );
FC_ASSERT( barts_balance == asset::from_string("210.0000 EOS") );
{
/// verify that dan now has 0.000
const asset dans_balance( test.get_balance( N(dan) ) );
FC_ASSERT( dans_balance == asset::from_string("0.0000 EOS") );
}
/// should throw because -1 becomes uint64 max which is greater than balance
BOOST_REQUIRE_THROW(test.transfer(N(bart),N(dan), asset(-1), "memo"), assert_exception);
auto resolver = [&]( const account_name& name ) -> optional<abi_serializer> {
try {
const auto& accnt = test.control->get_database().get<account_object,by_name>( name );
abi_def abi;
if (abi_serializer::to_abi(accnt.abi, abi)) {
return abi_serializer(abi);
}
return optional<abi_serializer>();
} FC_RETHROW_EXCEPTIONS(error, "Failed to find or parse ABI for ${name}", ("name", name))
};
{
auto from = N(bart);
auto to = N(dan);
asset amount(1);
variant pretty_trx = mutable_variant_object()
("actions", variants({
mutable_variant_object()
("account", name(config::eosio_system_account_name))
("name", "transfer")
("authorization", variants({
mutable_variant_object()
("actor", "bart")
("permission", name(config::active_name).to_string())
}))
("data", mutable_variant_object()
("from", "bart")
("to", "dan")
("quantity", amount)
("memo", "memo")
)
})
);
signed_transaction trx;
abi_serializer::from_variant(pretty_trx, trx, resolver);
test.set_tapos( trx );
BOOST_REQUIRE_THROW( test.push_transaction( trx ), tx_missing_sigs );
trx.sign( test.get_private_key( from, "active" ), chain_id_type() );
test.push_transaction( trx );
}
{
auto from = N(bart);
auto to = N(dan);
asset amount(1);
variant pretty_trx = mutable_variant_object()
("actions", variants({
mutable_variant_object()
("account", name(config::eosio_system_account_name))
("name", "transfer")
("authorization", variants({
mutable_variant_object()
("actor", "dan")
("permission", name(config::active_name).to_string())
}))
("data", mutable_variant_object()
("from", "bart")
("to", "dan")
("quantity", amount)
("memo", "memo")
)
})
);
signed_transaction trx;
abi_serializer::from_variant(pretty_trx, trx, resolver);
test.set_tapos( trx );
trx.sign( test.get_private_key( to, "active" ), chain_id_type() );
/// action not provided from authority
BOOST_REQUIRE_THROW( test.push_transaction( trx ), tx_missing_auth);
}
} FC_LOG_AND_RETHROW() } /// transfer_test
/**
* This test case will attempt to allow one account to transfer on behalf
* of another account by updating the active authority.
*/
BOOST_AUTO_TEST_CASE( transfer_delegation ) { try {
tester test;
test.produce_blocks(1000);
test.create_accounts( {N(dan),N(bart),N(trust)}, asset::from_string("100.0000 EOS") );
test.transfer( N(inita), N(dan), "10.0000 EOS" );
test.transfer( N(inita), N(trust), "10.0000 EOS" );
test.transfer( N(trust), N(dan), "1.0000 EOS" );
test.produce_block();
auto dans_active_auth = authority( 1, {},
{
{ .permission = {N(trust),config::active_name}, .weight = 1}
});
test.set_authority( N(dan), config::active_name, dans_active_auth );
const auto& danauth = test.control->get_permission( permission_level{N(dan),config::active_name} );
const auto& trustauth = test.control->get_permission( permission_level{N(trust),config::active_name} );
test.produce_block( fc::hours(2) ); ///< skip 2 hours
auto resolver = [&]( const account_name& name ) -> optional<abi_serializer> {
try {
const auto& accnt = test.control->get_database().get<account_object,by_name>( name );
abi_def abi;
if (abi_serializer::to_abi(accnt.abi, abi)) {
return abi_serializer(abi);
}
return optional<abi_serializer>();
} FC_RETHROW_EXCEPTIONS(error, "Failed to find or parse ABI for ${name}", ("name", name))
};
/// execute a transfer from dan to bart signed by trust
{
auto from = N(bart);
auto to = N(dan);
asset amount(1);
variant pretty_trx = mutable_variant_object()
("actions", variants({
mutable_variant_object()
("account", name(config::eosio_system_account_name))
("name", "transfer")
("authorization", variants({
mutable_variant_object()
("actor", "dan")
("permission", name(config::active_name).to_string())
}))
("data", mutable_variant_object()
("from", "dan")
("to", "trust")
("quantity", amount)
("memo", "memo")
)
})
);
signed_transaction trx;
abi_serializer::from_variant(pretty_trx, trx, resolver);
test.set_tapos( trx );
trx.sign( test.get_private_key( N(trust), "active" ), chain_id_type() );
wdump((fc::raw::pack_size(trx)));
/// action not provided from authority
test.push_transaction( trx );
}
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_SUITE_END()
......@@ -1411,7 +1411,6 @@ BOOST_AUTO_TEST_CASE(general)
"accounts":[{"permission":{"actor":"acc1","permission":"permname1"},"weight":"1"},{"permission":{"actor":"acc2","permission":"permname2"},"weight":"2"}]
}],
"chainconfig": {
"producer_pay": "100",
"target_block_size": "200",
"max_block_size": "300",
"target_block_acts_per_scope": "400",
......@@ -1428,7 +1427,6 @@ BOOST_AUTO_TEST_CASE(general)
"max_generated_transaction_size": "1500"
},
"chainconfig_arr": [{
"producer_pay": "100",
"target_block_size": "200",
"max_block_size": "300",
"target_block_acts_per_scope": "400",
......@@ -1444,7 +1442,6 @@ BOOST_AUTO_TEST_CASE(general)
"max_inline_action_size": "1400",
"max_generated_transaction_size": "1500"
},{
"producer_pay": "100",
"target_block_size": "200",
"max_block_size": "300",
"target_block_acts_per_scope": "400",
......
......@@ -9,6 +9,7 @@
#include <Runtime/Runtime.h>
#include <fc/variant_object.hpp>
#include <fc/io/json.hpp>
using namespace eosio;
using namespace eosio::chain;
......@@ -16,161 +17,181 @@ using namespace eosio::chain::contracts;
using namespace eosio::testing;
using namespace fc;
struct issue {
static uint64_t get_account(){ return N(currency); }
static uint64_t get_name(){ return N(issue); }
account_name to;
asset quantity;
class currency_tester : tester {
public:
currency_tester()
:tester()
,abi_ser(json::from_string(currency_abi).as<abi_def>())
{
const auto token_supply = asset::from_string("1000000.0000 CUR");
create_account( N(currency));
set_code( N(currency), currency_wast );
push_action(N(currency), N(transfer), {{N(currency), config::active_name}}, mutable_variant_object()
("to", "currency")
("quantity", "1000000.0000 CUR")
);
produce_block();
}
auto push_action(const account_name& signer, const action_name &name, const variant_object &data ) {
string action_type_name = abi_ser.get_action_type(name);
action act;
act.account = N(currency);
act.name = name;
act.authorization = vector<permission_level>{{signer, config::active_name}};
act.data = abi_ser.variant_to_binary(action_type_name, data);
signed_transaction trx;
trx.actions.emplace_back(std::move(act));
set_tapos(trx);
trx.sign(get_private_key(signer, "active"), chain_id_type());
return push_transaction(trx);
}
auto get_balance(const account_name& account) const {
return get_currency_balance(N(currency), SY(4,CUR), account);
}
abi_serializer abi_ser;
};
FC_REFLECT( issue, (to)(quantity) )
BOOST_AUTO_TEST_SUITE(currency_tests)
BOOST_FIXTURE_TEST_CASE( test_generic_currency, tester ) try {
produce_blocks(2000);
create_accounts( {N(currency), N(usera), N(userb)}, asset::from_string("1000.0000 EOS") );
produce_blocks(2);
set_code( N(currency), currency_wast );
produce_blocks(2);
auto expected = asset::from_string( "10.0000 CUR" );
BOOST_AUTO_TEST_CASE( bootstrap ) try {
auto expected = asset::from_string( "1000000.0000 CUR" );
currency_tester t;
auto actual = t.get_currency_balance(N(currency), expected.get_symbol(), N(currency));
BOOST_REQUIRE_EQUAL(expected, actual);
} FC_LOG_AND_RETHROW() /// test_api_bootstrap
BOOST_FIXTURE_TEST_CASE( test_transfer, currency_tester ) try {
create_accounts( {N(alice)} );
// make a transfer from the contract to a user
{
signed_transaction trx;
trx.actions.emplace_back(vector<permission_level>{{N(currency), config::active_name}},
issue{ .to = N(usera),
.quantity = expected
});
auto trace = push_action(N(currency), N(transfer), mutable_variant_object()
("from", "currency")
("to", "alice")
("quantity", "100.0000 CUR")
("memo", "fund Alice")
);
set_tapos(trx);
trx.sign(get_private_key(N(currency), "active"), chain_id_type());
auto result = push_transaction(trx);
for( const auto& act : result.action_traces )
std::cerr << act.console << "\n";
produce_block();
auto actual = get_currency_balance(N(currency), expected.get_symbol(), N(usera));
BOOST_REQUIRE_EQUAL(expected, actual);
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace.id));
BOOST_REQUIRE_EQUAL(get_balance(N(alice)), asset::from_string( "100.0000 CUR" ));
}
} FC_LOG_AND_RETHROW() /// test_transfer
} FC_LOG_AND_RETHROW() /// test_api_bootstrap
BOOST_FIXTURE_TEST_CASE( test_addtransfer, currency_tester ) try {
create_accounts( {N(alice)} );
BOOST_FIXTURE_TEST_CASE( test_currency, tester ) try {
produce_blocks(2000);
create_accounts( {N(currency), N(alice), N(bob)}, asset::from_string("1000.0000 EOS") );
transfer( N(inita), N(currency), "10.0000 EOS", "memo" );
produce_block();
set_code(N(currency), currency_wast);
set_abi(N(currency), currency_abi);
produce_blocks(1);
const auto& accnt = control->get_database().get<account_object,by_name>( N(currency) );
abi_def abi;
BOOST_REQUIRE_EQUAL(abi_serializer::to_abi(accnt.abi, abi), true);
abi_serializer abi_ser(abi);
const auto token_supply = asset::from_string("1000000.0000 CUR");
// issue tokens
{
signed_transaction trx;
action issue_act;
issue_act.account = N(currency);
issue_act.name = N(issue);
issue_act.authorization = vector<permission_level>{{N(currency), config::active_name}};
issue_act.data = abi_ser.variant_to_binary("issue", mutable_variant_object()
("to", "currency")
("quantity", "1000000.0000 CUR")
// make a transfer from the contract to a user
{
auto trace = push_action(N(currency), N(transfer), mutable_variant_object()
("from", "currency")
("to", "alice")
("quantity", "100.0000 CUR")
("memo", "fund Alice")
);
trx.actions.emplace_back(std::move(issue_act));
set_tapos(trx);
trx.sign(get_private_key(N(currency), "active"), chain_id_type());
push_transaction(trx);
produce_block();
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.get_symbol(), N(currency)), asset::from_string( "1000000.0000 CUR" ));
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace.id));
BOOST_REQUIRE_EQUAL(get_balance(N(alice)), asset::from_string( "100.0000 CUR" ));
}
// make a transfer from the contract to a user
{
signed_transaction trx;
action transfer_act;
transfer_act.account = N(currency);
transfer_act.name = N(transfer);
transfer_act.authorization = vector<permission_level>{{N(currency), config::active_name}};
transfer_act.data = abi_ser.variant_to_binary("transfer", mutable_variant_object()
auto trace = push_action(N(currency), N(transfer), mutable_variant_object()
("from", "currency")
("to", "alice")
("quantity", "10.0000 CUR")
("memo", "add Alice")
);
produce_block();
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace.id));
BOOST_REQUIRE_EQUAL(get_balance(N(alice)), asset::from_string( "110.0000 CUR" ));
}
} FC_LOG_AND_RETHROW() /// test_transfer
BOOST_FIXTURE_TEST_CASE( test_overspend, currency_tester ) try {
create_accounts( {N(alice), N(bob)} );
// make a transfer from the contract to a user
{
auto trace = push_action(N(currency), N(transfer), mutable_variant_object()
("from", "currency")
("to", "alice")
("quantity", "100.0000 CUR")
("memo", "fund Alice")
);
trx.actions.emplace_back(std::move(transfer_act));
set_tapos(trx);
trx.sign(get_private_key(N(currency), "active"), chain_id_type());
push_transaction(trx);
produce_block();
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.get_symbol(), N(alice)), asset::from_string( "100.0000 CUR" ));
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace.id));
BOOST_REQUIRE_EQUAL(get_balance(N(alice)), asset::from_string( "100.0000 CUR" ));
}
// Overspend!
{
signed_transaction trx;
action transfer_act;
transfer_act.account = N(currency);
transfer_act.name = N(transfer);
transfer_act.authorization = vector<permission_level>{{N(alice), config::active_name}};
transfer_act.data = abi_ser.variant_to_binary("transfer", mutable_variant_object()
variant_object data = mutable_variant_object()
("from", "alice")
("to", "bob")
("quantity", "101.0000 CUR")
("memo", "overspend! Alice")
("memo", "overspend! Alice");
BOOST_CHECK_EXCEPTION(push_action(N(alice), N(transfer), data), fc::assert_exception, assert_message_is("integer underflow subtracting token balance"));
produce_block();
BOOST_REQUIRE_EQUAL(get_balance(N(alice)), asset::from_string( "100.0000 CUR" ));
BOOST_REQUIRE_EQUAL(get_balance(N(bob)), asset::from_string( "0.0000 CUR" ));
}
} FC_LOG_AND_RETHROW() /// test_overspend
BOOST_FIXTURE_TEST_CASE( test_fullspend, currency_tester ) try {
create_accounts( {N(alice), N(bob)} );
// make a transfer from the contract to a user
{
auto trace = push_action(N(currency), N(transfer), mutable_variant_object()
("from", "currency")
("to", "alice")
("quantity", "100.0000 CUR")
("memo", "fund Alice")
);
trx.actions.emplace_back(std::move(transfer_act));
set_tapos(trx);
trx.sign(get_private_key(N(alice), "active"), chain_id_type());
BOOST_CHECK_EXCEPTION(push_transaction(trx), fc::assert_exception, assert_message_is("integer underflow subtracting token balance"));
produce_block();
BOOST_REQUIRE_EQUAL(false, chain_has_transaction(trx.id()));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.get_symbol(), N(alice)), asset::from_string( "100.0000 CUR" ));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.get_symbol(), N(bob)), asset::from_string( "0.0000 CUR" ));
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace.id));
BOOST_REQUIRE_EQUAL(get_balance(N(alice)), asset::from_string( "100.0000 CUR" ));
}
// Full spend
{
signed_transaction trx;
action transfer_act;
transfer_act.account = N(currency);
transfer_act.name = N(transfer);
transfer_act.authorization = vector<permission_level>{{N(alice), config::active_name}};
transfer_act.data = abi_ser.variant_to_binary("transfer", mutable_variant_object()
variant_object data = mutable_variant_object()
("from", "alice")
("to", "bob")
("quantity", "100.0000 CUR")
("memo", "all in! Alice")
);
trx.actions.emplace_back(std::move(transfer_act));
("memo", "all in! Alice");
set_tapos(trx);
trx.sign(get_private_key(N(alice), "active"), chain_id_type());
push_transaction(trx);
auto trace = push_action(push_action(N(alice), N(transfer), data);
produce_block();
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.get_symbol(), N(alice)), asset::from_string( "0.0000 CUR" ));
BOOST_REQUIRE_EQUAL(get_currency_balance(N(currency), token_supply.get_symbol(), N(bob)), asset::from_string( "100.0000 CUR" ));
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trace.id));
BOOST_REQUIRE_EQUAL(get_balance(N(alice)), asset::from_string( "0.0000 CUR" ));
BOOST_REQUIRE_EQUAL(get_balance(N(bob)), asset::from_string( "100.0000 CUR" ));
}
} FC_LOG_AND_RETHROW() /// test_currency
} FC_LOG_AND_RETHROW() /// test_fullspend
BOOST_FIXTURE_TEST_CASE(test_symbol, tester) try {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册