Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Ref #15: Implement CreateProducer
Browse files Browse the repository at this point in the history
Also add stream insertion operators for oid<T> and PublicKey, so they
can be used in BOOST_CHECK_EQUAL tests, and also sent over ostreams.
  • Loading branch information
nathanielhourt committed May 3, 2017
1 parent 83d5740 commit 9ebb2dd
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 103 deletions.
7 changes: 3 additions & 4 deletions libraries/chain/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -798,10 +798,9 @@ void database::init_genesis(const genesis_state_type& genesis_state)
create<account_object>([&](account_object& a) {
a.name = "sys";
});
register_type<types::Transfer>("sys");
register_type<types::CreateAccount>("sys");
register_type<types::DefineStruct>("sys");
register_type<types::SetMessageHandler>("sys");
#define MACRO(r, data, elem) register_type<types::elem>("sys");
BOOST_PP_SEQ_FOR_EACH(MACRO, x, EOS_SYSTEM_CONTRACT_FUNCTIONS)
#undef MACRO

// Create initial accounts
for (const auto& acct : genesis_state.initial_accounts) {
Expand Down
24 changes: 17 additions & 7 deletions libraries/chain/include/eos/chain/message.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,33 @@ struct message {
* scoped according to the recipient. This means two contracts can can define
* two different types with the same name.
*/
types::TypeName type;
types::TypeName type;

/// The message contents
vector<char> data;
vector<char> data;

message() = default;
message(const AccountName& sender, const AccountName& recipient, const vector<AccountName>& notify)
: sender(sender), recipient(recipient), notify(notify) {}
template<typename T>
void set( const TypeName& t, const T& value ) {
message(const AccountName& sender, const AccountName& recipient, const vector<AccountName>& notify,
const TypeName& type, T&& value)
: message(sender, recipient, notify) {
set<T>(type, std::forward<T>(value));
}

template<typename T>
void set(const TypeName& t, const T& value) {
type = t;
data = fc::raw::pack( value );
data = fc::raw::pack(value);
}
template<typename T>
T as()const {
return fc::raw::unpack<T>(data);
}
bool has_notify( const AccountName& n )const {
for( const auto& no : notify )
if( no == n ) return true;
bool has_notify(const AccountName& n)const {
for(const auto& no : notify)
if(no == n) return true;
return false;
}
};
Expand Down
4 changes: 2 additions & 2 deletions libraries/chain/include/eos/chain/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
{ c(*this); }
#define OBJECT_CTOR(...) BOOST_PP_OVERLOAD(OBJECT_CTOR, __VA_ARGS__)(__VA_ARGS__)

#define EOS_SYSTEM_CONTRACT_FUNCTIONS (Transfer)(CreateAccount)(CreateProducer)(DefineStruct)(SetMessageHandler)

namespace eos { namespace chain {
using std::map;
using std::vector;
Expand Down Expand Up @@ -172,8 +174,6 @@ namespace eos { namespace chain {

} } // eos::chain



FC_REFLECT(eos::chain::account_id_type, (_id))
FC_REFLECT(eos::chain::producer_id_type, (_id))

Expand Down
2 changes: 1 addition & 1 deletion libraries/chainbase
5 changes: 5 additions & 0 deletions libraries/types/PublicKey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ namespace eos { namespace types {
return p1.key_data < p2.key_data;
};

std::ostream& operator<<(std::ostream& s, const PublicKey& k) {
s << "PublicKey(" << std::string(k) << ')';
return s;
}

}} // eos::types

namespace fc
Expand Down
1 change: 1 addition & 0 deletions libraries/types/include/eos/types/PublicKey.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace eos { namespace types {
friend bool operator == ( const PublicKey& p1, const PublicKey& p2);
friend bool operator != ( const PublicKey& p1, const PublicKey& p2);
friend bool operator < ( const PublicKey& p1, const PublicKey& p2);
friend std::ostream& operator<< (std::ostream& s, const PublicKey& k);
bool is_valid_v1(const std::string& base58str);
};
}} // namespace eos::types
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#include <eos/native_system_contract_plugin/native_system_contract_plugin.hpp>

#include <eos/chain/action_objects.hpp>
#include <eos/chain/producer_object.hpp>
#include <eos/chain/exceptions.hpp>
#include <eos/types/native.hpp>
#include <eos/types/generated.hpp>

#include <boost/preprocessor/seq/for_each.hpp>

namespace eos {
using namespace chain;
using namespace types;
Expand All @@ -31,16 +34,37 @@ void native_system_contract_plugin::plugin_startup() {
void native_system_contract_plugin::plugin_shutdown() {
}

void CreateProducer_validate(chain::message_validate_context& context) {
auto create = context.msg.as<CreateProducer>();
EOS_ASSERT(create.name.size() > 0, message_validate_exception, "Producer owner name cannot be empty");
EOS_ASSERT(create.key != PublicKey(), message_validate_exception, "Producer signing key cannot be null");
}
void CreateProducer_validate_preconditions(chain::precondition_validate_context& context) {
auto create = context.msg.as<CreateProducer>();
const auto& db = context.db;
const auto& owner = db.get_account(create.name);
auto producer = db.find<producer_object, by_owner>(owner.id);
EOS_ASSERT(producer == nullptr, message_precondition_exception,
"Account ${name} already has a block producer", ("name", create.name));
}
void CreateProducer_apply(chain::apply_context& context) {
auto create = context.msg.as<CreateProducer>();
auto& db = context.mutable_db;
const auto& owner = db.get_account(create.name);
db.create<producer_object>([&create, &owner](producer_object& p) {
p.owner = owner.id;
p.signing_key = create.key;
});
}

#include "system_contract_impl.hpp"
void native_system_contract_plugin::install(database& db) {
#define SET_HANDLERS(name) \
db.set_validate_handler("sys", "sys", #name, &name ## _validate); \
db.set_precondition_validate_handler("sys", "sys", #name, &name ## _validate_preconditions); \
db.set_apply_handler("sys", "sys", #name, &name ## _apply)
db.set_apply_handler("sys", "sys", #name, &name ## _apply);
#define FWD_SET_HANDLERS(r, data, elem) SET_HANDLERS(elem)

SET_HANDLERS(Transfer);
SET_HANDLERS(CreateAccount);
SET_HANDLERS(DefineStruct);
SET_HANDLERS(SetMessageHandler);
BOOST_PP_SEQ_FOR_EACH(FWD_SET_HANDLERS, x, EOS_SYSTEM_CONTRACT_FUNCTIONS)
}
}
36 changes: 18 additions & 18 deletions plugins/native_system_contract_plugin/system_contract_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ void Transfer_validate(chain::message_validate_context& context) {
try {
EOS_ASSERT(transfer.amount > Asset(0), message_validate_exception, "Must transfer a positive amount");
EOS_ASSERT(context.msg.has_notify(transfer.to), message_validate_exception, "Must notify recipient of transfer");
} FC_CAPTURE_AND_RETHROW( (transfer) )
} FC_CAPTURE_AND_RETHROW((transfer))
}

void Transfer_validate_preconditions(chain::precondition_validate_context& context) {
Expand Down Expand Up @@ -40,27 +40,27 @@ void Transfer_apply(chain::apply_context& context) {
***********************************************************/
void DefineStruct_validate(chain::message_validate_context& context) {
auto msg = context.msg.as<DefineStruct>();
FC_ASSERT( msg.definition.name != TypeName(), "must define a type name" );
// TODO: validate_type_name( msg.definition.name );
// validate_type_name( msg.definition.base );
FC_ASSERT(msg.definition.name != TypeName(), "must define a type name");
// TODO: validate_type_name( msg.definition.name)
// validate_type_name( msg.definition.base)
}
void DefineStruct_validate_preconditions(chain::precondition_validate_context& context) {
auto& db = context.db;
auto msg = context.msg.as<DefineStruct>();
db.get<account_object,by_name>( msg.scope );
#warning TODO: db.get<account_object>(msg.base_scope )
db.get<account_object,by_name>(msg.scope);
#warning TODO: db.get<account_object>(sg.base_scope)
}
void DefineStruct_apply(chain::apply_context& context) {
auto& db = context.mutable_db;
auto msg = context.msg.as<DefineStruct>();

db.create<type_object>( [&]( auto& type ) {
db.create<type_object>( [&](auto& type) {
type.scope = msg.scope;
type.name = msg.definition.name;
type.fields.reserve( msg.definition.fields.size() );
type.fields.reserve(msg.definition.fields.size());
#warning TODO: type.base_scope =
type.base = msg.definition.base;
for( const auto& f : msg.definition.fields ) {
for(const auto& f : msg.definition.fields) {
type.fields.push_back(f);
}
});
Expand All @@ -85,17 +85,17 @@ void SetMessageHandler_validate_preconditions(chain::precondition_validate_conte
auto& db = context.db;
auto msg = context.msg.as<SetMessageHandler>();
idump((msg.recipient)(msg.processor)(msg.type));
// db.get<type_object,by_scope_name>( boost::make_tuple(msg.account, msg.type) );
// db.get<type_object,by_scope_name>( boost::make_tuple(msg.account, msg.type))

// TODO: verify code compiles
} FC_CAPTURE_AND_RETHROW() }

void SetMessageHandler_apply(chain::apply_context& context) {
auto& db = context.mutable_db;
auto msg = context.msg.as<SetMessageHandler>();
const auto& processor_acnt = db.get<account_object,by_name>( msg.processor );
const auto& recipient_acnt = db.get<account_object,by_name>( msg.recipient );
db.create<action_code_object>( [&]( auto& action ){
const auto& processor_acnt = db.get<account_object,by_name>(msg.processor);
const auto& recipient_acnt = db.get<account_object,by_name>(msg.recipient);
db.create<action_code_object>( [&](auto& action){
action.processor = processor_acnt.id;
action.recipient = recipient_acnt.id;
action.type = msg.type;
Expand All @@ -118,8 +118,8 @@ void SetMessageHandler_apply(chain::apply_context& context) {


void Authority_validate_preconditions(const Authority& auth, chain::precondition_validate_context& context) {
for( const auto& a : auth.accounts )
context.db.get<account_object,by_name>( a.permission.account );
for(const auto& a : auth.accounts)
context.db.get<account_object,by_name>(a.permission.account);
}

void CreateAccount_validate(chain::message_validate_context& context) {
Expand All @@ -146,9 +146,9 @@ void CreateAccount_validate_preconditions(chain::precondition_validate_context&

#warning TODO: make sure creation deposit is greater than min account balance

Authority_validate_preconditions( create.owner, context );
Authority_validate_preconditions( create.active, context );
Authority_validate_preconditions( create.recovery, context );
Authority_validate_preconditions(create.owner, context);
Authority_validate_preconditions(create.active, context);
Authority_validate_preconditions(create.recovery, context);
}

void CreateAccount_apply(chain::apply_context& context) {
Expand Down
66 changes: 0 additions & 66 deletions tests/tests/block_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,72 +160,6 @@ BOOST_FIXTURE_TEST_CASE(create_script, testing_fixture)

} FC_LOG_AND_RETHROW() }

//Simple test of account creation
BOOST_FIXTURE_TEST_CASE(create_account, testing_fixture)
{ try {
MKDB(db);
db.produce_blocks(10);

const auto& init1_account = db.get_account("init1");

BOOST_CHECK_EQUAL(init1_account.balance, Asset(100000));

auto joe_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash("joe"));
public_key_type joe_public_key = joe_private_key.get_public_key();

signed_transaction trx;
trx.messages.resize(1);
trx.set_reference_block(db.head_block_id());
trx.expiration = db.head_block_time() + 100;
trx.messages[0].sender = "init1";
trx.messages[0].recipient = "sys";
trx.messages[0].type = "CreateAccount";
trx.messages[0].set("CreateAccount",
CreateAccount{"init1", "joe", {1, {{joe_public_key, 1}}, {}}, {1, {{joe_public_key, 1}}, {}}, {}, Asset(1000)});
db.push_transaction(trx);

{ // test in the pending state
const auto& joe_account = db.get_account("joe");
BOOST_CHECK_EQUAL(joe_account.balance, Asset(1000));
BOOST_CHECK_EQUAL(init1_account.balance, Asset(100000 - 1000));

const auto& joe_owner_authority = db.get<permission_object, by_owner>(boost::make_tuple(joe_account.id, "owner"));
BOOST_CHECK_EQUAL(joe_owner_authority.auth.threshold, 1);
BOOST_CHECK_EQUAL(joe_owner_authority.auth.accounts.size(), 0);
BOOST_CHECK_EQUAL(joe_owner_authority.auth.keys.size(), 1);
BOOST_CHECK_EQUAL(string(joe_owner_authority.auth.keys[0].key), string(joe_public_key));
BOOST_CHECK_EQUAL(joe_owner_authority.auth.keys[0].weight, 1);

const auto& joe_active_authority = db.get<permission_object, by_owner>(boost::make_tuple(joe_account.id, "active"));
BOOST_CHECK_EQUAL(joe_active_authority.auth.threshold, 1);
BOOST_CHECK_EQUAL(joe_active_authority.auth.accounts.size(), 0);
BOOST_CHECK_EQUAL(joe_active_authority.auth.keys.size(), 1);
BOOST_CHECK_EQUAL(string(joe_active_authority.auth.keys[0].key), string(joe_public_key));
BOOST_CHECK_EQUAL(joe_active_authority.auth.keys[0].weight, 1);
}

db.produce_blocks(1); /// verify changes survived creating a new block
{
const auto& joe_account = db.get_account("joe");
BOOST_CHECK_EQUAL(joe_account.balance, Asset(1000));
BOOST_CHECK_EQUAL(init1_account.balance, Asset(100000 - 1000));

const auto& joe_owner_authority = db.get<permission_object, by_owner>(boost::make_tuple(joe_account.id, "owner"));
BOOST_CHECK_EQUAL(joe_owner_authority.auth.threshold, 1);
BOOST_CHECK_EQUAL(joe_owner_authority.auth.accounts.size(), 0);
BOOST_CHECK_EQUAL(joe_owner_authority.auth.keys.size(), 1);
BOOST_CHECK_EQUAL(string(joe_owner_authority.auth.keys[0].key), string(joe_public_key));
BOOST_CHECK_EQUAL(joe_owner_authority.auth.keys[0].weight, 1);

const auto& joe_active_authority = db.get<permission_object, by_owner>(boost::make_tuple(joe_account.id, "active"));
BOOST_CHECK_EQUAL(joe_active_authority.auth.threshold, 1);
BOOST_CHECK_EQUAL(joe_active_authority.auth.accounts.size(), 0);
BOOST_CHECK_EQUAL(joe_active_authority.auth.keys.size(), 1);
BOOST_CHECK_EQUAL(string(joe_active_authority.auth.keys[0].key), string(joe_public_key));
BOOST_CHECK_EQUAL(joe_active_authority.auth.keys[0].weight, 1);
}
} FC_LOG_AND_RETHROW() }

// Simple test of block production when a block is missed
BOOST_FIXTURE_TEST_CASE(missed_blocks, testing_fixture)
{ try {
Expand Down
Loading

0 comments on commit 9ebb2dd

Please sign in to comment.