Skip to content
This repository has been archived by the owner on Aug 30, 2022. It is now read-only.

Commit

Permalink
Merge pull request #121 from EOSIO/87-approve-with-hash-check
Browse files Browse the repository at this point in the history
Optionally assert multisig proposed transaction has particular ID as a condition for approval
  • Loading branch information
arhag authored Nov 8, 2018
2 parents 6c507c9 + a3cc6e6 commit c1f7e29
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 4 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
cmake_minimum_required(VERSION 3.5)
project(eosio_contracts VERSION 1.4.0)

set(EOSIO_CDT_VERSION_MIN "1.3")
set(EOSIO_CDT_VERSION_SOFT_MAX "1.3")
set(EOSIO_CDT_VERSION_MIN "1.4")
set(EOSIO_CDT_VERSION_SOFT_MAX "1.4")
#set(EOSIO_CDT_VERSION_HARD_MAX "")

find_package(eosio.cdt)
Expand Down
3 changes: 2 additions & 1 deletion eosio.msig/include/eosio.msig/eosio.msig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ namespace eosio {
void propose(ignore<name> proposer, ignore<name> proposal_name,
ignore<std::vector<permission_level>> requested, ignore<transaction> trx);
[[eosio::action]]
void approve( name proposer, name proposal_name, permission_level level );
void approve( name proposer, name proposal_name, permission_level level,
const eosio::binary_extension<eosio::checksum256>& proposal_hash );
[[eosio::action]]
void unapprove( name proposer, name proposal_name, permission_level level );
[[eosio::action]]
Expand Down
11 changes: 10 additions & 1 deletion eosio.msig/src/eosio.msig.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <eosio.msig/eosio.msig.hpp>
#include <eosiolib/action.hpp>
#include <eosiolib/permission.hpp>
#include <eosiolib/crypto.hpp>

namespace eosio {

Expand Down Expand Up @@ -57,9 +58,17 @@ void multisig::propose( ignore<name> proposer,
});
}

void multisig::approve( name proposer, name proposal_name, permission_level level ) {
void multisig::approve( name proposer, name proposal_name, permission_level level,
const eosio::binary_extension<eosio::checksum256>& proposal_hash )
{
require_auth( level );

if( proposal_hash ) {
proposals proptable( _self, proposer.value );
auto& prop = proptable.get( proposal_name.value, "proposal not found" );
assert_sha256( prop.packed_transaction.data(), prop.packed_transaction.size(), *proposal_hash );
}

approvals apptable( _self, proposer.value );
auto apps_it = apptable.find( proposal_name.value );
if ( apps_it != apptable.end() ) {
Expand Down
86 changes: 86 additions & 0 deletions tests/eosio.msig_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -861,4 +861,90 @@ BOOST_FIXTURE_TEST_CASE( approve_by_two_old, eosio_msig_tester ) try {

} FC_LOG_AND_RETHROW()

BOOST_FIXTURE_TEST_CASE( approve_with_hash, eosio_msig_tester ) try {
auto trx = reqauth("alice", {permission_level{N(alice), config::active_name}}, abi_serializer_max_time );
auto trx_hash = fc::sha256::hash( trx );
auto not_trx_hash = fc::sha256::hash( trx_hash );

push_action( N(alice), N(propose), mvo()
("proposer", "alice")
("proposal_name", "first")
("trx", trx)
("requested", vector<permission_level>{{ N(alice), config::active_name }})
);

//fail to approve with incorrect hash
BOOST_REQUIRE_EXCEPTION( push_action( N(alice), N(approve), mvo()
("proposer", "alice")
("proposal_name", "first")
("level", permission_level{ N(alice), config::active_name })
("proposal_hash", not_trx_hash)
),
eosio::chain::crypto_api_exception,
fc_exception_message_is("hash mismatch")
);

//approve and execute
push_action( N(alice), N(approve), mvo()
("proposer", "alice")
("proposal_name", "first")
("level", permission_level{ N(alice), config::active_name })
("proposal_hash", trx_hash)
);

transaction_trace_ptr trace;
control->applied_transaction.connect([&]( const transaction_trace_ptr& t) { if (t->scheduled) { trace = t; } } );
push_action( N(alice), N(exec), mvo()
("proposer", "alice")
("proposal_name", "first")
("executer", "alice")
);

BOOST_REQUIRE( bool(trace) );
BOOST_REQUIRE_EQUAL( 1, trace->action_traces.size() );
BOOST_REQUIRE_EQUAL( transaction_receipt::executed, trace->receipt->status );
} FC_LOG_AND_RETHROW()

BOOST_FIXTURE_TEST_CASE( switch_proposal_and_fail_approve_with_hash, eosio_msig_tester ) try {
auto trx1 = reqauth("alice", {permission_level{N(alice), config::active_name}}, abi_serializer_max_time );
auto trx1_hash = fc::sha256::hash( trx1 );

push_action( N(alice), N(propose), mvo()
("proposer", "alice")
("proposal_name", "first")
("trx", trx1)
("requested", vector<permission_level>{{ N(alice), config::active_name }})
);

auto trx2 = reqauth("alice",
{ permission_level{N(alice), config::active_name},
permission_level{N(alice), config::owner_name} },
abi_serializer_max_time );

push_action( N(alice), N(cancel), mvo()
("proposer", "alice")
("proposal_name", "first")
("canceler", "alice")
);

push_action( N(alice), N(propose), mvo()
("proposer", "alice")
("proposal_name", "first")
("trx", trx2)
("requested", vector<permission_level>{ { N(alice), config::active_name },
{ N(alice), config::owner_name } })
);

//fail to approve with hash meant for old proposal
BOOST_REQUIRE_EXCEPTION( push_action( N(alice), N(approve), mvo()
("proposer", "alice")
("proposal_name", "first")
("level", permission_level{ N(alice), config::active_name })
("proposal_hash", trx1_hash)
),
eosio::chain::crypto_api_exception,
fc_exception_message_is("hash mismatch")
);
} FC_LOG_AND_RETHROW()

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit c1f7e29

Please sign in to comment.