struct proposal {
name proposal_name;
vector packed_transaction;
auto primary_key()const { return proposal_name.value; }
};
typedef eosio::multi_index proposals;
struct approvals_info {
name proposal_name;
vector requested_approvals;
vector provided_approvals;
auto primary_key()const { return proposal_name.value; }
};
typedef eosio::multi_index approvals;
该接口会在合约接口实现中分析输入数据(而不是在系统的分发器),因为如果在交易数据很大,在系统分发器分析数据会消耗非常多的CPU。因为这样我们看到propose接口的函数声明是
propose()
如果使用系统的分发器,那么接口的函数声明应该是
propose(account_name proposer, name proposal_name, vector
requested, transaction trx)
constexpr size_t max_stack_buffer_size = 512;
size_t size = action_data_size();
char* buffer = (char*)( max_stack_buffer_size < size ? malloc(size) : alloca(size) );
read_action_data( buffer, size );
account_name proposer;
name proposal_name;
vector requested;
transaction_header trx_header;
datastream ds( buffer, size );
ds >> proposer >> proposal_name >> requested;
size_t trx_pos = ds.tellp();
ds >> trx_header;
require_auth( proposer );
eosio_assert( trx_header.expiration >= eosio::time_point_sec(now()), "transaction expired" );
proposals proptable( _self, proposer );
eosio_assert( proptable.find( proposal_name ) == proptable.end(), "proposal with the same name exists" );
bytes packed_requested = pack(requested);
auto res = ::check_transaction_authorization( buffer+trx_pos, size-trx_pos,
(const char*)0, 0,
packed_requested.data(),
packed_requested.size()
);
eosio_assert( res > 0, "transaction authorization failed" );
proptable.emplace( proposer, [&]( auto& prop ) {
prop.proposal_name = proposal_name;
prop.packed_transaction = bytes( buffer+trx_pos, buffer+size );
});
approvals apptable( _self, proposer );
apptable.emplace( proposer, [&]( auto& a ) {
a.proposal_name = proposal_name;
a.requested_approvals = std::move(requested);
});
require_auth( level );
approvals apptable( _self, proposer );
auto& apps = apptable.get( proposal_name, "proposal not found" );
auto itr = std::find( apps.requested_approvals.begin(), apps.requested_approvals.end(), level );
eosio_assert( itr != apps.requested_approvals.end(), "approval is not on the list of requested approvals" );
apptable.modify( apps, proposer, [&]( auto& a ) {
a.provided_approvals.push_back( level );
a.requested_approvals.erase( itr );
});
approve的逆操作。
任何人都可以取消提案,但是只有提案的提出者可以在提案有效期内中途取消提案。
// ...
if( canceler != proposer ) {
eosio_assert( unpack( prop.packed_transaction ).expiration < eosio::time_point_sec(now()), "cannot cancel until expiration" );
}
// ...
proptable.erase(prop);
apptable.erase(apps);
任何人都可以执行已经通过的提案。
提案只要被任何一个人执行,就会清除唯一的持久化记录。
提案是存在时效性的,过期的提案不可以被执行。
提案作为延时交易(deferred transaction)被执行,无论提案执行成功与否,持久化的提案记录都会被删除。
require_auth( executer );
// ...
eosio_assert( trx_header.expiration >= eosio::time_point_sec(now()), "transaction expired" );
// ...
send_deferred( (uint128_t(proposer) << 64) | proposal_name, executer, prop.packed_transaction.data(), prop.packed_transaction.size() );
proptable.erase(prop);
apptable.erase(apps);