Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions libraries/chain/host_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ host_context::host_context(controller& con, transaction_context& trx_ctx)
}

// used to create a sync call context
host_context::host_context(controller& con, transaction_context& trx_ctx, account_name receiver, uint32_t sync_call_depth)
host_context::host_context(controller& con, transaction_context& trx_ctx, account_name receiver, bool privileged, uint32_t sync_call_depth)
: control(con)
, db(con.mutable_db())
, trx_context(trx_ctx)
, receiver(receiver)
, privileged(privileged)
, sync_call_depth(sync_call_depth)
, idx64(*this)
, idx128(*this)
Expand Down Expand Up @@ -74,7 +75,8 @@ uint32_t host_context::execute_sync_call(name call_receiver, uint64_t flags, std

try {
// use a new sync_call_context for next sync call
sync_call_context call_ctx(control, trx_context, get_sync_call_sender(), call_receiver, depth, flags, data);
sync_call_context call_ctx(control, trx_context, get_sync_call_sender(), call_receiver, receiver_account->is_privileged(), depth, flags, data);

control.get_wasm_interface().do_sync_call(receiver_account->code_hash, receiver_account->vm_type, receiver_account->vm_version, call_ctx);

// store return value
Expand Down
12 changes: 2 additions & 10 deletions libraries/chain/include/eosio/chain/apply_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,6 @@ class apply_context : public host_context {
bool cancel_deferred_transaction( const uint128_t& sender_id, account_name sender );
bool cancel_deferred_transaction( const uint128_t& sender_id ) override { return cancel_deferred_transaction(sender_id, receiver); }

// Not callable from apply_context (actions)
uint32_t get_call_data(std::span<char> memory) const override {
EOS_ASSERT(false, sync_call_validate_exception, "get_call_data can be only used in sync call");
};
void set_call_return_value(std::span<const char> return_value) override {
EOS_ASSERT(false, sync_call_validate_exception, "set_call_return_value can be only used in sync call");
};

protected:
uint32_t schedule_action( uint32_t ordinal_of_action_to_schedule, account_name receiver, bool context_free );
uint32_t schedule_action( action&& act_to_schedule, account_name receiver, bool context_free );
Expand Down Expand Up @@ -75,6 +67,8 @@ class apply_context : public host_context {

/// Misc methods:
public:
bool is_action() const override { return true; }

int get_action( uint32_t type, uint32_t index, char* buffer, size_t buffer_size )const override;
int get_context_free_data( uint32_t index, char* buffer, size_t buffer_size )const override;

Expand All @@ -86,7 +80,6 @@ class apply_context : public host_context {
void finalize_trace( action_trace& trace, const fc::time_point& start );

bool is_context_free()const override { return context_free; }
bool is_privileged()const override { return privileged; }
const action& get_action()const override { return *act; }
const action* get_action_ptr()const { return act; }

Expand All @@ -102,7 +95,6 @@ class apply_context : public host_context {
uint32_t recurse_depth; ///< how deep inline actions can recurse
uint32_t first_receiver_action_ordinal = 0;
uint32_t action_ordinal = 0;
bool privileged = false;
bool context_free = false;

private:
Expand Down
35 changes: 19 additions & 16 deletions libraries/chain/include/eosio/chain/host_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -484,8 +484,8 @@ class host_context {

public:
/// Constructor and destructor:
host_context(controller& con, transaction_context& trx_ctx);
host_context(controller& con, transaction_context& trx_ctx, account_name receiver, uint32_t sync_call_depth );
host_context(controller& con, transaction_context& trx_ctx); // for actions
host_context(controller& con, transaction_context& trx_ctx, account_name receiver, bool privileged, uint32_t sync_call_depth); // for sync calls
virtual ~host_context();

/// Authorization methods:
Expand All @@ -499,9 +499,9 @@ class host_context {
*
* @throws missing_auth_exception If no sufficient permission was found
*/
virtual void require_authorization(const account_name& account) = 0;
virtual bool has_authorization(const account_name& account) const = 0;
virtual void require_authorization(const account_name& account, const permission_name& permission) = 0;
virtual void require_authorization(const account_name& account) { assert(false); } // This function should never be called in sync calls due to require_auth host wrapper preconditions. The `assert` is used to prevent any coding errors.
virtual bool has_authorization(const account_name& account) const { assert(false); __builtin_unreachable(); }
virtual void require_authorization(const account_name& account, const permission_name& permission) { assert(false); }

/**
* @return true if account exists, false if it does not
Expand All @@ -514,7 +514,7 @@ class host_context {
/**
* Requires that the current action be delivered to account
*/
virtual void require_recipient(account_name account) = 0;
virtual void require_recipient(account_name account) { assert(false); }

/**
* Return true if the current action has already been scheduled to be
Expand Down Expand Up @@ -554,12 +554,12 @@ class host_context {
public:
vector<account_name> get_active_producers() const;

virtual int get_action( uint32_t type, uint32_t index, char* buffer, size_t buffer_size )const = 0;
virtual int get_context_free_data( uint32_t index, char* buffer, size_t buffer_size )const = 0;
virtual int get_action( uint32_t type, uint32_t index, char* buffer, size_t buffer_size ) const { assert(false); __builtin_unreachable(); }
virtual int get_context_free_data( uint32_t index, char* buffer, size_t buffer_size )const { assert(false); __builtin_unreachable(); }
virtual bool is_context_free()const = 0;
virtual bool is_privileged()const = 0;
bool is_privileged()const { return privileged; }
action_name get_receiver()const { return receiver; };
virtual const action& get_action()const = 0;
virtual const action& get_action()const { assert(false); __builtin_unreachable(); }
virtual action_name get_sender() const = 0;
account_name get_sync_call_sender() const { return receiver; } // current action or sync call's receiver is next call's sender

Expand All @@ -568,14 +568,16 @@ class host_context {
// sync calls can be initiated from actions or other sync calls
uint32_t execute_sync_call(name receiver, uint64_t flags, std::span<const char> data);
uint32_t get_call_return_value(std::span<char> memory) const;
virtual bool is_action() const { return false; }
virtual bool is_sync_call() const { return false; }

virtual uint32_t get_call_data(std::span<char> memory) const = 0;
virtual void set_call_return_value(std::span<const char> return_value) = 0;
virtual uint32_t get_call_data(std::span<char> memory) const { return 0; };
virtual void set_call_return_value(std::span<const char> return_value) {};

virtual void execute_inline( action&& a ) = 0;
virtual void execute_context_free_inline( action&& a ) = 0;
virtual void schedule_deferred_transaction( const uint128_t& sender_id, account_name payer, transaction&& trx, bool replace_existing ) = 0;
virtual bool cancel_deferred_transaction( const uint128_t& sender_id ) = 0;
virtual void execute_inline( action&& a ) { assert(false); }
virtual void execute_context_free_inline( action&& a ) { assert(false); }
virtual void schedule_deferred_transaction( const uint128_t& sender_id, account_name payer, transaction&& trx, bool replace_existing ) { assert(false); }
virtual bool cancel_deferred_transaction( const uint128_t& sender_id ) { assert(false); __builtin_unreachable(); }

/// Fields:
public:
Expand All @@ -585,6 +587,7 @@ class host_context {
transaction_context& trx_context; ///< transaction context in which the action is running
account_name receiver; ///< the code that is currently running
std::vector<char> action_return_value;
bool privileged = false;

std::optional<std::vector<char>> last_sync_call_return_value{}; // return value of last sync call initiated by the current code (host context)
const uint32_t sync_call_depth = 0; // depth for sync call
Expand Down
18 changes: 3 additions & 15 deletions libraries/chain/include/eosio/chain/sync_call_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ enum class sync_call_flags {

class sync_call_context : public host_context {
public:
sync_call_context(controller& con, transaction_context& trx_ctx, account_name sender, account_name receiver, uint32_t sync_call_depth, uint64_t flags, std::span<const char> data);
sync_call_context(controller& con, transaction_context& trx_ctx, account_name sender, account_name receiver, bool privileged, uint32_t sync_call_depth, uint64_t flags, std::span<const char> data);

uint32_t get_call_data(std::span<char> memory) const override;
void set_call_return_value(std::span<const char> return_value) override;

bool is_sync_call() const override { return true; }

bool is_read_only()const;
bool no_op_if_receiver_not_support_sync_call()const;
action_name get_sender() const override;
Expand All @@ -26,23 +28,9 @@ class sync_call_context : public host_context {
std::span<const char> data{}; // includes function name, arguments, and other information
std::vector<char> return_value{};

// Those cannot be called from sync_call_context. EOS_ASSERTs and tests will be added
// in next PR.
void require_authorization(const account_name& account) override;
bool has_authorization(const account_name& account) const override;
void require_authorization(const account_name& account, const permission_name& permission) override;
void require_recipient(account_name account) override;
bool has_recipient(account_name account)const override;
void update_db_usage( const account_name& payer, int64_t delta ) override;
int get_action( uint32_t type, uint32_t index, char* buffer, size_t buffer_size)const override;
int get_context_free_data( uint32_t index, char* buffer, size_t buffer_size )const override;
bool is_context_free()const override;
bool is_privileged()const override;
const action& get_action()const override;
void execute_inline( action&& a ) override;
void execute_context_free_inline( action&& a ) override;
void schedule_deferred_transaction( const uint128_t& sender_id, account_name payer, transaction&& trx, bool replace_existing ) override;
bool cancel_deferred_transaction( const uint128_t& sender_id ) override;
};

} } /// namespace eosio::chain
10 changes: 10 additions & 0 deletions libraries/chain/include/eosio/chain/webassembly/preconditions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,16 @@ namespace eosio { namespace chain { namespace webassembly {
"${code} does not have permission to call this API", ("code", ctx.get_host().get_context().get_receiver()));
}));

EOS_VM_PRECONDITION(action_check,
EOS_VM_INVOKE_ONCE([&](auto&&...) {
EOS_ASSERT(ctx.get_host().get_context().is_action(), unaccessible_api, "this API may only be called from action");
}));

EOS_VM_PRECONDITION(sync_call_check,
EOS_VM_INVOKE_ONCE([&](auto&&...) {
EOS_ASSERT(ctx.get_host().get_context().is_sync_call(), unaccessible_api, "this API may only be called from sync call");
}));

namespace detail {
template<typename T>
vm::span<const char> to_span(const vm::argument_proxy<T*>& val) {
Expand Down
40 changes: 4 additions & 36 deletions libraries/chain/sync_call_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

namespace eosio::chain {

sync_call_context::sync_call_context(controller& con, transaction_context& trx_ctx, account_name sender, account_name receiver, uint32_t sync_call_depth, uint64_t flags, std::span<const char>data)
: host_context(con, trx_ctx, receiver, sync_call_depth)
sync_call_context::sync_call_context(controller& con, transaction_context& trx_ctx, account_name sender, account_name receiver, bool privileged, uint32_t sync_call_depth, uint64_t flags, std::span<const char>data)
: host_context(con, trx_ctx, receiver, privileged, sync_call_depth)
, sender(sender)
, flags(flags)
, data(data)
Expand Down Expand Up @@ -52,46 +52,14 @@ action_name sync_call_context::get_sender() const {
}

// Always return false in sync calls
bool sync_call_context::has_authorization(const account_name& account) const {
return false;
}
bool sync_call_context::has_recipient(account_name account)const {
return false;
}
bool sync_call_context::is_context_free()const {
return false;
}
bool sync_call_context::is_privileged()const {
return false;
}

// EOS_ASSERTs and tests will be added for the following methods in next PR
void sync_call_context::require_authorization(const account_name& account) {
}
void sync_call_context::require_authorization(const account_name& account, const permission_name& permission) {
}
void sync_call_context::require_recipient(account_name account) {
}
void sync_call_context::update_db_usage( const account_name& payer, int64_t delta ) {
}
int sync_call_context::get_action( uint32_t type, uint32_t index, char* buffer, size_t buffer_size)const {
return 0;
}
int sync_call_context::get_context_free_data( uint32_t index, char* buffer, size_t buffer_size )const {
return 0;
}
const action& sync_call_context::get_action()const {
static action t;
return t;
}
void sync_call_context::execute_inline( action&& a ) {
}
void sync_call_context::execute_context_free_inline( action&& a ) {
}
void sync_call_context::schedule_deferred_transaction( const uint128_t& sender_id, account_name payer, transaction&& trx, bool replace_existing ) {
}
bool sync_call_context::cancel_deferred_transaction( const uint128_t& sender_id) {
return false;
}
// This needs to be investigated further
void sync_call_context::update_db_usage( const account_name& payer, int64_t delta ) {}

} /// eosio::chain
28 changes: 14 additions & 14 deletions libraries/chain/webassembly/runtimes/eos-vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,10 +513,10 @@ REGISTER_HOST_FUNCTION(get_permission_last_used);
REGISTER_HOST_FUNCTION(get_account_creation_time);

// authorization api
REGISTER_HOST_FUNCTION(require_auth);
REGISTER_HOST_FUNCTION(require_auth2);
REGISTER_HOST_FUNCTION(has_auth);
REGISTER_HOST_FUNCTION(require_recipient);
REGISTER_HOST_FUNCTION(require_auth, action_check);
REGISTER_HOST_FUNCTION(require_auth2, action_check);
REGISTER_HOST_FUNCTION(has_auth, action_check);
REGISTER_HOST_FUNCTION(require_recipient, action_check);
REGISTER_HOST_FUNCTION(is_account);
REGISTER_HOST_FUNCTION(get_code_hash);

Expand All @@ -534,16 +534,16 @@ REGISTER_CF_HOST_FUNCTION(eosio_assert_code)
REGISTER_CF_HOST_FUNCTION(eosio_exit)

// action api
REGISTER_LEGACY_CF_HOST_FUNCTION(read_action_data);
REGISTER_CF_HOST_FUNCTION(action_data_size);
REGISTER_LEGACY_CF_HOST_FUNCTION(read_action_data, action_check);
REGISTER_CF_HOST_FUNCTION(action_data_size, action_check);
REGISTER_CF_HOST_FUNCTION(current_receiver);
REGISTER_HOST_FUNCTION(set_action_return_value);
REGISTER_HOST_FUNCTION(set_action_return_value, action_check);

// sync call api. sync calls are not allowed in context-free actions
REGISTER_HOST_FUNCTION(call);
REGISTER_HOST_FUNCTION(get_call_return_value);
REGISTER_HOST_FUNCTION(get_call_data);
REGISTER_HOST_FUNCTION(set_call_return_value);
REGISTER_HOST_FUNCTION(get_call_data, sync_call_check);
REGISTER_HOST_FUNCTION(set_call_return_value, sync_call_check);

// console api
REGISTER_LEGACY_CF_HOST_FUNCTION(prints);
Expand Down Expand Up @@ -638,18 +638,18 @@ REGISTER_LEGACY_CF_HOST_FUNCTION(memcmp);
REGISTER_LEGACY_CF_HOST_FUNCTION(memset);

// transaction api
REGISTER_LEGACY_HOST_FUNCTION(send_inline);
REGISTER_LEGACY_HOST_FUNCTION(send_context_free_inline);
REGISTER_LEGACY_HOST_FUNCTION(send_deferred);
REGISTER_LEGACY_HOST_FUNCTION(cancel_deferred);
REGISTER_LEGACY_HOST_FUNCTION(send_inline, action_check);
REGISTER_LEGACY_HOST_FUNCTION(send_context_free_inline, action_check);
REGISTER_LEGACY_HOST_FUNCTION(send_deferred, action_check);
REGISTER_LEGACY_HOST_FUNCTION(cancel_deferred, action_check);

// context-free transaction api
REGISTER_LEGACY_CF_HOST_FUNCTION(read_transaction);
REGISTER_CF_HOST_FUNCTION(transaction_size);
REGISTER_CF_HOST_FUNCTION(expiration);
REGISTER_CF_HOST_FUNCTION(tapos_block_num);
REGISTER_CF_HOST_FUNCTION(tapos_block_prefix);
REGISTER_LEGACY_CF_HOST_FUNCTION(get_action);
REGISTER_LEGACY_CF_HOST_FUNCTION(get_action, action_check);

// compiler builtins api
REGISTER_LEGACY_CF_HOST_FUNCTION(__ashlti3);
Expand Down
Loading