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

Commit

Permalink
Fix build, but everything is still broken
Browse files Browse the repository at this point in the history
It builds, but the tests are a complete mess.

Also define some types and stuff for #7... Lost in the mix.
  • Loading branch information
nathanielhourt committed Jul 5, 2017
1 parent f0c0ed7 commit 17528b2
Show file tree
Hide file tree
Showing 15 changed files with 204 additions and 153 deletions.
1 change: 1 addition & 0 deletions libraries/chain/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ add_library( eos_chain

types.cpp
chain_administration_interface.cpp
message_handling_contexts.cpp

${HEADERS}
)
Expand Down
64 changes: 30 additions & 34 deletions libraries/chain/chain_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -552,21 +552,18 @@ void chain_controller::validate_referenced_accounts(const SignedTransaction& trx
require_account(auth.account);
}
for(const auto& msg : trx.messages) {
require_account(msg.sender);
require_account(msg.recipient);
const AccountName* previous_notify_account = nullptr;
for(const auto& current_notify_account : msg.notify) {
require_account(current_notify_account);
if(previous_notify_account) {
EOS_ASSERT(current_notify_account < *previous_notify_account, message_validate_exception,
require_account(msg.code);
const AccountName* previous_recipient = nullptr;
for(const auto& current_recipient : msg.recipients) {
require_account(current_recipient);
if(previous_recipient) {
EOS_ASSERT(current_recipient < *previous_recipient, message_validate_exception,
"Message notify accounts out of order. Possibly a bug in the wallet?");
}

EOS_ASSERT(current_notify_account != msg.sender, message_validate_exception,
"Message sender is listed in accounts to notify. Possibly a bug in the wallet?");
EOS_ASSERT(current_notify_account != msg.recipient, message_validate_exception,
"Message recipient is listed in accounts to notify. Possibly a bug in the wallet?");
previous_notify_account = &current_notify_account;
EOS_ASSERT(current_recipient != msg.code, message_validate_exception,
"Code account is listed among recipients. Possibly a bug in the wallet?");
previous_recipient = &current_recipient;
}
}
}
Expand All @@ -588,53 +585,52 @@ void chain_controller::validate_expiration(const SignedTransaction& trx) const
void chain_controller::validate_message_precondition( precondition_validate_context& context )const
{ try {
const auto& m = context.msg;
auto contract_handlers_itr = precondition_validate_handlers.find( context.scope );
if( contract_handlers_itr != precondition_validate_handlers.end() ) {
auto message_handler_itr = contract_handlers_itr->second.find( {m.recipient, m.type} );
if( message_handler_itr != contract_handlers_itr->second.end() ) {
auto contract_handlers_itr = precondition_validate_handlers.find(context.scope);
if (contract_handlers_itr != precondition_validate_handlers.end()) {
auto message_handler_itr = contract_handlers_itr->second.find({m.code, m.type});
if (message_handler_itr != contract_handlers_itr->second.end()) {
message_handler_itr->second(context);
return;
}
}
const auto& recipient = _db.get<account_object,by_name>( context.scope );
if( recipient.code.size() ) {
wasm_interface::get().precondition( context );
const auto& recipient = _db.get<account_object,by_name>(context.scope);
if (recipient.code.size()) {
wasm_interface::get().precondition(context);
}
} FC_CAPTURE_AND_RETHROW() }

void chain_controller::process_message(Message message) {
apply_context apply_ctx(_db, message, message.recipient);
apply_context apply_ctx(_db, message, message.code);

/** TODO: pre condition validation and application can occur in parallel */
/** TODO: verify that message is fully authorized
(check that @ref SignedTransaction::authorizations are all present) */
validate_message_precondition(apply_ctx);
apply_message(apply_ctx);

for (const auto& notify_account : message.notify) {
for (const auto& recipient : message.recipients) {
try {
apply_context notify_ctx(_db, message, notify_account);
validate_message_precondition(notify_ctx);
apply_message(notify_ctx);
} FC_CAPTURE_AND_RETHROW((notify_account)(message))
apply_context recipient_ctx(_db, message, recipient);
validate_message_precondition(recipient_ctx);
apply_message(recipient_ctx);
} FC_CAPTURE_AND_RETHROW((recipient)(message))
}
}

void chain_controller::apply_message( apply_context& context )
void chain_controller::apply_message(apply_context& context)
{ try {
const auto& m = context.msg;
auto contract_handlers_itr = apply_handlers.find( context.scope );
if( contract_handlers_itr != apply_handlers.end() ) {
auto message_handler_itr = contract_handlers_itr->second.find( {m.recipient, m.type} );
if( message_handler_itr != contract_handlers_itr->second.end() ) {
auto contract_handlers_itr = apply_handlers.find(context.scope);
if (contract_handlers_itr != apply_handlers.end()) {
auto message_handler_itr = contract_handlers_itr->second.find({m.code, m.type});
if (message_handler_itr != contract_handlers_itr->second.end()) {
message_handler_itr->second(context);
return;
}
}
//ilog( "no native handler found" );
const auto& recipient = _db.get<account_object,by_name>( context.scope );
if( recipient.code.size() ) {
wasm_interface::get().apply( context );
const auto& recipient = _db.get<account_object,by_name>(context.scope);
if (recipient.code.size()) {
wasm_interface::get().apply(context);
}

} FC_CAPTURE_AND_RETHROW((context.msg)) }
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/include/eos/chain/authority.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class AuthorityChecker {
return true;
}
for (const auto& apw : authority.accounts)
#warning TODO: Recursion limit?
#warning TODO: Recursion limit? Yes: implement as producer-configurable parameter
if (satisfied(apw.permission)) {
weight += apw.weight;
if (weight >= authority.threshold)
Expand Down
25 changes: 14 additions & 11 deletions libraries/chain/include/eos/chain/message.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,10 @@ namespace eos { namespace chain {
*/
struct Message : public types::Message {
Message() = default;
Message(const AccountName& sender, const AccountName& recipient, const vector<AccountName>& notify)
: types::Message(sender, recipient, notify, "", {}) {}
template<typename T>
Message(const AccountName& sender, const AccountName& recipient, const vector<AccountName>& notify,
const TypeName& type, T&& value)
: Message(sender, recipient, notify) {
Message(const AccountName& code, const vector<types::AccountName>& recipients,
const vector<types::AccountPermission>& authorization, const TypeName& type, T&& value)
: types::Message(code, recipients, authorization, {}, {}) {
set<T>(type, std::forward<T>(value));
}
Message(const types::Message& m) : types::Message(m) {}
Expand All @@ -40,17 +38,22 @@ struct Message : public types::Message {
return fc::raw::unpack<T>(data);
}
bool has_notify(const AccountName& n)const {
for(const auto& no : notify)
for(const auto& no : recipients)
if(no == n) return true;
return false;
}

template<typename Lambda>
void for_each_handler( Lambda&& l )const {
l( sender );
l( recipient );
for( const auto& notice : notify )
l(notice);
void for_each_handler(Lambda&& l)const {
l(code);
for(const auto& recipient : recipients)
l(recipient);
}

types::AccountName recipient(UInt8 index) const {
FC_ASSERT(index < recipients.size(), "Invalid recipient index: ${index}/${size}",
("index", index)("size", recipients.size()));
return recipients.at(int(index));
}
};

Expand Down
20 changes: 17 additions & 3 deletions libraries/chain/include/eos/chain/message_handling_contexts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,25 @@ namespace eos { namespace chain {
class message_validate_context {
public:
explicit message_validate_context(const chainbase::database& d, const chain::Message& m, types::AccountName s)
:msg(m),db(d),scope(s){}
:msg(m),db(d),scope(s),used_authorizations(msg.authorization.size(), false){}

/**
* @brief Require @ref account to have approved of this message
* @param account The account whose approval is required
*
* This method will check that @ref account is listed in the message's declared authorizations, and marks the
* authorization as used. Note that all authorizations on a message must be used, or the message is invalid.
*
* @throws tx_missing_auth If no sufficient permission was found
*/
void require_authorization(const types::AccountName& account);
bool all_authorizations_used() const;

const chain::Message& msg;
const chainbase::database& db; /// required only for loading the contract code
types::AccountName scope; /// the contract that is being called
const chainbase::database& db;
types::AccountName scope;
///< Parallel to msg.authorization; tracks which permissions have been used while processing the message
vector<bool> used_authorizations;
};

class precondition_validate_context : public message_validate_context {
Expand Down
24 changes: 24 additions & 0 deletions libraries/chain/message_handling_contexts.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <eos/chain/message_handling_contexts.hpp>
#include <eos/chain/permission_object.hpp>
#include <eos/chain/exceptions.hpp>

#include <boost/algorithm/cxx11/all_of.hpp>
#include <boost/range/algorithm/find_if.hpp>

namespace eos { namespace chain {

void message_validate_context::require_authorization(const types::AccountName& account) {
auto itr = boost::find_if(msg.authorization, [&account](const types::AccountPermission& ap) {
return ap.account == account;
});
EOS_ASSERT(itr != msg.authorization.end(), tx_missing_auth,
"Required authorization ${auth} not found", ("auth", account));

used_authorizations[itr - msg.authorization.begin()] = true;
}

bool message_validate_context::all_authorizations_used() const {
return boost::algorithm::all_of_equal(used_authorizations, true);
}

} } // namespace eos::chain
54 changes: 27 additions & 27 deletions libraries/chain/wasm_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ DEFINE_INTRINSIC_FUNCTION2(env,remove,remove,i32,i32,keyptr,i32,keylen) {

const auto* obj = db.find<key_value_object,by_scope_key>( boost::make_tuple(scope, keystr) );
if( obj ) {
db.remove( *obj );
db.remove( *obj );
return true;
}
return false;
Expand All @@ -88,9 +88,9 @@ DEFINE_INTRINSIC_FUNCTION3(env,memcpy,memcpy,i32,i32,dstp,i32,srcp,i32,len) {
#warning TODO: wasm memcpy has undefined behavior if memory ranges overlap
/*
if( dst > src )
FC_ASSERT( dst < src_end && src < dst_end, "overlap of memory range is undefined", ("d",dstp)("s",srcp)("l",len) );
FC_ASSERT( dst < src_end && src < dst_end, "overlap of memory range is undefined", ("d",dstp)("s",srcp)("l",len) );
else
FC_ASSERT( src < dst_end && dst < src_end, "overlap of memory range is undefined", ("d",dstp)("s",srcp)("l",len) );
FC_ASSERT( src < dst_end && dst < src_end, "overlap of memory range is undefined", ("d",dstp)("s",srcp)("l",len) );
*/
memcpy( dst, src, uint32_t(len) );
return dstp;
Expand Down Expand Up @@ -254,7 +254,7 @@ DEFINE_INTRINSIC_FUNCTION1(env,toUpper,toUpper,none,i32,charptr) {
if( !wasm )
{
wlog( "Runtime::init" );
Runtime::init();
Runtime::init();
wasm = new wasm_interface();
}
return *wasm;
Expand All @@ -277,10 +277,10 @@ DEFINE_INTRINSIC_FUNCTION1(env,toUpper,toUpper,none,i32,charptr) {


char* wasm_interface::vm_allocate( int bytes ) {
FunctionInstance* alloc_function = asFunctionNullable(getInstanceExport(current_module,"alloc"));
const FunctionType* functionType = getFunctionType(alloc_function);
FunctionInstance* alloc_function = asFunctionNullable(getInstanceExport(current_module,"alloc"));
const FunctionType* functionType = getFunctionType(alloc_function);
FC_ASSERT( functionType->parameters.size() == 1 );
std::vector<Value> invokeArgs(1);
std::vector<Value> invokeArgs(1);
invokeArgs[0] = U32(bytes);

auto result = Runtime::invokeFunction(alloc_function,invokeArgs);
Expand All @@ -295,28 +295,28 @@ DEFINE_INTRINSIC_FUNCTION1(env,toUpper,toUpper,none,i32,charptr) {
void wasm_interface::vm_call( std::string name ) {
try {
try {
name += "_" + std::string( current_validate_context->msg.recipient ) + "_";
name += "_" + std::string( current_validate_context->msg.code ) + "_";
name += std::string( current_validate_context->msg.type );

FunctionInstance* apply = asFunctionNullable(getInstanceExport(current_module,name.c_str()));
if( !apply ) {
FunctionInstance* apply = asFunctionNullable(getInstanceExport(current_module,name.c_str()));
if( !apply ) {
return; /// if not found then it is a no-op
}

const FunctionType* functionType = getFunctionType(apply);
FC_ASSERT( functionType->parameters.size() == 0 );
std::vector<Value> args(0);
const FunctionType* functionType = getFunctionType(apply);
FC_ASSERT( functionType->parameters.size() == 0 );
std::vector<Value> args(0);

auto& state = *current_state;
char* memstart = &memoryRef<char>( current_memory, 0 );
memset( memstart + state.mem_end, 0, ((1<<16) - state.mem_end) );
memcpy( memstart, state.init_memory.data(), state.mem_end);

Runtime::invokeFunction(apply,args);
Runtime::invokeFunction(apply,args);
} catch( const Runtime::Exception& e ) {
edump((std::string(describeExceptionCause(e.cause))));
edump((e.callStack));
throw;
edump((e.callStack));
throw;
}
} FC_CAPTURE_AND_RETHROW( (name)(current_validate_context->msg.type) ) }

Expand All @@ -328,22 +328,22 @@ DEFINE_INTRINSIC_FUNCTION1(env,toUpper,toUpper,none,i32,charptr) {
{ try {
try {
// wlog( "on_init" );
FunctionInstance* apply = asFunctionNullable(getInstanceExport(current_module,"init"));
if( !apply ) {
wlog( "no onInit method found" );
return; /// if not found then it is a no-op
FunctionInstance* apply = asFunctionNullable(getInstanceExport(current_module,"init"));
if( !apply ) {
wlog( "no onInit method found" );
return; /// if not found then it is a no-op
}

const FunctionType* functionType = getFunctionType(apply);
FC_ASSERT( functionType->parameters.size() == 0 );
const FunctionType* functionType = getFunctionType(apply);
FC_ASSERT( functionType->parameters.size() == 0 );

std::vector<Value> args(0);
std::vector<Value> args(0);

Runtime::invokeFunction(apply,args);
Runtime::invokeFunction(apply,args);
} catch( const Runtime::Exception& e ) {
edump((std::string(describeExceptionCause(e.cause))));
edump((e.callStack));
throw;
edump((e.callStack));
throw;
}
} FC_CAPTURE_AND_RETHROW() }

Expand Down Expand Up @@ -425,7 +425,7 @@ DEFINE_INTRINSIC_FUNCTION1(env,toUpper,toUpper,none,i32,charptr) {
for( uint32_t i = 0; i < 10000; ++i )
if( memstart[i] ) {
state.mem_end = i;
// std::cerr << (char)memstart[i];
//std::cerr << (char)memstart[i];
}

state.init_memory.resize(state.mem_end);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void validate_staked_okproducer(chain::message_validate_context& context);
void precondition_staked_okproducer(chain::precondition_validate_context& context);
void apply_staked_okproducer(chain::apply_context& context);

//void validate_staked_setproxy(chain::message_validate_context&) {}
void validate_staked_setproxy(chain::message_validate_context&context);
void precondition_staked_setproxy(chain::precondition_validate_context& context);
void apply_staked_setproxy(chain::apply_context& context);
///@}
Expand Down
19 changes: 11 additions & 8 deletions libraries/native_contract/native_contract_chain_initializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,18 @@ std::vector<chain::Message> native_contract_chain_initializer::prepare_database(
return types::Authority(1, {{k, 1}}, {});
};
for (const auto& acct : genesis.initial_accounts) {
chain::Message message(config::SystemContractName, config::SystemContractName,
{config::EosContractName, config::StakedBalanceContractName},
chain::Message message(config::SystemContractName,
vector<AccountName>{config::EosContractName, config::StakedBalanceContractName},
vector<types::AccountPermission>{},
"newaccount", types::newaccount(config::SystemContractName, acct.name,
KeyAuthority(acct.owner_key),
KeyAuthority(acct.active_key),
KeyAuthority(acct.owner_key),
acct.staking_balance));
KeyAuthority(acct.owner_key),
KeyAuthority(acct.active_key),
KeyAuthority(acct.owner_key),
acct.staking_balance));
messages_to_process.emplace_back(std::move(message));
if (acct.liquid_balance > 0) {
message = chain::Message(config::SystemContractName, config::EosContractName, {},
message = chain::Message(config::SystemContractName, vector<AccountName>{config::EosContractName},
vector<types::AccountPermission>{},
"transfer", types::transfer(config::SystemContractName, acct.name,
acct.liquid_balance, "Genesis Allocation"));
messages_to_process.emplace_back(std::move(message));
Expand All @@ -135,7 +137,8 @@ std::vector<chain::Message> native_contract_chain_initializer::prepare_database(

// Create initial producers
auto CreateProducer = boost::adaptors::transformed([config = genesis.initial_configuration](const auto& p) {
return chain::Message(config::SystemContractName, config::StakedBalanceContractName, vector<AccountName>{},
return chain::Message(config::SystemContractName, {config::StakedBalanceContractName},
vector<types::AccountPermission>{},
"setproducer", types::setproducer(p.owner_name, p.block_signing_key, config));
});
boost::copy(genesis.initial_producers | CreateProducer, std::back_inserter(messages_to_process));
Expand Down
Loading

0 comments on commit 17528b2

Please sign in to comment.