Permalink
Switch branches/tags
1771-QA 1972-QA 2032 2153-QA 4064 4254-snapshots 4971-enable-stale-production-fix 4986-alternative-fix-2 5674-test-of-free-port 5674-under-min-avail DAWN-551-Contract-Debugging-Merge DAWN-551-Contract-Debugging april-26-workshop ben-demo-docs bft-dpos binaryen-recursion bios-boot-tutorial-block-age2 bitshares-fc-variant-fixes block_summaries bnet2 build-containers-on-commit buildkite-mojave cleos-R cleos-keos cleos-pretty-get-account-cleos-keos cleos-pretty-get-account cleos_warn_on_nonwasm cmake_boost_dep_cleanup constitution contextfree contract-refactor contracts-use-new-dbapi dan-slim dan-slim2 dan2 dawn-2.x dawn-617-genesis-claim dawn-690-gh#1844-enable-tests deferred-transactions deferred_transaction_fix develop dhaneshvb-malicious-contract diffie-hellman-key-exchange-545 docker-eosiocpp-fix docker-mongodb docs-112318 docs-pull-3991 doxygen-cpp-sdk ecc-r1 eos-noon-network eos-noon eos-repo-contract-refactor eos2 eosbios-gcc-compatibility eosio.system exchange2 feature/backport-docker-eosiocpp-fix feature/binary_release feature/bump-version-to-1.1.6 feature/bump-version-to-1.2.1 feature/bump-version-to-1.2.4 feature/bump-version-to-1.5.0-rc2 feature/logging-changes-for-testing feature/logging-changes feature/port-6222 feature/revert-6222 feature/1.0.8-security-omnibus feature/5057-subjectively-fail-ambiguous-dtrx-case final_keosd_unix_socket_changes fix_unused_lambda_captures fix/wasm_call_depth_limit fork-db-refactor gh#3612-bnet history-plugin-fix identity issue1760 issue2898 issue3187 jit-schedule-512 json-forever-loop-fix june-28-workshop keosd_daemon long-running-test-branch master merge/1.5.0-to-develop metric metric2 mongo-filter mongo-shard moxygen multisig native-contract-debugging network-buffer networkv2 new-checktime-injection new-ci-image-testing p2p-always-send p2p-connection-refactor p2p-issue-3017-fix packed-txn paul port-1.1.4 producer-txns read-mode-irreversible regularize-replay-logging release/1.0.x release/1.1.x release/1.2.x release/1.3.x release/1.4.x release/1.5.x remove-docker-nodeos-wallet-plugin-settings replay-irreversible-mode sdk sigabrt-net-plugin sim skip_skip_trx_checks slim snapshot-plugin staging superhero-01-25 system-contract-deferred-unstaking system-contract-upgrade system-test-fix-draft system systemcontract taokayan-abiarray token-refactor trivial_wallet_dir_lock txn_gen_modified txn_test_plugin_wasm_mt update-block-num vote-max-transaction-delay-2 vote-max-transaction-delay wasm32
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
138 lines (103 sloc) 5.25 KB
#include <eosio.msig/eosio.msig.hpp>
#include <eosiolib/action.hpp>
#include <eosiolib/permission.hpp>
namespace eosio {
/*
propose function manually parses input data (instead of taking parsed arguments from dispatcher)
because parsing data in the dispatcher uses too much CPU in case if proposed transaction is big
If we use dispatcher the function signature should be:
void multisig::propose( account_name proposer,
name proposal_name,
vector<permission_level> requested,
transaction trx)
*/
void multisig::propose() {
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<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;
require_auth( proposer );
eosio_assert( trx_header.expiration >= eosio::time_point_sec(now()), "transaction expired" );
//eosio_assert( trx_header.actions.size() > 0, "transaction must have at least one action" );
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);
});
}
void multisig::approve( account_name proposer, name proposal_name, permission_level level ) {
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 );
});
}
void multisig::unapprove( account_name proposer, name proposal_name, permission_level level ) {
require_auth( level );
approvals apptable( _self, proposer );
auto& apps = apptable.get( proposal_name, "proposal not found" );
auto itr = std::find( apps.provided_approvals.begin(), apps.provided_approvals.end(), level );
eosio_assert( itr != apps.provided_approvals.end(), "no approval previously granted" );
apptable.modify( apps, proposer, [&]( auto& a ) {
a.requested_approvals.push_back(level);
a.provided_approvals.erase(itr);
});
}
void multisig::cancel( account_name proposer, name proposal_name, account_name canceler ) {
require_auth( canceler );
proposals proptable( _self, proposer );
auto& prop = proptable.get( proposal_name, "proposal not found" );
if( canceler != proposer ) {
eosio_assert( unpack<transaction_header>( prop.packed_transaction ).expiration < eosio::time_point_sec(now()), "cannot cancel until expiration" );
}
approvals apptable( _self, proposer );
auto& apps = apptable.get( proposal_name, "proposal not found" );
proptable.erase(prop);
apptable.erase(apps);
}
void multisig::exec( account_name proposer, name proposal_name, account_name executer ) {
require_auth( executer );
proposals proptable( _self, proposer );
auto& prop = proptable.get( proposal_name, "proposal not found" );
approvals apptable( _self, proposer );
auto& apps = apptable.get( proposal_name, "proposal not found" );
transaction_header trx_header;
datastream<const char*> ds( prop.packed_transaction.data(), prop.packed_transaction.size() );
ds >> trx_header;
eosio_assert( trx_header.expiration >= eosio::time_point_sec(now()), "transaction expired" );
bytes packed_provided_approvals = pack(apps.provided_approvals);
auto res = ::check_transaction_authorization( prop.packed_transaction.data(), prop.packed_transaction.size(),
(const char*)0, 0,
packed_provided_approvals.data(), packed_provided_approvals.size()
);
eosio_assert( res > 0, "transaction authorization failed" );
send_deferred( (uint128_t(proposer) << 64) | proposal_name, executer, prop.packed_transaction.data(), prop.packed_transaction.size() );
proptable.erase(prop);
apptable.erase(apps);
}
} /// namespace eosio
EOSIO_ABI( eosio::multisig, (propose)(approve)(unapprove)(cancel)(exec) )