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 create/update producer
Browse files Browse the repository at this point in the history
This commit implements and tests the CreateProducer and UpdateProducer
sys contract methods.
  • Loading branch information
nathanielhourt committed May 3, 2017
1 parent e09354e commit a3fa6ec
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 46 deletions.
9 changes: 7 additions & 2 deletions libraries/chain/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1144,7 +1144,12 @@ void database::set_apply_handler( const AccountName& contract, const AccountName

const account_object& database::get_account( const AccountName& name )const {
try {
return get<account_object,by_name>(name);
} FC_CAPTURE_AND_RETHROW( (name) ) }
return get<account_object,by_name>(name);
} FC_CAPTURE_AND_RETHROW((name)) }

const producer_object&database::get_producer(const types::AccountName& name) const {
try {
return get<producer_object, by_owner>(get_account(name).id);
} FC_CAPTURE_AND_RETHROW((name)) }

} }
3 changes: 2 additions & 1 deletion libraries/chain/include/eos/chain/database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ namespace eos { namespace chain {
const signed_transaction& get_recent_transaction( const transaction_id_type& trx_id )const;
std::vector<block_id_type> get_block_ids_on_fork(block_id_type head_of_fork) const;

const account_object& get_account( const AccountName& name )const;
const account_object& get_account(const AccountName& name)const;
const producer_object& get_producer(const AccountName& name)const;

/**
* Calculate the percent of block production slots that were missed in the
Expand Down
3 changes: 2 additions & 1 deletion libraries/chain/include/eos/chain/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +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)
#define EOS_SYSTEM_CONTRACT_FUNCTIONS (Transfer)(CreateAccount)(CreateProducer)(UpdateProducer) \
(DefineStruct)(SetMessageHandler)

namespace eos { namespace chain {
using std::map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,29 +34,6 @@ 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) \
Expand Down
57 changes: 49 additions & 8 deletions plugins/native_system_contract_plugin/system_contract_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,6 @@ void DefineStruct_apply(chain::apply_context& context) {
});
}


void validate_type_name(const TypeName& name) {
// TODO: starts with capital letter and is alphanumeric
}


/************************************************************
*
* SetMessageHandler
Expand Down Expand Up @@ -115,8 +109,6 @@ 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);
Expand Down Expand Up @@ -175,3 +167,52 @@ void CreateAccount_apply(chain::apply_context& context) {
});
}
///@} Create Account Handlers

/************************************************************
*
* Create/Update Producer Handlers
*
***********************************************************/
///@{
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");
}
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;
});
}

void UpdateProducer_validate(chain::message_validate_context& context) {
auto update = context.msg.as<UpdateProducer>();
EOS_ASSERT(update.name.size() > 0, message_validate_exception, "Producer owner name cannot be empty");
}
void UpdateProducer_validate_preconditions(chain::precondition_validate_context& context) {
const auto& db = context.db;
auto update = context.msg.as<UpdateProducer>();
const auto& producer = db.get_producer(update.name);
EOS_ASSERT(producer.signing_key != update.newKey, message_validate_exception,
"Producer's new key may not be identical to old key");
}
void UpdateProducer_apply(chain::apply_context& context) {
auto& db = context.mutable_db;
auto update = context.msg.as<UpdateProducer>();
const auto& producer = db.get_producer(update.name);
db.modify(producer, [&update](producer_object& p) {
p.signing_key = update.newKey;
});
}
///@} Create/Update Producer Handlers
28 changes: 17 additions & 11 deletions tests/tests/system_contract_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ BOOST_FIXTURE_TEST_CASE(create_account, testing_fixture)
}
} FC_LOG_AND_RETHROW() }

// Simple test of creating a new block producer
// Simple test of creating/updating a new block producer
BOOST_FIXTURE_TEST_CASE(producer_creation, testing_fixture)
{ try {
MKDB(db)
Expand All @@ -100,24 +100,30 @@ BOOST_FIXTURE_TEST_CASE(producer_creation, testing_fixture)
CreateAccount ca{"init0", "producer", producer_authority, producer_authority, {}, Asset(100)};
trx.messages.emplace_back("init0", "sys", vector<AccountName>{}, "CreateAccount", ca);
db.push_transaction(trx);
trx.messages.clear();
trx.clear();

CreateProducer cp{"producer", producer_pub_key};
trx.messages.emplace_back("producer", "sys", vector<AccountName>{}, "CreateProducer", cp);
db.push_transaction(trx);

while (db.head_block_num() < 3) {
auto producer_account = db.find<account_object, by_name>("producer");
BOOST_REQUIRE(producer_account != nullptr);
auto producer = db.find<producer_object, by_owner>(producer_account->id);
BOOST_REQUIRE(producer != nullptr);
BOOST_CHECK_EQUAL(producer->owner, producer_account->id);
BOOST_CHECK_EQUAL(producer->signing_key, producer_pub_key);
BOOST_CHECK_EQUAL(producer->last_aslot, 0);
BOOST_CHECK_EQUAL(producer->total_missed, 0);
BOOST_CHECK_EQUAL(producer->last_confirmed_block_num, 0);
auto& producer = db.get_producer("producer");
BOOST_CHECK_EQUAL(db.get(producer.owner).name, "producer");
BOOST_CHECK_EQUAL(producer.signing_key, producer_pub_key);
BOOST_CHECK_EQUAL(producer.last_aslot, 0);
BOOST_CHECK_EQUAL(producer.total_missed, 0);
BOOST_CHECK_EQUAL(producer.last_confirmed_block_num, 0);
db.produce_blocks();
}

auto signing_key = private_key_type::regenerate(fc::digest("producer signing key"));
PublicKey signing_public_key = signing_key.get_public_key();
trx.clear();
trx.messages.emplace_back("producer", "sys", vector<AccountName>{}, "UpdateProducer",
UpdateProducer{"producer", signing_key.get_public_key()});
db.push_transaction(trx);
auto& producer = db.get_producer("producer");
BOOST_CHECK_EQUAL(producer.signing_key, signing_public_key);
} FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit a3fa6ec

Please sign in to comment.