diff --git a/community/Readme.md b/community/Readme.md index 322d8f4..127886f 100644 --- a/community/Readme.md +++ b/community/Readme.md @@ -601,7 +601,7 @@ $ cleos get table governance23 community241 codeexecrule ```bash // last parameter is identify set for amendment code (1 is set for amendment code, 0 is set for code) $ cleos convert pack_action_data governance23 setexectype '["community241", 2, 1, 0]' -108af0d94d2d254504000000000000000100 +208af0d94d2d254529000000000000000000 ``` 2. pack `setapprotype` action data to set approval type of code proposal (approval type 1 is approval consensus): diff --git a/community/community.abi b/community/community.abi index 010b62f..94dd14a 100644 --- a/community/community.abi +++ b/community/community.abi @@ -263,6 +263,76 @@ } ] }, + { + "name": "configbadge", + "base": "", + "fields": [ + { + "name": "community_account", + "type": "name" + }, + { + "name": "badge_id", + "type": "uint64" + }, + { + "name": "issue_type", + "type": "uint8" + }, + { + "name": "update_badge_proposal_name", + "type": "name" + }, + { + "name": "issue_exec_type", + "type": "uint8" + }, + { + "name": "issue_sole_right_accounts", + "type": "name[]" + }, + { + "name": "issue_sole_right_pos_ids", + "type": "uint64[]" + }, + { + "name": "issue_proposer_right_accounts", + "type": "name[]" + }, + { + "name": "issue_proposer_right_pos_ids", + "type": "uint64[]" + }, + { + "name": "issue_approval_type", + "type": "uint8" + }, + { + "name": "issue_approver_right_accounts", + "type": "name[]" + }, + { + "name": "issue_approver_right_pos_ids", + "type": "uint64[]" + }, + { + "name": "issue_voter_right_accounts", + "type": "name[]" + }, + { + "name": "issue_voter_right_pos_ids", + "type": "uint64[]" + }, + { + "name": "issue_pass_rule", + "type": "float64" + }, + { + "name": "issue_vote_duration", + "type": "uint64" + } + ] + }, { "name": "configpos", "base": "", @@ -377,9 +447,65 @@ "name": "community_account", "type": "name" }, + { + "name": "badge_id", + "type": "uint64" + }, + { + "name": "issue_type", + "type": "uint8" + }, { "name": "badge_propose_name", "type": "name" + }, + { + "name": "issue_exec_type", + "type": "uint8" + }, + { + "name": "issue_sole_right_accounts", + "type": "name[]" + }, + { + "name": "issue_sole_right_pos_ids", + "type": "uint64[]" + }, + { + "name": "issue_proposer_right_accounts", + "type": "name[]" + }, + { + "name": "issue_proposer_right_pos_ids", + "type": "uint64[]" + }, + { + "name": "issue_approval_type", + "type": "uint8" + }, + { + "name": "issue_approver_right_accounts", + "type": "name[]" + }, + { + "name": "issue_approver_right_pos_ids", + "type": "uint64[]" + }, + { + "name": "issue_voter_right_accounts", + "type": "name[]" + }, + { + "name": "issue_voter_right_pos_ids", + "type": "uint64[]" + }, + { + "name": "issue_pass_rule", + "type": "float64" + }, + { + "name": "issue_vote_duration", + "type": "uint64" } ] }, @@ -1059,6 +1185,11 @@ "type": "approvepos", "ricardian_contract": "" }, + { + "name": "configbadge", + "type": "configbadge", + "ricardian_contract": "" + }, { "name": "configpos", "type": "configpos", diff --git a/community/community.wasm b/community/community.wasm index f77a92b..105c97c 100755 Binary files a/community/community.wasm and b/community/community.wasm differ diff --git a/community/include/community.hpp b/community/include/community.hpp index 9e02948..a7d793b 100644 --- a/community/include/community.hpp +++ b/community/include/community.hpp @@ -56,6 +56,11 @@ CONTRACT community : public contract BADGE, }; + enum BadgeIssueType { + WITHOUT_CLAIM = 0, + CLAIM_APPROVE_BY_ISSUER, + }; + struct permission_level_weight { permission_level permission; uint16_t weight; @@ -193,7 +198,43 @@ CONTRACT community : public contract ACTION dismisspos(name community_account, uint64_t pos_id, name holder, const string& dismissal_reason); - ACTION createbadge(name community_account, name badge_propose_name); + ACTION createbadge( + name community_account, + uint64_t badge_id, + uint8_t issue_type, + name badge_propose_name, + uint8_t issue_exec_type, + vector issue_sole_right_accounts, + vector issue_sole_right_pos_ids, + vector issue_proposer_right_accounts, + vector issue_proposer_right_pos_ids, + uint8_t issue_approval_type, + vector issue_approver_right_accounts, + vector issue_approver_right_pos_ids, + vector issue_voter_right_accounts, + vector issue_voter_right_pos_ids, + double issue_pass_rule, + uint64_t issue_vote_duration + ); + + ACTION configbadge( + name community_account, + uint64_t badge_id, + uint8_t issue_type, + name update_badge_proposal_name, + uint8_t issue_exec_type, + vector issue_sole_right_accounts, + vector issue_sole_right_pos_ids, + vector issue_proposer_right_accounts, + vector issue_proposer_right_pos_ids, + uint8_t issue_approval_type, + vector issue_approver_right_accounts, + vector issue_approver_right_pos_ids, + vector issue_voter_right_accounts, + vector issue_voter_right_pos_ids, + double issue_pass_rule, + uint64_t issue_vote_duration + ); ACTION issuebadge(name community_account, name badge_propose_name); diff --git a/community/src/community.cpp b/community/src/community.cpp index 652b35e..4ead174 100644 --- a/community/src/community.cpp +++ b/community/src/community.cpp @@ -37,6 +37,7 @@ const name PO_Dismiss = "po.dismiss"_n; const name BA_Create = "ba.create"_n; const name BA_Issue = "ba.issue"_n; +const name BA_Claim = "ba.claim"_n; const name BA_Config = "ba.config"_n; const name BA_Adopt = "ba.adopt"_n; const name BA_Discard = "ba.discard"_n; @@ -652,46 +653,51 @@ ACTION community::createcode(name community_account, name code_name, name contra code_sole_decision_table _code_execution_rule(_self, community_account.value); amend_sole_decision_table _amend_execution_rule(_self, community_account.value); - bool admin_is_created = false; - position_table _positions(_self, community_account.value); + code_collective_decision_table _code_vote_rule(_self, community_account.value); + ammend_collective_decision_table _amend_vote_rule(_self, community_account.value); - auto pos_itr = _positions.find(pos_admin_id); - admin_is_created = pos_itr != _positions.end(); + position_table _positions(_self, community_account.value); RightHolder _init_right_holder; + auto getByCodeName = _codes.get_index<"by.code.name"_n>(); + auto co_amend_code = getByCodeName.find(CO_Amend.value); + // save new code to the table auto new_codes = _codes.emplace(community_account, [&](auto &row) { row.code_id = _codes.available_primary_key(); row.code_name = code_name; row.contract_name = contract_name; row.code_actions = code_actions; - row.code_exec_type = ExecutionType::SOLE_DECISION; - row.amendment_exec_type = ExecutionType::SOLE_DECISION; + row.code_exec_type = co_amend_code->code_exec_type; + row.amendment_exec_type = co_amend_code->amendment_exec_type; row.code_type = {NORMAL, 0}; }); - if (admin_is_created) - { - _init_right_holder.required_positions.push_back(pos_admin_id); + if (co_amend_code->code_exec_type != ExecutionType::COLLECTIVE_DECISION) { + auto co_amend_code_sole_decision = _code_execution_rule.find(co_amend_code->code_id); + if(co_amend_code_sole_decision != _code_execution_rule.end()) { + _amend_execution_rule.emplace(community_account, [&](auto &row) { + row.code_id = new_codes->code_id; + row.right_executor = co_amend_code_sole_decision->right_executor; + }); + } } - else - { - auto com_itr = _communitys.find(community_account.value); - check(com_itr != _communitys.end(), "ERR::CREATEPROP_NOT_EXIST::Community does not exist."); - _init_right_holder.accounts.push_back(com_itr->creator); + if (co_amend_code->code_exec_type != ExecutionType::SOLE_DECISION) { + auto co_amend_code_collective_decision = _code_vote_rule.find(co_amend_code->code_id); + if (co_amend_code_collective_decision != _code_vote_rule.end()) { + _amend_vote_rule.emplace(community_account, [&](auto &row) { + row.code_id = new_codes->code_id; + row.right_proposer = co_amend_code_collective_decision->right_proposer; + row.right_approver = co_amend_code_collective_decision->right_approver; + row.right_voter = co_amend_code_collective_decision->right_voter; + row.approval_type = co_amend_code_collective_decision->approval_type; + row.pass_rule = co_amend_code_collective_decision->pass_rule; + row.vote_duration = co_amend_code_collective_decision->vote_duration; + }); + } } - - _code_execution_rule.emplace(community_account, [&](auto &row) { - row.code_id = new_codes->code_id; - row.right_executor = _init_right_holder; - }); - - _amend_execution_rule.emplace(community_account, [&](auto &row) { - row.code_id = new_codes->code_id; - row.right_executor = _init_right_holder; - }); } ACTION community::setexectype(name community_account, uint64_t code_id, uint8_t exec_type, bool is_amend_code) { @@ -1402,6 +1408,7 @@ ACTION community::configpos(name community_account, uint64_t pos_id, string pos_ }); } + cancel_deferred(pos_id); eosio::transaction auto_execute; auto_execute.actions.emplace_back(eosio::permission_level{community_account, "active"_n}, _self, "approvepos"_n, std::make_tuple(community_account, pos_id)); auto_execute.delay_sec = votting_end_date - current_time_point().sec_since_epoch(); @@ -1579,8 +1586,24 @@ ACTION community::dismisspos(name community_account, uint64_t pos_id, name holde }); } -ACTION community::createbadge(name community_account, name badge_propose_name) -{ +ACTION community::createbadge( + name community_account, + uint64_t badge_id, + uint8_t issue_type, + name badge_propose_name, + uint8_t issue_exec_type, + vector issue_sole_right_accounts, + vector issue_sole_right_pos_ids, + vector issue_proposer_right_accounts, + vector issue_proposer_right_pos_ids, + uint8_t issue_approval_type, + vector issue_approver_right_accounts, + vector issue_approver_right_pos_ids, + vector issue_voter_right_accounts, + vector issue_voter_right_pos_ids, + double issue_pass_rule, + uint64_t issue_vote_duration +) { // Todo: Verify badge param: action( permission_level{community_account, "active"_n}, @@ -1595,6 +1618,264 @@ ACTION community::createbadge(name community_account, name badge_propose_name) "exec"_n, std::make_tuple(cryptobadge_contract, badge_propose_name, community_account)) .send(); + + code_table _codes(_self, community_account.value); + + code_sole_decision_table _code_execution_rule(_self, community_account.value); + amend_sole_decision_table _amend_execution_rule(_self, community_account.value); + + code_collective_decision_table _code_vote_rule(_self, community_account.value); + ammend_collective_decision_table _amend_vote_rule(_self, community_account.value); + + position_table _positions(_self, community_account.value); + + auto getByCodeName = _codes.get_index<"by.code.name"_n>(); + auto ba_create_code = getByCodeName.find(BA_Create.value); + + vector code_actions; + code_actions.push_back("issuebadge"_n); + + name issue_badge_code_name; + if (issue_type == BadgeIssueType::WITHOUT_CLAIM) { + issue_badge_code_name = BA_Issue; + } else if (issue_type == BadgeIssueType::CLAIM_APPROVE_BY_ISSUER) { + issue_badge_code_name = BA_Claim; + } else { + check(false, "ERR::BADGE_ISSUE_TYPE_INVALID::Badge issue type is invalid"); + } + + // save new code to the table + auto issue_badge_code = _codes.emplace(community_account, [&](auto &row) { + row.code_id = _codes.available_primary_key(); + row.code_name = issue_badge_code_name; + row.contract_name = get_self(); + row.code_actions = code_actions; + row.code_exec_type = issue_exec_type; + row.code_type = {CodeTypeEnum::BADGE, badge_id}; + }); + + if (issue_exec_type != ExecutionType::COLLECTIVE_DECISION) { + RightHolder _right_holder; + _right_holder.accounts = issue_sole_right_accounts; + _right_holder.required_positions = issue_sole_right_pos_ids; + _code_execution_rule.emplace(community_account, [&](auto &row) { + row.code_id = issue_badge_code->code_id; + row.right_executor = _right_holder; + }); + } + + if (issue_exec_type != ExecutionType::SOLE_DECISION) { + RightHolder _right_proposer; + _right_proposer.accounts = issue_proposer_right_accounts; + _right_proposer.required_positions = issue_proposer_right_pos_ids; + RightHolder _right_approver; + _right_proposer.accounts = issue_approver_right_accounts; + _right_proposer.required_positions = issue_approver_right_pos_ids; + RightHolder _right_voter; + _right_proposer.accounts = issue_voter_right_accounts; + _right_proposer.required_positions = issue_voter_right_pos_ids; + _code_vote_rule.emplace(community_account, [&](auto &row) { + row.code_id = issue_badge_code->code_id; + row.right_proposer = _right_proposer; + row.right_approver = _right_approver; + row.right_voter = _right_voter; + row.approval_type = issue_approval_type; + row.pass_rule = issue_pass_rule; + row.vote_duration = issue_vote_duration; + }); + } + + code_actions.clear(); + code_actions.push_back("configbadge"_n); + + // save new code to the table + auto config_badge_code = _codes.emplace(community_account, [&](auto &row) { + row.code_id = _codes.available_primary_key(); + row.code_name = BA_Config; + row.contract_name = get_self(); + row.code_actions = code_actions; + row.amendment_exec_type = ba_create_code->code_exec_type; + row.code_type = {CodeTypeEnum::BADGE, badge_id}; + }); + + if (ba_create_code->code_exec_type != ExecutionType::COLLECTIVE_DECISION) { + auto ba_create_code_sole_decision = _code_execution_rule.find(ba_create_code->code_id); + if(ba_create_code_sole_decision != _code_execution_rule.end()) { + _amend_execution_rule.emplace(community_account, [&](auto &row) { + row.code_id = config_badge_code->code_id; + row.right_executor = ba_create_code_sole_decision->right_executor; + }); + + _code_execution_rule.emplace(community_account, [&](auto &row) { + row.code_id = config_badge_code->code_id; + row.right_executor = ba_create_code_sole_decision->right_executor; + }); + } + } + + if (ba_create_code->code_exec_type != ExecutionType::SOLE_DECISION) { + auto ba_create_code_collective_decision = _code_vote_rule.find(ba_create_code->code_id); + if (ba_create_code_collective_decision != _code_vote_rule.end()) { + _amend_vote_rule.emplace(community_account, [&](auto &row) { + row.code_id = config_badge_code->code_id; + row.right_proposer = ba_create_code_collective_decision->right_proposer; + row.right_approver = ba_create_code_collective_decision->right_approver; + row.right_voter = ba_create_code_collective_decision->right_voter; + row.approval_type = ba_create_code_collective_decision->approval_type; + row.pass_rule = ba_create_code_collective_decision->pass_rule; + row.vote_duration = ba_create_code_collective_decision->vote_duration; + }); + + _code_vote_rule.emplace(community_account, [&](auto &row) { + row.code_id = config_badge_code->code_id; + row.right_proposer = ba_create_code_collective_decision->right_proposer; + row.right_approver = ba_create_code_collective_decision->right_approver; + row.right_voter = ba_create_code_collective_decision->right_voter; + row.approval_type = ba_create_code_collective_decision->approval_type; + row.pass_rule = ba_create_code_collective_decision->pass_rule; + row.vote_duration = ba_create_code_collective_decision->vote_duration; + }); + } + } +} + +ACTION community::configbadge( + name community_account, + uint64_t badge_id, + uint8_t issue_type, + name update_badge_proposal_name, + uint8_t issue_exec_type, + vector issue_sole_right_accounts, + vector issue_sole_right_pos_ids, + vector issue_proposer_right_accounts, + vector issue_proposer_right_pos_ids, + uint8_t issue_approval_type, + vector issue_approver_right_accounts, + vector issue_approver_right_pos_ids, + vector issue_voter_right_accounts, + vector issue_voter_right_pos_ids, + double issue_pass_rule, + uint64_t issue_vote_duration +) { + if (update_badge_proposal_name != name("")) { + // Todo: Verify badge param: + action( + permission_level{community_account, "active"_n}, + "eosio.msig"_n, + "approve"_n, + std::make_tuple(cryptobadge_contract, update_badge_proposal_name, permission_level{community_account, "active"_n})) + .send(); + + action( + permission_level{community_account, "active"_n}, + "eosio.msig"_n, + "exec"_n, + std::make_tuple(cryptobadge_contract, update_badge_proposal_name, community_account)) + .send(); + } + + code_table _codes(_self, community_account.value); + + code_sole_decision_table _code_execution_rule(_self, community_account.value); + amend_sole_decision_table _amend_execution_rule(_self, community_account.value); + + code_collective_decision_table _code_vote_rule(_self, community_account.value); + ammend_collective_decision_table _amend_vote_rule(_self, community_account.value); + + position_table _positions(_self, community_account.value); + + auto getByCodeName = _codes.get_index<"by.code.name"_n>(); + auto ba_create_code = getByCodeName.find(BA_Create.value); + + name issue_badge_code_name; + if (issue_type == BadgeIssueType::WITHOUT_CLAIM) { + issue_badge_code_name = BA_Issue; + } else if (issue_type == BadgeIssueType::CLAIM_APPROVE_BY_ISSUER){ + issue_badge_code_name = BA_Claim; + } else { + check(false, "ERR::BADGE_ISSUE_TYPE_INVALID::Badge issue type is invalid"); + } + + auto getByCodeReferId = _codes.get_index<"by.refer.id"_n>(); + auto issue_badge_code_itr = getByCodeReferId.find(badge_id); + + while (issue_badge_code_itr != getByCodeReferId.end()) { + if (issue_badge_code_itr->code_type.type == CodeTypeEnum::BADGE && + ( issue_badge_code_itr->code_name == BA_Issue || issue_badge_code_itr->code_name == BA_Claim)) { + break; + } + issue_badge_code_itr++; + } + + // save new code to the table + if (issue_badge_code_itr == getByCodeReferId.end()) { + vector code_actions; + code_actions.push_back("issuebadge"_n); + _codes.emplace(community_account, [&](auto &row) { + row.code_id = _codes.available_primary_key(); + row.code_name = issue_badge_code_name; + row.contract_name = get_self(); + row.code_actions = code_actions; + row.amendment_exec_type = issue_exec_type; + row.code_type = {CodeTypeEnum::BADGE, badge_id}; + }); + } else { + getByCodeReferId.modify(issue_badge_code_itr, community_account, [&](auto &row) { + row.code_name = issue_badge_code_name; + row.code_exec_type = issue_exec_type; + row.code_type = {CodeTypeEnum::BADGE, badge_id}; + }); + } + + if (issue_exec_type != ExecutionType::COLLECTIVE_DECISION) { + RightHolder _right_holder; + _right_holder.accounts = issue_sole_right_accounts; + _right_holder.required_positions = issue_sole_right_pos_ids; + auto code_exec_type_itr = _code_execution_rule.find(issue_badge_code_itr->code_id); + if (code_exec_type_itr == _code_execution_rule.end()) { + _code_execution_rule.emplace(community_account, [&](auto &row) { + row.code_id = issue_badge_code_itr->code_id; + row.right_executor = _right_holder; + }); + } else { + _code_execution_rule.modify(code_exec_type_itr, community_account, [&](auto &row) { + row.right_executor = _right_holder; + }); + } + } + + if (issue_exec_type != ExecutionType::SOLE_DECISION) { + RightHolder _right_proposer; + _right_proposer.accounts = issue_proposer_right_accounts; + _right_proposer.required_positions = issue_proposer_right_pos_ids; + RightHolder _right_approver; + _right_approver.accounts = issue_approver_right_accounts; + _right_approver.required_positions = issue_approver_right_pos_ids; + RightHolder _right_voter; + _right_voter.accounts = issue_voter_right_accounts; + _right_voter.required_positions = issue_voter_right_pos_ids; + auto code_vote_rule_itr = _code_vote_rule.find(issue_badge_code_itr->code_id); + if (code_vote_rule_itr == _code_vote_rule.end()) { + _code_vote_rule.emplace(community_account, [&](auto &row) { + row.code_id = issue_badge_code_itr->code_id; + row.right_proposer = _right_proposer; + row.right_approver = _right_approver; + row.right_voter = _right_voter; + row.approval_type = issue_approval_type; + row.pass_rule = issue_pass_rule; + row.vote_duration = issue_vote_duration; + }); + } else { + _code_vote_rule.modify(code_vote_rule_itr, community_account, [&](auto &row) { + row.right_proposer = _right_proposer; + row.right_approver = _right_approver; + row.right_voter = _right_voter; + row.approval_type = issue_approval_type; + row.pass_rule = issue_pass_rule; + row.vote_duration = issue_vote_duration; + }); + } + } } ACTION community::issuebadge(name community_account, name badge_propose_name) @@ -1759,4 +2040,34 @@ bool community::is_amend_action(name calling_action) { } \ } -EOSIO_ABI_CUSTOM(community, (setapprotype)(setvoter)(setapprover)(transfer)(verifyamend)(createacc)(create)(initcode)(initadminpos)(execcode)(createcode)(createpos)(configpos)(nominatepos)(approvepos)(voteforcode)(voteforpos)(dismisspos)(setexectype)(appointpos)(proposecode)(execproposal)(verifyholder)(createbadge)(issuebadge)(setproposer)(setvoterule)) +EOSIO_ABI_CUSTOM(community, +(setapprotype) +(setvoter) +(setapprover) +(transfer) +(verifyamend) +(createacc) +(create) +(initcode) +(initadminpos) +(execcode) +(createcode) +(createpos) +(configpos) +(nominatepos) +(approvepos) +(voteforcode) +(voteforpos) +(dismisspos) +(setexectype) +(appointpos) +(proposecode) +(execproposal) +(verifyholder) +(createbadge) +(issuebadge) +(configbadge) +(setsoleexec) +(setproposer) +(setvoterule) +)