eosio.msig合约源码分析

本文深入解析了 EOSIO 系统中 msig 模块的功能与工作原理,包括 propose、approve、unapprove、cancel 和 exec 等关键接口的详细流程,以及其在提案、审批和执行过程中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

eosio.msig

接口

  • propose()
  • propose(account_name proposer, name proposal_name, vector<permission_level> requested, transaction trx)
  • approve(account_name proposer, name proposal_name, permission_level level)
  • unapprove(account_name proposer, name proposal_name, permission_level level)
  • cancel(account_name proposer, name proposal_name, account_name canceler)
  • exec(account_name proposer, name proposal_name, account_name executer)

数据结构

struct proposal {
	name                       proposal_name;
	vector<char>               packed_transaction;

	auto primary_key()const { return proposal_name.value; }
};
typedef eosio::multi_index<N(proposal),proposal> proposals;

struct approvals_info {
	name                       proposal_name;
	vector<permission_level>   requested_approvals;
    vector<permission_level>   provided_approvals;

    auto primary_key()const { return proposal_name.value; }
};
typedef eosio::multi_index<N(approvals),approvals_info> approvals;

分析

propose

该接口会在合约接口实现中分析输入数据(而不是在系统的分发器),因为如果在交易数据很大,在系统分发器分析数据会消耗非常多的CPU。因为这样我们看到propose接口的函数声明是

propose()

如果使用系统的分发器,那么接口的函数声明应该是

propose(account_name proposer, name proposal_name, vector<permission_level> requested, transaction trx)

  1. propose首先会通过调用read_action_data读取传入的action数据
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 );
  1. 然后通过数据流datastream<const char*>反序列化参数数据
account_name proposer;
name proposal_name;
vector<permission_level> requested;
transaction_header trx_header;

datastream<const char*> ds( buffer, size );
ds >> proposer >> proposal_name >> requested;

size_t trx_pos = ds.tellp();
ds >> trx_header;
  1. 接着,要求poster的授权,检测提交方案的合约数据的时限是否还有效和提案是否重复
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" );
  1. 校验交易是否存在requested中指定的授权。
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" );
  1. 存储提案交易数据到持久化数据表
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);
});

approve

  1. 校验提案是否存在
  2. 校验提供的授权是否是需要的授权
  3. 添加授权到提案持久化数据与去除需要的对应授权。
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 );
});

unapprove

approve的逆操作。

cancel

任何人都可以取消提案,但是只有提案的提出者可以在提案有效期内中途取消提案。

// ...
if( canceler != proposer ) {
   eosio_assert( unpack<transaction_header>( prop.packed_transaction ).expiration < eosio::time_point_sec(now()), "cannot cancel until expiration" );
}
// ...
proptable.erase(prop);
apptable.erase(apps);

exec

任何人都可以执行已经通过的提案。
提案只要被任何一个人执行,就会清除唯一的持久化记录。
提案是存在时效性的,过期的提案不可以被执行。
提案作为延时交易(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);
EOSIO的设计包括: 免费汇率限制交易 低延迟阻止确认(0.5秒) 低开销的拜占庭容错终结 可选的高开销,低延迟BFT终端 由Web Assembly支持的智能合约平台 专为稀疏头灯客户端验证而设计 计划的周期性事务 时间延迟安全 基于角色的权限分级 支持生物识别硬件安全密钥(例如Apple安全飞地) 并行执行上下文自由验证逻辑 区块链间通信 EOSIO允许开发人员编写与需求确定性执行的共识算法兼容的业务逻辑。您的用户群可以使用安全的公钥基础结构与此业务逻辑进行交互,为您的业务带来区块链级别的安全性,责任性和可审计性。业务逻辑根据组织的治理结构轻松更新。 EOSIO旨在在没有任何令牌的环境中运行,系统管理员为用户分配可能无限制的资源配额。或者,智能合约可以通过其他方式分配资源配额,例如令牌销售,市场费用或投票。这使得EOSIO非常适合企业和社区驱动的区块链。 根据您的使用情况,可以将EOSIO配置为使用两种不同的Web装配引擎之一Binaryen和WAVM。单个EOSIO区块链可支持高达1,000 TPS,未来版本的EOSIO将提供简化区块链间通信所需的工具,使您的业务能够水平扩展。 EOSIO是在开放源代码MIT许可下发布的,按“原样”提供,没有任何明示或暗示的担保。EOSIO软件提供的任何安全性部分取决于它的使用,配置和部署方式。EOSIO建立在许多第三方库上,如Binaryen(Apache许可证)和WAVM(BSD 3-clause),它们也是“按现状”提供的,没有任何形式的保证。在不限制前述内容的一般性的情况下,Block.one不作任何陈述或保证EOSIO或任何第三方库将按预期执行或不会出现错误,错误或错误代码。这两种方式都可能以很大或很小的方式失败,这可能会完全或部分地限制功能或危害计算机系统。如果您使用或实施EOSIO,则自行承担风险。在任何情况下都不会阻止。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值