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

Commit

Permalink
Merge pull request #79 from elmato/create-special-accounts
Browse files Browse the repository at this point in the history
Create special accounts
  • Loading branch information
bytemaster authored Jul 17, 2017
2 parents 89ab14b + 1265a87 commit 7178ea5
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 16 deletions.
13 changes: 12 additions & 1 deletion libraries/chain/chain_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,8 @@ void chain_controller::create_block_summary(const signed_block& next_block) {
}

void chain_controller::update_global_properties(const signed_block& b) {
// If we're at the end of a round, update the BlockchainConfiguration and producer schedule
// If we're at the end of a round, update the BlockchainConfiguration, producer schedule
// and "producers" special account authority
if (b.block_num() % config::BlocksPerRound == 0) {
auto schedule = calculate_next_round(b);
auto config = _admin->get_blockchain_configuration(_db, schedule);
Expand All @@ -718,6 +719,16 @@ void chain_controller::update_global_properties(const signed_block& b) {
gpo.active_producers = std::move(schedule);
gpo.configuration = std::move(config);
});

auto active_producers_authority = types::Authority(config::ProducersAuthorityThreshold, {}, {});
for(auto& name : gpo.active_producers) {
active_producers_authority.accounts.push_back({{name, config::ActiveName}, 1});
}

auto& po = _db.get<permission_object, by_owner>( boost::make_tuple(config::ProducersAccountName, config::ActiveName) );
_db.modify(po,[active_producers_authority] (permission_object& po) {
po.auth = active_producers_authority;
});
}
}

Expand Down
19 changes: 14 additions & 5 deletions libraries/chain/include/eos/chain/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,29 @@
* THE SOFTWARE.
*/
#pragma once
#include <eos/types/native.hpp>
#include <eos/types/Asset.hpp>
#include <eos/types/types.hpp>

namespace eos { namespace config {
using types::UInt32;
using types::UInt64;
using types::UInt128;
using types::ShareType;
using types::Asset;
using types::AccountName;
using types::PermissionName;

const static char KeyPrefix[] = "EOS";

const static char SystemContractName[] = "system";
const static char EosContractName[] = "eos";
const static char StakedBalanceContractName[] = "staked";
const static AccountName SystemContractName = N(system);
const static AccountName EosContractName = N(eos);
const static AccountName StakedBalanceContractName = N(staked);

const static AccountName NobodyAccountName = N(nobody);
const static AccountName AnybodyAccountName = N(anybody);
const static AccountName ProducersAccountName = N(producers);

const static PermissionName ActiveName = N(active);
const static PermissionName OwnerName = N(owner);

const static ShareType InitialTokenSupply = Asset::fromString("90000000.00000000 EOS").amount;

Expand All @@ -53,6 +61,7 @@ const static ShareType DefaultElectedPay = Asset(100).amount;
const static ShareType DefaultRunnerUpPay = Asset(75).amount;
const static ShareType DefaultMinEosBalance = Asset(100).amount;
const static UInt32 DefaultMaxTrxLifetime = 60*60;
const static UInt32 ProducersAuthorityThreshold = 14;

const static int BlocksPerRound = 21;
const static int VotedProducersPerRound = 20;
Expand Down
31 changes: 31 additions & 0 deletions libraries/native_contract/native_contract_chain_initializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <eos/native_contract/system_contract.hpp>

#include <eos/chain/producer_object.hpp>
#include <eos/chain/permission_object.hpp>

#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>
Expand Down Expand Up @@ -143,6 +144,36 @@ std::vector<chain::Message> native_contract_chain_initializer::prepare_database(
});
boost::copy(genesis.initial_producers | CreateProducer, std::back_inserter(messages_to_process));

// Create special accounts
auto create_special_account = [this, &db](Name name, const auto& owner, const auto& active) {
db.create<account_object>([this, &name](account_object& a) {
a.name = name;
a.creation_date = genesis.initial_timestamp;
});
const auto& owner_permission = db.create<permission_object>([&owner, &name](permission_object& p) {
p.name = config::OwnerName;
p.parent = 0;
p.owner = name;
p.auth = std::move(owner);
});
db.create<permission_object>([&active, &owner_permission](permission_object& p) {
p.name = config::ActiveName;
p.parent = owner_permission.id;
p.owner = owner_permission.owner;
p.auth = std::move(active);
});
};

auto empty_authority = types::Authority(0, {}, {});
auto active_producers_authority = types::Authority(config::ProducersAuthorityThreshold, {}, {});
for(auto& p : genesis.initial_producers) {
active_producers_authority.accounts.push_back({{p.owner_name, config::ActiveName}, 1});
}

//CreateNativeAccount(config::AnybodyAccountName, 0);
create_special_account(config::NobodyAccountName, empty_authority, empty_authority);
create_special_account(config::ProducersAccountName, empty_authority, active_producers_authority);

return messages_to_process;
}

Expand Down
38 changes: 28 additions & 10 deletions libraries/types/include/eos/types/native.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

#include <fc/reflect/reflect.hpp>

#define N(X) eos::types::string_to_name(#X)

namespace eos { namespace types {
using namespace boost::multiprecision;

Expand Down Expand Up @@ -55,7 +57,33 @@ namespace eos { namespace types {
using Int128 = boost::multiprecision::int128_t;
using Int256 = boost::multiprecision::int256_t;
using uint128_t = unsigned __int128; /// native clang/gcc 128 intrinisic

static constexpr char char_to_symbol( char c ) {
if( c >= 'a' && c <= 'z' )
return (c - 'a') + 1;
if( c >= '1' && c <= '5' )
return (c - '1') + 26;
return 0;
}

static constexpr uint64_t string_to_name( const char* str ) {
uint32_t len = 0;
while( str[len] ) ++len;

uint64_t value = 0;

for( uint32_t i = 0; i <= 12 && i < len; ++i ) {
value <<= 5;
value |= char_to_symbol( str[ len -1 - i ] );
}

if( len == 13 ) {
value <<= 4;
value |= 0x0f & char_to_symbol( str[ 12 ] );
}
return value;
}

struct Name {
uint64_t value = 0;
bool valid()const { return 0 == (value >> 60); }
Expand All @@ -80,16 +108,6 @@ namespace eos { namespace types {
}
}FC_CAPTURE_AND_RETHROW( (str) ) }


char char_to_symbol( char c ) const {
if( c >= 'a' && c <= 'z' )
return (c - 'a') + 1;
if( c >= '1' && c <= '5' )
return (c - '1') + 27;
//FC_ASSERT( c == '.', "invalid character '${c}' (${i}) in Name string", ("c", String(&c,1))("i",int(c)) );
return 0;
}

Name( uint64_t v = 0 ):value(v){
// FC_ASSERT( !(v>>(5*12)), "invalid name id" );
}
Expand Down
140 changes: 140 additions & 0 deletions tests/tests/special_accounts_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#include <algorithm>
#include <vector>
#include <iterator>
#include <boost/test/unit_test.hpp>

#include <eos/chain/chain_controller.hpp>
#include <eos/chain/exceptions.hpp>
#include <eos/chain/permission_object.hpp>
#include <eos/chain/key_value_object.hpp>

#include <eos/native_contract/producer_objects.hpp>

#include <eos/utilities/tempdir.hpp>

#include <fc/crypto/digest.hpp>

#include <boost/test/unit_test.hpp>
#include <boost/range/algorithm/find.hpp>
#include <boost/range/algorithm/find_if.hpp>
#include <boost/range/algorithm/permutation.hpp>

#include "../common/database_fixture.hpp"

using namespace eos;
using namespace chain;

BOOST_AUTO_TEST_SUITE(special_account_tests)

//Check special accounts exits in genesis
BOOST_FIXTURE_TEST_CASE(accounts_exists, testing_fixture)
{ try {

Make_Blockchain(chain);

auto nobody = chain_db.find<account_object, by_name>(config::NobodyAccountName);
BOOST_CHECK(nobody != nullptr);
const auto& nobody_active_authority = chain_db.get<permission_object, by_owner>(boost::make_tuple(config::NobodyAccountName, config::ActiveName));
BOOST_CHECK_EQUAL(nobody_active_authority.auth.threshold, 0);
BOOST_CHECK_EQUAL(nobody_active_authority.auth.accounts.size(), 0);
BOOST_CHECK_EQUAL(nobody_active_authority.auth.keys.size(), 0);

const auto& nobody_owner_authority = chain_db.get<permission_object, by_owner>(boost::make_tuple(config::NobodyAccountName, config::OwnerName));
BOOST_CHECK_EQUAL(nobody_owner_authority.auth.threshold, 0);
BOOST_CHECK_EQUAL(nobody_owner_authority.auth.accounts.size(), 0);
BOOST_CHECK_EQUAL(nobody_owner_authority.auth.keys.size(), 0);

// TODO: check for anybody account
//auto anybody = chain_db.find<account_object, by_name>(config::AnybodyAccountName);
//BOOST_CHECK(anybody == nullptr);

auto producers = chain_db.find<account_object, by_name>(config::ProducersAccountName);
BOOST_CHECK(producers != nullptr);

auto& gpo = chain_db.get<global_property_object>();

const auto& producers_active_authority = chain_db.get<permission_object, by_owner>(boost::make_tuple(config::ProducersAccountName, config::ActiveName));
BOOST_CHECK_EQUAL(producers_active_authority.auth.threshold, config::ProducersAuthorityThreshold);
BOOST_CHECK_EQUAL(producers_active_authority.auth.accounts.size(), gpo.active_producers.size());
BOOST_CHECK_EQUAL(producers_active_authority.auth.keys.size(), 0);

std::vector<AccountName> active_auth;
for(auto& apw : producers_active_authority.auth.accounts) {
active_auth.emplace_back(apw.permission.account);
}

std::vector<AccountName> diff;
std::set_difference(
active_auth.begin(),
active_auth.end(),
gpo.active_producers.begin(),
gpo.active_producers.end(),
std::inserter(diff, diff.begin())
);

BOOST_CHECK_EQUAL(diff.size(), 0);

const auto& producers_owner_authority = chain_db.get<permission_object, by_owner>(boost::make_tuple(config::ProducersAccountName, config::OwnerName));
BOOST_CHECK_EQUAL(producers_owner_authority.auth.threshold, 0);
BOOST_CHECK_EQUAL(producers_owner_authority.auth.accounts.size(), 0);
BOOST_CHECK_EQUAL(producers_owner_authority.auth.keys.size(), 0);

} FC_LOG_AND_RETHROW() }

//Check correct authority when new set of producers are elected
BOOST_FIXTURE_TEST_CASE(producers_authority, testing_fixture)
{ try {

Make_Blockchain(chain)
chain.produce_blocks();

Make_Account(chain, alice);
Make_Account(chain, bob);
Make_Account(chain, charlie);

Make_Account(chain, newproducer1); Make_Producer(chain, newproducer1);
Make_Account(chain, newproducer2); Make_Producer(chain, newproducer2);
Make_Account(chain, newproducer3); Make_Producer(chain, newproducer3);

Approve_Producer(chain, alice, newproducer1, true);
Approve_Producer(chain, bob, newproducer2, true);
Approve_Producer(chain, charlie, newproducer3, true);

chain.produce_blocks(config::BlocksPerRound - chain.head_block_num() );

auto& gpo = chain_db.get<global_property_object>();

BOOST_REQUIRE(boost::find(gpo.active_producers, "newproducer1") != gpo.active_producers.end());
BOOST_REQUIRE(boost::find(gpo.active_producers, "newproducer2") != gpo.active_producers.end());
BOOST_REQUIRE(boost::find(gpo.active_producers, "newproducer3") != gpo.active_producers.end());

const auto& producers_active_authority = chain_db.get<permission_object, by_owner>(boost::make_tuple(config::ProducersAccountName, config::ActiveName));
BOOST_CHECK_EQUAL(producers_active_authority.auth.threshold, config::ProducersAuthorityThreshold);
BOOST_CHECK_EQUAL(producers_active_authority.auth.accounts.size(), gpo.active_producers.size());
BOOST_CHECK_EQUAL(producers_active_authority.auth.keys.size(), 0);

std::vector<AccountName> active_auth;
for(auto& apw : producers_active_authority.auth.accounts) {
active_auth.emplace_back(apw.permission.account);
}

std::vector<AccountName> diff;
std::set_difference(
active_auth.begin(),
active_auth.end(),
gpo.active_producers.begin(),
gpo.active_producers.end(),
std::inserter(diff, diff.begin())
);

BOOST_CHECK_EQUAL(diff.size(), 0);

const auto& producers_owner_authority = chain_db.get<permission_object, by_owner>(boost::make_tuple(config::ProducersAccountName, config::OwnerName));
BOOST_CHECK_EQUAL(producers_owner_authority.auth.threshold, 0);
BOOST_CHECK_EQUAL(producers_owner_authority.auth.accounts.size(), 0);
BOOST_CHECK_EQUAL(producers_owner_authority.auth.keys.size(), 0);

} FC_LOG_AND_RETHROW() }


BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 7178ea5

Please sign in to comment.