提交 4cfcb97b 编写于 作者: D Daniel Larimer

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
上级 02dada8b
...@@ -111,7 +111,7 @@ else( WIN32 ) # Apple AND Linux ...@@ -111,7 +111,7 @@ else( WIN32 ) # Apple AND Linux
if( APPLE ) if( APPLE )
# Apple Specific Options Here # Apple Specific Options Here
message( STATUS "Configuring Eos on OS X" ) 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 ) else( APPLE )
# Linux Specific Options Here # Linux Specific Options Here
message( STATUS "Configuring Eos on Linux" ) message( STATUS "Configuring Eos on Linux" )
......
...@@ -5,6 +5,7 @@ file(GLOB PROTOCOL_HEADERS "include/eos/chain/protocol/*.hpp") ...@@ -5,6 +5,7 @@ file(GLOB PROTOCOL_HEADERS "include/eos/chain/protocol/*.hpp")
## SORT .cpp by most likely to change / break compile ## SORT .cpp by most likely to change / break compile
add_library( eos_chain add_library( eos_chain
database.cpp database.cpp
sys_contract.cpp
fork_database.cpp fork_database.cpp
protocol/types.cpp protocol/types.cpp
......
...@@ -520,7 +520,7 @@ try { ...@@ -520,7 +520,7 @@ try {
message_validate_context mvc( trx, m ); message_validate_context mvc( trx, m );
auto contract_handlers_itr = message_validate_handlers.find( m.recipient ); auto contract_handlers_itr = message_validate_handlers.find( m.recipient );
if( contract_handlers_itr != message_validate_handlers.end() ) { 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() ) { if( message_handelr_itr != contract_handlers_itr->second.end() ) {
message_handelr_itr->second(mvc); message_handelr_itr->second(mvc);
continue; continue;
...@@ -535,7 +535,7 @@ void database::validate_message_precondition( precondition_validate_context& con ...@@ -535,7 +535,7 @@ void database::validate_message_precondition( precondition_validate_context& con
const auto& m = context.msg; const auto& m = context.msg;
auto contract_handlers_itr = precondition_validate_handlers.find( context.receiver ); auto contract_handlers_itr = precondition_validate_handlers.find( context.receiver );
if( contract_handlers_itr != precondition_validate_handlers.end() ) { 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() ) { if( message_handelr_itr != contract_handlers_itr->second.end() ) {
message_handelr_itr->second(context); message_handelr_itr->second(context);
return; return;
...@@ -548,7 +548,7 @@ void database::apply_message( apply_context& context ) { ...@@ -548,7 +548,7 @@ void database::apply_message( apply_context& context ) {
const auto& m = context.msg; const auto& m = context.msg;
auto contract_handlers_itr = apply_handlers.find( context.receiver ); auto contract_handlers_itr = apply_handlers.find( context.receiver );
if( contract_handlers_itr != apply_handlers.end() ) { 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() ) { if( message_handelr_itr != contract_handlers_itr->second.end() ) {
message_handelr_itr->second(context); message_handelr_itr->second(context);
return; return;
...@@ -697,32 +697,6 @@ void database::initialize_indexes() { ...@@ -697,32 +697,6 @@ void database::initialize_indexes() {
void database::init_genesis(const genesis_state_type& genesis_state) void database::init_genesis(const genesis_state_type& genesis_state)
{ try { { try {
set_validate_handler( "sys", "sys/Transfer", [&]( message_validate_context& context ) {
idump((context.msg));
auto transfer = context.msg.as<Transfer>();
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<Transfer>();
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<Transfer>();
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 != time_point_sec(), "Must initialize genesis timestamp." );
FC_ASSERT( genesis_state.initial_timestamp.sec_since_epoch() % config::BlockIntervalSeconds == 0, 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) ...@@ -743,6 +717,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
create<account_object>([&](account_object& a) { create<account_object>([&](account_object& a) {
a.name = "sys"; a.name = "sys";
}); });
init_sys_contract();
// Create initial accounts // Create initial accounts
for (const auto& acct : genesis_state.initial_accounts) { for (const auto& acct : genesis_state.initial_accounts) {
...@@ -1058,14 +1033,14 @@ uint32_t database::producer_participation_rate()const ...@@ -1058,14 +1033,14 @@ uint32_t database::producer_participation_rate()const
void database::update_producer_schedule() void database::update_producer_schedule()
{ {
} }
void database::set_validate_handler( const account_name& contract, const message_type& action, message_validate_handler 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][action] = 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 ) { 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][action] = 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 ) { void database::set_apply_handler( const account_name& contract, const account_name& scope, const message_type& action, apply_handler v ) {
apply_handlers[contract][action] = v; apply_handlers[contract][std::make_pair(scope,action)] = v;
} }
const account_object& database::get_account( const account_name& name )const { const account_object& database::get_account( const account_name& name )const {
......
...@@ -23,10 +23,22 @@ ...@@ -23,10 +23,22 @@
*/ */
#pragma once #pragma once
#include <eos/chain/protocol/types.hpp> #include <eos/chain/protocol/types.hpp>
#include <eos/chain/protocol/authority.hpp>
#include "multi_index_includes.hpp" #include "multi_index_includes.hpp"
namespace eos { namespace chain { namespace eos { namespace chain {
class shared_authority {
shared_authority( chainbase::allocator<char> alloc )
:accounts(alloc),keys(alloc)
{}
uint32_t threshold = 0;
shared_vector<PermissionLevel> accounts;
shared_vector<KeyPermission> keys;
};
class account_object : public chainbase::object<account_object_type, account_object> class account_object : public chainbase::object<account_object_type, account_object>
{ {
OBJECT_CTOR(account_object, (name)) OBJECT_CTOR(account_object, (name))
......
...@@ -106,9 +106,9 @@ namespace eos { namespace chain { ...@@ -106,9 +106,9 @@ namespace eos { namespace chain {
* The database can override any script handler with native code. * 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_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 message_type& action, precondition_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 message_type& action, apply_handler v ); void set_apply_handler( const account_name& contract, const account_name& scope, const message_type& action, apply_handler v );
//@} //@}
enum validation_steps enum validation_steps
...@@ -302,6 +302,7 @@ namespace eos { namespace chain { ...@@ -302,6 +302,7 @@ namespace eos { namespace chain {
/// Reset the object graph in-memory /// Reset the object graph in-memory
void initialize_indexes(); void initialize_indexes();
void init_genesis(const genesis_state_type& genesis_state = genesis_state_type()); void init_genesis(const genesis_state_type& genesis_state = genesis_state_type());
void init_sys_contract(); ///< defined insys_contract.cpp
void debug_dump(); void debug_dump();
void apply_debug_updates(); void apply_debug_updates();
...@@ -362,9 +363,10 @@ namespace eos { namespace chain { ...@@ -362,9 +363,10 @@ namespace eos { namespace chain {
node_property_object _node_property_object; node_property_object _node_property_object;
map< account_name, map<message_type, message_validate_handler> > message_validate_handlers; typedef pair<account_name,message_type> handler_key;
map< account_name, map<message_type, precondition_validate_handler> > precondition_validate_handlers; map< account_name, map<handler_key, message_validate_handler> > message_validate_handlers;
map< account_name, map<message_type, apply_handler> > apply_handlers; map< account_name, map<handler_key, precondition_validate_handler> > precondition_validate_handlers;
map< account_name, map<handler_key, apply_handler> > apply_handlers;
}; };
} } } }
#pragma once
#include <eos/chain/protocol/types.hpp>
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<PermissionLevel> accounts;
vector<KeyPermission> keys;
};
} } // eos::chain
FC_REFLECT( eos::chain::Authority, (threshold)(accounts)(keys) )
...@@ -135,7 +135,7 @@ namespace eos { namespace chain { ...@@ -135,7 +135,7 @@ namespace eos { namespace chain {
/// The account authorizing the transaction /// The account authorizing the transaction
account_name authorizing_account; account_name authorizing_account;
/// The privileges being invoked to authorize the transaction /// The privileges being invoked to authorize the transaction
privilege_class privileges; permission_name privileges;
}; };
/** /**
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <fc/static_variant.hpp> #include <fc/static_variant.hpp>
#include <fc/smart_ref_fwd.hpp> #include <fc/smart_ref_fwd.hpp>
#include <fc/crypto/ripemd160.hpp> #include <fc/crypto/ripemd160.hpp>
#include <fc/fixed_string.hpp>
#include <memory> #include <memory>
#include <vector> #include <vector>
...@@ -104,9 +105,12 @@ namespace eos { namespace chain { ...@@ -104,9 +105,12 @@ namespace eos { namespace chain {
using private_key_type = fc::ecc::private_key; using private_key_type = fc::ecc::private_key;
using chain_id_type = fc::sha256; using chain_id_type = fc::sha256;
using account_name = std::string; typedef fc::fixed_string<> account_name;
using message_type = std::string; typedef fc::fixed_string<> permission_name;
using privilege_class = std::string; 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 * List all object types from all namespaces here so they can
......
#pragma once #pragma once
#include <eos/chain/protocol/types.hpp> #include <eos/chain/protocol/types.hpp>
#include <eos/chain/protocol/authority.hpp>
/** /**
...@@ -12,13 +13,20 @@ namespace eos { namespace chain { ...@@ -12,13 +13,20 @@ namespace eos { namespace chain {
struct Transfer { struct Transfer {
account_name from;
account_name to; account_name to;
uint64_t amount = 0; uint64_t amount = 0;
string memo; 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) )
#include <eos/chain/database.hpp>
#include <eos/chain/sys_contract.hpp>
#include <eos/chain/account_object.hpp>
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<Transfer>();
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<Transfer>();
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<Transfer>();
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
...@@ -71,10 +71,10 @@ BOOST_FIXTURE_TEST_CASE(transfer, testing_fixture) ...@@ -71,10 +71,10 @@ BOOST_FIXTURE_TEST_CASE(transfer, testing_fixture)
trx.messages[0].sender = "init1"; trx.messages[0].sender = "init1";
trx.messages[0].recipient = "sys"; trx.messages[0].recipient = "sys";
trx.messages[0].type = "Transfer"; 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" BOOST_REQUIRE_THROW( db.push_transaction(trx), fc::assert_exception ); // "fail to notify receiver, init2"
trx.messages[0].notify = {"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); db.push_transaction(trx);
BOOST_CHECK_EQUAL( db.get_account( "init1" ).balance, 100000 - 100 ); BOOST_CHECK_EQUAL( db.get_account( "init1" ).balance, 100000 - 100 );
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册