提交 248049c5 编写于 作者: D Daniel Larimer

Basic transfer working for base token

- absent signature verification
上级 4bf961e4
......@@ -32,6 +32,8 @@
#include <eos/chain/transaction_object.hpp>
#include <eos/chain/producer_object.hpp>
#include <eos/chain/sys_contract.hpp>
#include <fc/smart_ref_impl.hpp>
#include <fc/uint128.hpp>
#include <fc/crypto/digest.hpp>
......@@ -487,18 +489,38 @@ void database::validate_uniqueness( const signed_transaction& trx )const {
auto& trx_idx = get_index<transaction_multi_index>();
FC_ASSERT( trx_idx.indices().get<by_trx_id>().find(trx_id) == trx_idx.indices().get<by_trx_id>().end());
}
void database::validate_referenced_accounts( const signed_transaction& trx )const {
for( const auto& auth : trx.provided_authorizations ) {
get_account( auth.authorizing_account );
}
for( const auto& msg : trx.messages ) {
get_account( msg.sender );
get_account( msg.recipient );
const account_name* prev = nullptr;
for( const auto& acnt : msg.notify ) {
get_account( acnt );
if( prev )
FC_ASSERT( acnt < *prev );
FC_ASSERT( acnt != msg.sender );
FC_ASSERT( acnt != msg.recipient );
prev = &acnt;
}
}
}
void database::validate_transaction( const signed_transaction& trx )const {
try {
FC_ASSERT( trx.messages.size() > 0, "A transaction must have at least one message" );
validate_uniqueness( trx );
validate_tapos( trx );
validate_referenced_accounts( trx );
for( const auto& m : trx.messages ) { /// TODO: this loop can be processed in parallel
message_validate_context mvc( trx, m );
auto contract_handlers_itr = message_validate_handlers.find( m.recipient );
if( contract_handlers_itr != message_validate_handlers.end() ) {
auto message_handelr_itr = contract_handlers_itr->second.find( m.type );
auto message_handelr_itr = contract_handlers_itr->second.find( m.recipient + '/' + m.type );
if( message_handelr_itr != contract_handlers_itr->second.end() ) {
message_handelr_itr->second(mvc);
continue;
......@@ -675,6 +697,33 @@ void database::initialize_indexes() {
void database::init_genesis(const genesis_state_type& genesis_state)
{ try {
set_validate_handler( "sys", "sys/Transfer", [&]( message_validate_context& context ) {
idump((context.msg));
auto transfer = context.msg.as<Transfer>();
FC_ASSERT( context.msg.has_notify( transfer.to ), "Must notify recipient of transfer" );
});
set_precondition_validate_handler( "sys", "sys/Transfer", [&]( precondition_validate_context& context ) {
idump((context.msg)(context.receiver));
auto transfer = context.msg.as<Transfer>();
const auto& from = get_account( transfer.from );
FC_ASSERT( from.balance > transfer.amount, "Insufficient Funds",
("from.balance",from.balance)("transfer.amount",transfer.amount) );
});
set_apply_handler( "sys", "sys/Transfer", [&]( apply_context& context ) {
idump((context.msg)(context.receiver));
auto transfer = context.msg.as<Transfer>();
const auto& from = get_account( transfer.from );
const auto& to = get_account( transfer.to );
modify( from, [&]( account_object& a ) {
a.balance -= transfer.amount;
});
modify( to, [&]( account_object& a ) {
a.balance += transfer.amount;
});
});
FC_ASSERT( genesis_state.initial_timestamp != time_point_sec(), "Must initialize genesis timestamp." );
FC_ASSERT( genesis_state.initial_timestamp.sec_since_epoch() % config::BlockIntervalSeconds == 0,
"Genesis timestamp must be divisible by config::BlockIntervalSeconds." );
......@@ -689,10 +738,18 @@ void database::init_genesis(const genesis_state_type& genesis_state)
uint32_t old_flags;
} inhibitor(*this);
/// create the system contract
create<account_object>([&](account_object& a) {
a.name = "sys";
});
// Create initial accounts
for (const auto& acct : genesis_state.initial_accounts) {
create<account_object>([&acct](account_object& a) {
a.name = acct.name.c_str();
a.balance = acct.balance;
idump((acct.name)(a.balance));
// a.active_key = acct.active_key;
// a.owner_key = acct.owner_key;
});
......@@ -1011,4 +1068,9 @@ void database::set_apply_handler( const account_name& contract, const message_ty
apply_handlers[contract][action] = v;
}
const account_object& database::get_account( const account_name& name )const {
try {
return get<account_object,by_name>(name);
} FC_CAPTURE_AND_RETHROW( (name) ) }
} }
......@@ -173,6 +173,8 @@ namespace eos { namespace chain {
const signed_transaction& get_recent_transaction( const transaction_id_type& trx_id )const;
std::vector<block_id_type> get_block_ids_on_fork(block_id_type head_of_fork) const;
const account_object& get_account( const account_name& name )const;
/**
* Calculate the percent of block production slots that were missed in the
* past 128 blocks, not including the current block.
......@@ -305,14 +307,17 @@ namespace eos { namespace chain {
void apply_debug_updates();
void debug_update(const fc::variant_object& update);
private:
/**
* This method validates transactions without adding it to the pending state.
* @return true if the transaction would validate
*/
void validate_transaction(const signed_transaction& trx)const;
void validate_tapos( const signed_transaction& trx )const;
void validate_referenced_accounts( const signed_transaction& trx )const;
private:
optional<session> _pending_tx_session;
public:
......
......@@ -39,13 +39,15 @@ using std::vector;
struct genesis_state_type {
struct initial_account_type {
initial_account_type(const string& name = string(),
uint64_t bal = 0,
const public_key_type& owner_key = public_key_type(),
const public_key_type& active_key = public_key_type())
: name(name),
: name(name), balance(bal),
owner_key(owner_key),
active_key(active_key == public_key_type()? owner_key : active_key)
{}
string name;
uint64_t balance = 0;
public_key_type owner_key;
public_key_type active_key;
};
......@@ -80,7 +82,7 @@ struct genesis_state_type {
} } // namespace eos::chain
FC_REFLECT(eos::chain::genesis_state_type::initial_account_type, (name)(owner_key)(active_key))
FC_REFLECT(eos::chain::genesis_state_type::initial_account_type, (name)(balance)(owner_key)(active_key))
FC_REFLECT(eos::chain::genesis_state_type::initial_producer_type, (owner_name)(block_signing_key))
......
......@@ -43,6 +43,15 @@ struct message {
type = t;
data = fc::raw::pack( value );
}
template<typename T>
T as()const {
return fc::raw::unpack<T>(data);
}
bool has_notify( const account_name& n )const {
for( const auto& no : notify )
if( no == n ) return true;
return false;
}
};
......
......@@ -49,7 +49,7 @@ testing_fixture::testing_fixture() {
auto name = std::string("init") + fc::to_string(i);
auto private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(name));
public_key_type public_key = private_key.get_public_key();
default_genesis_state.initial_accounts.emplace_back(name, public_key, public_key);
default_genesis_state.initial_accounts.emplace_back(name, 100000, public_key, public_key);
key_ring[public_key] = private_key;
private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(name + ".producer"));
......
......@@ -27,6 +27,7 @@
#include <eos/chain/database.hpp>
#include <eos/chain/exceptions.hpp>
#include <eos/chain/account_object.hpp>
#include <eos/chain/sys_contract.hpp>
#include <eos/utilities/tempdir.hpp>
......@@ -65,16 +66,20 @@ BOOST_FIXTURE_TEST_CASE(transfer, testing_fixture)
signed_transaction trx;
BOOST_REQUIRE_THROW( db.push_transaction(trx), fc::assert_exception ); /// no messages
trx.messages.resize(1);
trx.set_reference_block( db.head_block_id() );
trx.set_expiration( db.head_block_time() );
ilog(".");
trx.messages[0].sender = "init1";
trx.messages[0].recipient = "sys";
trx.messages[0].type = "Transfer";
trx.messages[0].set( "Transfer", eos::chain::Transfer{ "init1", "init2", 100, "memo" } );
BOOST_REQUIRE_THROW( db.push_transaction(trx), fc::assert_exception ); // "fail to notify receiver, init2"
trx.messages[0].notify = {"init2"};
trx.messages[0].set( "Transfer", eos::chain::Transfer{ "init1", "init2", 100, "memo" } );
db.push_transaction(trx);
ilog(".");
BOOST_CHECK_EQUAL( db.get_account( "init1" ).balance, 100000 - 100 );
BOOST_CHECK_EQUAL( db.get_account( "init2" ).balance, 100000 + 100 );
db.produce_blocks(1);
ilog(".");
BOOST_REQUIRE_THROW( db.push_transaction(trx), fc::assert_exception ); /// no messages
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册