Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
sysio::multisig Class Reference

#include <sysio.msig.hpp>

Inheritance diagram for sysio::multisig:
Collaboration diagram for sysio::multisig:

Public Types

using propose_action = sysio::action_wrapper<"propose"_n, &multisig::propose>
 
using approve_action = sysio::action_wrapper<"approve"_n, &multisig::approve>
 
using unapprove_action = sysio::action_wrapper<"unapprove"_n, &multisig::unapprove>
 
using cancel_action = sysio::action_wrapper<"cancel"_n, &multisig::cancel>
 
using exec_action = sysio::action_wrapper<"exec"_n, &multisig::exec>
 
using invalidate_action = sysio::action_wrapper<"invalidate"_n, &multisig::invalidate>
 

Public Member Functions

void propose (ignore< name > proposer, ignore< name > proposal_name, ignore< std::vector< permission_level > > requested, ignore< transaction > trx)
 
void approve (name proposer, name proposal_name, permission_level level, const sysio::binary_extension< sysio::checksum256 > &proposal_hash)
 
void unapprove (name proposer, name proposal_name, permission_level level)
 
void cancel (name proposer, name proposal_name, name canceler)
 
void exec (name proposer, name proposal_name, name executer)
 
void invalidate (name account)
 

Detailed Description

The sysio.msig system contract allows for creation of proposed transactions which require authorization from a list of accounts, approval of the proposed transactions by those accounts required to approve it, and finally, it also allows the execution of the approved transactions on the blockchain.

In short, the workflow to propose, review, approve and then executed a transaction it can be described by the following:

  • first you create a transaction json file,
  • then you submit this proposal to the sysio.msig contract, and you also insert the account permissions required to approve this proposal into the command that submits the proposal to the blockchain,
  • the proposal then gets stored on the blockchain by the sysio.msig contract, and is accessible for review and approval to those accounts required to approve it,
  • after each of the appointed accounts required to approve the proposed transactions reviews and approves it, you can execute the proposed transaction. The sysio.msig contract will execute it automatically, but not before validating that the transaction has not expired, it is not cancelled, and it has been signed by all the permissions in the initial proposal's required permission list.

Definition at line 19 of file sysio.msig.hpp.

Member Typedef Documentation

◆ approve_action

using sysio::multisig::approve_action = sysio::action_wrapper<"approve"_n, &multisig::approve>

Definition at line 110 of file sysio.msig.hpp.

◆ cancel_action

using sysio::multisig::cancel_action = sysio::action_wrapper<"cancel"_n, &multisig::cancel>

Definition at line 112 of file sysio.msig.hpp.

◆ exec_action

using sysio::multisig::exec_action = sysio::action_wrapper<"exec"_n, &multisig::exec>

Definition at line 113 of file sysio.msig.hpp.

◆ invalidate_action

using sysio::multisig::invalidate_action = sysio::action_wrapper<"invalidate"_n, &multisig::invalidate>

Definition at line 114 of file sysio.msig.hpp.

◆ propose_action

using sysio::multisig::propose_action = sysio::action_wrapper<"propose"_n, &multisig::propose>

Definition at line 109 of file sysio.msig.hpp.

◆ unapprove_action

using sysio::multisig::unapprove_action = sysio::action_wrapper<"unapprove"_n, &multisig::unapprove>

Definition at line 111 of file sysio.msig.hpp.

Member Function Documentation

◆ approve()

void sysio::multisig::approve ( name proposer,
name proposal_name,
permission_level level,
const sysio::binary_extension< sysio::checksum256 > & proposal_hash )

Approve action approves an existing proposal. Allows an account, the owner of level permission, to approve a proposal proposal_name proposed by proposer. If the proposal's requested approval list contains the level permission then the level permission is moved from internal requested_approvals list to internal provided_approvals list of the proposal, thus persisting the approval for the proposal_name proposal. Storage changes are billed to proposer.

Parameters
proposer- The account proposing a transaction
proposal_name- The name of the proposal (should be unique for proposer)
level- Permission level approving the transaction
proposal_hash- Transaction's checksum

Definition at line 59 of file sysio.msig.cpp.

61{
62 require_auth( level );
63
64 if( proposal_hash ) {
65 proposals proptable( get_self(), proposer.value );
66 auto& prop = proptable.get( proposal_name.value, "proposal not found" );
67 assert_sha256( prop.packed_transaction.data(), prop.packed_transaction.size(), *proposal_hash );
68 }
69
70 approvals apptable( get_self(), proposer.value );
71 auto apps_it = apptable.find( proposal_name.value );
72 if ( apps_it != apptable.end() ) {
73 auto itr = std::find_if( apps_it->requested_approvals.begin(), apps_it->requested_approvals.end(), [&](const approval& a) { return a.level == level; } );
74 check( itr != apps_it->requested_approvals.end(), "approval is not on the list of requested approvals" );
75
76 apptable.modify( apps_it, proposer, [&]( auto& a ) {
77 a.provided_approvals.push_back( approval{ level, current_time_point() } );
78 a.requested_approvals.erase( itr );
79 });
80 } else {
81 old_approvals old_apptable( get_self(), proposer.value );
82 auto& apps = old_apptable.get( proposal_name.value, "proposal not found" );
83
84 auto itr = std::find( apps.requested_approvals.begin(), apps.requested_approvals.end(), level );
85 check( itr != apps.requested_approvals.end(), "approval is not on the list of requested approvals" );
86
87 old_apptable.modify( apps, proposer, [&]( auto& a ) {
88 a.provided_approvals.push_back( level );
89 a.requested_approvals.erase( itr );
90 });
91 }
92}
uint32_t level
Type of a channel package.
Definition levels.hpp:37
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181

◆ cancel()

void sysio::multisig::cancel ( name proposer,
name proposal_name,
name canceler )

Cancel action cancels an existing proposal.

Parameters
proposer- The account proposing a transaction
proposal_name- The name of the proposal (should be an existing proposal)
canceler- The account cancelling the proposal (only the proposer can cancel an unexpired transaction, and the canceler has to be different than the proposer)

Allows the canceler account to cancel the proposal_name proposal, created by a proposer, only after time has expired on the proposed transaction. It removes corresponding entries from internal proptable and from approval (or old approvals) tables as well.

Definition at line 118 of file sysio.msig.cpp.

118 {
119 require_auth( canceler );
120
121 proposals proptable( get_self(), proposer.value );
122 auto& prop = proptable.get( proposal_name.value, "proposal not found" );
123
124 if( canceler != proposer ) {
125 check( unpack<transaction_header>( prop.packed_transaction ).expiration < sysio::time_point_sec(current_time_point()), "cannot cancel until expiration" );
126 }
127 proptable.erase(prop);
128
129 //remove from new table
130 approvals apptable( get_self(), proposer.value );
131 auto apps_it = apptable.find( proposal_name.value );
132 if ( apps_it != apptable.end() ) {
133 apptable.erase(apps_it);
134 } else {
135 old_approvals old_apptable( get_self(), proposer.value );
136 auto apps_it = old_apptable.find( proposal_name.value );
137 check( apps_it != old_apptable.end(), "proposal not found" );
138 old_apptable.erase(apps_it);
139 }
140}

◆ exec()

void sysio::multisig::exec ( name proposer,
name proposal_name,
name executer )

Exec action allows an executer account to execute a proposal.

Preconditions:

  • executer has authorization,
  • proposal_name is found in the proposals table,
  • all requested approvals are received,
  • proposed transaction is not expired,
  • and approval accounts are not found in invalidations table.

If all preconditions are met the transaction is executed as a deferred transaction, and the proposal is erased from the proposals table.

Parameters
proposer- The account proposing a transaction
proposal_name- The name of the proposal (should be an existing proposal)
executer- The account executing the transaction

Definition at line 142 of file sysio.msig.cpp.

142 {
143 require_auth( executer );
144
145 proposals proptable( get_self(), proposer.value );
146 auto& prop = proptable.get( proposal_name.value, "proposal not found" );
147 transaction_header trx_header;
148 datastream<const char*> ds( prop.packed_transaction.data(), prop.packed_transaction.size() );
149 ds >> trx_header;
150 check( trx_header.expiration >= sysio::time_point_sec(current_time_point()), "transaction expired" );
151
152 approvals apptable( get_self(), proposer.value );
153 auto apps_it = apptable.find( proposal_name.value );
154 std::vector<permission_level> approvals;
155 invalidations inv_table( get_self(), get_self().value );
156 if ( apps_it != apptable.end() ) {
157 approvals.reserve( apps_it->provided_approvals.size() );
158 for ( auto& p : apps_it->provided_approvals ) {
159 auto it = inv_table.find( p.level.actor.value );
160 if ( it == inv_table.end() || it->last_invalidation_time < p.time ) {
161 approvals.push_back(p.level);
162 }
163 }
164 apptable.erase(apps_it);
165 } else {
166 old_approvals old_apptable( get_self(), proposer.value );
167 auto& apps = old_apptable.get( proposal_name.value, "proposal not found" );
168 for ( auto& level : apps.provided_approvals ) {
169 auto it = inv_table.find( level.actor.value );
170 if ( it == inv_table.end() ) {
171 approvals.push_back( level );
172 }
173 }
174 old_apptable.erase(apps);
175 }
176 auto packed_provided_approvals = pack(approvals);
177 auto res = check_transaction_authorization(
178 prop.packed_transaction.data(), prop.packed_transaction.size(),
179 (const char*)0, 0,
180 packed_provided_approvals.data(), packed_provided_approvals.size()
181 );
182
183 check( res > 0, "transaction authorization failed" );
184
185 send_deferred( (uint128_t(proposer.value) << 64) | proposal_name.value, executer,
186 prop.packed_transaction.data(), prop.packed_transaction.size() );
187
188 proptable.erase(prop);
189}
const mie::Vuint & p
Definition bn.cpp:27
static const Segment ds(Segment::ds)
__uint128_t uint128_t
Definition config.hpp:8
void pack(instruction_stream *stream, uint32_t field)
#define value
Definition pkcs11.h:157

◆ invalidate()

void sysio::multisig::invalidate ( name account)

Invalidate action allows an account to invalidate itself, that is, its name is added to the invalidations table and this table will be cross referenced when exec is performed.

Parameters
account- The account invalidating the transaction

Definition at line 191 of file sysio.msig.cpp.

191 {
192 require_auth( account );
193 invalidations inv_table( get_self(), get_self().value );
194 auto it = inv_table.find( account.value );
195 if ( it == inv_table.end() ) {
196 inv_table.emplace( account, [&](auto& i) {
197 i.account = account;
198 i.last_invalidation_time = current_time_point();
199 });
200 } else {
201 inv_table.modify( it, account, [&](auto& i) {
202 i.last_invalidation_time = current_time_point();
203 });
204 }
205}

◆ propose()

void sysio::multisig::propose ( ignore< name > proposer,
ignore< name > proposal_name,
ignore< std::vector< permission_level > > requested,
ignore< transaction > trx )

Propose action, creates a proposal containing one transaction. Allows an account proposer to make a proposal proposal_name which has requested permission levels expected to approve the proposal, and if approved by all expected permission levels then trx transaction can we executed by this proposal. The proposer account is authorized and the trx transaction is verified if it was authorized by the provided keys and permissions, and if the proposal name doesn’t already exist; if all validations pass the proposal_name and trx trasanction are saved in the proposals table and the requested permission levels to the approvals table (for the proposer context). Storage changes are billed to proposer.

Parameters
proposer- The account proposing a transaction
proposal_name- The name of the proposal (should be unique for proposer)
requested- Permission levels expected to approve the proposal
trx- Proposed transaction

Definition at line 9 of file sysio.msig.cpp.

13{
14 name _proposer;
15 name _proposal_name;
16 std::vector<permission_level> _requested;
17 transaction_header _trx_header;
18
19 _ds >> _proposer >> _proposal_name >> _requested;
20
21 const char* trx_pos = _ds.pos();
22 size_t size = _ds.remaining();
23 _ds >> _trx_header;
24
25 require_auth( _proposer );
26 check( _trx_header.expiration >= sysio::time_point_sec(current_time_point()), "transaction expired" );
27 //check( trx_header.actions.size() > 0, "transaction must have at least one action" );
28
29 proposals proptable( get_self(), _proposer.value );
30 check( proptable.find( _proposal_name.value ) == proptable.end(), "proposal with the same name exists" );
31
32 auto packed_requested = pack(_requested);
33 auto res = check_transaction_authorization(
34 trx_pos, size,
35 (const char*)0, 0,
36 packed_requested.data(), packed_requested.size()
37 );
38
39 check( res > 0, "transaction authorization failed" );
40
41 std::vector<char> pkd_trans;
42 pkd_trans.resize(size);
43 memcpy((char*)pkd_trans.data(), trx_pos, size);
44 proptable.emplace( _proposer, [&]( auto& prop ) {
45 prop.proposal_name = _proposal_name;
46 prop.packed_transaction = pkd_trans;
47 });
48
49 approvals apptable( get_self(), _proposer.value );
50 apptable.emplace( _proposer, [&]( auto& a ) {
51 a.proposal_name = _proposal_name;
52 a.requested_approvals.reserve( _requested.size() );
53 for ( auto& level : _requested ) {
54 a.requested_approvals.push_back( approval{ level, time_point{ microseconds{0} } } );
55 }
56 });
57}
std::string name
memcpy((char *) pInfo->slotDescription, s, l)
Here is the call graph for this function:

◆ unapprove()

void sysio::multisig::unapprove ( name proposer,
name proposal_name,
permission_level level )

Unapprove action revokes an existing proposal. This action is the reverse of the approve action: if all validations pass the level permission is erased from internal provided_approvals and added to the internal requested_approvals list, and thus un-approve or revoke the proposal.

Parameters
proposer- The account proposing a transaction
proposal_name- The name of the proposal (should be an existing proposal)
level- Permission level revoking approval for proposal

Definition at line 94 of file sysio.msig.cpp.

94 {
95 require_auth( level );
96
97 approvals apptable( get_self(), proposer.value );
98 auto apps_it = apptable.find( proposal_name.value );
99 if ( apps_it != apptable.end() ) {
100 auto itr = std::find_if( apps_it->provided_approvals.begin(), apps_it->provided_approvals.end(), [&](const approval& a) { return a.level == level; } );
101 check( itr != apps_it->provided_approvals.end(), "no approval previously granted" );
102 apptable.modify( apps_it, proposer, [&]( auto& a ) {
103 a.requested_approvals.push_back( approval{ level, current_time_point() } );
104 a.provided_approvals.erase( itr );
105 });
106 } else {
107 old_approvals old_apptable( get_self(), proposer.value );
108 auto& apps = old_apptable.get( proposal_name.value, "proposal not found" );
109 auto itr = std::find( apps.provided_approvals.begin(), apps.provided_approvals.end(), level );
110 check( itr != apps.provided_approvals.end(), "no approval previously granted" );
111 old_apptable.modify( apps, proposer, [&]( auto& a ) {
112 a.requested_approvals.push_back( level );
113 a.provided_approvals.erase( itr );
114 });
115 }
116}

The documentation for this class was generated from the following files: