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

Commit

Permalink
Progress #5: Structures
Browse files Browse the repository at this point in the history
Define structures around cycles/threads, etc.

Also implement merkle digests. :)
  • Loading branch information
nathanielhourt committed Apr 11, 2017
1 parent dd72f34 commit 935c701
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 137 deletions.
35 changes: 18 additions & 17 deletions libraries/app/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,23 +111,24 @@ namespace eos { namespace app {

void network_broadcast_api::on_applied_block( const signed_block& b )
{
if( _callbacks.size() )
{
/// we need to ensure the database_api is not deleted for the life of the async operation
auto capture_this = shared_from_this();
for( uint32_t trx_num = 0; trx_num < b.transactions.size(); ++trx_num )
{
const auto& trx = b.transactions[trx_num];
auto id = trx.id();
auto itr = _callbacks.find(id);
if( itr != _callbacks.end() )
{
auto block_num = b.block_num();
auto& callback = _callbacks.find(id)->second;
fc::async( [capture_this,this,id,block_num,trx_num,trx,callback](){ callback( fc::variant(transaction_confirmation{ id, block_num, trx_num, trx}) ); } );
}
}
}
#warning TODO: Figure out how to handle this
// if( _callbacks.size() )
// {
// /// we need to ensure the database_api is not deleted for the life of the async operation
// auto capture_this = shared_from_this();
// for( uint32_t trx_num = 0; trx_num < b.transactions.size(); ++trx_num )
// {
// const auto& trx = b.transactions[trx_num];
// auto id = trx.id();
// auto itr = _callbacks.find(id);
// if( itr != _callbacks.end() )
// {
// auto block_num = b.block_num();
// auto& callback = _callbacks.find(id)->second;
// fc::async( [capture_this,this,id,block_num,trx_num,trx,callback](){ callback( fc::variant(transaction_confirmation{ id, block_num, trx_num, trx}) ); } );
// }
// }
// }
}

void network_broadcast_api::broadcast_transaction(const signed_transaction& trx)
Expand Down
13 changes: 7 additions & 6 deletions libraries/app/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,12 +536,13 @@ namespace detail {
// included in blocks before we see the free-floating transaction itself. If that
// happens, there's no reason to fetch the transactions, so construct a list of the
// transaction message ids we no longer need.
// during sync, it is unlikely that we'll see any old
for (const signed_transaction& transaction : blk_msg.block.transactions)
{
eos::net::trx_message transaction_message(transaction);
contained_transaction_message_ids.push_back(eos::net::message(transaction_message).id());
}
for (const auto& cycle : blk_msg.block.cycles)
for (const auto& thread : cycle)
for (const auto& transaction : thread.input_transactions)
if (transaction.which() == decay_t<decltype(transaction)>::tag<signed_transaction>::value) {
eos::net::trx_message transaction_message(transaction.get<signed_transaction>());
contained_transaction_message_ids.push_back(eos::net::message(transaction_message).id());
}
}

return result;
Expand Down
93 changes: 46 additions & 47 deletions libraries/chain/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,35 +229,30 @@ bool database::_push_block(const signed_block& new_block)
* queues full as well, it will be kept in the queue to be propagated later when a new block flushes out the pending
* queues.
*/
signed_transaction database::push_transaction( const signed_transaction& trx, uint32_t skip )
void database::push_transaction(const signed_transaction& trx, uint32_t skip)
{ try {
signed_transaction result;
detail::with_skip_flags( *this, skip, [&]()
detail::with_skip_flags(*this, skip, [&]()
{
result = _push_transaction( trx );
} );
return result;
} FC_CAPTURE_AND_RETHROW( (trx) ) }
_push_transaction(trx);
});
} FC_CAPTURE_AND_RETHROW((trx)) }

signed_transaction database::_push_transaction( const signed_transaction& trx )
{
void database::_push_transaction(const signed_transaction& trx) {
auto temp_session = start_undo_session(true);
auto processed_trx = _apply_transaction( trx );
_pending_tx.push_back(processed_trx);
_apply_transaction(trx);
_pending_tx.push_back(trx);

// notify_changed_objects();
// The transaction applied successfully. Merge its changes into the pending block session.
temp_session.squash();

// notify anyone listening to pending transactions
on_pending_transaction( trx );
return processed_trx;
on_pending_transaction(trx);
}

signed_transaction database::validate_transaction( const signed_transaction& trx )
{
void database::validate_transaction(const signed_transaction& trx) {
auto session = start_undo_session(true);
return _apply_transaction( trx );
_apply_transaction(trx);
}

signed_block database::generate_block(
Expand Down Expand Up @@ -329,14 +324,12 @@ signed_block database::_generate_block(
try
{
auto temp_session = start_undo_session(true);
signed_transaction ptx = _apply_transaction( tx );
_apply_transaction(tx);
temp_session.squash();

// We have to recompute pack_size(ptx) because it may be different
// than pack_size(tx) (i.e. if one or more results increased
// their size)
total_block_size += fc::raw::pack_size( ptx );
pending_block.transactions.push_back( ptx );
total_block_size += fc::raw::pack_size(tx);
// pending_block.transactions.push_back(tx);
#warning TODO: Populate generated blocks with transactions
}
catch ( const fc::exception& e )
{
Expand Down Expand Up @@ -378,8 +371,7 @@ signed_block database::_generate_block(
} FC_CAPTURE_AND_RETHROW( (producer_id) ) }

/**
* Removes the most recent block from the database and
* undoes any changes it made.
* Removes the most recent block from the database and undoes any changes it made.
*/
void database::pop_block()
{ try {
Expand All @@ -390,9 +382,6 @@ void database::pop_block()

_fork_db.pop_block();
undo();

_popped_tx.insert( _popped_tx.begin(), head_block->transactions.begin(), head_block->transactions.end() );

} FC_CAPTURE_AND_RETHROW() }

void database::clear_pending()
Expand Down Expand Up @@ -424,7 +413,7 @@ void database::apply_block( const signed_block& next_block, uint32_t skip )
return;
}

void database::_apply_block( const signed_block& next_block )
void database::_apply_block(const signed_block& next_block)
{ try {
uint32_t next_block_num = next_block.block_num();
uint32_t skip = get_node_properties().skip_flags;
Expand All @@ -436,17 +425,31 @@ void database::_apply_block( const signed_block& next_block )
_current_block_num = next_block_num;
_current_trx_in_block = 0;

for( const auto& trx : next_block.transactions )
{
/* We do not need to push the undo state for each transaction
* because they either all apply and are valid or the
* entire block fails to apply. We only need an "undo" state
* for transactions when validating broadcast transactions or
* when building a block.
*/
apply_transaction( trx, skip | skip_transaction_signatures );
++_current_trx_in_block;
}
/* We do not need to push the undo state for each transaction
* because they either all apply and are valid or the
* entire block fails to apply. We only need an "undo" state
* for transactions when validating broadcast transactions or
* when building a block.
*/
for (const auto& cycle : next_block.cycles)
for (const auto& thread : cycle)
for(const auto& trx : thread.input_transactions)
{
struct {
using result_type = void;
void operator()(const signed_transaction& trx) {
db.apply_transaction(trx);
}
void operator()(generated_transaction_id_type) {
#warning TODO: Process generated transaction
}

database& db;
} visitor{*this};

trx.visit(visitor);
++_current_trx_in_block;
}

update_global_dynamic_data(next_block);
update_signing_producer(signing_producer, next_block);
Expand All @@ -467,17 +470,15 @@ void database::_apply_block( const signed_block& next_block )

} FC_CAPTURE_AND_RETHROW( (next_block.block_num()) ) }

signed_transaction database::apply_transaction(const signed_transaction& trx, uint32_t skip)
void database::apply_transaction(const signed_transaction& trx, uint32_t skip)
{
signed_transaction result;
detail::with_skip_flags( *this, skip, [&]()
detail::with_skip_flags(*this, skip, [&]()
{
result = _apply_transaction(trx);
_apply_transaction(trx);
});
return result;
}

signed_transaction database::_apply_transaction(const signed_transaction& trx)
void database::_apply_transaction(const signed_transaction& trx)
{ try {
uint32_t skip = get_node_properties().skip_flags;

Expand Down Expand Up @@ -526,8 +527,6 @@ signed_transaction database::_apply_transaction(const signed_transaction& trx)
#warning TODO: Process messages in transaction
++_current_message_in_trx;
}

return ptrx;
} FC_CAPTURE_AND_RETHROW( (trx) ) }

const producer_object& database::validate_block_header( uint32_t skip, const signed_block& next_block )const
Expand Down
27 changes: 11 additions & 16 deletions libraries/chain/include/eos/chain/database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ namespace eos { namespace chain {
bool before_last_checkpoint()const;

bool push_block( const signed_block& b, uint32_t skip = skip_nothing );
signed_transaction push_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing );
void push_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing );
bool _push_block( const signed_block& b );
signed_transaction _push_transaction( const signed_transaction& trx );
void _push_transaction( const signed_transaction& trx );

signed_block generate_block(
const fc::time_point_sec when,
Expand Down Expand Up @@ -217,38 +217,33 @@ namespace eos { namespace chain {

void debug_dump();
void apply_debug_updates();
void debug_update( const fc::variant_object& update );
void debug_update(const fc::variant_object& update);

/**
* This method validates transactions without adding it to the pending state.
* @return true if the transaction would validate
*/
signed_transaction validate_transaction( const signed_transaction& trx );


/** when popping a block, the transactions that were removed get cached here so they
* can be reapplied at the proper time */
std::deque< signed_transaction > _popped_tx;
void validate_transaction(const signed_transaction& trx);

private:
optional<session> _pending_tx_session;

public:
// these were formerly private, but they have a fairly well-defined API, so let's make them public
void apply_block( const signed_block& next_block, uint32_t skip = skip_nothing );
signed_transaction apply_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing );
void apply_block(const signed_block& next_block, uint32_t skip = skip_nothing);
void apply_transaction(const signed_transaction& trx, uint32_t skip = skip_nothing);
private:
void _apply_block( const signed_block& next_block );
signed_transaction _apply_transaction( const signed_transaction& trx );
void _apply_block(const signed_block& next_block);
void _apply_transaction(const signed_transaction& trx);

///Steps involved in applying a new block
///@{

const producer_object& validate_block_header( uint32_t skip, const signed_block& next_block )const;
const producer_object& _validate_block_header( const signed_block& next_block )const;
const producer_object& validate_block_header(uint32_t skip, const signed_block& next_block)const;
const producer_object& _validate_block_header(const signed_block& next_block)const;
void create_block_summary(const signed_block& next_block);

void update_global_dynamic_data( const signed_block& b );
void update_global_dynamic_data(const signed_block& b);
void update_signing_producer(const producer_object& signing_producer, const signed_block& new_block);
void update_last_irreversible_block();
void clear_expired_transactions();
Expand Down
20 changes: 16 additions & 4 deletions libraries/chain/include/eos/chain/protocol/block.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,26 @@ namespace eos { namespace chain {
signature_type producer_signature;
};

struct thread {
using input_transaction = static_variant<signed_transaction, generated_transaction_id_type>;

vector<input_transaction> input_transactions;
vector<generated_transaction> output_transactions;

digest_type merkle_digest() const;
};

using cycle = vector<thread>;

struct signed_block : public signed_block_header
{
checksum_type calculate_merkle_root()const;
vector<signed_transaction> transactions;
vector<cycle> cycles;
};

} } // eos::chain

FC_REFLECT( eos::chain::block_header, (previous)(timestamp)(producer)(transaction_merkle_root) )
FC_REFLECT_DERIVED( eos::chain::signed_block_header, (eos::chain::block_header), (producer_signature) )
FC_REFLECT_DERIVED( eos::chain::signed_block, (eos::chain::signed_block_header), (transactions) )
FC_REFLECT(eos::chain::block_header, (previous)(timestamp)(producer)(transaction_merkle_root))
FC_REFLECT_DERIVED(eos::chain::signed_block_header, (eos::chain::block_header), (producer_signature))
FC_REFLECT(eos::chain::thread, (input_transactions)(output_transactions))
FC_REFLECT_DERIVED(eos::chain::signed_block, (eos::chain::signed_block_header), (cycles))
20 changes: 20 additions & 0 deletions libraries/chain/include/eos/chain/protocol/transaction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,25 @@ namespace eos { namespace chain {
void set_reference_block(const block_id_type& reference_block);
};

/**
* @brief A generated_transaction is a transaction which was internally generated by the blockchain, typically as a
* result of running a contract.
*
* When contracts run and seek to interact with other contracts, or mutate chain state, they generate transactions
* containing messages which effect these interactions and mutations. These generated transactions are automatically
* generated by contracts, and thus are authorized by the script that generated them rather than by signatures. The
* generated_transaction struct records such a transaction.
*
* These transactions are generated while processing other transactions. The generated transactions are assigned a
* sequential ID, then stored in the block that generated them. These generated transactions can then be included in
* subsequent blocks by referencing this ID.
*/
struct generated_transaction : public transaction {
generated_transaction_id_type id;

digest_type merkle_digest() const;
};

/**
* @brief A single authorization used to authorize a transaction
*
Expand Down Expand Up @@ -169,5 +188,6 @@ namespace eos { namespace chain {
} } // eos::chain

FC_REFLECT(eos::chain::transaction, (ref_block_num)(ref_block_prefix)(expiration)(messages))
FC_REFLECT(eos::chain::generated_transaction, (id))
FC_REFLECT(eos::chain::authorization, (authorizing_account)(privileges))
FC_REFLECT_DERIVED(eos::chain::signed_transaction, (eos::chain::transaction), (signatures))
25 changes: 13 additions & 12 deletions libraries/chain/include/eos/chain/protocol/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ namespace eos { namespace chain {
using privilege_class = std::string;

/**
* List all object types from all namespaces here so they can
* be easily reflected and displayed in debug output. If a 3rd party
* wants to extend the core code then they will have to change the
* packed_object::type field from enum_type to uint16 to avoid
* warnings when converting packed_objects to/from json.
* List all object types from all namespaces here so they can
* be easily reflected and displayed in debug output. If a 3rd party
* wants to extend the core code then they will have to change the
* packed_object::type field from enum_type to uint16 to avoid
* warnings when converting packed_objects to/from json.
*/
enum object_type
{
Expand All @@ -123,13 +123,14 @@ namespace eos { namespace chain {
using account_id_type = chainbase::oid<account_object>;
using producer_id_type = chainbase::oid<producer_object>;

typedef fc::ripemd160 block_id_type;
typedef fc::ripemd160 checksum_type;
typedef fc::ripemd160 transaction_id_type;
typedef fc::sha256 digest_type;
typedef fc::ecc::compact_signature signature_type;
typedef safe<int64_t> share_type;
typedef uint16_t weight_type;
using generated_transaction_id_type = uint32_t;
using block_id_type = fc::ripemd160;
using checksum_type = fc::ripemd160;
using transaction_id_type = fc::ripemd160;
using digest_type = fc::sha256;
using signature_type = fc::ecc::compact_signature;
using share_type = safe<int64_t>;
using weight_type = uint16_t;

struct public_key_type
{
Expand Down
Loading

0 comments on commit 935c701

Please sign in to comment.