提交 3d8fc22c 编写于 作者: N Nathan Hourt

Ref #15: Implement CreateAccount

上级 76148312
......@@ -738,6 +738,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
a.name = "sys";
});
register_message_type("sys", "Transfer");
register_message_type("sys", "CreateAccount");
// Create initial accounts
for (const auto& acct : genesis_state.initial_accounts) {
......
......@@ -29,11 +29,28 @@
namespace eos { namespace chain {
class shared_authority {
struct shared_authority {
shared_authority( chainbase::allocator<char> alloc )
:accounts(alloc),keys(alloc)
{}
shared_authority& operator=(const Authority& a) {
threshold = a.threshold;
accounts = decltype(accounts)(a.accounts.begin(), a.accounts.end(), accounts.get_allocator());
keys = decltype(keys)(a.keys.begin(), a.keys.end(), keys.get_allocator());
return *this;
}
shared_authority& operator=(Authority&& a) {
threshold = a.threshold;
accounts.reserve(a.accounts.size());
for (auto& p : a.accounts)
accounts.emplace_back(std::move(p));
keys.reserve(a.keys.size());
for (auto& p : a.keys)
keys.emplace_back(std::move(p));
return *this;
}
uint32_t threshold = 0;
shared_vector<PermissionLevel> accounts;
shared_vector<KeyPermission> keys;
......@@ -41,10 +58,10 @@ namespace eos { namespace chain {
class account_object : public chainbase::object<account_object_type, account_object>
{
OBJECT_CTOR(account_object, (name))
OBJECT_CTOR(account_object)
id_type id;
shared_string name;
account_name name;
uint64_t balance = 0;
uint64_t votes = 0;
uint64_t converting_votes = 0;
......@@ -56,8 +73,7 @@ namespace eos { namespace chain {
account_object,
indexed_by<
ordered_unique<tag<by_id>, member<account_object, account_object::id_type, &account_object::id>>,
ordered_unique<tag<by_name>, member<account_object, shared_string, &account_object::name>,
chainbase::strcmp_less>
ordered_unique<tag<by_name>, member<account_object, account_name, &account_object::name>>
>
>;
......
......@@ -19,8 +19,27 @@ namespace eos { namespace chain {
uint32_t threshold = 0;
vector<PermissionLevel> accounts;
vector<KeyPermission> keys;
bool validate() const {
if (threshold == 0)
return false;
uint32_t score = 0;
for (const auto& p : accounts)
score += p.weight;
for (const auto& p : keys)
score += p.weight;
return score >= threshold;
}
set<account_name> referenced_accounts() const {
set<account_name> results;
std::transform(accounts.begin(), accounts.end(), std::inserter(results, results.begin()),
[](const PermissionLevel& p) { return p.account; });
return results;
}
};
} } // eos::chain
FC_REFLECT( eos::chain::Authority, (threshold)(accounts)(keys) )
FC_REFLECT(eos::chain::PermissionLevel, (account)(level)(weight))
FC_REFLECT(eos::chain::KeyPermission, (key)(weight))
FC_REFLECT(eos::chain::Authority, (threshold)(accounts)(keys))
......@@ -14,7 +14,7 @@ void Transfer_validate_preconditions(chain::precondition_validate_context& conte
const auto& db = context.db;
auto transfer = context.msg.as<Transfer>();
const auto& from = db.get_account(context.msg.sender);
EOS_ASSERT(from.balance > transfer.amount, message_precondition_exception, "Insufficient Funds",
EOS_ASSERT(from.balance >= transfer.amount, message_precondition_exception, "Insufficient Funds",
("from.balance",from.balance)("transfer.amount",transfer.amount));
}
void Transfer_apply(chain::apply_context& context) {
......@@ -30,6 +30,52 @@ void Transfer_apply(chain::apply_context& context) {
});
}
void CreateAccount_validate(chain::message_validate_context& context) {
auto create = context.msg.as<CreateAccount>();
EOS_ASSERT(create.owner.validate(), message_validate_exception, "Invalid owner authority");
EOS_ASSERT(create.active.validate(), message_validate_exception, "Invalid active authority");
}
void CreateAccount_validate_preconditions(chain::precondition_validate_context& context) {
const auto& db = context.db;
auto create = context.msg.as<CreateAccount>();
auto existing_account = db.find<account_object, by_name>(create.new_account);
EOS_ASSERT(existing_account == nullptr, message_precondition_exception,
"Cannot create account named ${name}, as that name is already taken",
("name", create.new_account));
const auto& creator = db.get_account(context.msg.sender);
EOS_ASSERT(creator.balance >= create.initial_balance, message_precondition_exception, "Insufficient Funds");
for (const auto& account : create.owner.referenced_accounts())
db.get_account(account);
for (const auto& account : create.active.referenced_accounts())
db.get_account(account);
}
void CreateAccount_apply(chain::apply_context& context) {
auto& db = context.mutable_db;
auto create = context.msg.as<CreateAccount>();
db.modify(db.get_account(context.msg.sender), [&create](account_object& a) {
a.balance -= create.initial_balance;
});
const auto& new_account = db.create<account_object>([&create](account_object& a) {
a.name = create.new_account;
a.balance = create.initial_balance;
});
const auto& owner_permission = db.create<permission_object>([&create, &new_account](permission_object& p) {
p.name = "owner";
p.parent = 0;
p.owner = new_account.id;
p.auth = std::move(create.owner);
});
db.create<permission_object>([&create, &owner_permission](permission_object& p) {
p.name = "active";
p.parent = owner_permission.id;
p.owner = owner_permission.owner;
p.auth = std::move(create.active);
});
}
class native_system_contract_plugin_impl {
public:
native_system_contract_plugin_impl(database& db)
......@@ -61,5 +107,6 @@ void native_system_contract_plugin::install(database& db) {
db.set_apply_handler("sys", "sys", #name, &name ## _apply)
SET_HANDLERS(Transfer);
SET_HANDLERS(CreateAccount);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册