diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index 457eb309c7685afac0ce1bd9f8529ee23a4cc57a..8727580828c59576f33cb1e790aea43eba190d32 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -1,7 +1,8 @@ add_subdirectory( fc ) add_subdirectory( chainbase ) add_subdirectory( wasm-jit ) -add_subdirectory( chain ) add_subdirectory( egenesis ) add_subdirectory( utilities ) add_subdirectory( appbase ) +add_subdirectory( chain ) +add_subdirectory( testing ) diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index c40e8cbcd0ab3d64b520394551b9ef942f83f4e8..6ef59f020c19b610f48c67ef44f8037da0b5bd69 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -46,7 +46,7 @@ INSTALL( TARGETS LIBRARY DESTINATION lib ARCHIVE DESTINATION lib ) -INSTALL( FILES ${HEADERS} DESTINATION "include/eos/chain" ) +INSTALL( FILES ${HEADERS} DESTINATION "include/eosio/chain" ) -add_executable( test test.cpp ) -target_link_libraries( test eos_chain ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ${Intl_LIBRARIES} ) +#add_executable( test test.cpp ) +#target_link_libraries( test eos_chain ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ${Intl_LIBRARIES} ) diff --git a/libraries/chain/chain_controller.cpp b/libraries/chain/chain_controller.cpp index 7707ee7b76803310d7dbdb87f798d3106bf60656..b6b1a935da7fcb429b49fd95ff14134b26b34467 100644 --- a/libraries/chain/chain_controller.cpp +++ b/libraries/chain/chain_controller.cpp @@ -256,13 +256,11 @@ void chain_controller::_push_transaction(const signed_transaction& trx) { auto temp_session = _db.start_undo_session(true); -#if 0 validate_referenced_accounts(trx); check_transaction_authorization(trx); - /*auto pt = */_apply_transaction(trx); - _pending_transactions.push_back(trx); + _apply_transaction(trx); +// _pending_transactions.push_back(trx); -#endif // notify_changed_objects(); // The transaction applied successfully. Merge its changes into the pending block session. diff --git a/libraries/chain/contracts/chain_initializer.cpp b/libraries/chain/contracts/chain_initializer.cpp index f9bdd7d123c8564f9d5204859105286fa150d628..e0572a8df43203472d4c4f832b29ba6d3b14b45f 100644 --- a/libraries/chain/contracts/chain_initializer.cpp +++ b/libraries/chain/contracts/chain_initializer.cpp @@ -235,11 +235,11 @@ std::vector chain_initializer::prepare_database( chain_controller& chain // Queue up messages which will run contracts to create the initial accounts for (const auto& acct : genesis.initial_accounts) { action message( {{config::system_account_name, config::active_name}}, - newaccount( config::system_account_name, acct.name, + newaccount{ config::system_account_name, acct.name, authority(acct.owner_key), authority(acct.active_key), authority(acct.owner_key), - acct.staking_balance)); + acct.staking_balance}); messages_to_process.emplace_back(move(message)); diff --git a/libraries/chain/contracts/eos_contract.cpp b/libraries/chain/contracts/eos_contract.cpp index b5c96d7324851c90d7856f0f6e0932fcc11a2f78..8a761d72e13aafbd0dc8377a99992e2c32ff1c30 100644 --- a/libraries/chain/contracts/eos_contract.cpp +++ b/libraries/chain/contracts/eos_contract.cpp @@ -491,7 +491,7 @@ void apply_eosio_unlinkauth(apply_context& context) { db.remove(*link); } -void apply_eos_nonce(apply_context&) { +void apply_eosio_nonce(apply_context&) { /// do nothing } diff --git a/libraries/chain/include/eosio/chain/config.hpp b/libraries/chain/include/eosio/chain/config.hpp index 4dc93bf828d61cca29462cc7e49b89f221d48179..14c9db3548f4901b8688fc65d2517e0e41f69e24 100644 --- a/libraries/chain/include/eosio/chain/config.hpp +++ b/libraries/chain/include/eosio/chain/config.hpp @@ -19,6 +19,7 @@ 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_auth_scope = N(eosio.auth); const static uint64_t active_name = N(active); const static uint64_t owner_name = N(owner); diff --git a/libraries/chain/include/eosio/chain/contracts/types.hpp b/libraries/chain/include/eosio/chain/contracts/types.hpp index 5ca9d0fadf15648195cda59fd7275df5686d6060..19d57e3a931b7ae3ade67338d7e2b6e9bbf3767e 100644 --- a/libraries/chain/include/eosio/chain/contracts/types.hpp +++ b/libraries/chain/include/eosio/chain/contracts/types.hpp @@ -178,10 +178,12 @@ struct claim { }; struct newaccount { + /* newaccount() = default; newaccount(const account_name& creator, const account_name& name, const authority& owner, const authority& active, const authority& recovery, const asset& deposit) :creator(creator), name(name), owner(owner), active(active), recovery(recovery), deposit(deposit) {} + */ account_name creator; account_name name; diff --git a/libraries/chain/include/eosio/chain/wasm_interface.hpp b/libraries/chain/include/eosio/chain/wasm_interface.hpp index d9fc5a402cc8984efcb860ae281797514d843dae..9768fe058d0f027a1a4b84f20cc1eb7ffa26efb1 100644 --- a/libraries/chain/include/eosio/chain/wasm_interface.hpp +++ b/libraries/chain/include/eosio/chain/wasm_interface.hpp @@ -55,6 +55,10 @@ namespace eosio { namespace chain { */ void apply( apply_context& context ); + /** + */ + void error( apply_context& context ); + private: wasm_interface(); unique_ptr my; diff --git a/libraries/chain/wasm_interface.cpp b/libraries/chain/wasm_interface.cpp index 445d97ee8986f05a1a77d354d29596633cac4eec..029f3d69ab9558f008dd37b5b1415211afefae69 100644 --- a/libraries/chain/wasm_interface.cpp +++ b/libraries/chain/wasm_interface.cpp @@ -216,6 +216,10 @@ namespace eosio { namespace chain { std::cerr << name(val).to_string(); } + + + + DEFINE_INTRINSIC_FUNCTION1(env,prints,prints,none,i32,charptr) { auto& wasm = wasm_interface::get(); auto mem = wasm.memory(); diff --git a/libraries/testing/CMakeLists.txt b/libraries/testing/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..893ca21a4cdf8e2aa54ffe62061d791997a54098 --- /dev/null +++ b/libraries/testing/CMakeLists.txt @@ -0,0 +1,29 @@ +file(GLOB HEADERS "include/eosio/tester/*.hpp") + +## SORT .cpp by most likely to change / break compile +add_library( eosio_testing + tester.cpp + ${HEADERS} + ) + +target_link_libraries( eosio_testing eos_chain eos_utilities fc chainbase Logging IR WAST WASM Runtime ) +target_include_directories( eosio_testing + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include" + "${CMAKE_CURRENT_SOURCE_DIR}/../wasm-jit/Include" + ) + +if(MSVC) + set_source_files_properties( db_init.cpp db_block.cpp database.cpp block_log.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) +endif(MSVC) + +INSTALL( TARGETS + eosio_testing + + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) +INSTALL( FILES ${HEADERS} DESTINATION "include/eos/chain" ) + +add_executable( runtest main.cpp ) +target_link_libraries( runtest eosio_testing ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ${Intl_LIBRARIES} ) diff --git a/libraries/testing/include/eosio/testing/tester.hpp b/libraries/testing/include/eosio/testing/tester.hpp new file mode 100644 index 0000000000000000000000000000000000000000..307f14f33c0ab50c6194ec57af31619e093677a0 --- /dev/null +++ b/libraries/testing/include/eosio/testing/tester.hpp @@ -0,0 +1,39 @@ +#pragma once +#include + +namespace eosio { namespace testing { + + using namespace eosio::chain; + + + /** + * @class tester + * @brief provides utility function to simplify the creation of unit tests + */ + class tester { + public: + tester(); + + void close(); + void open(); + + signed_block produce_block( fc::microseconds skip_time = fc::milliseconds(config::block_interval_ms) ); + void produce_blocks( uint32_t n = 1 ); + + void push_transaction( signed_transaction& trx ); + void set_tapos( signed_transaction& trx ); + + void create_account( account_name name, asset initial_balance = asset(), account_name creator = N(inita) ); + void create_account( account_name name, string balance = "0.0000 EOS", account_name creator = N(inita)); + + public_key_type get_public_key( name keyname, string role = "owner" ); + private_key_type get_private_key( name keyname, string role = "owner" ); + + unique_ptr control; + + private: + fc::temp_directory tempdir; + chain_controller::controller_config cfg; + }; + +} } /// eosio::testing diff --git a/libraries/testing/main.cpp b/libraries/testing/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ef5c88c096d04d080cc3ecd1d838380b393a27f --- /dev/null +++ b/libraries/testing/main.cpp @@ -0,0 +1,17 @@ +#include + +using namespace eosio; +using namespace eosio::testing; + +int main( int argc, char** argv ) { + + try { + tester test; + test.produce_blocks(50); + + test.create_account( N(dan), "100.0000 EOS" ); + + } catch ( const fc::exception& e ) { + elog("${e}", ("e",e.to_detail_string()) ); + } +} diff --git a/libraries/testing/tester.cpp b/libraries/testing/tester.cpp new file mode 100644 index 0000000000000000000000000000000000000000..133cc51776c4e37f0181afc5cbe1ecafd98eeb4c --- /dev/null +++ b/libraries/testing/tester.cpp @@ -0,0 +1,97 @@ +#include +#include +#include + +namespace eosio { namespace testing { + + + tester::tester() { + cfg.block_log_dir = tempdir.path() / "blocklog"; + cfg.shared_memory_dir = tempdir.path() / "shared"; + cfg.shared_memory_size = 1024*1024*8; + + cfg.genesis.initial_timestamp = fc::time_point::from_iso_string("2020-01-01T00:00:00.000"); + cfg.genesis.initial_accounts.resize( config::producer_count ); + cfg.genesis.initial_producers.resize( config::producer_count ); + + uint64_t init_name = N(inita); + for( uint32_t i = 0; i < config::producer_count; ++i ) { + auto pubkey = get_public_key(init_name); + cfg.genesis.initial_accounts[i].name = string(account_name(init_name)); + cfg.genesis.initial_accounts[i].owner_key = get_public_key(init_name,"owner"); + cfg.genesis.initial_accounts[i].active_key = get_public_key(init_name,"active"); + cfg.genesis.initial_accounts[i].liquid_balance = asset::from_string( "1000000.0000 EOS" ); + cfg.genesis.initial_accounts[i].staking_balance = asset::from_string( "1000000.0000 EOS" ); + cfg.genesis.initial_producers[i].owner_name = string(account_name(init_name)); + cfg.genesis.initial_producers[i].block_signing_key = get_public_key( init_name, "producer" ); + + init_name++; + } + open(); + } + + public_key_type tester::get_public_key( name keyname, string role ) { + return get_private_key( keyname, role ).get_public_key(); + } + + private_key_type tester::get_private_key( name keyname, string role ) { + return private_key_type::regenerate(fc::sha256::hash(string(keyname)+role)); + } + + void tester::close() { + control.reset(); + } + void tester::open() { + control.reset( new chain_controller(cfg) ); + } + + signed_block tester::produce_block( fc::microseconds skip_time ) { + 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, "producer" ); + + return control->generate_block( next_time, sch_pro, priv_key ); + } + + + void tester::produce_blocks( uint32_t n ) { + for( uint32_t i = 0; i < n; ++i ) + produce_block(); + } + + void tester::set_tapos( signed_transaction& trx ) { + trx.set_reference_block( control->head_block_id() ); + } + + + void tester::create_account( account_name a, asset initial_balance, account_name creator ) { + signed_transaction trx; + set_tapos( trx ); + trx.write_scope = { creator, config::eosio_auth_scope }; + + trx.actions.emplace_back( vector{{creator,config::active_name}}, contracts::newaccount{ + .creator = creator, + .name = a, + .owner = authority( get_public_key( a, "owner" ) ), + .active = authority( get_public_key( a, "active" ) ), + .recovery = authority( get_public_key( a, "recovery" ) ), + .deposit = initial_balance + }); + trx.sign( get_private_key( creator, "active" ), chain_id_type() ); + + push_transaction(trx); + } + + void tester::push_transaction( signed_transaction& trx ) { + set_tapos(trx); + control->push_transaction( trx ); + } + + void tester::create_account( account_name a, string initial_balance, account_name creator ) { + create_account( a, asset::from_string(initial_balance), creator ); + } + + +} } /// eosio::test