提交 23a995b5 编写于 作者: D Daniel Larimer

restore apply context...

上级 5967bc77
......@@ -13,6 +13,7 @@ add_library( eosio_chain
resource_limits.cpp
block_log.cpp
genesis_state.cpp
context.cpp
# chain_config.cpp
# block_trace.cpp
......
此差异已折叠。
#include <eosio/chain/apply_context.hpp>
#include <eosio/chain/context.hpp>
namespace eosio { namespace chain {
void transaction_context::exec() {
control.record_transaction( trx_meta );
for( const auto& act : trx_meta->trx.context_free_actions ) {
dispatch_action( act, act.account, true );
}
for( const auto& act : trx_meta->trx.actions ) {
dispatch_action( act, act.account, false );
}
undo_session.squash();
}
void transaction_context::dispatch_action( const action& a, account_name receiver, bool context_free ) {
apply_context acontext( control, a, *trx_meta );
acontext.context_free = context_free;
acontext.receiver = receiver;
acontext.exec();
fc::move_append(executed, move(acontext.executed) );
}
} }
......@@ -1159,5 +1159,10 @@ const apply_handler* controller::find_apply_handler( account_name receiver, acco
wasm_interface& controller::get_wasm_interface() {
return my->wasmif;
}
const account_object& controller::get_account( account_name name )const
{ try {
return my->db.get<account_object, by_name>(name);
} FC_CAPTURE_AND_RETHROW( (name) ) }
} } /// eosio::chain
此差异已折叠。
......@@ -14,33 +14,8 @@ namespace eosio { namespace chain {
executed.reserve( trx_meta->total_actions() );
}
void exec() {
control.record_transaction( trx_meta );
for( const auto& act : trx_meta->trx.context_free_actions ) {
dispatch_action( act, act.account, true );
}
for( const auto& act : trx_meta->trx.actions ) {
dispatch_action( act, act.account, false );
}
undo_session.squash();
}
void dispatch_action( const action& a, account_name receiver, bool context_free = false ) {
action_receipt r;
r.receiver = receiver;
r.act = a;
r.global_sequence = control.next_global_sequence();
r.recv_sequence = control.next_recv_sequence( receiver );
for( const auto& auth : a.authorization ) {
r.auth_sequence[auth.actor] = control.next_auth_sequence( auth.actor );
}
executed.emplace_back( move(r) );
}
void exec();
void dispatch_action( const action& a, account_name receiver, bool context_free = false );
vector<action_receipt> executed;
......
......@@ -21,6 +21,7 @@ namespace eosio { namespace chain {
class dynamic_global_property_object;
class global_property_object;
class permission_object;
class account_object;
using resource_limits::resource_limits_manager;
using apply_handler = std::function<void(apply_context&)>;
......@@ -86,6 +87,7 @@ namespace eosio { namespace chain {
uint64_t next_auth_sequence( account_name actor );
void record_transaction( const transaction_metadata_ptr& trx );
const account_object& get_account( account_name n )const;
const global_property_object& get_global_properties()const;
const dynamic_global_property_object& get_dynamic_global_properties()const;
const permission_object& get_permission( const permission_level& level )const;
......
......@@ -18,17 +18,18 @@ class transaction_metadata {
signed_transaction trx;
packed_transaction packed_trx;
bytes raw_packed; /// fc::raw::pack(trx)
bytes raw_packed_with_cfd; /// fc::raw::pack(trx)
optional<flat_set<public_key_type>> signing_keys;
transaction_metadata( const signed_transaction& t )
:trx(t),packed_trx(t,packed_transaction::zlib) {
id = trx.id();
raw_packed = fc::raw::pack( trx );
raw_packed = fc::raw::pack( static_cast<const transaction&>(trx) );
}
transaction_metadata( const packed_transaction& ptrx )
:trx( ptrx.get_signed_transaction() ), packed_trx(ptrx) {
raw_packed = fc::raw::pack( trx );
raw_packed = fc::raw::pack( static_cast<const transaction&>(trx) );
id = trx.id();
}
......
#pragma once
#include <eosio/chain/wasm_interface.hpp>
#include <eosio/chain/webassembly/wavm.hpp>
#include <eosio/chain/webassembly/binaryen.hpp>
#include <eosio/chain/webassembly/runtime_interface.hpp>
#include <eosio/chain/wasm_eosio_injection.hpp>
#include "IR/Module.h"
#include "Runtime/Intrinsics.h"
#include "Platform/Platform.h"
#include "WAST/WAST.h"
#include "IR/Validate.h"
using namespace fc;
using namespace eosio::chain::webassembly;
using namespace IR;
using namespace Runtime;
namespace eosio { namespace chain {
struct wasm_interface_impl {
wasm_interface_impl(wasm_interface::vm_type vm) {
if(vm == wasm_interface::vm_type::wavm)
runtime_interface = std::make_unique<webassembly::wavm::wavm_runtime>();
else if(vm == wasm_interface::vm_type::binaryen)
runtime_interface = std::make_unique<webassembly::binaryen::binaryen_runtime>();
else
FC_THROW("wasm_interface_impl fall through");
}
std::vector<uint8_t> parse_initial_memory(const Module& module) {
std::vector<uint8_t> mem_image;
for(const DataSegment& data_segment : module.dataSegments) {
FC_ASSERT(data_segment.baseOffset.type == InitializerExpression::Type::i32_const);
FC_ASSERT(module.memories.defs.size());
const U32 base_offset = data_segment.baseOffset.i32;
const Uptr memory_size = (module.memories.defs[0].type.size.min << IR::numBytesPerPageLog2);
if(base_offset >= memory_size || base_offset + data_segment.data.size() > memory_size)
FC_THROW_EXCEPTION(wasm_execution_error, "WASM data segment outside of valid memory range");
if(base_offset + data_segment.data.size() > mem_image.size())
mem_image.resize(base_offset + data_segment.data.size(), 0x00);
memcpy(mem_image.data() + base_offset, data_segment.data.data(), data_segment.data.size());
}
return mem_image;
}
std::unique_ptr<wasm_instantiated_module_interface>& get_instantiated_module(const digest_type& code_id, const shared_vector<char>& code) {
auto it = instantiation_cache.find(code_id);
if(it == instantiation_cache.end()) {
IR::Module module;
try {
Serialization::MemoryInputStream stream((const U8*)code.data(), code.size());
WASM::serialize(stream, module);
} catch(Serialization::FatalSerializationException& e) {
EOS_ASSERT(false, wasm_serialization_error, e.message.c_str());
}
wasm_injections::wasm_binary_injection injector(module);
injector.inject();
std::vector<U8> bytes;
try {
Serialization::ArrayOutputStream outstream;
WASM::serialize(outstream, module);
bytes = outstream.getBytes();
} catch(Serialization::FatalSerializationException& e) {
EOS_ASSERT(false, wasm_serialization_error, e.message.c_str());
}
it = instantiation_cache.emplace(code_id, runtime_interface->instantiate_module((const char*)bytes.data(), bytes.size(), parse_initial_memory(module))).first;
}
return it->second;
}
std::unique_ptr<wasm_runtime_interface> runtime_interface;
map<digest_type, std::unique_ptr<wasm_instantiated_module_interface>> instantiation_cache;
};
#define _REGISTER_INTRINSIC_EXPLICIT(CLS, MOD, METHOD, WASM_SIG, NAME, SIG)\
_REGISTER_WAVM_INTRINSIC(CLS, MOD, METHOD, WASM_SIG, NAME, SIG)\
_REGISTER_BINARYEN_INTRINSIC(CLS, MOD, METHOD, WASM_SIG, NAME, SIG)
#define _REGISTER_INTRINSIC4(CLS, MOD, METHOD, WASM_SIG, NAME, SIG)\
_REGISTER_INTRINSIC_EXPLICIT(CLS, MOD, METHOD, WASM_SIG, NAME, SIG )
#define _REGISTER_INTRINSIC3(CLS, MOD, METHOD, WASM_SIG, NAME)\
_REGISTER_INTRINSIC_EXPLICIT(CLS, MOD, METHOD, WASM_SIG, NAME, decltype(&CLS::METHOD) )
#define _REGISTER_INTRINSIC2(CLS, MOD, METHOD, WASM_SIG)\
_REGISTER_INTRINSIC_EXPLICIT(CLS, MOD, METHOD, WASM_SIG, BOOST_PP_STRINGIZE(METHOD), decltype(&CLS::METHOD) )
#define _REGISTER_INTRINSIC1(CLS, MOD, METHOD)\
static_assert(false, "Cannot register " BOOST_PP_STRINGIZE(CLS) ":" BOOST_PP_STRINGIZE(METHOD) " without a signature");
#define _REGISTER_INTRINSIC0(CLS, MOD, METHOD)\
static_assert(false, "Cannot register " BOOST_PP_STRINGIZE(CLS) ":<unknown> without a method name and signature");
#define _UNWRAP_SEQ(...) __VA_ARGS__
#define _EXPAND_ARGS(CLS, MOD, INFO)\
( CLS, MOD, _UNWRAP_SEQ INFO )
#define _REGISTER_INTRINSIC(R, CLS, INFO)\
BOOST_PP_CAT(BOOST_PP_OVERLOAD(_REGISTER_INTRINSIC, _UNWRAP_SEQ INFO) _EXPAND_ARGS(CLS, "env", INFO), BOOST_PP_EMPTY())
#define REGISTER_INTRINSICS(CLS, MEMBERS)\
BOOST_PP_SEQ_FOR_EACH(_REGISTER_INTRINSIC, CLS, _WRAPPED_SEQ(MEMBERS))
#define _REGISTER_INJECTED_INTRINSIC(R, CLS, INFO)\
BOOST_PP_CAT(BOOST_PP_OVERLOAD(_REGISTER_INTRINSIC, _UNWRAP_SEQ INFO) _EXPAND_ARGS(CLS, EOSIO_INJECTED_MODULE_NAME, INFO), BOOST_PP_EMPTY())
#define REGISTER_INJECTED_INTRINSICS(CLS, MEMBERS)\
BOOST_PP_SEQ_FOR_EACH(_REGISTER_INJECTED_INTRINSIC, CLS, _WRAPPED_SEQ(MEMBERS))
} } // eosio::chain
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <vector>
#include <string>
namespace eosio { namespace chain {
std::vector<uint8_t> wast_to_wasm( const std::string& wast );
std::string wasm_to_wast( const std::vector<uint8_t>& wasm );
std::string wasm_to_wast( const uint8_t* data, uint64_t size );
} } /// eosio::chain
#pragma once
#include <eosio/chain/wasm_interface.hpp>
#include <eosio/chain/wasm_eosio_constraints.hpp>
#define EOSIO_INJECTED_MODULE_NAME "eosio_injection"
using namespace fc;
namespace eosio { namespace chain {
class apply_context;
template<typename T>
struct class_from_wasm {
/**
* by default this is just constructing an object
* @param wasm - the wasm_interface to use
* @return
*/
static auto value(apply_context& ctx) {
return T(ctx);
}
};
template<>
struct class_from_wasm<apply_context> {
/**
* Don't construct a new apply_context, just return a reference to the existing ont
* @param wasm
* @return
*/
static auto &value(apply_context& ctx) {
return ctx;
}
};
/**
* class to represent an in-wasm-memory array
* it is a hint to the transcriber that the next parameter will
* be a size (data bytes length) and that the pair are validated together
* This triggers the template specialization of intrinsic_invoker_impl
* @tparam T
*/
template<typename T>
struct array_ptr {
explicit array_ptr (T * value) : value(value) {}
typename std::add_lvalue_reference<T>::type operator*() const {
return *value;
}
T *operator->() const noexcept {
return value;
}
template<typename U>
operator U *() const {
return static_cast<U *>(value);
}
T *value;
};
/**
* class to represent an in-wasm-memory char array that must be null terminated
*/
struct null_terminated_ptr {
explicit null_terminated_ptr(char* value) : value(value) {}
typename std::add_lvalue_reference<char>::type operator*() const {
return *value;
}
char *operator->() const noexcept {
return value;
}
template<typename U>
operator U *() const {
return static_cast<U *>(value);
}
char *value;
};
} } // eosio::chain
#pragma once
#include <vector>
#include <memory>
namespace eosio { namespace chain {
class apply_context;
class wasm_instantiated_module_interface {
public:
virtual void apply(apply_context& context) = 0;
virtual ~wasm_instantiated_module_interface();
};
class wasm_runtime_interface {
public:
virtual std::unique_ptr<wasm_instantiated_module_interface> instantiate_module(const char* code_bytes, size_t code_size, std::vector<uint8_t> initial_memory) = 0;
virtual ~wasm_runtime_interface();
};
}}
\ No newline at end of file
......@@ -15,8 +15,8 @@ int main( int argc, char** argv ) {
signed_transaction trx;
trx.actions.resize(1);
trx.actions[0].account = N(exchange);
trx.actions[0].name = N(transfer);
trx.actions[0].account = N(eosio);
trx.actions[0].name = N(setcode);
trx.actions[0].authorization = { {N(dan),N(active) } };
trx.expiration = c.head_block_time() + fc::seconds(3);
trx.ref_block_num = c.head_block_num();
......
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <eosio/chain/wast_to_wasm.hpp>
#include <Inline/BasicTypes.h>
#include <IR/Module.h>
#include <IR/Validate.h>
#include <WAST/WAST.h>
#include <WASM/WASM.h>
#include <Runtime/Runtime.h>
#include <sstream>
#include <iomanip>
#include <fc/exception/exception.hpp>
namespace eosio { namespace chain {
std::vector<uint8_t> wast_to_wasm( const std::string& wast )
{
std::stringstream ss;
try {
IR::Module module;
std::vector<WAST::Error> parse_errors;
WAST::parseModule(wast.c_str(),wast.size(),module,parse_errors);
if(parse_errors.size())
{
// Print any parse errors;
ss << "Error parsing WebAssembly text file:" << std::endl;
for(auto& error : parse_errors)
{
ss << ":" << error.locus.describe() << ": " << error.message.c_str() << std::endl;
ss << error.locus.sourceLine << std::endl;
ss << std::setw(error.locus.column(8)) << "^" << std::endl;
}
FC_ASSERT( !"error parsing wast", "${msg}", ("msg",ss.str()) );
}
for(auto sectionIt = module.userSections.begin();sectionIt != module.userSections.end();++sectionIt)
{
if(sectionIt->name == "name") { module.userSections.erase(sectionIt); break; }
}
try
{
// Serialize the WebAssembly module.
Serialization::ArrayOutputStream stream;
WASM::serialize(stream,module);
return stream.getBytes();
}
catch(Serialization::FatalSerializationException exception)
{
ss << "Error serializing WebAssembly binary file:" << std::endl;
ss << exception.message << std::endl;
FC_ASSERT( !"error converting to wasm", "${msg}", ("msg",ss.get()) );
}
} FC_CAPTURE_AND_RETHROW( (wast) ) } /// wast_to_wasm
std::string wasm_to_wast( const std::vector<uint8_t>& wasm ) {
return wasm_to_wast( wasm.data(), wasm.size() );
} /// wasm_to_wast
std::string wasm_to_wast( const uint8_t* data, uint64_t size )
{ try {
IR::Module module;
Serialization::MemoryInputStream stream((const U8*)data,size);
WASM::serialize(stream,module);
// Print the module to WAST.
return WAST::print(module);
} FC_CAPTURE_AND_RETHROW() } /// wasm_to_wast
} } // eosio::chain
#include <eosio/chain/webassembly/binaryen.hpp>
#include <eosio/chain/apply_context.hpp>
#include <wasm-binary.h>
namespace eosio { namespace chain { namespace webassembly { namespace binaryen {
class binaryen_instantiated_module : public wasm_instantiated_module_interface {
public:
binaryen_instantiated_module(linear_memory_type& shared_linear_memory,
std::vector<uint8_t> initial_memory,
call_indirect_table_type table,
import_lut_type import_lut,
unique_ptr<Module>&& module) :
_shared_linear_memory(shared_linear_memory),
_initial_memory(initial_memory),
_table(forward<decltype(table)>(table)),
_import_lut(forward<decltype(import_lut)>(import_lut)),
_module(forward<decltype(module)>(module)) {
}
void apply(apply_context& context) override {
LiteralList args = {Literal(uint64_t(context.receiver)),
Literal(uint64_t(context.act.account)),
Literal(uint64_t(context.act.name))};
call("apply", args, context);
}
private:
linear_memory_type& _shared_linear_memory;
std::vector<uint8_t> _initial_memory;
call_indirect_table_type _table;
import_lut_type _import_lut;
unique_ptr<Module> _module;
void call(const string& entry_point, LiteralList& args, apply_context& context){
const unsigned initial_memory_size = _module->memory.initial*Memory::kPageSize;
interpreter_interface local_interface(_shared_linear_memory, _table, _import_lut, initial_memory_size, context);
//zero out the initial pages
memset(_shared_linear_memory.data, 0, initial_memory_size);
//copy back in the initial data
memcpy(_shared_linear_memory.data, _initial_memory.data(), _initial_memory.size());
//be aware that construction of the ModuleInstance implictly fires the start function
ModuleInstance instance(*_module.get(), &local_interface);
instance.callExport(Name(entry_point), args);
}
};
binaryen_runtime::binaryen_runtime() {
}
std::unique_ptr<wasm_instantiated_module_interface> binaryen_runtime::instantiate_module(const char* code_bytes, size_t code_size, std::vector<uint8_t> initial_memory) {
try {
vector<char> code(code_bytes, code_bytes + code_size);
unique_ptr<Module> module(new Module());
WasmBinaryBuilder builder(*module, code, false);
builder.read();
FC_ASSERT(module->memory.initial * Memory::kPageSize <= wasm_constraints::maximum_linear_memory);
// create a temporary globals to use
TrivialGlobalManager globals;
for (auto& global : module->globals) {
globals[global->name] = ConstantExpressionRunner<TrivialGlobalManager>(globals).visit(global->init).value;
}
call_indirect_table_type table;
table.resize(module->table.initial);
for (auto& segment : module->table.segments) {
Address offset = ConstantExpressionRunner<TrivialGlobalManager>(globals).visit(segment.offset).value.geti32();
assert(offset + segment.data.size() <= module->table.initial);
for (size_t i = 0; i != segment.data.size(); ++i) {
table[offset + i] = segment.data[i];
}
}
// initialize the import lut
import_lut_type import_lut;
import_lut.reserve(module->imports.size());
for (auto& import : module->imports) {
std::string full_name = string(import->module.c_str()) + "." + string(import->base.c_str());
if (import->kind == ExternalKind::Function) {
auto& intrinsic_map = intrinsic_registrator::get_map();
auto intrinsic_itr = intrinsic_map.find(full_name);
if (intrinsic_itr != intrinsic_map.end()) {
import_lut.emplace(make_pair((uintptr_t)import.get(), intrinsic_itr->second));
continue;
}
}
FC_ASSERT( !"unresolvable", "${module}.${export}", ("module",import->module.c_str())("export",import->base.c_str()) );
}
return std::make_unique<binaryen_instantiated_module>(_memory, initial_memory, move(table), move(import_lut), move(module));
} catch (const ParseException &e) {
FC_THROW_EXCEPTION(wasm_execution_error, "Error building interpreter: ${s}", ("s", e.text));
}
}
}}}}
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册