Skip to content

Commit

Permalink
Merge pull request #668 from gofractally/rename
Browse files Browse the repository at this point in the history
Add rename action which requires authorization by 2/3+1 of the chief …
  • Loading branch information
swatanabe authored Feb 23, 2022
2 parents e6efedc + f0f1c0c commit b0e7e45
Show file tree
Hide file tree
Showing 18 changed files with 225 additions and 2 deletions.
1 change: 1 addition & 0 deletions contracts/eden/include/accounts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ namespace eden
std::optional<account> get_account(eosio::name owner);
void add_balance(eosio::name owner, const eosio::asset& quantity, bool enforce_minimum);
void sub_balance(eosio::name owner, const eosio::asset& quantity);
void on_rename(eosio::name old_account, eosio::name new_account);

// this method is used only for administrative purposes,
// it should never be used outside genesis or test environments
Expand Down
1 change: 1 addition & 0 deletions contracts/eden/include/bylaws.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ namespace eden
// - Approvals on the pending bylaws are cleared
void new_board();
void on_resign(eosio::name member);
void on_rename(eosio::name member, eosio::name new_account);

void clear_all();
};
Expand Down
1 change: 1 addition & 0 deletions contracts/eden/include/distributions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ namespace eden
eosio::asset amount);
uint32_t on_election_kick(eosio::name member, uint32_t max_steps);
void on_resign(const member& member);
void on_rename(eosio::name old_account, eosio::name new_account);
void clear_all();
};
} // namespace eden
3 changes: 3 additions & 0 deletions contracts/eden/include/eden.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ namespace eden

void resign(eosio::name member);

void rename(eosio::name member, eosio::name newaccount);

void setencpubkey(eosio::name member, const eosio::public_key& key);

void electsettime(eosio::time_point_sec election_time);
Expand Down Expand Up @@ -288,6 +290,7 @@ namespace eden
eden_verb(inductcancel, 9, account, id, ricardian_contract(inductcancel_ricardian)),
action(inducted, inductee, ricardian_contract(inducted_ricardian)),
action(resign, account),
action(rename, old_account, new_account),
action(gc, limit, ricardian_contract(gc_ricardian)),
action(migrate, limit),
action(unmigrate),
Expand Down
2 changes: 1 addition & 1 deletion contracts/eden/include/eden_dispatcher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ namespace eden
#define EDEN_GET_SESSION_ACTION_INTERNAL_1(r, type, member) \
f(EDEN_EXTRACT_SESSION_ACTION_INDEX(member), \
BOOST_PP_STRINGIZE(EOSIO_EXTRACT_ACTION_NAME(member)), \
&type::EOSIO_EXTRACT_ACTION_NAME(member));
&type::EOSIO_EXTRACT_ACTION_NAME(member));
#define EDEN_GET_SESSION_ACTION_INTERNAL(r, type, member) \
BOOST_PP_IIF(EDEN_MATCH_SESSION_ACTION(member), EDEN_GET_SESSION_ACTION_INTERNAL_1, \
EOSIO_EMPTY) \
Expand Down
4 changes: 3 additions & 1 deletion contracts/eden/include/elections.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,6 @@ namespace eden
uint32_t randomize_voters(current_election_state_init_voters_v0& state, uint32_t max_steps);
std::vector<eosio::name> extract_board();
void finish_election(std::vector<eosio::name>&& board, eosio::name winner);
void set_board_permission(const std::vector<eosio::name>& board);
bool remove_from_board(eosio::name member);

public:
Expand All @@ -281,6 +280,8 @@ namespace eden
globals(contract)
{
}
void set_board_permission(const std::vector<eosio::name>& board);
void link_board_permission();
std::optional<eosio::block_timestamp> get_next_election_time();
std::uint8_t election_schedule_version();
void set_time(uint8_t day, const std::string& time);
Expand All @@ -292,6 +293,7 @@ namespace eden
uint32_t prepare_election(uint32_t max_steps);
uint32_t finish_round(uint32_t max_steps);
void on_resign(eosio::name member);
void on_rename(eosio::name old_account, eosio::name new_account);
// \pre voter and candidate are members of the same group
void vote(uint8_t round, eosio::name voter, eosio::name candidate);
boost::logic::tribool can_upload_video(uint8_t round, eosio::name voter);
Expand Down
2 changes: 2 additions & 0 deletions contracts/eden/include/inductions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ namespace eden
// Should only be used during genesis
void endorse_all(const induction& induction);

void on_rename(eosio::name old_account, eosio::name new_account);

// this method is used only for administrative purposes,
// it should never be used outside genesis or test environments
void clear_all();
Expand Down
1 change: 1 addition & 0 deletions contracts/eden/include/members.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ namespace eden
member_table_type::const_iterator erase(member_table_type::const_iterator iter);
void remove(eosio::name account);
void remove_if_pending(eosio::name account);
void rename(eosio::name old_account, eosio::name new_account);
bool is_new_member(eosio::name account) const;
void check_active_member(eosio::name account);
void check_pending_member(eosio::name account);
Expand Down
23 changes: 23 additions & 0 deletions contracts/eden/include/migrations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ namespace eden
eosio::name contract;
migration_singleton migration_sing;

template <int N>
static constexpr bool is_no_migration(const no_migration<N>&)
{
return true;
}
template <typename T>
static constexpr bool is_no_migration(const T&)
{
return false;
}

public:
migrations(eosio::name contract) : contract(contract), migration_sing(contract, default_scope)
{
Expand Down Expand Up @@ -65,5 +76,17 @@ namespace eden
return migration_sing.exists() &&
migration_sing.get().index() > boost::mp11::mp_find<migration_variant, T>::value;
}
void on_rename(eosio::name /*old_account*/, eosio::name /*new_account*/)
{
if (migration_sing.exists())
{
std::visit(
[](const auto& var) {
eosio::check(is_no_migration(var),
"Cannot rename account while a migration is in progress");
},
migration_sing.get());
}
}
};
} // namespace eden
13 changes: 13 additions & 0 deletions contracts/eden/src/accounts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,19 @@ namespace eden
account_tb.modify(record, contract, [&](auto& r) { r.balance() -= quantity; });
}

void accounts::on_rename(eosio::name old_account, eosio::name new_account)
{
auto record = account_tb.find(old_account.value);
if (record != account_tb.end())
{
account_tb.emplace(contract, [&](auto& new_record) {
new_record = *record;
new_record.owner() = new_account;
});
account_tb.erase(record);
}
}

void accounts::clear_all() { clear_table(account_tb); }

void add_to_pool(eosio::name contract, eosio::name pool, eosio::asset amount)
Expand Down
2 changes: 2 additions & 0 deletions contracts/eden/src/actions/genesis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ namespace eden

elections elections{get_self()};
elections.set_time(election_day, election_time);
elections.set_board_permission({});
elections.link_board_permission();

auto inviter = get_self();
auto total_endorsements = initial_members.size() - 1;
Expand Down
21 changes: 21 additions & 0 deletions contracts/eden/src/actions/induct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,4 +237,25 @@ namespace eden
bylaws.on_resign(account);
}

void eden::rename(eosio::name account, eosio::name new_account)
{
eosio::require_auth(new_account);
eosio::require_auth(eosio::permission_level{get_self(), "board.major"_n});
accounts accounts{get_self()};
accounts.on_rename(account, new_account);
members members{get_self()};
members.check_active_member(account);
distributions dist{get_self()};
dist.on_rename(account, new_account);
elections elections{get_self()};
elections.on_rename(account, new_account);
inductions inductions{get_self()};
inductions.on_rename(account, new_account);
members.rename(account, new_account);
bylaws bylaws{get_self()};
bylaws.on_rename(account, new_account);
migrations migrations{get_self()};
migrations.on_rename(account, new_account);
}

} // namespace eden
15 changes: 15 additions & 0 deletions contracts/eden/src/bylaws.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,20 @@ namespace eden
}
}

void bylaws::on_rename(eosio::name old_account, eosio::name new_account)
{
for (auto key : {proposed, pending})
{
auto pos = bylaws_tb.find(key.value);
if (pos != bylaws_tb.end())
{
bylaws_tb.modify(pos, contract, [&](auto& row) {
std::replace(row.approvals().begin(), row.approvals().end(), old_account,
new_account);
});
}
}
}

void bylaws::clear_all() { clear_table(bylaws_tb); }
} // namespace eden
24 changes: 24 additions & 0 deletions contracts/eden/src/distributions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,30 @@ namespace eden
}
}

void distributions::on_rename(eosio::name old_account, eosio::name new_account)
{
{
distribution_table_type distribution_tb{contract, default_scope};
auto iter = distribution_tb.begin();
eosio::check(iter == distribution_tb.end() ||
!std::holds_alternative<current_distribution>(iter->value),
"Cannot rename member while a distribution is in progress");
}

accounts owned_accounts{contract, "owned"_n};
setup_distribution(contract, owned_accounts);
auto member_idx = distribution_account_tb.get_index<"byowner"_n>();
for (auto iter = member_idx.lower_bound(uint128_t(old_account.value) << 64),
end = member_idx.end();
iter != end && iter->owner() == old_account;)
{
auto next = iter;
++next;
member_idx.modify(iter, contract, [&](auto& acct) { acct.owner() = new_account; });
iter = next;
}
}

void distributions::clear_all()
{
clear_table(distribution_account_tb);
Expand Down
34 changes: 34 additions & 0 deletions contracts/eden/src/elections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,15 @@ namespace eden
.send();
}

void elections::link_board_permission()
{
eosio::action{{contract, "active"_n},
"eosio"_n,
"linkauth"_n,
std::tuple(contract, contract, "rename"_n, "board.major"_n)}
.send();
}

void elections::finish_election(std::vector<eosio::name>&& board, eosio::name winner)
{
election_state_singleton results(contract, default_scope);
Expand Down Expand Up @@ -1020,6 +1029,31 @@ namespace eden
}
}

void elections::on_rename(eosio::name old_account, eosio::name new_account)
{
eosio::check(!is_election_running(state_sing), "Cannot rename account during an election");

// Update the board
election_state_singleton global_state{contract, default_scope};
if (!global_state.exists())
{
return;
}
auto value = std::get<election_state_v0>(global_state.get());
auto pos = std::find(value.board.begin(), value.board.end(), old_account);
if (pos != value.board.end())
{
*pos = new_account;
global_state.set(value, contract);
set_board_permission(value.board);
}
if (old_account == value.lead_representative)
{
value.lead_representative = new_account;
global_state.set(value, contract);
}
}

boost::logic::tribool elections::can_upload_video(uint8_t round, eosio::name voter)
{
auto iter = vote_tb.find(voter.value);
Expand Down
21 changes: 21 additions & 0 deletions contracts/eden/src/inductions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,27 @@ namespace eden
return pos != invitee_idx.end() && pos->invitee() == invitee;
}

void inductions::on_rename(eosio::name old_account, eosio::name new_account)
{
eosio::check(!has_induction(old_account), "Cannot rename: gc required");
// change all endorsements
auto endorser_idx = endorsement_tb.get_index<"byendorser"_n>();
for (auto iter = endorser_idx.lower_bound(uint128_t{old_account.value} << 64),
end = endorser_idx.end();
iter != end && iter->endorser() == old_account;)
{
auto next = iter;
++next;
endorser_idx.modify(iter, contract,
[&](auto& endorsement) { endorsement.endorser() = new_account; });
iter = next;
}
auto inviter_idx = induction_tb.get_index<"byinviter"_n>();
auto iter = inviter_idx.lower_bound(combine_names(old_account, ""_n));
eosio::check(iter == inviter_idx.end() || iter->inviter() != old_account,
"Cannot rename an account that is the inviter of a pending invitation");
}

void inductions::clear_all()
{
clear_table(induction_tb);
Expand Down
29 changes: 29 additions & 0 deletions contracts/eden/src/members.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,35 @@ namespace eden
}
}

void members::rename(eosio::name account, eosio::name new_account)
{
auto iter = member_tb.find(account.value);
eosio::check(iter != member_tb.end(), "Unknown member");
std::uint8_t rank = iter->election_rank();
remove_sessions(contract, account);
// Update the members table entry
member_tb.emplace(contract, [&](auto& new_member) {
new_member = *iter;
new_member.account() = new_account;
});
member_tb.erase(iter);
// update delegate records
auto delegate_idx = member_tb.get_index<"byrep"_n>();
for (uint8_t i = 0; i <= rank; ++i)
{
for (auto iter = delegate_idx.lower_bound((uint128_t{i} << 64) | account.value),
end = delegate_idx.end();
iter != end && iter->representative() == account;)
{
auto next = iter;
++next;
delegate_idx.modify(iter, contract,
[&](auto& member) { member.representative() = new_account; });
iter = next;
}
}
}

void members::set_nft(eosio::name account, int32_t nft_template_id)
{
check_pending_member(account);
Expand Down
30 changes: 30 additions & 0 deletions contracts/eden/tests/test-eden.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,32 @@ TEST_CASE("board resignation")
t.pip.act<actions::resign>("pip"_n);
}

TEST_CASE("renaming")
{
eden_tester t;
t.genesis();
auto distribution_time = t.next_election_time();
t.run_election();
t.alice.act<actions::distribute>(100);
t.alice.act<actions::fundtransfer>("alice"_n, distribution_time, 1, "alice"_n, s2a("0.0001 EOS"),
"");
test_chain::user_context{t.chain, {{"eden.gm"_n, "board.major"_n}, {"ahab"_n, "active"_n}}}
.act<actions::rename>("alice"_n, "ahab"_n);

expect(t.alice.trace<actions::withdraw>("alice"_n, s2a("0.0001 EOS")), "insufficient balance");
t.ahab.act<actions::withdraw>("ahab"_n, s2a("0.0001 EOS"));

t.chain.start_block();
expect(t.alice.trace<actions::fundtransfer>("alice"_n, distribution_time, 1, "alice"_n,
s2a("0.0001 EOS"), ""),
"member alice not found");
t.ahab.act<actions::fundtransfer>("ahab"_n, distribution_time, 1, "ahab"_n, s2a("0.0001 EOS"),
"");

CHECK(get_eden_membership("pip"_n).representative() == "ahab"_n);
CHECK(get_eden_membership("ahab"_n).representative() == "ahab"_n);
}

TEST_CASE("auction")
{
eden_tester t;
Expand Down Expand Up @@ -1176,6 +1202,10 @@ TEST_CASE("clearall")
eden_tester t;
t.genesis();
t.eden_gm.act<actions::clearall>();
t.chain.transact({{{"eden.gm"_n, "active"_n},
"eosio"_n,
"unlinkauth"_n,
std::tuple("eden.gm"_n, "eden.gm"_n, "rename"_n)}});
t.chain.start_block();
t.genesis();
}
Expand Down

0 comments on commit b0e7e45

Please sign in to comment.