提交 a3fa6ecd 编写于 作者: N Nathan Hourt

Ref #15: Implement create/update producer

This commit implements and tests the CreateProducer and UpdateProducer
sys contract methods.
上级 e09354ea
......@@ -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)) }
} }
......@@ -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
......
......@@ -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;
......
......@@ -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) \
......
......@@ -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
......@@ -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);
......@@ -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
......@@ -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)
......@@ -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()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册