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

Commit

Permalink
Merge pull request #7111 from taokayan/get-sender-kayan
Browse files Browse the repository at this point in the history
Implement GET_SENDER protocol feature
  • Loading branch information
arhag authored Apr 12, 2019
2 parents a95b594 + da8b444 commit 632138d
Show file tree
Hide file tree
Showing 18 changed files with 246 additions and 8 deletions.
8 changes: 8 additions & 0 deletions libraries/chain/apply_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -814,5 +814,13 @@ void apply_context::add_ram_usage( account_name account, int64_t ram_delta ) {
}
}

action_name apply_context::get_sender() const {
const action_trace& trace = trx_context.get_action_trace( action_ordinal );
if (trace.creator_action_ordinal > 0) {
const action_trace& creator_trace = trx_context.get_action_trace( trace.creator_action_ordinal );
return creator_trace.receiver;
}
return 0;
}

} } /// eosio::chain
8 changes: 8 additions & 0 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ struct controller_impl {

set_activation_handler<builtin_protocol_feature_t::preactivate_feature>();
set_activation_handler<builtin_protocol_feature_t::replace_deferred>();
set_activation_handler<builtin_protocol_feature_t::get_sender>();


#define SET_APP_HANDLER( receiver, contract, action) \
Expand Down Expand Up @@ -3024,6 +3025,13 @@ void controller_impl::on_activation<builtin_protocol_feature_t::preactivate_feat
} );
}

template<>
void controller_impl::on_activation<builtin_protocol_feature_t::get_sender>() {
db.modify( db.get<protocol_state_object>(), [&]( auto& ps ) {
add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "get_sender" );
} );
}

template<>
void controller_impl::on_activation<builtin_protocol_feature_t::replace_deferred>() {
const auto& indx = db.get_index<account_ram_correction_index, by_id>();
Expand Down
2 changes: 2 additions & 0 deletions libraries/chain/include/eosio/chain/apply_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,8 @@ class apply_context {
action_name get_receiver()const { return receiver; }
const action& get_action()const { return *act; }

action_name get_sender() const;

/// Fields:
public:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ enum class builtin_protocol_feature_t : uint32_t {
disallow_empty_producer_schedule,
restrict_action_to_self,
only_bill_first_authorizer,
forward_setcode
forward_setcode,
get_sender
};

struct protocol_feature_subjective_restrictions {
Expand Down
11 changes: 11 additions & 0 deletions libraries/chain/protocol_feature_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,17 @@ Adds CPU and network bandwidth usage to only the first authorizer of a transacti
Builtin protocol feature: FORWARD_SETCODE
Forward eosio::setcode actions to the WebAssembly code deployed on the eosio account.
*/
{}
} )
( builtin_protocol_feature_t::get_sender, builtin_protocol_feature_spec{
"GET_SENDER",
fc::variant("1eab748b95a2e6f4d7cb42065bdee5566af8efddf01a55a0a8d831b823f8828a").as<digest_type>(),
// SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
/*
Builtin protocol feature: GET_SENDER
Allows contracts to determine which account is the sender of an inline action.
*/
{}
} )
Expand Down
4 changes: 4 additions & 0 deletions libraries/chain/wasm_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,9 @@ class system_api : public context_aware_api {
return context.control.is_protocol_feature_activated( feature_digest );
}

name get_sender() {
return context.get_sender();
}
};

constexpr size_t max_assert_message = 1024;
Expand Down Expand Up @@ -1811,6 +1814,7 @@ REGISTER_INTRINSICS(system_api,
(current_time, int64_t() )
(publication_time, int64_t() )
(is_feature_activated, int(int) )
(get_sender, int64_t() )
);

REGISTER_INTRINSICS(context_free_system_api,
Expand Down
1 change: 1 addition & 0 deletions unittests/contracts.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ namespace eosio {
// Contracts in `eos/unittests/unittests/test-contracts' directory
MAKE_READ_WASM_ABI(asserter, asserter, test-contracts)
MAKE_READ_WASM_ABI(deferred_test, deferred_test, test-contracts)
MAKE_READ_WASM_ABI(get_sender_test, get_sender_test, test-contracts)
MAKE_READ_WASM_ABI(noop, noop, test-contracts)
MAKE_READ_WASM_ABI(payloadless, payloadless, test-contracts)
MAKE_READ_WASM_ABI(proxy, proxy, test-contracts)
Expand Down
53 changes: 53 additions & 0 deletions unittests/protocol_feature_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -966,4 +966,57 @@ BOOST_AUTO_TEST_CASE( forward_setcode_test ) { try {
c2.produce_block();
} FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_CASE( get_sender_test ) { try {
tester c( setup_policy::preactivate_feature_and_new_bios );

const auto& tester1_account = account_name("tester1");
const auto& tester2_account = account_name("tester2");
c.create_accounts( {tester1_account, tester2_account} );
c.produce_block();

BOOST_CHECK_EXCEPTION( c.set_code( tester1_account, contracts::get_sender_test_wasm() ),
wasm_exception,
fc_exception_message_is( "env.get_sender unresolveable" ) );

const auto& pfm = c.control->get_protocol_feature_manager();
const auto& d = pfm.get_builtin_digest( builtin_protocol_feature_t::get_sender );
BOOST_REQUIRE( d );

c.preactivate_protocol_features( {*d} );
c.produce_block();

c.set_code( tester1_account, contracts::get_sender_test_wasm() );
c.set_abi( tester1_account, contracts::get_sender_test_abi().data() );
c.set_code( tester2_account, contracts::get_sender_test_wasm() );
c.set_abi( tester2_account, contracts::get_sender_test_abi().data() );
c.produce_block();

BOOST_CHECK_EXCEPTION( c.push_action( tester1_account, N(sendinline), tester1_account, mutable_variant_object()
("to", tester2_account.to_string())
("expected_sender", account_name{}) ),
eosio_assert_message_exception,
eosio_assert_message_is( "sender did not match" ) );

c.push_action( tester1_account, N(sendinline), tester1_account, mutable_variant_object()
("to", tester2_account.to_string())
("expected_sender", tester1_account.to_string())
);

c.push_action( tester1_account, N(notify), tester1_account, mutable_variant_object()
("to", tester2_account.to_string())
("expected_sender", tester1_account.to_string())
("send_inline", false)
);

c.push_action( tester1_account, N(notify), tester1_account, mutable_variant_object()
("to", tester2_account.to_string())
("expected_sender", tester2_account.to_string())
("send_inline", true)
);

c.push_action( tester1_account, N(assertsender), tester1_account, mutable_variant_object()
("expected_sender", account_name{})
);
} FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_SUITE_END()
1 change: 1 addition & 0 deletions unittests/test-contracts/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ endif()

add_subdirectory( asserter )
add_subdirectory( deferred_test )
add_subdirectory( get_sender_test )
add_subdirectory( integration_test )
add_subdirectory( noop )
add_subdirectory( payloadless )
Expand Down
2 changes: 1 addition & 1 deletion unittests/test-contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ test_ram_limit contract was compiled with eosio.cdt v1.4.1

That contract was ported to compile with eosio.cdt v1.5.0, but the test that uses it is very sensitive to stdlib/eosiolib changes, compilation flags and linker flags.

deferred_test, proxy, and reject_all contracts were compiled with eosio.cdt v1.6.1
deferred_test, get_sender_test, proxy, reject_all, and test_api contracts were compiled with eosio.cdt v1.6.1

The remaining contracts have been ported to compile with eosio.cdt v1.6.x. They were compiled with a patched version of eosio.cdt v1.6.0-rc1 (commit 1c9180ff5a1e431385180ce459e11e6a1255c1a4).
6 changes: 6 additions & 0 deletions unittests/test-contracts/get_sender_test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
if( EOSIO_COMPILE_TEST_CONTRACTS )
add_contract( get_sender_test get_sender_test get_sender_test.cpp )
else()
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/get_sender_test.wasm ${CMAKE_CURRENT_BINARY_DIR}/get_sender_test.wasm COPYONLY )
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/get_sender_test.abi ${CMAKE_CURRENT_BINARY_DIR}/get_sender_test.abi COPYONLY )
endif()
69 changes: 69 additions & 0 deletions unittests/test-contracts/get_sender_test/get_sender_test.abi
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"____comment": "This file was generated with eosio-abigen. DO NOT EDIT ",
"version": "eosio::abi/1.1",
"types": [],
"structs": [
{
"name": "assertsender",
"base": "",
"fields": [
{
"name": "expected_sender",
"type": "name"
}
]
},
{
"name": "notify",
"base": "",
"fields": [
{
"name": "to",
"type": "name"
},
{
"name": "expected_sender",
"type": "name"
},
{
"name": "send_inline",
"type": "bool"
}
]
},
{
"name": "sendinline",
"base": "",
"fields": [
{
"name": "to",
"type": "name"
},
{
"name": "expected_sender",
"type": "name"
}
]
}
],
"actions": [
{
"name": "assertsender",
"type": "assertsender",
"ricardian_contract": ""
},
{
"name": "notify",
"type": "notify",
"ricardian_contract": ""
},
{
"name": "sendinline",
"type": "sendinline",
"ricardian_contract": ""
}
],
"tables": [],
"ricardian_clauses": [],
"variants": []
}
30 changes: 30 additions & 0 deletions unittests/test-contracts/get_sender_test/get_sender_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* @file
* @copyright defined in eos/LICENSE
*/
#include "get_sender_test.hpp"
#include <eosio/transaction.hpp>

using namespace eosio;

void get_sender_test::assertsender( name expected_sender ) {
check( get_sender() == expected_sender, "sender did not match" );
}

void get_sender_test::sendinline( name to, name expected_sender ) {
assertsender_action a( to, std::vector<eosio::permission_level>{} );
a.send( expected_sender );
}

void get_sender_test::notify( name to, name expected_sender, bool send_inline ) {
require_recipient( to );
}

void get_sender_test::on_notify( name to, name expected_sender, bool send_inline ) {
if( send_inline ) {
assertsender_action a( get_first_receiver(), std::vector<eosio::permission_level>{} );
a.send( expected_sender );
} else {
check( get_sender() == expected_sender, "sender did not match" );
}
}
43 changes: 43 additions & 0 deletions unittests/test-contracts/get_sender_test/get_sender_test.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* @file
* @copyright defined in eos/LICENSE
*/
#pragma once

#include <eosio/eosio.hpp>

namespace eosio {
namespace internal_use_do_not_use {
extern "C" {
__attribute__((eosio_wasm_import))
uint64_t get_sender();
}
}
}

namespace eosio {
name get_sender() {
return name( internal_use_do_not_use::get_sender() );
}
}

class [[eosio::contract]] get_sender_test : public eosio::contract {
public:
using eosio::contract::contract;

[[eosio::action]]
void assertsender( eosio::name expected_sender );
using assertsender_action = eosio::action_wrapper<"assertsender"_n, &get_sender_test::assertsender>;

[[eosio::action]]
void sendinline( eosio::name to, eosio::name expected_sender );

[[eosio::action]]
void notify( eosio::name to, eosio::name expected_sender, bool send_inline );

// eosio.cdt 1.6.1 has a problem with "*::notify" so hardcode to tester1 for now.
// TODO: Change it back to "*::notify" when the bug is fixed in eosio.cdt.
[[eosio::on_notify("tester1::notify")]]
void on_notify( eosio::name to, eosio::name expected_sender, bool send_inline );

};
Binary file not shown.
10 changes: 5 additions & 5 deletions unittests/test-contracts/test_api/test_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ void test_action::test_action_ordinal1(uint64_t receiver, uint64_t code, uint64_
print("exec 1");
eosio::require_recipient( "bob"_n ); //-> exec 2 which would then cause execution of 4, 10

eosio::action act1({name(_self), "active"_n}, name(_self),
eosio::action act1({name(_self), "active"_n}, name(_self),
name(WASM_TEST_ACTION("test_action", "test_action_ordinal2")),
std::tuple<>());
act1.send(); // -> exec 5 which would then cause execution of 6, 7, 8
Expand All @@ -275,7 +275,7 @@ void test_action::test_action_ordinal1(uint64_t receiver, uint64_t code, uint64_
eosio_assert(false, "fail at point 1");
}

eosio::action act2({name(_self), "active"_n}, name(_self),
eosio::action act2({name(_self), "active"_n}, name(_self),
name(WASM_TEST_ACTION("test_action", "test_action_ordinal3")),
std::tuple<>());
act2.send(); // -> exec 9
Expand All @@ -284,15 +284,15 @@ void test_action::test_action_ordinal1(uint64_t receiver, uint64_t code, uint64_

} else if (receiver == "bob"_n.value) {
print("exec 2");
eosio::action act1({name(_self), "active"_n}, name(_self),
eosio::action act1({name(_self), "active"_n}, name(_self),
name(WASM_TEST_ACTION("test_action", "test_action_ordinal_foo")),
std::tuple<>());
act1.send(); // -> exec 10

eosio::require_recipient( "david"_n ); // -> exec 4
} else if (receiver == "charlie"_n.value) {
print("exec 3");
eosio::action act1({name(_self), "active"_n}, name(_self),
eosio::action act1({name(_self), "active"_n}, name(_self),
name(WASM_TEST_ACTION("test_action", "test_action_ordinal_bar")),
std::tuple<>()); // exec 11
act1.send();
Expand All @@ -314,7 +314,7 @@ void test_action::test_action_ordinal2(uint64_t receiver, uint64_t code, uint64_
eosio::require_recipient( "david"_n ); // -> exec 6
eosio::require_recipient( "erin"_n ); // -> exec 7

eosio::action act1({name(_self), "active"_n}, name(_self),
eosio::action act1({name(_self), "active"_n}, name(_self),
name(WASM_TEST_ACTION("test_action", "test_action_ordinal4")),
std::tuple<>());
act1.send(); // -> exec 8
Expand Down
3 changes: 2 additions & 1 deletion unittests/test-contracts/test_api/test_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ extern "C" {
}
WASM_TEST_HANDLER( test_action, assert_true_cf );

if ( action != WASM_TEST_ACTION("test_transaction", "stateful_api") && action != WASM_TEST_ACTION("test_transaction", "context_free_api") )
if ( action != WASM_TEST_ACTION("test_transaction", "stateful_api") &&
action != WASM_TEST_ACTION("test_transaction", "context_free_api") )
require_auth(code);

//test_types
Expand Down
Binary file modified unittests/test-contracts/test_api/test_api.wasm
Binary file not shown.

0 comments on commit 632138d

Please sign in to comment.