From 4cfcb97ba2668d683e2fdc1b12199566a7ef9e15 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Sun, 23 Apr 2017 14:18:51 -0400 Subject: [PATCH] Refactor Sys Contract - make account names, permissions, and message types fixed strings - move sys_contract implementation to separate cpp file - disable deprecated warnings on OS X - define authority class --- CMakeLists.txt | 2 +- libraries/chain/CMakeLists.txt | 1 + libraries/chain/database.cpp | 45 +++++-------------- .../include/eos/chain/account_object.hpp | 12 +++++ .../chain/include/eos/chain/database.hpp | 14 +++--- .../include/eos/chain/protocol/authority.hpp | 26 +++++++++++ .../eos/chain/protocol/transaction.hpp | 2 +- .../include/eos/chain/protocol/types.hpp | 10 +++-- .../chain/include/eos/chain/sys_contract.hpp | 12 ++++- libraries/chain/sys_contract.cpp | 35 +++++++++++++++ tests/tests/block_tests.cpp | 4 +- 11 files changed, 113 insertions(+), 50 deletions(-) create mode 100644 libraries/chain/include/eos/chain/protocol/authority.hpp create mode 100644 libraries/chain/sys_contract.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 206e73392..6244500fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,7 +111,7 @@ else( WIN32 ) # Apple AND Linux if( APPLE ) # Apple Specific Options Here message( STATUS "Configuring Eos on OS X" ) - set( CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -Wall" ) + set( CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-deprecated-declarations" ) else( APPLE ) # Linux Specific Options Here message( STATUS "Configuring Eos on Linux" ) diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index 1c76bb228..61b75518e 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -5,6 +5,7 @@ file(GLOB PROTOCOL_HEADERS "include/eos/chain/protocol/*.hpp") ## SORT .cpp by most likely to change / break compile add_library( eos_chain database.cpp + sys_contract.cpp fork_database.cpp protocol/types.cpp diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index 6e2cd1cb8..6005a5597 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -520,7 +520,7 @@ try { message_validate_context mvc( trx, m ); auto contract_handlers_itr = message_validate_handlers.find( m.recipient ); if( contract_handlers_itr != message_validate_handlers.end() ) { - auto message_handelr_itr = contract_handlers_itr->second.find( m.recipient + '/' + m.type ); + auto message_handelr_itr = contract_handlers_itr->second.find( {m.recipient, m.type} ); if( message_handelr_itr != contract_handlers_itr->second.end() ) { message_handelr_itr->second(mvc); continue; @@ -535,7 +535,7 @@ void database::validate_message_precondition( precondition_validate_context& con const auto& m = context.msg; auto contract_handlers_itr = precondition_validate_handlers.find( context.receiver ); if( contract_handlers_itr != precondition_validate_handlers.end() ) { - auto message_handelr_itr = contract_handlers_itr->second.find( m.recipient + "/" + m.type ); + auto message_handelr_itr = contract_handlers_itr->second.find( {m.recipient, m.type} ); if( message_handelr_itr != contract_handlers_itr->second.end() ) { message_handelr_itr->second(context); return; @@ -548,7 +548,7 @@ void database::apply_message( apply_context& context ) { const auto& m = context.msg; auto contract_handlers_itr = apply_handlers.find( context.receiver ); if( contract_handlers_itr != apply_handlers.end() ) { - auto message_handelr_itr = contract_handlers_itr->second.find( m.recipient + "/" + m.type ); + auto message_handelr_itr = contract_handlers_itr->second.find( {m.recipient, m.type} ); if( message_handelr_itr != contract_handlers_itr->second.end() ) { message_handelr_itr->second(context); return; @@ -697,32 +697,6 @@ void database::initialize_indexes() { void database::init_genesis(const genesis_state_type& genesis_state) { try { - set_validate_handler( "sys", "sys/Transfer", [&]( message_validate_context& context ) { - idump((context.msg)); - auto transfer = context.msg.as(); - FC_ASSERT( context.msg.has_notify( transfer.to ), "Must notify recipient of transfer" ); - }); - - set_precondition_validate_handler( "sys", "sys/Transfer", [&]( precondition_validate_context& context ) { - idump((context.msg)(context.receiver)); - auto transfer = context.msg.as(); - const auto& from = get_account( transfer.from ); - FC_ASSERT( from.balance > transfer.amount, "Insufficient Funds", - ("from.balance",from.balance)("transfer.amount",transfer.amount) ); - }); - - set_apply_handler( "sys", "sys/Transfer", [&]( apply_context& context ) { - idump((context.msg)(context.receiver)); - auto transfer = context.msg.as(); - const auto& from = get_account( transfer.from ); - const auto& to = get_account( transfer.to ); - modify( from, [&]( account_object& a ) { - a.balance -= transfer.amount; - }); - modify( to, [&]( account_object& a ) { - a.balance += transfer.amount; - }); - }); FC_ASSERT( genesis_state.initial_timestamp != time_point_sec(), "Must initialize genesis timestamp." ); FC_ASSERT( genesis_state.initial_timestamp.sec_since_epoch() % config::BlockIntervalSeconds == 0, @@ -743,6 +717,7 @@ void database::init_genesis(const genesis_state_type& genesis_state) create([&](account_object& a) { a.name = "sys"; }); + init_sys_contract(); // Create initial accounts for (const auto& acct : genesis_state.initial_accounts) { @@ -1058,14 +1033,14 @@ uint32_t database::producer_participation_rate()const void database::update_producer_schedule() { } -void database::set_validate_handler( const account_name& contract, const message_type& action, message_validate_handler v ) { - message_validate_handlers[contract][action] = v; +void database::set_validate_handler( const account_name& contract, const account_name& scope, const message_type& action, message_validate_handler v ) { + message_validate_handlers[contract][std::make_pair(scope,action)] = v; } -void database::set_precondition_validate_handler( const account_name& contract, const message_type& action, precondition_validate_handler v ) { - precondition_validate_handlers[contract][action] = v; +void database::set_precondition_validate_handler( const account_name& contract, const account_name& scope, const message_type& action, precondition_validate_handler v ) { + precondition_validate_handlers[contract][std::make_pair(scope,action)] = v; } -void database::set_apply_handler( const account_name& contract, const message_type& action, apply_handler v ) { - apply_handlers[contract][action] = v; +void database::set_apply_handler( const account_name& contract, const account_name& scope, const message_type& action, apply_handler v ) { + apply_handlers[contract][std::make_pair(scope,action)] = v; } const account_object& database::get_account( const account_name& name )const { diff --git a/libraries/chain/include/eos/chain/account_object.hpp b/libraries/chain/include/eos/chain/account_object.hpp index 4ce4ac132..a1925da76 100644 --- a/libraries/chain/include/eos/chain/account_object.hpp +++ b/libraries/chain/include/eos/chain/account_object.hpp @@ -23,10 +23,22 @@ */ #pragma once #include +#include #include "multi_index_includes.hpp" namespace eos { namespace chain { + + class shared_authority { + shared_authority( chainbase::allocator alloc ) + :accounts(alloc),keys(alloc) + {} + + uint32_t threshold = 0; + shared_vector accounts; + shared_vector keys; + }; + class account_object : public chainbase::object { OBJECT_CTOR(account_object, (name)) diff --git a/libraries/chain/include/eos/chain/database.hpp b/libraries/chain/include/eos/chain/database.hpp index 2fec4f897..3e02eaa27 100644 --- a/libraries/chain/include/eos/chain/database.hpp +++ b/libraries/chain/include/eos/chain/database.hpp @@ -106,9 +106,9 @@ namespace eos { namespace chain { * The database can override any script handler with native code. */ ///@{ - void set_validate_handler( const account_name& contract, const message_type& action, message_validate_handler v ); - void set_precondition_validate_handler( const account_name& contract, const message_type& action, precondition_validate_handler v ); - void set_apply_handler( const account_name& contract, const message_type& action, apply_handler v ); + void set_validate_handler( const account_name& contract, const account_name& scope, const message_type& action, message_validate_handler v ); + void set_precondition_validate_handler( const account_name& contract, const account_name& scope, const message_type& action, precondition_validate_handler v ); + void set_apply_handler( const account_name& contract, const account_name& scope, const message_type& action, apply_handler v ); //@} enum validation_steps @@ -302,6 +302,7 @@ namespace eos { namespace chain { /// Reset the object graph in-memory void initialize_indexes(); void init_genesis(const genesis_state_type& genesis_state = genesis_state_type()); + void init_sys_contract(); ///< defined insys_contract.cpp void debug_dump(); void apply_debug_updates(); @@ -362,9 +363,10 @@ namespace eos { namespace chain { node_property_object _node_property_object; - map< account_name, map > message_validate_handlers; - map< account_name, map > precondition_validate_handlers; - map< account_name, map > apply_handlers; + typedef pair handler_key; + map< account_name, map > message_validate_handlers; + map< account_name, map > precondition_validate_handlers; + map< account_name, map > apply_handlers; }; } } diff --git a/libraries/chain/include/eos/chain/protocol/authority.hpp b/libraries/chain/include/eos/chain/protocol/authority.hpp new file mode 100644 index 000000000..1296cca38 --- /dev/null +++ b/libraries/chain/include/eos/chain/protocol/authority.hpp @@ -0,0 +1,26 @@ +#pragma once +#include + + +namespace eos { namespace chain { + + struct PermissionLevel { + account_name account; + permission_name level; + uint16_t weight; + }; + + struct KeyPermission { + public_key_type key; + uint16_t weight; + }; + + struct Authority { + uint32_t threshold = 0; + vector accounts; + vector keys; + }; + +} } // eos::chain + +FC_REFLECT( eos::chain::Authority, (threshold)(accounts)(keys) ) diff --git a/libraries/chain/include/eos/chain/protocol/transaction.hpp b/libraries/chain/include/eos/chain/protocol/transaction.hpp index 3668ca46e..e840280d9 100644 --- a/libraries/chain/include/eos/chain/protocol/transaction.hpp +++ b/libraries/chain/include/eos/chain/protocol/transaction.hpp @@ -135,7 +135,7 @@ namespace eos { namespace chain { /// The account authorizing the transaction account_name authorizing_account; /// The privileges being invoked to authorize the transaction - privilege_class privileges; + permission_name privileges; }; /** diff --git a/libraries/chain/include/eos/chain/protocol/types.hpp b/libraries/chain/include/eos/chain/protocol/types.hpp index 4eebf7820..1f746892c 100644 --- a/libraries/chain/include/eos/chain/protocol/types.hpp +++ b/libraries/chain/include/eos/chain/protocol/types.hpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -104,9 +105,12 @@ namespace eos { namespace chain { using private_key_type = fc::ecc::private_key; using chain_id_type = fc::sha256; - using account_name = std::string; - using message_type = std::string; - using privilege_class = std::string; + typedef fc::fixed_string<> account_name; + typedef fc::fixed_string<> permission_name; + typedef fc::fixed_string<> message_type; + //using account_name = std::string; + //using message_type = std::string; + //using permission_name = std::string; /** * List all object types from all namespaces here so they can diff --git a/libraries/chain/include/eos/chain/sys_contract.hpp b/libraries/chain/include/eos/chain/sys_contract.hpp index b6d29ba40..62a881a12 100644 --- a/libraries/chain/include/eos/chain/sys_contract.hpp +++ b/libraries/chain/include/eos/chain/sys_contract.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include /** @@ -12,13 +13,20 @@ namespace eos { namespace chain { struct Transfer { - account_name from; account_name to; uint64_t amount = 0; string memo; }; + struct CreateAccount { + account_name new_account; + Authority owner; + Authority active; + uint64_t initial_balance = 0; + }; + } } -FC_REFLECT( eos::chain::Transfer, (from)(to)(amount)(memo) ) +FC_REFLECT( eos::chain::Transfer, (to)(amount)(memo) ) +FC_REFLECT( eos::chain::CreateAccount, (new_account)(owner)(active)(initial_balance) ) diff --git a/libraries/chain/sys_contract.cpp b/libraries/chain/sys_contract.cpp new file mode 100644 index 000000000..7e98453c2 --- /dev/null +++ b/libraries/chain/sys_contract.cpp @@ -0,0 +1,35 @@ +#include +#include +#include + +namespace eos { namespace chain { + +void database::init_sys_contract() { + wlog( "init sys contract" ); + + set_validate_handler( "sys", "sys", "Transfer", [&]( message_validate_context& context ) { + auto transfer = context.msg.as(); + FC_ASSERT( context.msg.has_notify( transfer.to ), "Must notify recipient of transfer" ); + }); + + set_precondition_validate_handler( "sys", "sys", "Transfer", [&]( precondition_validate_context& context ) { + auto transfer = context.msg.as(); + const auto& from = get_account( context.msg.sender ); + FC_ASSERT( from.balance > transfer.amount, "Insufficient Funds", + ("from.balance",from.balance)("transfer.amount",transfer.amount) ); + }); + + set_apply_handler( "sys", "sys", "Transfer", [&]( apply_context& context ) { + auto transfer = context.msg.as(); + const auto& from = get_account( context.msg.sender ); + const auto& to = get_account( transfer.to ); + modify( from, [&]( account_object& a ) { + a.balance -= transfer.amount; + }); + modify( to, [&]( account_object& a ) { + a.balance += transfer.amount; + }); + }); +} + +} } // namespace eos::chain diff --git a/tests/tests/block_tests.cpp b/tests/tests/block_tests.cpp index ba3adb1c7..9d66ec83c 100644 --- a/tests/tests/block_tests.cpp +++ b/tests/tests/block_tests.cpp @@ -71,10 +71,10 @@ BOOST_FIXTURE_TEST_CASE(transfer, testing_fixture) trx.messages[0].sender = "init1"; trx.messages[0].recipient = "sys"; trx.messages[0].type = "Transfer"; - trx.messages[0].set( "Transfer", eos::chain::Transfer{ "init1", "init2", 100, "memo" } ); + trx.messages[0].set( "Transfer", eos::chain::Transfer{ "init2", 100, "memo" } ); BOOST_REQUIRE_THROW( db.push_transaction(trx), fc::assert_exception ); // "fail to notify receiver, init2" trx.messages[0].notify = {"init2"}; - trx.messages[0].set( "Transfer", eos::chain::Transfer{ "init1", "init2", 100, "memo" } ); + trx.messages[0].set( "Transfer", eos::chain::Transfer{ "init2", 100, "memo" } ); db.push_transaction(trx); BOOST_CHECK_EQUAL( db.get_account( "init1" ).balance, 100000 - 100 ); -- GitLab