提交 898947fc 编写于 作者: D Daniel Larimer

Merge branch 'master' of github.com:EOSIO/eos

......@@ -17,6 +17,7 @@ add_library( eos_chain
types.cpp
chain_administration_interface.cpp
message_handling_contexts.cpp
${HEADERS}
)
......
......@@ -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;
}
}
}
......@@ -588,22 +585,22 @@ 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
......@@ -611,30 +608,29 @@ void chain_controller::process_message(Message message) {
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)) }
......
......@@ -62,7 +62,7 @@ public:
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)
......
......@@ -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) {}
......@@ -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));
}
};
......
......@@ -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 {
......
#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
......@@ -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;
......@@ -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;
......@@ -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;
......@@ -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);
......@@ -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) ) }
......@@ -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() }
......@@ -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);
......
......@@ -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);
///@}
......
......@@ -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));
......@@ -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));
......
......@@ -122,20 +122,20 @@ void validate_staked_okproducer(message_validate_context& context) {
auto approve = context.msg.as<types::okproducer>();
EOS_ASSERT(approve.approve == 0 || approve.approve == 1, message_validate_exception,
"Unknown approval value: ${val}; must be either 0 or 1", ("val", approve.approve));
EOS_ASSERT(approve.producer.good(), message_validate_exception,
"Approved producer's name cannot be empty");
context.msg.recipient(approve.voter);
context.msg.recipient(approve.producer);
}
void precondition_staked_okproducer(precondition_validate_context& context) {
const auto& db = context.db;
auto approve = context.msg.as<types::okproducer>();
auto producer = db.find<ProducerVotesObject, byOwnerName>(approve.producer);
auto voter = db.find<StakedBalanceObject, byOwnerName>(context.msg.sender);
auto producer = db.find<ProducerVotesObject, byOwnerName>(context.msg.recipient(approve.producer));
auto voter = db.find<StakedBalanceObject, byOwnerName>(context.msg.recipient(approve.voter));
EOS_ASSERT(producer != nullptr, message_precondition_exception,
"Could not approve producer '${name}'; no such producer found", ("name", approve.producer));
"Could not approve producer '${name}'; no such producer found", ("name", producer->ownerName));
EOS_ASSERT(voter != nullptr, message_precondition_exception,
"Could not find balance for '${name}'", ("name", context.msg.sender));
"Could not find balance for '${name}'", ("name", voter->ownerName));
EOS_ASSERT(voter->producerVotes.contains<ProducerSlate>(), message_precondition_exception,
"Cannot approve producer; approving account '${name}' proxies its votes to '${proxy}'",
("name", voter->ownerName)("proxy", voter->producerVotes.get<AccountName>()));
......@@ -145,20 +145,20 @@ void precondition_staked_okproducer(precondition_validate_context& context) {
EOS_ASSERT(slate.size < config::MaxProducerVotes, message_precondition_exception,
"Cannot approve producer; approved producer count is already at maximum");
if (approve.approve)
EOS_ASSERT(!slate.contains(approve.producer), message_precondition_exception,
EOS_ASSERT(!slate.contains(producer->ownerName), message_precondition_exception,
"Cannot add approval to producer '${name}'; producer is already approved",
("name", approve.producer));
("name", producer->ownerName));
else
EOS_ASSERT(slate.contains(approve.producer), message_precondition_exception,
EOS_ASSERT(slate.contains(producer->ownerName), message_precondition_exception,
"Cannot remove approval from producer '${name}'; producer is not approved",
("name", approve.producer));
("name", producer->ownerName));
}
void apply_staked_okproducer(apply_context& context) {
auto& db = context.mutable_db;
auto approve = context.msg.as<types::okproducer>();
const auto& producer = db.get<ProducerVotesObject, byOwnerName>(approve.producer);
const auto& voter = db.get<StakedBalanceObject, byOwnerName>(context.msg.sender);
const auto& producer = db.get<ProducerVotesObject, byOwnerName>(context.msg.recipient(approve.producer));
const auto& voter = db.get<StakedBalanceObject, byOwnerName>(context.msg.recipient(approve.voter));
auto raceTime = ProducerScheduleObject::get(db).currentRaceTime;
auto totalVotingStake = voter.stakedBalance;
......@@ -174,51 +174,57 @@ void apply_staked_okproducer(apply_context& context) {
pvo.updateVotes(-totalVotingStake, raceTime);
});
// Add/remove producer from voter's approved producer list
db.modify(voter, [&approve](StakedBalanceObject& sbo) {
db.modify(voter, [&approve, producer = producer.ownerName](StakedBalanceObject& sbo) {
auto& slate = sbo.producerVotes.get<ProducerSlate>();
if (approve.approve)
slate.add(approve.producer);
slate.add(producer);
else
slate.remove(approve.producer);
slate.remove(producer);
});
}
void validate_staked_setproxy(message_validate_context& context) {
auto svp = context.msg.as<types::setproxy>();
context.msg.recipient(svp.stakeholder);
context.msg.recipient(svp.proxy);
}
void precondition_staked_setproxy(precondition_validate_context& context) {
auto svp = context.msg.as<types::setproxy>();
const auto& db = context.db;
auto proxy = db.find<ProxyVoteObject, byTargetName>(context.msg.sender);
auto proxy = db.find<ProxyVoteObject, byTargetName>(context.msg.recipient(svp.proxy));
EOS_ASSERT(proxy == nullptr, message_precondition_exception,
"Account '${src}' cannot proxy its votes, since it allows other accounts to proxy to it",
("src", context.msg.sender));
("src", context.msg.recipient(svp.stakeholder)));
if (svp.proxy != context.msg.sender) {
// We are trying to enable proxying to svp.proxy
auto proxy = db.find<ProxyVoteObject, byTargetName>(svp.proxy);
if (svp.proxy != svp.stakeholder) {
// We are trying to enable proxying from svp.stakeholder to svp.proxy
auto proxy = db.find<ProxyVoteObject, byTargetName>(context.msg.recipient(svp.proxy));
EOS_ASSERT(proxy != nullptr, message_precondition_exception,
"Proxy target '${target}' does not allow votes to be proxied to it", ("target", svp.proxy));
"Proxy target '${target}' does not allow votes to be proxied to it", ("target", proxy->proxyTarget));
} else {
// We are trying to disable proxying to sender.producerVotes.get<AccountName>()
const auto& sender = db.get<StakedBalanceObject, byOwnerName>(context.msg.sender);
const auto& sender = db.get<StakedBalanceObject, byOwnerName>(context.msg.recipient(svp.stakeholder));
EOS_ASSERT(sender.producerVotes.contains<AccountName>(), message_precondition_exception,
"Account '${name}' does not currently proxy its votes to any account", ("name", context.msg.sender));
"Account '${name}' does not currently proxy its votes to any account",
("name", context.msg.recipient(svp.stakeholder)));
}
}
void apply_staked_setproxy(apply_context& context) {
auto svp = context.msg.as<types::setproxy>();
auto& db = context.mutable_db;
const auto& proxy = db.get<ProxyVoteObject, byTargetName>(svp.proxy);
const auto& balance = db.get<StakedBalanceObject, byOwnerName>(context.msg.sender);
const auto& proxy = db.get<ProxyVoteObject, byTargetName>(context.msg.recipient(svp.proxy));
const auto& balance = db.get<StakedBalanceObject, byOwnerName>(context.msg.recipient(svp.stakeholder));
if (svp.proxy != context.msg.sender) {
if (svp.proxy != svp.stakeholder) {
// We are enabling proxying to svp.proxy
proxy.addProxySource(context.msg.sender, balance.stakedBalance, db);
db.modify(balance, [target = svp.proxy](StakedBalanceObject& sbo) { sbo.producerVotes = target; });
proxy.addProxySource(context.msg.recipient(svp.stakeholder), balance.stakedBalance, db);
db.modify(balance, [target = proxy.proxyTarget](StakedBalanceObject& sbo) { sbo.producerVotes = target; });
} else {
// We are disabling proxying to balance.producerVotes.get<AccountName>()
proxy.removeProxySource(context.msg.sender, balance.stakedBalance, db);
proxy.removeProxySource(context.msg.recipient(svp.stakeholder), balance.stakedBalance, db);
db.modify(balance, [](StakedBalanceObject& sbo) { sbo.producerVotes = ProducerSlate{}; });
}
}
......
......@@ -3,6 +3,7 @@ typedef Name PermissionName
typedef Name FuncName
typedef FixedString32 MessageName
typedef FixedString32 TypeName
typedef UInt8 NameIndex # Index to an AccountName in Message::recipients
# import account type as localtype
......@@ -91,14 +92,13 @@ struct setproducer
# implies message.sender account
struct okproducer
producer AccountName
approve Int8 # 0 or 1
voter NameIndex # The account casting a vote
producer NameIndex # The producer being voted on
approve Int8 # 1 to approve, or 0 to disapprove
# implies message.sender account
# implies message.sender account
struct setproxy
proxy AccountName
stakeholder NameIndex # The account with stake to be proxied
proxy NameIndex # The account to cast votes with stakeholder's stake weight
struct UpdatePermission
......
......@@ -417,11 +417,12 @@ protected:
#define Set_Proxy(chain, stakeholder, proxy) \
{ \
eos::chain::SignedTransaction trx; \
vector<AccountName> notifies; \
if (std::string(#stakeholder) == std::string(#proxy)) \
notifies.emplace_back(#proxy); \
trx.emplaceMessage(#stakeholder, config::StakedBalanceContractName, notifies, "setproxy", \
types::setproxy{#proxy}); \
if (std::string(#stakeholder) != std::string(#proxy)) \
trx.emplaceMessage(config::StakedBalanceContractName, vector<AccountName>{#stakeholder, #proxy}, \
vector<types::AccountPermission>{}, "setproxy", types::setproxy{0, 1}); \
else \
trx.emplaceMessage(config::StakedBalanceContractName, vector<AccountName>{#stakeholder}, \
vector<types::AccountPermission>{}, "setproxy", types::setproxy{0, 0}); \
trx.expiration = chain.head_block_time() + 100; \
trx.set_reference_block(chain.head_block_id()); \
chain.push_transaction(trx); \
......
......@@ -26,10 +26,10 @@
#define MKACCT_IMPL(chain, name, creator, active, owner, recovery, deposit) \
{ \
eos::chain::SignedTransaction trx; \
trx.emplaceMessage(#creator, config::SystemContractName, \
vector<types::AccountName>{config::StakedBalanceContractName, \
config::EosContractName}, "newaccount", \
types::newaccount{#creator, #name, owner, active, recovery, deposit}); \
trx.emplaceMessage(config::SystemContractName, \
vector<AccountName>{#creator, config::StakedBalanceContractName, config::EosContractName}, \
vector<types::AccountPermission>{}, \
"newaccount", types::newaccount{#creator, #name, owner, active, recovery, deposit}); \
trx.expiration = chain.head_block_time() + 100; \
trx.set_reference_block(chain.head_block_id()); \
chain.push_transaction(trx); \
......@@ -58,8 +58,9 @@
#define XFER5(chain, sender, recipient, amount, memo) \
{ \
eos::chain::SignedTransaction trx; \
trx.emplaceMessage(#sender, config::EosContractName, vector<AccountName>{#recipient}, "transfer", \
types::transfer{#sender, #recipient, amount, memo}); \
trx.emplaceMessage(config::EosContractName, vector<AccountName>{#sender, #recipient}, \
vector<types::AccountPermission>{}, \
"transfer", types::transfer{#sender, #recipient, amount, memo}); \
trx.expiration = chain.head_block_time() + 100; \
trx.set_reference_block(chain.head_block_id()); \
chain.push_transaction(trx); \
......@@ -70,11 +71,11 @@
#define STAKE4(chain, sender, recipient, amount) \
{ \
eos::chain::SignedTransaction trx; \
trx.emplaceMessage(#sender, config::EosContractName, vector<AccountName>{config::StakedBalanceContractName}, \
"lock", types::lock{#sender, #recipient, amount}); \
trx.emplaceMessage(config::EosContractName, vector<AccountName>{#sender, config::StakedBalanceContractName}, \
vector<types::AccountPermission>{}, "lock", types::lock{#sender, #recipient, amount}); \
if (std::string(#sender) != std::string(#recipient)) { \
trx.messages.front().notify.emplace_back(#recipient); \
boost::sort(trx.messages.front().notify); \
trx.messages.front().recipients.emplace_back(#recipient); \
boost::sort(trx.messages.front().recipients); \
} \
trx.expiration = chain.head_block_time() + 100; \
trx.set_reference_block(chain.head_block_id()); \
......@@ -86,7 +87,8 @@
#define BEGIN_UNSTAKE3(chain, account, amount) \
{ \
eos::chain::SignedTransaction trx; \
trx.emplaceMessage(#account, config::StakedBalanceContractName, vector<AccountName>{}, \
trx.emplaceMessage(config::StakedBalanceContractName, vector<AccountName>{#account}, \
vector<types::AccountPermission>{}, \
"unlock", types::unlock{#account, amount}); \
trx.expiration = chain.head_block_time() + 100; \
trx.set_reference_block(chain.head_block_id()); \
......@@ -97,8 +99,8 @@
#define FINISH_UNSTAKE3(chain, account, amount) \
{ \
eos::chain::SignedTransaction trx; \
trx.emplaceMessage(#account, config::StakedBalanceContractName, vector<AccountName>{config::EosContractName}, \
"claim", types::claim{#account, amount}); \
trx.emplaceMessage(config::StakedBalanceContractName, vector<AccountName>{#account, config::EosContractName}, \
vector<types::AccountPermission>{}, "claim", types::claim{#account, amount}); \
trx.expiration = chain.head_block_time() + 100; \
trx.set_reference_block(chain.head_block_id()); \
chain.push_transaction(trx); \
......@@ -108,8 +110,9 @@
#define MKPDCR4(chain, owner, key, cfg) \
{ \
eos::chain::SignedTransaction trx; \
trx.emplaceMessage(#owner, config::StakedBalanceContractName, vector<AccountName>{}, "setproducer", \
types::setproducer{#owner, key, cfg}); \
trx.emplaceMessage(config::StakedBalanceContractName, vector<AccountName>{#owner}, \
vector<types::AccountPermission>{}, \
"setproducer", types::setproducer{#owner, key, cfg}); \
trx.expiration = chain.head_block_time() + 100; \
trx.set_reference_block(chain.head_block_id()); \
chain.push_transaction(trx); \
......@@ -123,8 +126,9 @@
#define APPDCR4(chain, voter, producer, approved) \
{ \
eos::chain::SignedTransaction trx; \
trx.emplaceMessage(#voter, config::StakedBalanceContractName, vector<AccountName>{}, "okproducer", \
types::okproducer{#producer, approved? 1 : 0}); \
trx.emplaceMessage(config::StakedBalanceContractName, vector<AccountName>{#voter, #producer}, \
vector<types::AccountPermission>{}, \
"okproducer", types::okproducer{0, 1, approved? 1 : 0}); \
trx.expiration = chain.head_block_time() + 100; \
trx.set_reference_block(chain.head_block_id()); \
chain.push_transaction(trx); \
......@@ -134,8 +138,9 @@
#define UPPDCR4(chain, owner, key, cfg) \
{ \
eos::chain::SignedTransaction trx; \
trx.emplaceMessage(owner, config::StakedBalanceContractName, vector<AccountName>{}, "setproducer", \
types::setproducer{owner, key, cfg}); \
trx.emplaceMessage(config::StakedBalanceContractName, vector<AccountName>{#owner}, \
vector<types::AccountPermission>{}, \
"setproducer", types::setproducer{owner, key, cfg}); \
trx.expiration = chain.head_block_time() + 100; \
trx.set_reference_block(chain.head_block_id()); \
chain.push_transaction(trx); \
......
......@@ -177,8 +177,7 @@ BOOST_FIXTURE_TEST_CASE(create_script, testing_fixture)
{
eos::chain::SignedTransaction trx;
trx.messages.resize(1);
trx.messages[0].sender = "simplecoin";
trx.messages[0].recipient = config::SystemContractName;
trx.messages[0].recipients = {"simplecoin", config::SystemContractName};
trx.setMessage(0, "setcode", handler);
trx.expiration = chain.head_block_time() + 100;
trx.set_reference_block(chain.head_block_id());
......@@ -191,8 +190,9 @@ BOOST_FIXTURE_TEST_CASE(create_script, testing_fixture)
for (uint32_t i = 0; i < 100000; ++i)
{
eos::chain::SignedTransaction trx;
trx.emplaceMessage("simplecoin", "simplecoin", vector<AccountName>{"inita"}, "transfer",
types::transfer{"simplecoin", "inita", 1+i, "hello"} );
trx.emplaceMessage("simplecoin", vector<AccountName>{"simplecoin", "inita"},
vector<types::AccountPermission>{},
"transfer", types::transfer{"simplecoin", "inita", 1+i, "hello"});
trx.expiration = chain.head_block_time() + 100;
trx.set_reference_block(chain.head_block_id());
chain.push_transaction(trx);
......@@ -971,8 +971,7 @@ R"(
eos::chain::SignedTransaction trx;
trx.messages.resize(1);
trx.messages[0].sender = "simplecoin";
trx.messages[0].recipient = config::SystemContractName;
trx.messages[0].recipients = {"simplecoin", config::SystemContractName};
trx.setMessage(0, "setcode", handler);
trx.expiration = chain.head_block_time() + 100;
trx.set_reference_block(chain.head_block_id());
......
......@@ -90,8 +90,7 @@ BOOST_FIXTURE_TEST_CASE(transfer, testing_fixture)
trx.messages.resize(1);
trx.set_reference_block(chain.head_block_id());
trx.expiration = chain.head_block_time() + 100;
trx.messages[0].sender = "inita";
trx.messages[0].recipient = config::EosContractName;
trx.messages[0].recipients = {"inita", config::EosContractName};
types::transfer trans = { "inita", "initb", Asset(100), "transfer 100" };
......@@ -105,7 +104,7 @@ BOOST_FIXTURE_TEST_CASE(transfer, testing_fixture)
auto unpack_trans = trx.messageAs<types::transfer>(0);
BOOST_REQUIRE_THROW(chain.push_transaction(trx), message_validate_exception); // "fail to notify receiver, initb"
trx.messages[0].notify = {"initb"};
trx.messages[0].recipients = {"inita", "initb"};
trx.setMessage(0, "transfer", trans);
chain.push_transaction(trx);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册