Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
sysio.msig.cpp
Go to the documentation of this file.
1#include <sysio/action.hpp>
2#include <sysio/crypto.hpp>
3#include <sysio/permission.hpp>
4
6
7namespace sysio {
8
9void multisig::propose( ignore<name> proposer,
10 ignore<name> proposal_name,
11 ignore<std::vector<permission_level>> requested,
12 ignore<transaction> trx )
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}
58
59void multisig::approve( name proposer, name proposal_name, permission_level level,
60 const sysio::binary_extension<sysio::checksum256>& proposal_hash )
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}
93
94void multisig::unapprove( name proposer, name proposal_name, permission_level level ) {
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}
117
118void multisig::cancel( name proposer, name proposal_name, name canceler ) {
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}
141
142void multisig::exec( name proposer, name proposal_name, name executer ) {
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}
190
191void multisig::invalidate( name account ) {
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}
206
207}
const mie::Vuint & p
Definition bn.cpp:27
void invalidate(name account)
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 approve(name proposer, name proposal_name, permission_level level, const sysio::binary_extension< sysio::checksum256 > &proposal_hash)
void propose(ignore< name > proposer, ignore< name > proposal_name, ignore< std::vector< permission_level > > requested, ignore< transaction > trx)
Definition sysio.msig.cpp:9
__uint128_t uint128_t
Definition config.hpp:8
#define value
Definition pkcs11.h:157
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
Immutable except for fc::from_variant.
Definition name.hpp:43
time_point_sec expiration
the time at which a transaction expires
memcpy((char *) pInfo->slotDescription, s, l)