提交 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
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" )
......
......@@ -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
......
......@@ -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<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.sec_since_epoch() % config::BlockIntervalSeconds == 0,
......@@ -743,6 +717,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
create<account_object>([&](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 {
......
......@@ -23,10 +23,22 @@
*/
#pragma once
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/protocol/authority.hpp>
#include "multi_index_includes.hpp"
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>
{
OBJECT_CTOR(account_object, (name))
......
......@@ -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_type, message_validate_handler> > message_validate_handlers;
map< account_name, map<message_type, precondition_validate_handler> > precondition_validate_handlers;
map< account_name, map<message_type, apply_handler> > apply_handlers;
typedef pair<account_name,message_type> handler_key;
map< account_name, map<handler_key, message_validate_handler> > message_validate_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 {
/// The account authorizing the transaction
account_name authorizing_account;
/// The privileges being invoked to authorize the transaction
privilege_class privileges;
permission_name privileges;
};
/**
......
......@@ -38,6 +38,7 @@
#include <fc/static_variant.hpp>
#include <fc/smart_ref_fwd.hpp>
#include <fc/crypto/ripemd160.hpp>
#include <fc/fixed_string.hpp>
#include <memory>
#include <vector>
......@@ -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
......
#pragma once
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/protocol/authority.hpp>
/**
......@@ -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) )
#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)
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 );
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册