提交 44e34285 编写于 作者: D Daniel Larimer

Remove DefineStruct and Fix Unit Tests

In original design all messages passed between contracts would consist
of well defined types, these types would be used with code generation to
parse message data and then pass rich Wren objects to user defined
message handlers.  The switch to Web Assembly made this irrelevent and
counter productive.

Going forward applications will be able to define and publish their own
ABI and serialization techniques. This will make the core platform simpler.

Fixed code caching
上级 c4768c29
......@@ -113,7 +113,8 @@ else( WIN32 ) # Apple AND Linux
if( APPLE )
# Apple Specific Options Here
message( STATUS "Configuring Eos on OS X" )
set( CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++14 -Wall -Wno-invalid-partial-specialization -Wno-deprecated-declarations" )
#set( CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++14 -Wall -Wno-invalid-partial-specialization -Wno-deprecated-declarations" )
set( CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++14 -Wall -Wno-deprecated-declarations" )
else( APPLE )
# Linux Specific Options Here
message( STATUS "Configuring Eos on Linux" )
......
......@@ -510,7 +510,6 @@ try {
validate_tapos(trx);
validate_referenced_accounts(trx);
validate_expiration(trx);
validate_message_types(trx);
for (const auto& tm : trx.messages) { /// TODO: this loop can be processed in parallel
Message m(tm);
......@@ -585,17 +584,6 @@ void chain_controller::validate_expiration(const SignedTransaction& trx) const
("now",now)("trx.exp",trx.expiration));
} FC_CAPTURE_AND_RETHROW((trx)) }
void chain_controller::validate_message_types(const SignedTransaction& trx)const {
try {
for( const auto& msg : trx.messages ) {
try {
_db.get<type_object, by_scope_name>( boost::make_tuple(msg.recipient, msg.type) );
} catch(std::out_of_range) {
FC_THROW_EXCEPTION(message_validate_exception, "Unrecognized message recipient and type",
("recipient", msg.recipient)("type", msg.type));
}
}
} FC_CAPTURE_AND_RETHROW( (trx) ) }
void chain_controller::validate_message_precondition( precondition_validate_context& context )const
{ try {
......@@ -778,7 +766,6 @@ void chain_controller::initialize_indexes() {
_db.add_index<account_index>();
_db.add_index<permission_index>();
_db.add_index<action_permission_index>();
_db.add_index<type_index>();
_db.add_index<key_value_index>();
_db.add_index<global_property_multi_index>();
......@@ -1084,60 +1071,6 @@ void chain_controller::set_apply_handler( const AccountName& contract, const Acc
chain_initializer_interface::~chain_initializer_interface() {}
template<typename T>
void chain_controller::to_binary( const AccountName& scope, const TypeName& type, const fc::variant& value, fc::datastream<T>& ds )const
{ try {
const auto& type_obj = _db.get<type_object,by_scope_name>( boost::make_tuple(scope, type) );
const auto& obj = value.get_object();
if( type_obj.base != TypeName() ) {
assert( type_obj.base_scope != AccountName() );
to_binary( type_obj.base_scope, type_obj.base, value, ds );
}
for( const auto& field : type_obj.fields ) {
// TODO: check to see if field.type is a built in type, otherwise recurse
#warning TODO: determine whether a stack overflow could be caused by nesting types, may be mitigated by controlling sizeof value
to_binary( scope, field.type, obj[field.name], ds );
}
} FC_CAPTURE_AND_RETHROW( (scope)(type)(value) ) }
/**
* This method should look up the type description in the chainstate and then use that description to unpack
* buffer into a fc::variant.
*
* @pre type is registered in type_index
* @post to_binary( scope, type, to_variant( scope, type, buffer ) ) == buffer
*/
fc::variant chain_controller::to_variant( const AccountName& scope, const TypeName& type, fc::datastream<const char*>& ds )const {
fc::mutable_variant_object mvo;
to_variant( scope, type, ds, mvo );
return fc::variant(std::move( mvo )) ;
}
void chain_controller::to_variant( const AccountName& scope, const TypeName& type, fc::datastream<const char*>& ds, fc::mutable_variant_object& mvo )const {
try {
const auto& type_obj = _db.get<type_object,by_scope_name>( boost::make_tuple(scope, type) );
if( type_obj.base != TypeName() ) {
assert( type_obj.base_scope != AccountName() );
to_variant( type_obj.base_scope, type_obj.base, ds, mvo );
}
for( const auto& field : type_obj.fields ) {
/// TODO: check to see if type is built in
mvo.set(field.type, to_variant( scope, field.type, ds ) );
}
} FC_CAPTURE_AND_RETHROW( (scope)(type) ) }
Bytes chain_controller::to_binary( const AccountName& scope, const TypeName& type, const fc::variant& value )const {
try {
fc::datastream<size_t> bytes_size;
to_binary( scope, type, value, bytes_size );
Bytes temp(bytes_size.tellp());
fc::datastream<char*> ds( temp.data(), temp.size() );
to_binary( scope, type, value, ds );
return temp;
} FC_CAPTURE_AND_RETHROW( (scope)(type)(value) ) }
} }
......@@ -63,7 +63,7 @@ namespace eos { namespace chain {
AccountName name;
uint8_t vm_type = 0;
uint8_t vm_version = 0;
uint16_t code_version = 0;
fc::sha256 code_version;
shared_vector<char> code;
Time creation_date;
};
......
......@@ -24,7 +24,6 @@
#pragma once
#include <eos/chain/global_property_object.hpp>
#include <eos/chain/account_object.hpp>
#include <eos/chain/type_object.hpp>
#include <eos/chain/node_property_object.hpp>
#include <eos/chain/fork_database.hpp>
#include <eos/chain/block_log.hpp>
......@@ -74,20 +73,6 @@ namespace eos { namespace chain {
*/
signal<void(const SignedTransaction&)> on_pending_transaction;
template<typename T>
void register_type( AccountName scope ) {
auto stru = eos::types::GetStruct<T>::type();
_db.create<type_object>([&](type_object& o) {
o.scope = scope;
o.name = stru.name;
o.base = stru.base;
#warning QUESTION Should we be setting o.base_scope here?
o.fields.reserve(stru.fields.size());
for( const auto& f : stru.fields )
o.fields.push_back( f );
});
_db.get<type_object,by_scope_name>( boost::make_tuple(scope, stru.name) );
}
/**
* The controller can override any script endpoint with native code.
......@@ -248,22 +233,10 @@ namespace eos { namespace chain {
uint32_t last_irreversible_block_num() const;
void from_variant( const AccountName& scope, const TypeName& type,
const fc::variant& value,
fc::datastream<char*>& ds )const;
types::Bytes to_binary( const AccountName& scope, const TypeName& type, const fc::variant& value )const;
fc::variant to_variant( const AccountName& scope, const TypeName& type, fc::datastream<const char*>& ds )const;
protected:
const chainbase::database& get_database() const { return _db; }
private:
template<typename T>
void to_binary( const AccountName& scope, const TypeName& type, const fc::variant& value, fc::datastream<T>& ds )const;
void to_variant( const AccountName& scope, const TypeName& type,
fc::datastream<const char*>& ds,
fc::mutable_variant_object& mvo )const;
/// Reset the object graph in-memory
void initialize_indexes();
......@@ -288,7 +261,6 @@ namespace eos { namespace chain {
void validate_tapos(const SignedTransaction& trx)const;
void validate_referenced_accounts(const SignedTransaction& trx)const;
void validate_expiration(const SignedTransaction& trx) const;
void validate_message_types( const SignedTransaction& trx )const;
/// @}
void validate_message_precondition(precondition_validate_context& c)const;
......
/*
* Copyright (c) 2017, Respective Authors.
*
* The MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include <eos/chain/types.hpp>
#include "multi_index_includes.hpp"
namespace eos { namespace chain {
struct type_object : public chainbase::object<type_object_type, type_object> {
OBJECT_CTOR(type_object, (fields))
id_type id;
AccountName scope;
TypeName name;
AccountName base_scope;
TypeName base;
shared_vector<Field> fields;
};
using type_id_type = type_object::id_type;
struct by_scope_name;
using type_index = chainbase::shared_multi_index_container<
type_object,
indexed_by<
ordered_unique<tag<by_id>, member<type_object, type_object::id_type, &type_object::id>>,
ordered_unique<tag<by_scope_name>,
composite_key< type_object,
member<type_object, AccountName, &type_object::scope>,
member<type_object, TypeName, &type_object::name>
>
>
>
>;
} } // eos::chain
CHAINBASE_SET_INDEX_TYPE(eos::chain::type_object, eos::chain::type_index)
FC_REFLECT(chainbase::oid<eos::chain::type_object>, (_id))
FC_REFLECT(eos::chain::type_object, (id)(scope)(name)(base_scope)(base)(fields) )
......@@ -64,7 +64,7 @@
{ c(*this); }
#define OBJECT_CTOR(...) BOOST_PP_OVERLOAD(OBJECT_CTOR, __VA_ARGS__)(__VA_ARGS__)
#define EOS_SYSTEM_CONTRACT_FUNCTIONS (CreateAccount)(DefineStruct)(SetCode)
#define EOS_SYSTEM_CONTRACT_FUNCTIONS (CreateAccount)(SetCode)
#define EOS_CONTRACT_FUNCTIONS (Transfer)(TransferToLocked)
#define EOS_STAKED_BALANCE_CONTRACT_FUNCTIONS \
(CreateProducer)(UpdateProducer)(ApproveProducer)(SetVoteProxy)(AllowVoteProxying)
......@@ -164,7 +164,6 @@ namespace eos { namespace chain {
account_object_type,
permission_object_type,
action_code_object_type,
type_object_type,
key_value_object_type,
action_permission_object_type,
global_property_object_type,
......@@ -209,7 +208,6 @@ FC_REFLECT_ENUM(eos::chain::object_type,
(account_object_type)
(permission_object_type)
(action_code_object_type)
(type_object_type)
(key_value_object_type)
(action_permission_object_type)
(global_property_object_type)
......
......@@ -47,7 +47,7 @@ class wasm_interface {
Runtime::ModuleInstance* instance = nullptr;
IR::Module* module = nullptr;
vector<char> init_memory;
uint16_t code_version = -1;
fc::sha256 code_version;
};
map<AccountName, ModuleState> instances;
......
......@@ -386,12 +386,13 @@ DEFINE_INTRINSIC_FUNCTION1(env,toUpper,toUpper,none,i32,charptr) {
#warning TODO: free existing module if the code has been updated, currently leak memory
state.instance = nullptr;
state.module = nullptr;
state.code_version = -1;
state.code_version = fc::sha256();
}
state.module = new IR::Module();
try
{
wlog( "LOADING CODE" );
Serialization::MemoryInputStream stream((const U8*)recipient.code.data(),recipient.code.size());
WASM::serialize(stream,*state.module);
......
......@@ -6,12 +6,6 @@
namespace eos {
struct DefineStruct {
static void validate(chain::message_validate_context& context);
static void validate_preconditions(chain::precondition_validate_context& context);
static void apply(chain::apply_context& context);
};
struct SetCode {
static void validate(chain::message_validate_context& context);
static void validate_preconditions(chain::precondition_validate_context& context);
......
......@@ -67,13 +67,6 @@ std::vector<chain::Message> native_contract_chain_initializer::prepare_database(
chainbase::database& db) {
std::vector<chain::Message> messages_to_process;
// Register native contract message types
#define MACRO(r, data, elem) chain.register_type<types::elem>(data);
BOOST_PP_SEQ_FOR_EACH(MACRO, config::SystemContractName, EOS_SYSTEM_CONTRACT_FUNCTIONS)
BOOST_PP_SEQ_FOR_EACH(MACRO, config::EosContractName, EOS_CONTRACT_FUNCTIONS)
BOOST_PP_SEQ_FOR_EACH(MACRO, config::StakedBalanceContractName, EOS_STAKED_BALANCE_CONTRACT_FUNCTIONS)
#undef MACRO
// Create the singleton object, ProducerScheduleObject
db.create<ProducerScheduleObject>([](const auto&){});
......
......@@ -108,19 +108,19 @@ ProducerRound ProducerScheduleObject::calculateNextRound(chainbase::database& db
try {
if (boost::distance(LapCompleters) < AllProducersByFinishTime.size()
&& newRaceTime < std::numeric_limits<UInt128>::max()) {
ilog("Processed producer race. ${count} producers completed a lap at virtual time ${time}",
("count", (int64_t)boost::distance(LapCompleters))("time", newRaceTime));
//ilog("Processed producer race. ${count} producers completed a lap at virtual time ${time}",
// ("count", (int64_t)boost::distance(LapCompleters))("time", newRaceTime));
boost::for_each(LapCompleters, StartNewLap);
db.modify(*this, [newRaceTime](ProducerScheduleObject& pso) {
pso.currentRaceTime = newRaceTime;
});
} else {
wlog("Producer race finished; restarting race.");
//wlog("Producer race finished; restarting race.");
resetProducerRace(db);
}
} catch (ProducerRaceOverflowException&) {
// Virtual race time has overflown. Reset race for everyone.
wlog("Producer race virtual time overflow detected! Resetting race.");
// wlog("Producer race virtual time overflow detected! Resetting race.");
resetProducerRace(db);
}
......
......@@ -2,7 +2,6 @@
#include <eos/chain/message_handling_contexts.hpp>
#include <eos/chain/account_object.hpp>
#include <eos/chain/type_object.hpp>
#include <eos/chain/exceptions.hpp>
#include <eos/chain/global_property_object.hpp>
......@@ -11,35 +10,6 @@
namespace eos {
using namespace chain;
void DefineStruct::validate(message_validate_context& context) {
auto msg = context.msg.as<types::DefineStruct>();
EOS_ASSERT(msg.definition.name != TypeName(), message_validate_exception, "must define a type name");
// TODO: validate_type_name( msg.definition.name)
// validate_type_name( msg.definition.base)
}
void DefineStruct::validate_preconditions(precondition_validate_context& context) {
auto& db = context.db;
auto msg = context.msg.as<types::DefineStruct>();
db.get<account_object,by_name>(msg.scope);
#warning TODO: db.get<account_object>(sg.base_scope)
}
void DefineStruct::apply(apply_context& context) {
auto& db = context.mutable_db;
auto msg = context.msg.as<types::DefineStruct>();
db.create<type_object>( [&](auto& type) {
type.scope = msg.scope;
type.name = msg.definition.name;
type.fields.reserve(msg.definition.fields.size());
#warning TODO: type.base_scope =
type.base = msg.definition.base;
for(const auto& f : msg.definition.fields) {
type.fields.push_back(f);
}
});
}
void SetCode::validate(message_validate_context& context) {
auto msg = context.msg.as<types::SetCode>();
......@@ -62,7 +32,8 @@ void SetCode::apply(apply_context& context) {
const auto& account = db.get<account_object,by_name>(msg.account);
wlog( "set code: ${size}", ("size",msg.code.size()));
db.modify( account, [&]( auto& a ) {
a.code_version++;
#warning TODO: update SetCode message to include the hash, then validate it in validate
a.code_version = fc::sha256::hash( msg.code.data(), msg.code.size() );
a.code.resize( msg.code.size() );
memcpy( a.code.data(), msg.code.data(), msg.code.size() );
});
......
......@@ -48,7 +48,7 @@ void AbstractSymbolTable::parse(std::istream& in) {
line = line.substr(0, line.find('#'));
line = fc::trim(line);
if(!line.size()) continue;
std::cerr << line << "\n";
//std::cerr << line << "\n";
line_tokens.clear();
split(line_tokens, line, boost::is_any_of(" \t"), boost::token_compress_on);
......@@ -69,7 +69,7 @@ void AbstractSymbolTable::parse(std::istream& in) {
FC_ASSERT(line_tokens.size() == 3, "Expected a struct name");
this->addTypeDef(line_tokens[1], line_tokens[2]);
} else if(in_struct) { // parse field
idump((line_tokens));
//idump((line_tokens));
FC_ASSERT(line_tokens.size() == 2, "a field must be two tokens long");
const auto& name = line_tokens[0];
const auto& type = line_tokens[1];
......
......@@ -49,7 +49,6 @@ void chain_api_plugin::plugin_startup() {
app().get_plugin<http_plugin>().add_api({
CHAIN_RO_CALL(get_info),
CHAIN_RO_CALL(get_block),
CHAIN_RO_CALL(get_types),
CHAIN_RW_CALL(push_block),
CHAIN_RW_CALL(push_transaction)
});
......
......@@ -18,8 +18,6 @@ using fc::flat_map;
using chain::block_id_type;
using chain::fork_database;
using chain::block_log;
using chain::type_index;
using chain::by_scope_name;
using chain::chain_id_type;
class chain_plugin_impl {
......@@ -174,23 +172,6 @@ read_only::get_block_results read_only::get_block(const read_only::get_block_par
"Could not find block: ${block}", ("block", params.block_num_or_id));
}
read_only::get_types_results read_only::get_types(const get_types_params& params) const {
auto& _db = app().get_plugin<database_plugin>().db();
auto& index = _db.get_index<type_index, by_scope_name>();
auto range = index.equal_range( boost::make_tuple( params.account_name ) );
get_types_results res;
for( const auto& to : boost::make_iterator_range( range.first, range.second ) ) {
fc::variant v;
fc::to_variant(to, v);
res.emplace_back(v);
}
return res;
}
read_write::push_block_results read_write::push_block(const read_write::push_block_params& params) {
db.push_block(params);
return read_write::push_block_results();
......
......@@ -37,12 +37,6 @@ public:
};
using get_block_results = chain::signed_block;
get_block_results get_block(const get_block_params& params) const;
struct get_types_params {
string account_name;
};
using get_types_results = std::vector<fc::variant>;
get_types_results get_types(const get_types_params& params) const;
};
class read_write {
......@@ -99,4 +93,3 @@ FC_REFLECT(eos::chain_apis::read_only::get_info_results,
(head_block_num)(head_block_id)(head_block_time)(head_block_producer)
(recent_slots)(participation_rate))
FC_REFLECT(eos::chain_apis::read_only::get_block_params, (block_num_or_id))
FC_REFLECT(eos::chain_apis::read_only::get_types_params, (account_name))
......@@ -858,9 +858,6 @@ R"(
types::SetCode handler;
handler.account = "simplecoin";
types::DefineStruct interface;
interface.scope = "simplecoin";
interface.definition = types::GetStruct<types::Transfer>::type();
auto wasm = assemble_wast( wast_apply );
handler.code.resize(wasm.size());
......@@ -868,13 +865,10 @@ R"(
{
eos::chain::SignedTransaction trx;
trx.messages.resize(2);
trx.messages.resize(1);
trx.messages[0].sender = "simplecoin";
trx.messages[0].recipient = config::SystemContractName;
trx.setMessage(0, "DefineStruct",interface);
trx.messages[1].sender = "simplecoin";
trx.messages[1].recipient = config::SystemContractName;
trx.setMessage(1, "SetCode", handler);
trx.setMessage(0, "SetCode", handler);
trx.expiration = db.head_block_time() + 100;
trx.set_reference_block(db.head_block_id());
db.push_transaction(trx);
......@@ -2014,22 +2008,16 @@ R"(
types::SetCode handler;
handler.account = "simplecoin";
types::DefineStruct interface;
interface.scope = "simplecoin";
interface.definition = types::GetStruct<types::Transfer>::type();
auto wasm = assemble_wast( wast_apply );
handler.code.resize(wasm.size());
memcpy( handler.code.data(), wasm.data(), wasm.size() );
eos::chain::SignedTransaction trx;
trx.messages.resize(2);
trx.messages.resize(1);
trx.messages[0].sender = "simplecoin";
trx.messages[0].recipient = config::SystemContractName;
trx.setMessage(0, "DefineStruct",interface);
trx.messages[1].sender = "simplecoin";
trx.messages[1].recipient = config::SystemContractName;
trx.setMessage(1, "SetCode", handler);
trx.setMessage(0, "SetCode", handler);
trx.expiration = db.head_block_time() + 100;
trx.set_reference_block(db.head_block_id());
try {
......
......@@ -82,8 +82,6 @@ BOOST_FIXTURE_TEST_CASE(transfer, testing_fixture)
trx.expiration = db.head_block_time() + 100;
trx.messages[0].sender = "init1";
trx.messages[0].recipient = config::EosContractName;
trx.messages[0].type = "Undefined";
BOOST_REQUIRE_THROW( db.push_transaction(trx), message_validate_exception ); // "Type Undefined is not defined"
types::Transfer trans = { "init1", "init2", Asset(100), "transfer 100" };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册