提交 7ec9ea6c 编写于 作者: B Bart Wyatt

nuked databse plugin, restored abi_serializer functions in chain and chain plugin

上级 62ef3faa
......@@ -22,6 +22,7 @@ add_library( eos_chain
contracts/staked_balance_objects.cpp
contracts/chain_initializer.cpp
contracts/genesis_state.cpp
contracts/abi_serializer.cpp
${HEADERS}
......
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <eosio/chain/contracts/abi_serializer.hpp>
#include <eosio/chain/contracts/types.hpp>
#include <eosio/chain/authority.hpp>
#include <eosio/chain/chain_config.hpp>
#include <eosio/chain/transaction.hpp>
#include <fc/io/raw.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/multiprecision/cpp_int.hpp>
using namespace boost;
namespace eosio { namespace chain { namespace contracts {
using boost::algorithm::ends_with;
using std::string;
template <typename T>
inline fc::variant variant_from_stream(fc::datastream<const char*>& stream) {
T temp;
fc::raw::unpack( stream, temp );
return fc::variant(temp);
}
template <typename T>
auto pack_unpack() {
return std::make_pair<abi_serializer::unpack_function, abi_serializer::pack_function>(
[]( fc::datastream<const char*>& stream, bool is_array) -> fc::variant {
if( is_array )
return variant_from_stream<vector<T>>(stream);
return variant_from_stream<T>(stream);
},
[]( const fc::variant& var, fc::datastream<char*>& ds, bool is_array ){
if( is_array )
fc::raw::pack( ds, var.as<vector<T>>() );
else
fc::raw::pack( ds, var.as<T>());
}
);
}
abi_serializer::abi_serializer( const abi_def& abi ) {
configure_built_in_types();
set_abi(abi);
}
void abi_serializer::configure_built_in_types() {
//public_key.hpp
built_in_types.emplace("public_key", pack_unpack<public_key_type>());
//asset.hpp
built_in_types.emplace("asset", pack_unpack<asset>());
built_in_types.emplace("price", pack_unpack<price>());
//native.hpp
built_in_types.emplace("string", pack_unpack<string>());
built_in_types.emplace("time", pack_unpack<fc::time_point_sec>());
built_in_types.emplace("signature", pack_unpack<signature_type>());
built_in_types.emplace("checksum", pack_unpack<checksum_type>());
built_in_types.emplace("field_name", pack_unpack<field_name>());
built_in_types.emplace("fixed_string32", pack_unpack<fixed_string32>());
built_in_types.emplace("fixed_string16", pack_unpack<fixed_string16>());
built_in_types.emplace("type_name", pack_unpack<type_name>());
built_in_types.emplace("bytes", pack_unpack<bytes>());
built_in_types.emplace("uint8", pack_unpack<uint8>());
built_in_types.emplace("uint16", pack_unpack<uint16>());
built_in_types.emplace("uint32", pack_unpack<uint32>());
built_in_types.emplace("uint64", pack_unpack<uint64>());
built_in_types.emplace("uint128", pack_unpack<boost::multiprecision::uint128_t>());
built_in_types.emplace("uint256", pack_unpack<boost::multiprecision::uint256_t>());
built_in_types.emplace("int8", pack_unpack<int8_t>());
built_in_types.emplace("int16", pack_unpack<int16_t>());
built_in_types.emplace("int32", pack_unpack<int32_t>());
built_in_types.emplace("int64", pack_unpack<int64_t>());
built_in_types.emplace("name", pack_unpack<name>());
built_in_types.emplace("field", pack_unpack<field_def>());
built_in_types.emplace("struct_def", pack_unpack<struct_def>());
built_in_types.emplace("fields", pack_unpack<vector<field_def>>());
built_in_types.emplace("account_name", pack_unpack<account_name>());
built_in_types.emplace("permission_name", pack_unpack<permission_name>());
built_in_types.emplace("action_name", pack_unpack<action_name>());
built_in_types.emplace("scope_name", pack_unpack<scope_name>());
built_in_types.emplace("permission_level", pack_unpack<permission_level>());
built_in_types.emplace("action", pack_unpack<action>());
built_in_types.emplace("permission_level_weight", pack_unpack<permission_level_weight>());
built_in_types.emplace("transaction", pack_unpack<transaction>());
built_in_types.emplace("signed_transaction", pack_unpack<signed_transaction>());
built_in_types.emplace("key_weight", pack_unpack<key_weight>());
built_in_types.emplace("authority", pack_unpack<authority>());
built_in_types.emplace("chain_config", pack_unpack<chain_config>());
built_in_types.emplace("type_def", pack_unpack<type_def>());
built_in_types.emplace("action", pack_unpack<action_def>());
built_in_types.emplace("table", pack_unpack<table_def>());
built_in_types.emplace("abi", pack_unpack<abi_def>());
built_in_types.emplace("nonce", pack_unpack<nonce>());
}
void abi_serializer::set_abi(const abi_def& abi) {
typedefs.clear();
structs.clear();
actions.clear();
tables.clear();
for( const auto& td : abi.types ) {
FC_ASSERT(is_type(td.type), "invalid type", ("type",td.type));
typedefs[td.new_type_name] = td.type;
}
for( const auto& st : abi.structs )
structs[st.name] = st;
for( const auto& a : abi.actions )
actions[a.name] = a.type;
for( const auto& t : abi.tables )
tables[t.name] = t.type;
/**
* The ABI vector may contain duplicates which would make it
* an invalid ABI
*/
FC_ASSERT( typedefs.size() == abi.types.size() );
FC_ASSERT( structs.size() == abi.structs.size() );
FC_ASSERT( actions.size() == abi.actions.size() );
FC_ASSERT( tables.size() == abi.tables.size() );
}
bool abi_serializer::is_array(const type_name& type)const {
return ends_with(string(type), "[]");
}
type_name abi_serializer::array_type(const type_name& type)const {
if( !is_array(type) ) return type;
return type_name(string(type).substr(0, type.size()-2));
}
bool abi_serializer::is_type(const type_name& rtype)const {
auto type = array_type(rtype);
if( built_in_types.find(type) != built_in_types.end() ) return true;
if( typedefs.find(type) != typedefs.end() ) return is_type(typedefs.find(type)->second);
if( structs.find(type) != structs.end() ) return true;
return false;
}
const struct_def& abi_serializer::get_struct(const type_name& type)const {
auto itr = structs.find(resolve_type(type) );
FC_ASSERT( itr != structs.end(), "Unknown struct ${type}", ("type",type) );
return itr->second;
}
void abi_serializer::validate()const {
for( const auto& t : typedefs ) { try {
vector<type_name> types_seen{t.first, t.second};
auto itr = typedefs.find(t.second);
while( itr != typedefs.end() ) {
FC_ASSERT( find(types_seen.begin(), types_seen.end(), itr->second) == types_seen.end(), "Circular reference in type ${type}", ("type",t.first) );
types_seen.emplace_back(itr->second);
itr = typedefs.find(itr->second);
}
} FC_CAPTURE_AND_RETHROW( (t) ) }
for( const auto& t : typedefs ) { try {
FC_ASSERT(is_type(t.second), "", ("type",t.second) );
} FC_CAPTURE_AND_RETHROW( (t) ) }
for( const auto& s : structs ) { try {
if( s.second.base != type_name() ) {
struct_def current = s.second;
vector<type_name> types_seen{current.name};
while( current.base != type_name() ) {
const auto& base = get_struct(current.base); //<-- force struct to inherit from another struct
FC_ASSERT( find(types_seen.begin(), types_seen.end(), base.name) == types_seen.end(), "Circular reference in struct ${type}", ("type",s.second.name) );
types_seen.emplace_back(base.name);
current = base;
}
}
for( const auto& field : s.second.fields ) { try {
FC_ASSERT(is_type(field.type) );
} FC_CAPTURE_AND_RETHROW( (field) ) }
} FC_CAPTURE_AND_RETHROW( (s) ) }
for( const auto& a : actions ) { try {
FC_ASSERT(is_type(a.second), "", ("type",a.second) );
} FC_CAPTURE_AND_RETHROW( (a) ) }
for( const auto& t : tables ) { try {
FC_ASSERT(is_type(t.second), "", ("type",t.second) );
} FC_CAPTURE_AND_RETHROW( (t) ) }
}
type_name abi_serializer::resolve_type(const type_name& type)const {
auto itr = typedefs.find(type);
if( itr != typedefs.end() )
return resolve_type(itr->second);
return type;
}
void abi_serializer::binary_to_variant(const type_name& type, fc::datastream<const char *>& stream,
fc::mutable_variant_object& obj)const {
const auto& st = get_struct(type);
if( st.base != type_name() ) {
binary_to_variant(resolve_type(st.base), stream, obj);
}
for( const auto& field : st.fields ) {
obj( field.name, binary_to_variant(resolve_type(field.type), stream) );
}
}
fc::variant abi_serializer::binary_to_variant(const type_name& type, fc::datastream<const char *>& stream)const
{
type_name rtype = resolve_type(type);
auto btype = built_in_types.find(array_type(rtype) );
if( btype != built_in_types.end() ) {
return btype->second.first(stream, is_array(rtype));
}
fc::mutable_variant_object mvo;
binary_to_variant(rtype, stream, mvo);
return fc::variant( std::move(mvo) );
}
fc::variant abi_serializer::binary_to_variant(const type_name& type, const bytes& binary)const{
fc::datastream<const char*> ds( binary.data(), binary.size() );
return binary_to_variant(type, ds);
}
void abi_serializer::variant_to_binary(const type_name& type, const fc::variant& var, fc::datastream<char *>& ds)const
{ try {
auto rtype = resolve_type(type);
auto btype = built_in_types.find(array_type(rtype));
if( btype != built_in_types.end() ) {
btype->second.second(var, ds, is_array(rtype));
} else {
const auto& st = get_struct(rtype);
const auto& vo = var.get_object();
if( st.base != type_name() ) {
variant_to_binary(resolve_type(st.base), var, ds);
}
for( const auto& field : st.fields ) {
if( vo.contains( string(field.name).c_str() ) ) {
variant_to_binary(field.type, vo[field.name], ds);
}
else {
/// TODO: default construct field and write it out
FC_ASSERT( !"missing field in variant object", "Missing '${f}' in variant object", ("f",field.name) );
}
}
}
} FC_CAPTURE_AND_RETHROW( (type)(var) ) }
bytes abi_serializer::variant_to_binary(const type_name& type, const fc::variant& var)const {
if( !is_type(type) ) {
return var.as<bytes>();
}
bytes temp( 1024*1024 );
fc::datastream<char*> ds(temp.data(), temp.size() );
variant_to_binary(type, var, ds);
temp.resize(ds.tellp());
return temp;
}
type_name abi_serializer::get_action_type(name action)const {
auto itr = actions.find(action);
if( itr != actions.end() ) return itr->second;
return type_name();
}
type_name abi_serializer::get_table_type(name action)const {
auto itr = tables.find(action);
if( itr != tables.end() ) return itr->second;
return type_name();
}
} } }
......@@ -51,16 +51,18 @@ void chain_initializer::register_types(chain_controller& chain, chainbase::datab
SET_APP_HANDLER( eos, eos, okproducer, eosio );
SET_APP_HANDLER( eos, eos, setproxy, eosio );
SET_APP_HANDLER( eos, eos, setcode, eosio );
SET_APP_HANDLER( eos, eos, setabi, eosio );
SET_APP_HANDLER( eos, eos, updateauth, eosio );
SET_APP_HANDLER( eos, eos, deleteauth, eosio );
SET_APP_HANDLER( eos, eos, linkauth, eosio );
SET_APP_HANDLER( eos, eos, unlinkauth, eosio );
SET_APP_HANDLER( eos, eos, nonce, eosio );
}
/*
abi chain_initializer::eos_contract_abi()
abi_def chain_initializer::eos_contract_abi()
{
abi eos_abi;
abi_def eos_abi;
eos_abi.types.push_back( type_def{"account_name","name"} );
eos_abi.types.push_back( type_def{"share_type","int64"} );
eos_abi.actions.push_back( action_def{name("transfer"), "transfer"} );
......@@ -71,28 +73,128 @@ abi chain_initializer::eos_contract_abi()
eos_abi.actions.push_back( action_def{name("setproducer"), "setproducer"} );
eos_abi.actions.push_back( action_def{name("setproxy"), "setproxy"} );
eos_abi.actions.push_back( action_def{name("setcode"), "setcode"} );
eos_abi.actions.push_back( action_def{name("setabi"), "setabi"} );
eos_abi.actions.push_back( action_def{name("linkauth"), "linkauth"} );
eos_abi.actions.push_back( action_def{name("unlinkauth"), "unlinkauth"} );
eos_abi.actions.push_back( action_def{name("updateauth"), "updateauth"} );
eos_abi.actions.push_back( action_def{name("deleteauth"), "deleteauth"} );
eos_abi.actions.push_back( action_def{name("newaccount"), "newaccount"} );
eos_abi.structs.push_back( eosio::get_struct<transfer>::type() );
eos_abi.structs.push_back( eosio::get_struct<lock>::type() );
eos_abi.structs.push_back( eosio::get_struct<unlock>::type() );
eos_abi.structs.push_back( eosio::get_struct<claim>::type() );
eos_abi.structs.push_back( eosio::get_struct<okproducer>::type() );
eos_abi.structs.push_back( eosio::get_struct<setproducer>::type() );
eos_abi.structs.push_back( eosio::get_struct<setproxy>::type() );
eos_abi.structs.push_back( eosio::get_struct<setcode>::type() );
eos_abi.structs.push_back( eosio::get_struct<updateauth>::type() );
eos_abi.structs.push_back( eosio::get_struct<linkauth>::type() );
eos_abi.structs.push_back( eosio::get_struct<unlinkauth>::type() );
eos_abi.structs.push_back( eosio::get_struct<deleteauth>::type() );
eos_abi.structs.push_back( eosio::get_struct<newaccount>::type() );
eos_abi.actions.push_back( action_def{name("nonce"), "nonce"} );
eos_abi.structs.emplace_back( struct_def {
"transfer", "", {
{"from", "account_name"},
{"to", "account_name"},
{"amount", "uint64"},
{"memo", "string"},
}
});
eos_abi.structs.emplace_back( struct_def {
"lock", "", {
{"from", "account_name"},
{"to", "account_name"},
{"amount", "share_type"},
}
});
eos_abi.structs.emplace_back( struct_def {
"unlock", "", {
{"account", "account_name"},
{"amount", "share_type"},
}
});
eos_abi.structs.emplace_back( struct_def {
"claim", "", {
{"account", "account_name"},
{"amount", "share_type"},
}
});
eos_abi.structs.emplace_back( struct_def {
"okproducer", "", {
{"voter", "account_name"},
{"producer", "account_name"},
{"approve", "int8"},
}
});
eos_abi.structs.emplace_back( struct_def {
"setproducer", "", {
{"name", "account_name"},
{"key", "public_key"},
{"configuration", "chain_config"},
}
});
eos_abi.structs.emplace_back( struct_def {
"setproxy", "", {
{"stakeholder", "account_name"},
{"proxy", "account_name"},
}
});
eos_abi.structs.emplace_back( struct_def {
"setcode", "", {
{"account", "account_name"},
{"vmtype", "uint8"},
{"vmversion", "uint8"},
{"code", "bytes"}
}
});
eos_abi.structs.emplace_back( struct_def {
"updateauth", "", {
{"account", "account_name"},
{"permission", "permission_name"},
{"parent", "permission_name"},
{"authority", "authority"},
}
});
eos_abi.structs.emplace_back( struct_def {
"linkauth", "", {
{"account", "account_name"},
{"code", "account_name"},
{"type", "action_name"},
{"requirement", "permission_name"},
}
});
eos_abi.structs.emplace_back( struct_def {
"unlinkauth", "", {
{"account", "account_name"},
{"code", "account_name"},
{"type", "action_name"},
}
});
eos_abi.structs.emplace_back( struct_def {
"deleteauth", "", {
{"account", "account_name"},
{"permission", "permission_name"},
}
});
eos_abi.structs.emplace_back( struct_def {
"newaccount", "", {
{"creator", "account_name"},
{"name", "account_name"},
{"owner", "authority"},
{"active", "authority"},
{"recovery", "authority"},
{"deposit", "asset"},
}
});
eos_abi.structs.emplace_back( struct_def {
"nonce", "", {
{"value", "name"}
}
});
return eos_abi;
}
*/
std::vector<action> chain_initializer::prepare_database( chain_controller& chain,
chainbase::database& db) {
......
......@@ -20,7 +20,7 @@
#include <eosio/chain/producer_object.hpp>
#include <eosio/chain/wasm_interface.hpp>
//#include <eos/types/abiSerializer.hpp>
#include <eosio/chain/contracts/abi_serializer.hpp>
namespace eosio { namespace chain { namespace contracts {
......@@ -191,12 +191,6 @@ void apply_eos_setcode(apply_context& context) {
FC_ASSERT( act.vmtype == 0 );
FC_ASSERT( act.vmversion == 0 );
/// if an ABI is specified make sure it is well formed and doesn't
/// reference any undefined types
// abiSerializer( act.abi ).validate();
// todo: figure out abi serilization location
const auto& account = db.get<account_object,by_name>(act.account);
// wlog( "set code: ${size}", ("size",act.code.size()));
db.modify( account, [&]( auto& a ) {
......@@ -206,13 +200,29 @@ void apply_eos_setcode(apply_context& context) {
a.code.resize( act.code.size() );
memcpy( a.code.data(), act.code.data(), act.code.size() );
//a.set_abi( act.abi );
});
apply_context init_context( context.mutable_controller, context.mutable_db, context.trx, context.act, act.account );
wasm_interface::get().init( init_context );
}
void apply_eos_setabi(apply_context& context) {
auto& db = context.mutable_db;
auto act = context.act.as<setabi>();
context.require_authorization(act.account);
/// if an ABI is specified make sure it is well formed and doesn't
/// reference any undefined types
abi_serializer(act.abi).validate();
// todo: figure out abi serilization location
const auto& account = db.get<account_object,by_name>(act.account);
db.modify( account, [&]( auto& a ) {
a.set_abi( act.abi );
});
}
void apply_eos_claim(apply_context& context) {
auto claim = context.act.as<contracts::claim>();
......@@ -481,4 +491,8 @@ void apply_eos_unlinkauth(apply_context& context) {
db.remove(*link);
}
void apply_eos_nonce(apply_context&) {
/// do nothing
}
} } } // namespace eosio::chain::contracts
......@@ -6,13 +6,14 @@
#include <eosio/chain/types.hpp>
#include <eosio/chain/authority.hpp>
#include <eosio/chain/block_timestamp.hpp>
#include <eosio/chain/contracts/types.hpp>
#include "multi_index_includes.hpp"
namespace eosio { namespace chain {
class account_object : public chainbase::object<account_object_type, account_object> {
OBJECT_CTOR(account_object,(code))
OBJECT_CTOR(account_object,(code)(abi))
id_type id;
account_name name;
......@@ -22,15 +23,14 @@ namespace eosio { namespace chain {
block_timestamp_type creation_date;
shared_vector<char> code;
/*
shared_vector<char> abi;
void set_abi( const eosio::types::Abi& a ) {
void set_abi( const eosio::chain::contracts::abi_def& a ) {
abi.resize( fc::raw::pack_size( a ) );
fc::datastream<char*> ds( abi.data(), abi.size() );
fc::raw::pack( ds, a );
}
*/
};
using account_id_type = account_object::id_type;
......
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <eosio/chain/contracts/types.hpp>
namespace eosio { namespace chain { namespace contracts {
using std::map;
using std::string;
using std::function;
using std::pair;
/**
* Describes the binary representation message and table contents so that it can
* be converted to and from JSON.
*/
struct abi_serializer {
abi_serializer(){ configure_built_in_types(); }
abi_serializer( const abi_def& abi );
void set_abi(const abi_def& abi);
map<type_name, type_name> typedefs;
map<type_name, struct_def> structs;
map<name,type_name> actions;
map<name,type_name> tables;
typedef std::function<fc::variant(fc::datastream<const char*>&, bool)> unpack_function;
typedef std::function<void(const fc::variant&, fc::datastream<char*>&, bool)> pack_function;
map<type_name, pair<unpack_function, pack_function>> built_in_types;
void configure_built_in_types();
bool has_cycle(const vector<pair<string, string>>& sedges)const;
void validate()const;
type_name resolve_type(const type_name& t)const;
bool is_array(const type_name& type)const;
bool is_type(const type_name& type)const;
bool is_struct(const type_name& type)const;
type_name array_type(const type_name& type)const;
const struct_def& get_struct(const type_name& type)const;
type_name get_action_type(name action)const;
type_name get_table_type(name action)const;
fc::variant binary_to_variant(const type_name& type, const bytes& binary)const;
bytes variant_to_binary(const type_name& type, const fc::variant& var)const;
fc::variant binary_to_variant(const type_name& type, fc::datastream<const char*>& binary)const;
void variant_to_binary(const type_name& type, const fc::variant& var, fc::datastream<char*>& ds)const;
template<typename Vec>
static bool is_empty_abi(const Vec& abi_vec)
{
return abi_vec.size() <= 4;
}
template<typename Vec>
static bool to_abi(const Vec& abi_vec, abi_def& abi)
{
if( !is_empty_abi(abi_vec) ) { /// 4 == packsize of empty Abi
fc::datastream<const char*> ds( abi_vec.data(), abi_vec.size() );
fc::raw::unpack( ds, abi );
return true;
}
return false;
}
private:
void binary_to_variant(const type_name& type, fc::datastream<const char*>& stream, fc::mutable_variant_object& obj)const;
};
} } } // eosio::chain::contracts
......@@ -5,7 +5,7 @@
#pragma once
#include <eosio/chain/contracts/genesis_state.hpp>
#include <eosio/chain/contracts/types.hpp>
#include <eosio/chain/chain_controller.hpp>
namespace eosio { namespace chain { namespace contracts {
......@@ -25,7 +25,7 @@ namespace eosio { namespace chain { namespace contracts {
std::vector<action> prepare_database(chain::chain_controller& chain, chainbase::database& db);
// static abi eos_contract_abi();
static abi_def eos_contract_abi();
private:
genesis_state_type genesis;
......
......@@ -19,9 +19,11 @@ namespace eosio { namespace chain { namespace contracts {
void apply_eos_setproducer(apply_context&);
void apply_eos_setproxy(apply_context&);
void apply_eos_setcode(apply_context&);
void apply_eos_setabi(apply_context&);
void apply_eos_updateauth(apply_context&);
void apply_eos_deleteauth(apply_context&);
void apply_eos_linkauth(apply_context&);
void apply_eos_unlinkauth(apply_context&);
void apply_eos_nonce(apply_context&);
} } } /// namespace eosio::contracts
#pragma once
#include <eosio/chain/authority.hpp>
#include <eosio/chain/chain_config.hpp>
#include <eosio/chain/config.hpp>
#include <eosio/chain/types.hpp>
#include <boost/multiprecision/cpp_int.hpp>
namespace eosio { namespace chain { namespace contracts {
using namespace boost::multiprecision;
template<size_t Size>
using uint_t = number<cpp_int_backend<Size, Size, unsigned_magnitude, unchecked, void> >;
template<size_t Size>
using int_t = number<cpp_int_backend<Size, Size, signed_magnitude, unchecked, void> >;
using uint8 = uint_t<8>;
using uint16 = uint_t<16>;
using uint32 = uint_t<32>;
using uint64 = uint_t<64>;
using fixed_string32 = fc::fixed_string<fc::array<uint64,4>>;
using fixed_string16 = fc::fixed_string<>;
using type_name = fixed_string32;
using field_name = fixed_string16;
using table_name = name;
struct type_def {
type_def() = default;
type_def(const type_name& new_type_name, const type_name& type)
:new_type_name(new_type_name), type(type)
{}
type_name new_type_name;
type_name type;
};
struct field_def {
field_def() = default;
field_def(const field_name& name, const type_name& type)
:name(name), type(type)
{}
field_name name;
type_name type;
bool operator==(const field_def& other) const {
return std::tie(name, type) == std::tie(other.name, other.type);
}
};
struct struct_def {
struct_def() = default;
struct_def(const type_name& name, const type_name& base, const vector<field_def>& fields)
:name(name), base(base), fields(fields)
{}
type_name name;
type_name base;
vector<field_def> fields;
bool operator==(const struct_def& other) const {
return std::tie(name, base, fields) == std::tie(other.name, other.base, other.fields);
}
};
struct action_def {
action_def() = default;
action_def(const action_name& name, const type_name& type)
:name(name), type(type)
{}
action_name name;
type_name type;
};
struct table_def {
table_def() = default;
table_def(const table_name& name, const type_name& index_type, const vector<type_name>& key_names, const vector<type_name>& key_types, const type_name& type)
:name(name), index_type(index_type), key_names(key_names), key_types(key_types), type(type)
{}
table_name name; // the name of the table
type_name index_type; // the kind of index, i64, i128i128, etc
vector<type_name> key_names; // names for the keys defined by key_types
vector<type_name> key_types; // the type of key parameters
type_name type; // type of binary data stored in this table
};
struct abi_def {
abi_def() = default;
abi_def(const vector<type_def>& types, const vector<struct_def>& structs, const vector<action_def>& actions, const vector<table_def>& tables)
:types(types), structs(structs), actions(actions), tables(tables)
{}
vector<type_def> types;
vector<struct_def> structs;
vector<action_def> actions;
vector<table_def> tables;
};
struct transfer {
transfer() = default;
transfer(const account_name& from, const account_name& to, const uint64_t& amount, const string& memo)
transfer(const account_name& from, const account_name& to, const uint64& amount, const string& memo)
:from(from), to(to), amount(amount), memo(memo)
{}
account_name from;
account_name to;
uint64_t amount;
uint64 amount;
string memo;
static name get_scope() {
......@@ -25,23 +122,6 @@ struct transfer {
}
};
/*
template<>
struct get_struct<transfer> {
static const struct_def& type() {
static struct_def result =
{ "transfer", "", {
{"from", "account_name"},
{"to", "account_name"},
{"amount", "uint64_t"},
{"memo", "string"},
}
};
return result;
}
};
*/
struct lock {
lock() = default;
lock(const account_name& from, const account_name& to, const share_type& amount)
......@@ -61,21 +141,6 @@ struct lock {
}
};
/*
template<>
struct get_struct<lock> {
static const struct_def& type() {
static struct_def result = { "lock", "", {
{"from", "account_name"},
{"to", "account_name"},
{"amount", "share_type"},
}
};
return result;
}
};
*/
struct unlock {
unlock() = default;
unlock(const account_name& account, const share_type& amount)
......@@ -94,19 +159,6 @@ struct unlock {
}
};
/*
template<> struct get_struct<unlock> {
static const struct_def& type() {
static struct_def result = { "unlock", "", {
{"account", "account_name"},
{"amount", "share_type"},
}
};
return result;
}
};
*/
struct claim {
claim() = default;
claim(const account_name& account, const share_type& amount)
......@@ -125,20 +177,6 @@ struct claim {
}
};
/*
template<> struct get_struct<claim> {
static const struct_def& type() {
static struct_def result = { "claim", "", {
{"account", "account_name"},
{"amount", "share_type"},
}
};
return result;
}
};
*/
struct newaccount {
newaccount() = default;
newaccount(const account_name& creator, const account_name& name, const authority& owner, const authority& active, const authority& recovery, const asset& deposit)
......@@ -161,34 +199,16 @@ struct newaccount {
}
};
/*
template<> struct get_struct<newaccount> {
static const struct_def& type() {
static struct_def result = { "newaccount", "", {
{"creator", "account_name"},
{"name", "account_name"},
{"owner", "authority"},
{"active", "authority"},
{"recovery", "authority"},
{"deposit", "asset"},
}
};
return result;
}
};
*/
struct setcode {
setcode() = default;
setcode(const account_name& account, const uint8_t& vmtype, const uint8_t& vmversion, const bytes& code/*, const abi& abi*/)
setcode(const account_name& account, const uint8& vmtype, const uint8& vmversion, const bytes& code/*, const abi& abi*/)
:account(account), vmtype(vmtype), vmversion(vmversion), code(code)//, abi(abi)
{}
account_name account;
uint8_t vmtype;
uint8_t vmversion;
uint8 vmtype;
uint8 vmversion;
bytes code;
// abi abi;
static scope_name get_scope() {
return config::system_account_name;
......@@ -199,21 +219,23 @@ struct setcode {
}
};
/*
template<> struct get_struct<setcode> {
static const struct_def& type() {
static struct_def result = { "setcode", "", {
{"account", "account_name"},
{"vmtype", "uint8_t"},
{"vmversion", "uint8_t"},
{"code", "bytes"}
// {"abi", "abi"},
struct setabi {
setabi() = default;
setabi(const account_name& account, const abi_def& abi)
:account(account), abi(abi)
{}
account_name account;
abi_def abi;
static scope_name get_scope() {
return config::system_account_name;
}
};
return result;
static action_name get_name() {
return N(setabi);
}
};
*/
struct setproducer {
setproducer() = default;
......@@ -234,20 +256,6 @@ struct setproducer {
}
};
/*
template<> struct get_struct<setproducer> {
static const struct_def& type() {
static struct_def result = { "setproducer", "", {
{"name", "account_name"},
{"key", "public_key"},
{"configuration", "chain_config"},
}
};
return result;
}
};
*/
struct okproducer {
okproducer() = default;
okproducer(const account_name& voter, const account_name& producer, const int8_t& approve)
......@@ -267,20 +275,6 @@ struct okproducer {
}
};
/*
template<> struct get_struct<okproducer> {
static const struct_def& type() {
static struct_def result = { "okproducer", "", {
{"voter", "account_name"},
{"producer", "account_name"},
{"approve", "int8_t"},
}
};
return result;
}
};
*/
struct setproxy {
setproxy() = default;
setproxy(const account_name& stakeholder, const account_name& proxy)
......@@ -299,19 +293,6 @@ struct setproxy {
}
};
/*
template<> struct get_struct<setproxy> {
static const struct_def& type() {
static struct_def result = { "setproxy", "", {
{"stakeholder", "account_name"},
{"proxy", "account_name"},
}
};
return result;
}
};
*/
struct updateauth {
updateauth() = default;
updateauth(const account_name& account, const permission_name& permission, const permission_name& parent, const authority& authority)
......@@ -332,21 +313,6 @@ struct updateauth {
}
};
/*
template<> struct get_struct<updateauth> {
static const struct_def& type() {
static struct_def result = { "updateauth", "", {
{"account", "account_name"},
{"permission", "permission_name"},
{"parent", "permission_name"},
{"authority", "authority"},
}
};
return result;
}
};
*/
struct deleteauth {
deleteauth() = default;
deleteauth(const account_name& account, const permission_name& permission)
......@@ -365,19 +331,6 @@ struct deleteauth {
}
};
/*
template<> struct get_struct<deleteauth> {
static const struct_def& type() {
static struct_def result = { "deleteauth", "", {
{"account", "account_name"},
{"permission", "permission_name"},
}
};
return result;
}
};
*/
struct linkauth {
linkauth() = default;
linkauth(const account_name& account, const account_name& code, const action_name& type, const permission_name& requirement)
......@@ -398,21 +351,6 @@ struct linkauth {
}
};
/*
template<> struct get_struct<linkauth> {
static const struct_def& type() {
static struct_def result = { "linkauth", "", {
{"account", "account_name"},
{"code", "account_name"},
{"type", "action_name"},
{"requirement", "permission_name"},
}
};
return result;
}
};
*/
struct unlinkauth {
unlinkauth() = default;
unlinkauth(const account_name& account, const account_name& code, const action_name& type)
......@@ -432,28 +370,39 @@ struct unlinkauth {
}
};
/*
template<> struct get_struct<unlinkauth> {
static const struct_def& type() {
static struct_def result = { "unlinkauth", "", {
{"account", "account_name"},
{"code", "account_name"},
{"type", "action_name"},
using nonce_type = name;
struct nonce {
nonce() = default;
nonce(const nonce_type& value)
:value(value)
{}
nonce_type value;
static scope_name get_scope() {
return config::system_account_name;
}
};
return result;
static action_name get_name() {
return N(nonce);
}
};
*/
} } } /// namespace eosio::chain::contracts
FC_REFLECT( eosio::chain::contracts::type_def , (new_type_name)(type) )
FC_REFLECT( eosio::chain::contracts::field_def , (name)(type) )
FC_REFLECT( eosio::chain::contracts::struct_def , (name)(base)(fields) )
FC_REFLECT( eosio::chain::contracts::action_def , (name)(type) )
FC_REFLECT( eosio::chain::contracts::table_def , (name)(index_type)(key_names)(key_types)(type) )
FC_REFLECT( eosio::chain::contracts::abi_def , (types)(structs)(actions)(tables) )
FC_REFLECT( eosio::chain::contracts::transfer , (from)(to)(amount)(memo) )
FC_REFLECT( eosio::chain::contracts::lock , (from)(to)(amount) )
FC_REFLECT( eosio::chain::contracts::unlock , (account)(amount) )
FC_REFLECT( eosio::chain::contracts::claim , (account)(amount) )
FC_REFLECT( eosio::chain::contracts::newaccount , (creator)(name)(owner)(active)(recovery)(deposit) )
FC_REFLECT( eosio::chain::contracts::setcode , (account)(vmtype)(vmversion)(code) ) //abi
FC_REFLECT( eosio::chain::contracts::setabi , (account)(abi) )
FC_REFLECT( eosio::chain::contracts::setproducer , (name)(key)(configuration) )
FC_REFLECT( eosio::chain::contracts::okproducer , (voter)(producer)(approve) )
FC_REFLECT( eosio::chain::contracts::setproxy , (stakeholder)(proxy) )
......@@ -461,3 +410,4 @@ FC_REFLECT( eosio::chain::contracts::updateauth , (account
FC_REFLECT( eosio::chain::contracts::deleteauth , (account)(permission) )
FC_REFLECT( eosio::chain::contracts::linkauth , (account)(code)(type)(requirement) )
FC_REFLECT( eosio::chain::contracts::unlinkauth , (account)(code)(type) )
FC_REFLECT( eosio::chain::contracts::nonce , (value) )
add_subdirectory(net_plugin)
#add_subdirectory(p2p_plugin)
add_subdirectory(http_plugin)
add_subdirectory(database_plugin)
add_subdirectory(db_plugin)
add_subdirectory(chain_plugin)
add_subdirectory(chain_api_plugin)
......
......@@ -3,7 +3,7 @@ add_library( chain_plugin
chain_plugin.cpp
${HEADERS} )
target_link_libraries( chain_plugin database_plugin db_plugin eos_native_contract eos_chain appbase )
target_link_libraries( chain_plugin db_plugin eos_native_contract eos_chain appbase )
target_include_directories( chain_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
install( TARGETS
......
......@@ -136,15 +136,16 @@ void chain_plugin::plugin_initialize(const variables_map& options) {
}
if (options.at("replay-blockchain").as<bool>()) {
fc::remove_all(app().data_dir() / default_shared_memory_dir);
ilog("Replay requested: wiping database");
app().get_plugin<database_plugin>().wipe_database();
if (db_plugin* db = app().find_plugin<db_plugin>()) {
db->wipe_database();
}
}
if (options.at("resync-blockchain").as<bool>()) {
fc::remove_all(app().data_dir() / default_shared_memory_dir);
ilog("Resync requested: wiping blocks");
app().get_plugin<database_plugin>().wipe_database();
if (db_plugin* db = app().find_plugin<db_plugin>()) {
db->wipe_database();
}
......@@ -192,10 +193,8 @@ using applied_irreversible_block_func = typename decltype(((chain_controller*)nu
void chain_plugin::plugin_startup()
{ try {
auto& db = app().get_plugin<database_plugin>().db();
optional<applied_irreversible_block_func> applied_func;
FC_ASSERT( fc::exists( my->genesis_file ),
"unable to find genesis file '${f}', check --genesis-json argument",
("f",my->genesis_file.generic_string()) );
......@@ -292,28 +291,27 @@ read_only::get_info_results read_only::get_info(const read_only::get_info_params
};
}
#warning TODO: ABI
/*types::abi getAbi( const chain_controller& db, const name& account ) {
abi_def get_abi( const chain_controller& db, const name& account ) {
const auto& d = db.get_database();
const auto& code_accnt = d.get<account_object,by_name>( account );
eosio::types::abi abi;
types::abi_serializer::to_abi(code_accnt.abi, abi);
abi_def abi;
abi_serializer::to_abi(code_accnt.abi, abi);
return abi;
}
string getTableType( const types::abi& abi, const name& tablename ) {
string get_table_type( const abi_def& abi, const name& table_name ) {
for( const auto& t : abi.tables ) {
if( t.table_name == tablename ){
if( t.name == table_name ){
return t.index_type;
}
}
FC_ASSERT( !"ABI does not define table", "Table ${table} not specified in ABI", ("table",tablename) );
FC_ASSERT( !"ABI does not define table", "Table ${table} not specified in ABI", ("table",table_name) );
}
read_only::get_table_rows_result read_only::get_table_rows( const read_only::get_table_rows_params& p )const {
const types::abi abi = getAbi( db, p.code );
auto table_type = getTableType( abi, p.table );
const abi_def abi = get_abi( db, p.code );
auto table_type = get_table_type( abi, p.table );
auto table_key = PRIMARY;
if( table_type == KEYi64 ) {
......@@ -335,7 +333,7 @@ read_only::get_table_rows_result read_only::get_table_rows( const read_only::get
}
FC_ASSERT( false, "invalid table type/key ${type}/${key}", ("type",table_type)("key",table_key)("abi",abi));
}
*/
read_only::get_block_results read_only::get_block(const read_only::get_block_params& params) const {
try {
if (auto block = db.fetch_block_by_id(fc::json::from_string(params.block_num_or_id).as<block_id_type>()))
......@@ -390,11 +388,12 @@ read_only::get_code_results read_only::get_code( const get_code_params& params )
result.wast = wasm_to_wast( (const uint8_t*)accnt.code.data(), accnt.code.size() );
result.code_hash = fc::sha256::hash( accnt.code.data(), accnt.code.size() );
}
#warning TODO: ABI
/*eosio::types::abi abi;
if( types::abi_serializer::to_abi(accnt.abi, abi) ) {
abi_def abi;
if( abi_serializer::to_abi(accnt.abi, abi) ) {
result.abi = std::move(abi);
}*/
}
return result;
}
......@@ -436,19 +435,27 @@ read_only::get_account_results read_only::get_account( const get_account_params&
return result;
}
#warning TODO: ABI
/*
read_only::abi_json_to_bin_result read_only::abi_json_to_bin( const read_only::abi_json_to_bin_params& params )const {
read_only::abi_json_to_bin_result read_only::abi_json_to_bin( const read_only::abi_json_to_bin_params& params )const try {
abi_json_to_bin_result result;
result.binargs = db.message_to_binary( params.code, params.action, params.args );
const auto& code_account = db.get_database().get<account_object,by_name>( params.code );
abi_def abi;
if( abi_serializer::to_abi(code_account.abi, abi) ) {
abi_serializer abis( abi );
result.binargs = abis.variant_to_binary( abis.get_action_type( params.action ), params.args );
}
return result;
}
} FC_CAPTURE_AND_RETHROW( (params.code)(params.action)(params.args) )
read_only::abi_bin_to_json_result read_only::abi_bin_to_json( const read_only::abi_bin_to_json_params& params )const {
abi_bin_to_json_result result;
result.args = db.message_from_binary( params.code, params.action, params.binargs );
const auto& code_account = db.get_database().get<account_object,by_name>( params.code );
abi_def abi;
if( abi_serializer::to_abi(code_account.abi, abi) ) {
abi_serializer abis( abi );
result.args = abis.binary_to_variant( abis.get_action_type( params.action ), params.binargs );
}
return result;
}
*/
read_only::get_required_keys_result read_only::get_required_keys( const get_required_keys_params& params )const {
signed_transaction pretty_input;
......
......@@ -11,11 +11,7 @@
#include <eosio/chain/chain_controller.hpp>
#include <eosio/chain/key_value_object.hpp>
#include <eosio/chain/transaction.hpp>
// TODO: hook in new abi stuff here
//#include <eos/types/abi_serializer.hpp>
#include <eos/database_plugin/database_plugin.hpp>
#include <eosio/chain/contracts/abi_serializer.hpp>
#include <boost/container/flat_set.hpp>
......@@ -33,6 +29,8 @@ namespace eosio {
using chain::asset;
using chain::authority;
using chain::account_name;
using chain::contracts::abi_def;
using chain::contracts::abi_serializer;
namespace chain_apis {
struct empty{};
......@@ -95,7 +93,7 @@ public:
name name;
string wast;
fc::sha256 code_hash;
//optional<types::abi> abi;
optional<abi_def> abi;
};
struct get_code_params {
......@@ -212,13 +210,12 @@ public:
}
template <typename IndexType, typename Scope>
read_only::get_table_rows_result get_table_rows_ex( const read_only::get_table_rows_params& p/*, const types::abi& abi */)const {
read_only::get_table_rows_result get_table_rows_ex( const read_only::get_table_rows_params& p, const abi_def& abi )const {
read_only::get_table_rows_result result;
const auto& d = db.get_database();
// TODO: ABI stuff
//types::abi_serializer abis;
//abis.setAbi(abi);
abi_serializer abis;
abis.set_abi(abi);
const auto& idx = d.get_index<IndexType, Scope>();
auto lower = idx.lower_bound( boost::make_tuple(p.scope, p.code, p.table ) );
......@@ -241,7 +238,7 @@ public:
copy_row(*itr, data);
if( p.json ) {
//result.rows.emplace_back(abis.binary_to_variant(abis.get_table_type(p.table), data) );
result.rows.emplace_back(abis.binary_to_variant(abis.get_table_type(p.table), data) );
} else {
result.rows.emplace_back(fc::variant(data));
}
......@@ -284,7 +281,7 @@ public:
class chain_plugin : public plugin<chain_plugin> {
public:
APPBASE_PLUGIN_REQUIRES((database_plugin))
APPBASE_PLUGIN_REQUIRES()
chain_plugin();
virtual ~chain_plugin();
......@@ -337,8 +334,7 @@ FC_REFLECT( eosio::chain_apis::read_only::get_table_rows_params, (json)(table_ke
FC_REFLECT( eosio::chain_apis::read_only::get_table_rows_result, (rows)(more) );
FC_REFLECT( eosio::chain_apis::read_only::get_account_results, (name)(eos_balance)(staked_balance)(unstaking_balance)(last_unstaking_time)(permissions)(producer) )
//TODO: ABI STUFF
FC_REFLECT( eosio::chain_apis::read_only::get_code_results, (name)(code_hash)(wast)/*(abi)*/ )
FC_REFLECT( eosio::chain_apis::read_only::get_code_results, (name)(code_hash)(wast)(abi) )
FC_REFLECT( eosio::chain_apis::read_only::get_account_params, (name) )
FC_REFLECT( eosio::chain_apis::read_only::get_code_params, (name) )
FC_REFLECT( eosio::chain_apis::read_only::producer_info, (name) )
......
file(GLOB HEADERS "include/eos/database_plugin/*.hpp")
add_library( database_plugin
database_plugin.cpp
${HEADERS} )
target_link_libraries( database_plugin appbase chainbase fc )
target_include_directories( database_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
install( TARGETS
database_plugin
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
install( FILES ${HEADERS} DESTINATION "include/eos/database_plugin" )
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <eos/database_plugin/database_plugin.hpp>
#include <fc/filesystem.hpp>
#include <fc/log/logger.hpp>
namespace eosio {
class database_plugin_impl {
public:
bool readonly = false;
uint64_t shared_memory_size = 0;
bfs::path shared_memory_dir;
fc::optional<chainbase::database> db;
};
database_plugin::database_plugin() : my(new database_plugin_impl){}
database_plugin::~database_plugin(){}
void database_plugin::set_program_options(options_description&, options_description& cfg) {
cfg.add_options()
("readonly", bpo::value<bool>()->default_value(false), "open the database in read only mode")
("shared-file-dir", bpo::value<bfs::path>()->default_value("blockchain"),
"the location of the chain shared memory files (absolute path or relative to application data dir)")
("shared-file-size", bpo::value<uint64_t>()->default_value(8*1024),
"Minimum size MB of database shared memory file")
;
}
void database_plugin::wipe_database() {
if (!my->shared_memory_dir.empty() && !my->db.valid())
fc::remove_all(my->shared_memory_dir);
else
elog("ERROR: database_plugin::wipe_database() called before configuration or after startup. Ignoring.");
}
void database_plugin::plugin_initialize(const variables_map& options) {
my->shared_memory_dir = app().data_dir() / "blockchain";
if(options.count("shared-file-dir")) {
auto sfd = options.at("shared-file-dir").as<bfs::path>();
if(sfd.is_relative())
my->shared_memory_dir = app().data_dir() / sfd;
else
my->shared_memory_dir = sfd;
}
my->shared_memory_size = options.at("shared-file-size").as<uint64_t>() * 1024 * 1024;
my->readonly = options.at("readonly").as<bool>();
}
void database_plugin::plugin_startup() {
using chainbase::database;
my->db = chainbase::database(my->shared_memory_dir,
my->readonly? database::read_only : database::read_write,
my->shared_memory_size);
}
void database_plugin::plugin_shutdown() {
ilog("closing database");
my->db.reset();
ilog("database closed successfully");
}
chainbase::database& database_plugin::db() {
assert(my->db.valid());
return *my->db;
}
const chainbase::database& database_plugin::db() const {
assert(my->db.valid());
return *my->db;
}
}
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <appbase/application.hpp>
#include <chainbase/chainbase.hpp>
namespace eosio {
using namespace appbase;
/**
* This is a template plugin, intended to serve as a starting point for making new plugins
*/
class database_plugin : public appbase::plugin<database_plugin> {
public:
database_plugin();
virtual ~database_plugin();
APPBASE_PLUGIN_REQUIRES()
virtual void set_program_options(options_description&, options_description& cfg) override;
// This may only be called after plugin_initialize() and before plugin_startup()!
void wipe_database();
void plugin_initialize(const variables_map& options);
void plugin_startup();
void plugin_shutdown();
// This may only be called after plugin_startup()!
chainbase::database& db();
// This may only be called after plugin_startup()!
const chainbase::database& db() const;
private:
std::unique_ptr<class database_plugin_impl> my;
};
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册