提交 ed7cb321 编写于 作者: D Daniel Larimer

progress

file(GLOB HEADERS "include/eos/chain/*.hpp")
file(GLOB PROTOCOL_HEADERS "include/eos/chain/protocol/*.hpp")
## SORT .cpp by most likely to change / break compile
add_library( eos_chain
database.cpp
fork_database.cpp
protocol/types.cpp
protocol/transaction.cpp
protocol/block.cpp
types.cpp
transaction.cpp
block.cpp
genesis_state.cpp
get_config.cpp
......@@ -36,4 +34,3 @@ INSTALL( TARGETS
ARCHIVE DESTINATION lib
)
INSTALL( FILES ${HEADERS} DESTINATION "include/eos/chain" )
INSTALL( FILES ${PROTOCOL_HEADERS} DESTINATION "include/eos/chain/protocol" )
......@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <eos/chain/protocol/block.hpp>
#include <eos/chain/block.hpp>
#include <fc/io/raw.hpp>
#include <fc/bitutil.hpp>
#include <algorithm>
......
......@@ -80,7 +80,7 @@ optional<signed_block> database::fetch_block_by_number(uint32_t num)const
if (const auto& block = _block_log.read_block_by_num(num))
return *block;
// Not in _block_id_to_block, so it must be since the last irreversible block. Grab it from _fork_db instead
// Not in _block_log, so it must be since the last irreversible block. Grab it from _fork_db instead
if (num <= head_block_num()) {
auto block = _fork_db.head();
while (block && block->num > num)
......@@ -458,25 +458,28 @@ void database::apply_transaction(const signed_transaction& trx, uint32_t skip)
with_skip_flags( skip, [&]() { _apply_transaction(trx); });
}
void database::validate_tapos( const signed_transaction& trx )const {
void database::validate_transaction(const signed_transaction& trx)const {
try {
if( !should_check_tapos() ) return;
const chain_parameters& chain_parameters = get_global_properties().parameters;
const auto& tapos_block_summary = get<block_summary_object>(trx.ref_block_num);
EOS_ASSERT(trx.messages.size() > 0, transaction_exception, "A transaction must have at least one message");
//Verify TaPoS block summary has correct ID prefix, and that this block's time is not past the expiration
EOS_ASSERT(trx.ref_block_prefix == tapos_block_summary.block_id._hash[1], transaction_exception,
"Transaction's reference block did not match. Is this transaction from a different fork?");
validate_uniqueness(trx);
validate_tapos(trx);
validate_referenced_accounts(trx);
validate_expiration(trx);
fc::time_point_sec now = head_block_time();
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_handler_itr = contract_handlers_itr->second.find( {m.recipient, m.type} );
if( message_handler_itr != contract_handlers_itr->second.end() ) {
message_handler_itr->second(mvc);
continue;
}
}
EOS_ASSERT(trx.expiration <= now + chain_parameters.maximum_time_until_expiration,
transaction_exception, "Transaction expiration is too far in the future",
("trx.expiration",trx.expiration)("now",now)
("max_til_exp",chain_parameters.maximum_time_until_expiration));
EOS_ASSERT(now <= trx.expiration, transaction_exception, "Transaction is expired",
("now",now)("trx.exp",trx.expiration));
/// TODO: dispatch to script if not handled above
}
} FC_CAPTURE_AND_RETHROW( (trx) ) }
void database::validate_uniqueness( const signed_transaction& trx )const {
......@@ -488,21 +491,35 @@ void database::validate_uniqueness( const signed_transaction& trx )const {
transaction_exception, "Transaction is not unique");
}
void database::validate_referenced_accounts( const signed_transaction& trx )const {
for( const auto& auth : trx.provided_authorizations ) {
get_account( auth.authorizing_account );
void database::validate_tapos( const signed_transaction& trx )const {
try {
if( !should_check_tapos() ) return;
const auto& tapos_block_summary = get<block_summary_object>(trx.ref_block_num);
//Verify TaPoS block summary has correct ID prefix, and that this block's time is not past the expiration
EOS_ASSERT(trx.ref_block_prefix == tapos_block_summary.block_id._hash[1], transaction_exception,
"Transaction's reference block did not match. Is this transaction from a different fork?");
} FC_CAPTURE_AND_RETHROW( (trx) ) }
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;
for(const auto& msg : trx.messages) {
get_account(msg.sender);
get_account(msg.recipient);
const account_name* previous_notify_account = nullptr;
for(const auto& current_notify_account : msg.notify) {
get_account(current_notify_account);
if(previous_notify_account)
EOS_ASSERT(current_notify_account < *previous_notify_account, 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;
}
}
}
......@@ -535,14 +552,24 @@ try {
continue;
}
}
/// TODO: dispatch to script if not handled above
}
} FC_CAPTURE_AND_RETHROW( (trx) ) }
}
void database::validate_expiration(const signed_transaction& trx) const
{ try {
fc::time_point_sec now = head_block_time();
const chain_parameters& chain_parameters = get_global_properties().parameters;
EOS_ASSERT(trx.expiration <= now + chain_parameters.maximum_time_until_expiration,
transaction_exception, "Transaction expiration is too far in the future",
("trx.expiration",trx.expiration)("now",now)
("max_til_exp",chain_parameters.maximum_time_until_expiration));
EOS_ASSERT(now <= trx.expiration, transaction_exception, "Transaction is expired",
("now",now)("trx.exp",trx.expiration));
} FC_CAPTURE_AND_RETHROW((trx)) }
void database::validate_message_precondition( precondition_validate_context& context )const {
const auto& m = context.msg;
auto contract_handlers_itr = precondition_validate_handlers.find( context.receiver );
auto contract_handlers_itr = precondition_validate_handlers.find( context.recipient );
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() ) {
......@@ -555,7 +582,7 @@ void database::validate_message_precondition( precondition_validate_context& con
void database::apply_message( apply_context& context ) {
const auto& m = context.msg;
auto contract_handlers_itr = apply_handlers.find( context.receiver );
auto contract_handlers_itr = apply_handlers.find( context.recipient );
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() ) {
......@@ -569,7 +596,7 @@ void database::apply_message( apply_context& context ) {
void database::_apply_transaction(const signed_transaction& trx)
{ try {
validate_transaction( trx );
validate_transaction(trx);
for( const auto& m : trx.messages ) {
apply_context ac( *this, trx, m, m.recipient );
......
......@@ -24,7 +24,7 @@
#include <eos/chain/get_config.hpp>
#include <eos/chain/config.hpp>
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/types.hpp>
namespace eos { namespace chain {
......
......@@ -22,8 +22,8 @@
* THE SOFTWARE.
*/
#pragma once
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/protocol/authority.hpp>
#include <eos/chain/types.hpp>
#include <eos/chain/authority.hpp>
#include "multi_index_includes.hpp"
......
#pragma once
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/types.hpp>
namespace eos { namespace chain {
......
......@@ -23,7 +23,7 @@
*/
#pragma once
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/types.hpp>
namespace eos { namespace chain {
......
......@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
#pragma once
#include <eos/chain/protocol/transaction.hpp>
#include <eos/chain/transaction.hpp>
namespace eos { namespace chain {
......
#pragma once
#include <fc/filesystem.hpp>
#include <eos/chain/protocol/block.hpp>
#include <eos/chain/block.hpp>
namespace eos { namespace chain {
......
......@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
#pragma once
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/types.hpp>
#include "multi_index_includes.hpp"
......
......@@ -22,8 +22,8 @@
* THE SOFTWARE.
*/
#pragma once
#include <eos/chain/protocol/base.hpp>
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/base.hpp>
#include <eos/chain/types.hpp>
#include <fc/smart_ref_fwd.hpp>
namespace eos { namespace chain {
......
......@@ -24,7 +24,7 @@
#pragma once
#include <eos/chain/immutable_chain_parameters.hpp>
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/types.hpp>
#include "multi_index_includes.hpp"
......
......@@ -32,7 +32,7 @@
#include <fc/scoped_exit.hpp>
#include <fc/signals.hpp>
#include <eos/chain/protocol/protocol.hpp>
#include <eos/chain/protocol.hpp>
#include <fc/log/logger.hpp>
......@@ -55,16 +55,16 @@ namespace eos { namespace chain {
class precondition_validate_context : public message_validate_context {
public:
precondition_validate_context( const database& d, const transaction& t, const message& m, const account_name& r )
:message_validate_context(t,m),receiver(r),db(d){}
:message_validate_context(t,m),recipient(r),db(d){}
const account_name& receiver;
const account_name& recipient;
const database& db;
};
class apply_context : public precondition_validate_context {
public:
apply_context( database& d, const transaction& t, const message& m, const account_name& receiver )
:precondition_validate_context(d,t,m,receiver),mutable_db(d){}
apply_context( database& d, const transaction& t, const message& m, const account_name& recipient )
:precondition_validate_context(d,t,m,recipient),mutable_db(d){}
database& mutable_db;
};
......@@ -326,13 +326,25 @@ namespace eos { namespace chain {
// 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);
void apply_transaction(const signed_transaction& trx, uint32_t skip = skip_nothing);
private:
private:
void _apply_block(const signed_block& next_block);
void _apply_transaction(const signed_transaction& trx);
void validate_uniqueness( const signed_transaction& trx )const;
void validate_message_precondition( precondition_validate_context& c )const;
void apply_message( apply_context& c );
/**
* 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;
/// Validate transaction helpers @{
void validate_uniqueness(const signed_transaction& trx)const;
void validate_tapos(const signed_transaction& trx)const;
void validate_referenced_accounts(const signed_transaction& trx)const;
void validate_expiration(const signed_transaction& trx) const;
/// @}
void validate_message_precondition(precondition_validate_context& c)const;
void apply_message(apply_context& c);
......@@ -351,18 +363,19 @@ namespace eos { namespace chain {
void update_last_irreversible_block();
void clear_expired_transactions();
deque< signed_transaction > _pending_transactions;
fork_database _fork_db;
optional<session> _pending_tx_session;
deque<signed_transaction> _pending_transactions;
fork_database _fork_db;
block_log _block_log;
block_log _block_log;
bool _producing = false;
bool _pushing = false;
uint64_t _skip_flags = 0;
bool _producing = false;
bool _pushing = false;
uint64_t _skip_flags = 0;
flat_map<uint32_t,block_id_type> _checkpoints;
flat_map<uint32_t,block_id_type> _checkpoints;
node_property_object _node_property_object;
node_property_object _node_property_object;
typedef pair<account_name,message_type> handler_key;
map< account_name, map<handler_key, message_validate_handler> > message_validate_handlers;
......
......@@ -24,7 +24,7 @@
#pragma once
#include <fc/exception/exception.hpp>
#include <eos/chain/protocol/protocol.hpp>
#include <eos/chain/protocol.hpp>
#define EOS_ASSERT( expr, exc_type, FORMAT, ... ) \
FC_MULTILINE_MACRO_BEGIN \
......
......@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
#pragma once
#include <eos/chain/protocol/block.hpp>
#include <eos/chain/block.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
......
......@@ -23,8 +23,8 @@
*/
#pragma once
#include <eos/chain/protocol/chain_parameters.hpp>
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/chain_parameters.hpp>
#include <eos/chain/types.hpp>
#include <eos/chain/immutable_chain_parameters.hpp>
#include <fc/crypto/sha256.hpp>
......
......@@ -25,8 +25,8 @@
#include <fc/uint128.hpp>
#include <fc/array.hpp>
#include <eos/chain/protocol/chain_parameters.hpp>
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/chain_parameters.hpp>
#include <eos/chain/types.hpp>
#include <eos/chain/database.hpp>
#include <chainbase/chainbase.hpp>
......
#pragma once
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/types.hpp>
namespace eos { namespace chain {
......@@ -11,7 +11,7 @@ namespace eos { namespace chain {
* -- all events and actions which take place in the chain are
* recorded as messages. Messages are sent from one account
* (@ref sender) to another account (@ref recipient), and are
* optionally also delivered to several other accounts (@ref notify_accounts).
* optionally also delivered to several other accounts (@ref notify).
*
* A message has a header that defines who sent it and who will
* be processing it. The message content is a binary blob,
......@@ -29,9 +29,9 @@ struct message {
vector<account_name> notify;
/**
* Every contract defines the set of types that it accepts, these types are
* scoped according to the recipient. This means two contracts can can define
* two different types with the same name.
* Every contract defines the set of types that it accepts, these types are
* scoped according to the recipient. This means two contracts can can define
* two different types with the same name.
*/
message_type type;
......
......@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
#pragma once
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/types.hpp>
namespace eos { namespace chain {
......
......@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
#pragma once
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/types.hpp>
#include "multi_index_includes.hpp"
......
......@@ -22,4 +22,4 @@
* THE SOFTWARE.
*/
#pragma once
#include <eos/chain/config.hpp>
#include <eos/chain/block.hpp>
/*
* Copyright (c) 2017, Respective Authors.
*
* The MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include <eos/chain/protocol/block.hpp>
......@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
#pragma once
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/types.hpp>
#include <eos/chain/message.hpp>
#include <numeric>
......
......@@ -24,7 +24,7 @@
#pragma once
#include <fc/io/raw.hpp>
#include <eos/chain/protocol/transaction.hpp>
#include <eos/chain/transaction.hpp>
#include <fc/uint128.hpp>
#include <boost/multi_index/hashed_index.hpp>
......
......@@ -44,7 +44,7 @@
#include <vector>
#include <deque>
#include <cstdint>
#include <eos/chain/protocol/config.hpp>
#include <eos/chain/config.hpp>
#include <chainbase/chainbase.hpp>
......
......@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
#include <eos/chain/config.hpp>
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/types.hpp>
#include <fc/crypto/base58.hpp>
#include <fc/crypto/ripemd160.hpp>
......
......@@ -17,7 +17,7 @@ ${generated_file_banner}
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/types.hpp>
#include <eos/egenesis/egenesis.hpp>
namespace eos { namespace egenesis {
......
......@@ -17,7 +17,7 @@ ${generated_file_banner}
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/types.hpp>
#include <eos/egenesis/egenesis.hpp>
namespace eos { namespace egenesis {
......
......@@ -35,7 +35,7 @@
#include <fc/io/fstream.hpp>
#include <fc/io/json.hpp>
#include <eos/chain/genesis_state.hpp>
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/types.hpp>
using namespace eos::chain;
......
......@@ -27,7 +27,7 @@
#include <string>
#include <fc/crypto/sha256.hpp>
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/types.hpp>
#include <eos/chain/genesis_state.hpp>
namespace eos { namespace egenesis {
......
......@@ -24,7 +24,7 @@
#pragma once
#include <eos/net/config.hpp>
#include <eos/chain/protocol/block.hpp>
#include <eos/chain/block.hpp>
#include <fc/crypto/ripemd160.hpp>
#include <fc/crypto/elliptic.hpp>
......
......@@ -27,7 +27,7 @@
#include <eos/net/message.hpp>
#include <eos/net/peer_database.hpp>
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/types.hpp>
#include <list>
......
......@@ -24,7 +24,8 @@ void chain_api_plugin::set_program_options(options_description&, options_descrip
void chain_api_plugin::plugin_initialize(const variables_map&) {}
#define CALL(api_name, api_handle, api_namespace, call_name) \
{std::string("/v1/" #api_name "/" #call_name), [this, api_handle](string, string body, url_response_callback cb) { \
{std::string("/v1/" #api_name "/" #call_name), \
[this, api_handle](string, string body, url_response_callback cb) mutable { \
try { \
if (body.empty()) body = "{}"; \
auto result = api_handle.call_name(fc::json::from_string(body).as<api_namespace::call_name ## _params>()); \
......@@ -39,13 +40,17 @@ void chain_api_plugin::plugin_initialize(const variables_map&) {}
}}
#define CHAIN_RO_CALL(call_name) CALL(chain, ro_api, chain_apis::read_only, call_name)
#define CHAIN_RW_CALL(call_name) CALL(chain, rw_api, chain_apis::read_write, call_name)
void chain_api_plugin::plugin_startup() {
auto ro_api = app().get_plugin<chain_plugin>().get_read_only_api();
auto rw_api = app().get_plugin<chain_plugin>().get_read_write_api();
app().get_plugin<http_plugin>().add_api({
CHAIN_RO_CALL(get_info),
CHAIN_RO_CALL(get_block)
CHAIN_RO_CALL(get_block),
CHAIN_RW_CALL(push_block),
CHAIN_RW_CALL(push_transaction)
});
}
......
......@@ -173,5 +173,13 @@ read_only::get_block_results read_only::get_block(const read_only::get_block_par
"Could not find block: ${block}", ("block", params.block_num_or_id));
}
read_write::push_block_results read_write::push_block(const read_write::push_block_params& params) {
db.push_block(params);
}
read_write::push_transaction_results read_write::push_transaction(const read_write::push_transaction_params& params) {
db.push_transaction(params);
}
} // namespace chain_apis
} // namespace eos
......@@ -34,6 +34,20 @@ public:
using get_block_results = chain::signed_block;
get_block_results get_block(const get_block_params& params) const;
};
class read_write {
database& db;
public:
read_write(database& db) : db(db) {}
using push_block_params = chain::signed_block;
using push_block_results = empty;
push_block_results push_block(const push_block_params& params);
using push_transaction_params = chain::signed_transaction;
using push_transaction_results = empty;
push_transaction_results push_transaction(const push_transaction_params& params);
};
} // namespace chain_apis
class chain_plugin : public plugin<chain_plugin> {
......@@ -49,9 +63,8 @@ public:
void plugin_startup();
void plugin_shutdown();
chain_apis::read_only get_read_only_api() const {
return chain_apis::read_only(db());
}
chain_apis::read_only get_read_only_api() const { return chain_apis::read_only(db()); }
chain_apis::read_write get_read_write_api() { return chain_apis::read_write(db()); }
bool accept_block(const chain::signed_block& block, bool currently_syncing);
void accept_transaction(const chain::signed_transaction& trx);
......
......@@ -3,8 +3,8 @@
#include <eos/chain_plugin/chain_plugin.hpp>
#include <eos/chain/protocol/authority.hpp>
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/authority.hpp>
#include <eos/chain/types.hpp>
namespace eos {
using namespace appbase;
......
#pragma once
#include <eos/chain/protocol/block.hpp>
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/block.hpp>
#include <eos/chain/types.hpp>
namespace eos {
using namespace chain;
......
#include <eos/chain/protocol/types.hpp>
#include <eos/chain/types.hpp>
#include <eos/net_plugin/net_plugin.hpp>
#include <eos/net_plugin/protocol.hpp>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册