提交 0620686f 编写于 作者: B Bart Wyatt

test cases for action proofs, additon of scope serial numbers and more fixes

上级 fe99d2ce
......@@ -2,6 +2,7 @@
#include <eosio/chain/chain_controller.hpp>
#include <eosio/chain/wasm_interface.hpp>
#include <eosio/chain/generated_transaction_object.hpp>
#include <eosio/chain/scope_serial_object.hpp>
namespace eosio { namespace chain {
void apply_context::exec_one()
......@@ -23,7 +24,41 @@ void apply_context::exec_one()
}
// create a receipt for this
results.applied_actions.emplace_back(action_trace {receiver, act, _pending_console_output.str()});
vector<data_access_info> data_access;
data_access.reserve(trx.write_scope.size() + trx.read_scope.size());
for (const auto& scope: trx.write_scope) {
auto key = boost::make_tuple(scope, receiver);
const auto& scope_serial = mutable_controller.get_database().find<scope_serial_object, by_scope_receiver>(key);
if (scope_serial == nullptr) {
try {
mutable_controller.get_mutable_database().create<scope_serial_object>([&](scope_serial_object &ss) {
ss.scope = scope;
ss.receiver = receiver;
ss.serial = 1;
});
} FC_CAPTURE_AND_RETHROW((scope)(receiver));
data_access.emplace_back(data_access_info{data_access_info::write, scope, 0});
} else {
data_access.emplace_back(data_access_info{data_access_info::write, scope, scope_serial->serial});
try {
mutable_controller.get_mutable_database().modify(*scope_serial, [&](scope_serial_object& ss) {
ss.serial += 1;
});
} FC_CAPTURE_AND_RETHROW((scope)(receiver));
}
}
for (const auto& scope: trx.read_scope) {
auto key = boost::make_tuple(scope, receiver);
const auto& scope_serial = mutable_controller.get_database().find<scope_serial_object, by_scope_receiver>(key);
if (scope_serial == nullptr) {
data_access.emplace_back(data_access_info{data_access_info::read, scope, 0});
} else {
data_access.emplace_back(data_access_info{data_access_info::read, scope, scope_serial->serial});
}
}
results.applied_actions.emplace_back(action_trace {receiver, act, _pending_console_output.str(), 0, 0, move(data_access)});
_pending_console_output = std::ostringstream();
}
......
......@@ -70,6 +70,8 @@ namespace eosio { namespace chain {
fc::raw::pack(enc, at.act.scope);
fc::raw::pack(enc, at.act.name);
fc::raw::pack(enc, at.act.data);
fc::raw::pack(enc, at.region_id);
fc::raw::pack(enc, at.cycle_index);
fc::raw::pack(enc, at.data_access);
action_roots.emplace_back(enc.result());
......@@ -78,42 +80,17 @@ namespace eosio { namespace chain {
shard_root = merkle(action_roots);
}
void cycle_trace::calculate_root() {
vector<digest_type> shard_roots;
shard_roots.reserve(shard_traces.size());
for (auto& s_trace :shard_traces) {
shard_roots.emplace_back(s_trace.shard_root);
}
cycle_root = merkle(shard_roots);
}
void region_trace::calculate_root() {
vector<digest_type> cycle_roots;
cycle_roots.reserve(cycle_traces.size());
for (uint32_t index = 0; index < cycle_traces.size(); index++) {
const auto& c_trace = cycle_traces.at(index);
digest_type::encoder enc;
fc::raw::pack(enc, index);
fc::raw::pack(enc, c_trace.cycle_root);
cycle_roots.emplace_back(enc.result());
}
region_root = merkle(cycle_roots);
}
digest_type block_trace::calculate_action_merkle_root()const {
vector<digest_type> region_roots;
region_roots.reserve(region_traces.size());
for (uint32_t index = 0; index < region_traces.size(); index++) {
const auto& r_trace = region_traces.at(index);
digest_type::encoder enc;
fc::raw::pack(enc, index);
fc::raw::pack(enc, r_trace.region_root);
region_roots.emplace_back(enc.result());
vector<digest_type> shard_roots;
shard_roots.reserve(1024);
for(const auto& rt: region_traces ) {
for(const auto& ct: rt.cycle_traces ) {
for(const auto& st: ct.shard_traces) {
shard_roots.emplace_back(st.shard_root);
}
}
}
return merkle(region_roots);
return merkle(shard_roots);
}
} }
......@@ -16,6 +16,7 @@
#include <eosio/chain/authority_checker.hpp>
#include <eosio/chain/contracts/chain_initializer.hpp>
#include <eosio/chain/contracts/producer_objects.hpp>
#include <eosio/chain/scope_serial_object.hpp>
#include <eosio/chain/merkle.hpp>
#include <eosio/chain/wasm_interface.hpp>
......@@ -265,11 +266,16 @@ transaction_trace chain_controller::_push_transaction(const signed_transaction&
// for now apply the transaction serially but schedule it according to those invariants
validate_referenced_accounts(trx);
check_transaction_authorization(trx);
auto result = _apply_transaction(trx);
auto tid = trx.id();
auto shardnum = _pending_cycle.schedule( trx );
auto cyclenum = _pending_block->regions.back().cycles_summary.size() - 1;
if (shardnum == -1) {
cyclenum += 1;
}
auto result = _apply_transaction(trx, _pending_block->regions.back().region, cyclenum);
if( shardnum == -1 ) { /// schedule conflict start new cycle
_finalize_pending_cycle();
_start_pending_cycle();
......@@ -282,6 +288,8 @@ transaction_trace chain_controller::_push_transaction(const signed_transaction&
_start_pending_shard();
}
auto tid = trx.id();
bcycle.at(shardnum).emplace_back( tid );
_pending_cycle_trace->shard_traces.at(shardnum).append(result);
......@@ -337,7 +345,6 @@ void chain_controller::_finalize_pending_cycle()
shard.calculate_root();
}
_pending_cycle_trace->calculate_root();
_apply_cycle_trace(*_pending_cycle_trace);
_pending_block_trace->region_traces.back().cycle_traces.emplace_back(std::move(*_pending_cycle_trace));
_pending_cycle_trace.reset();
......@@ -431,7 +438,6 @@ signed_block chain_controller::_generate_block( block_timestamp_type when,
}
_finalize_pending_cycle();
_pending_block_trace->region_traces.back().calculate_root();
if( !(skip & skip_producer_signature) )
FC_ASSERT( producer_obj.signing_key == block_signing_key.get_public_key() );
......@@ -546,7 +552,8 @@ void chain_controller::__apply_block(const signed_block& next_block)
region_trace r_trace;
r_trace.cycle_traces.reserve(r.cycles_summary.size());
for (const auto& cycle : r.cycles_summary) {
for (uint32_t cycle_index; cycle_index < r.cycles_summary.size(); cycle_index++) {
const auto& cycle = r.cycles_summary.at(cycle_index);
cycle_trace c_trace;
c_trace.shard_traces.reserve(cycle.size());
......@@ -556,7 +563,7 @@ void chain_controller::__apply_block(const signed_block& next_block)
if( receipt.status == transaction_receipt::executed ) {
auto itr = trx_index.find(receipt.id);
if( itr != trx_index.end() ) {
s_trace.append(_apply_transaction( *itr->second ));
s_trace.append(_apply_transaction( *itr->second, r.region, cycle_index));
}
else
{
......@@ -574,11 +581,9 @@ void chain_controller::__apply_block(const signed_block& next_block)
} /// for each shard
_apply_cycle_trace(c_trace);
c_trace.calculate_root();
r_trace.cycle_traces.emplace_back(move(c_trace));
} /// for each cycle
r_trace.calculate_root();
next_block_trace.region_traces.emplace_back(move(r_trace));
} /// for each region
......@@ -933,6 +938,7 @@ void chain_controller::_initialize_indexes() {
_db.add_index<transaction_multi_index>();
_db.add_index<generated_transaction_multi_index>();
_db.add_index<producer_multi_index>();
_db.add_index<scope_serial_multi_index>();
}
void chain_controller::_initialize_chain(contracts::chain_initializer& starter)
......@@ -968,7 +974,7 @@ void chain_controller::_initialize_chain(contracts::chain_initializer& starter)
ilog( "applying genesis transaction" );
with_skip_flags(skip_scope_check | skip_transaction_signatures | skip_authority_check | received_block,
[&](){
_apply_transaction( genesis_setup_transaction );
_apply_transaction( genesis_setup_transaction, 0, 0 );
});
});
......@@ -1255,7 +1261,7 @@ void chain_controller::_set_apply_handler( account_name contract, scope_name sco
_apply_handlers[contract][make_pair(scope,action)] = v;
}
transaction_trace chain_controller::_apply_transaction( const transaction& trx ) {
transaction_trace chain_controller::_apply_transaction( const transaction& trx, uint32_t region_id, uint32_t cycle_index ) {
transaction_trace result(trx.id());
for( const auto& act : trx.actions ) {
......@@ -1265,6 +1271,11 @@ transaction_trace chain_controller::_apply_transaction( const transaction& trx )
fc::move_append(result.deferred_transactions, std::move(context.results.generated_transactions));
}
for (auto& at: result.action_traces) {
at.region_id = region_id;
at.cycle_index = cycle_index;
}
return result;
}
......
......@@ -167,7 +167,7 @@ class apply_context {
*/
struct apply_results {
vector<action_trace> applied_actions;
vector<action_trace> applied_actions;
vector<deferred_transaction> generated_transactions;
};
......
......@@ -115,17 +115,11 @@ namespace eosio { namespace chain {
};
struct cycle_trace {
digest_type cycle_root;
vector<shard_trace> shard_traces;
void calculate_root();
};
struct region_trace {
digest_type region_root;
vector<cycle_trace> cycle_traces;
void calculate_root();
};
struct block_trace {
......@@ -150,6 +144,6 @@ FC_REFLECT( eosio::chain::region_summary, (region)(cycles_summary) )
FC_REFLECT_DERIVED(eosio::chain::signed_block_summary, (eosio::chain::signed_block_header), (regions))
FC_REFLECT_DERIVED(eosio::chain::signed_block, (eosio::chain::signed_block_header), (input_transactions))
FC_REFLECT( eosio::chain::shard_trace, (shard_root)(transaction_traces))
FC_REFLECT( eosio::chain::cycle_trace, (cycle_root)(shard_traces))
FC_REFLECT( eosio::chain::region_trace, (region_root)(cycle_traces))
FC_REFLECT( eosio::chain::cycle_trace, (shard_traces))
FC_REFLECT( eosio::chain::region_trace, (cycle_traces))
FC_REFLECT( eosio::chain::block_trace, (region_traces))
......@@ -304,7 +304,7 @@ namespace eosio { namespace chain {
transaction_trace _push_transaction( const signed_transaction& trx );
transaction_trace _apply_transaction( const transaction& trx );
transaction_trace _apply_transaction( const transaction& trx, uint32_t region_id, uint32_t cycle_index );
/// Reset the object graph in-memory
void _initialize_indexes();
......
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <eosio/chain/types.hpp>
#include <eosio/chain/authority.hpp>
#include <eosio/chain/block_timestamp.hpp>
#include <eosio/chain/contracts/types.hpp>
#include "multi_index_includes.hpp"
namespace eosio { namespace chain {
class scope_serial_object : public chainbase::object<scope_serial_object_type, scope_serial_object> {
OBJECT_CTOR(scope_serial_object)
id_type id;
scope_name scope;
account_name receiver;
uint64_t serial = 0;
};
using scope_serial_id_type = scope_serial_object::id_type;
struct by_scope_receiver;
using scope_serial_multi_index = chainbase::shared_multi_index_container<
scope_serial_object,
indexed_by<
ordered_unique<tag<by_id>, member<scope_serial_object, scope_serial_object::id_type, &scope_serial_object::id>>,
ordered_unique<tag<by_scope_receiver>,
composite_key< scope_serial_object,
member<scope_serial_object, scope_name, &scope_serial_object::scope>,
member<scope_serial_object, account_name, &scope_serial_object::receiver>
>
>
>
>;
typedef chainbase::generic_index<scope_serial_multi_index> scope_serial_index;
} } // eosio::chain
CHAINBASE_SET_INDEX_TYPE(eosio::chain::scope_serial_object, eosio::chain::scope_serial_multi_index)
FC_REFLECT(chainbase::oid<eosio::chain::scope_serial_object>, (_id))
FC_REFLECT(eosio::chain::scope_serial_object, (id)(scope)(receiver)(serial))
......@@ -166,6 +166,8 @@ namespace eosio { namespace chain {
account_name receiver;
action act;
string console;
uint32_t region_id;
uint32_t cycle_index;
vector<data_access_info> data_access;
};
......@@ -186,7 +188,7 @@ FC_REFLECT_DERIVED( eosio::chain::signed_transaction, (eosio::chain::transaction
FC_REFLECT_DERIVED( eosio::chain::deferred_transaction, (eosio::chain::transaction), (sender_id)(sender)(execute_after) )
FC_REFLECT_ENUM( eosio::chain::data_access_info::access_type, (read)(write))
FC_REFLECT( eosio::chain::data_access_info, (type)(scope)(serial))
FC_REFLECT( eosio::chain::action_trace, (receiver)(act)(console)(data_access) )
FC_REFLECT( eosio::chain::action_trace, (receiver)(act)(console)(region_id)(cycle_index)(data_access) )
FC_REFLECT( eosio::chain::transaction_receipt, (status)(id))
FC_REFLECT_ENUM( eosio::chain::transaction_receipt::status_enum, (executed)(soft_fail)(hard_fail))
FC_REFLECT_DERIVED( eosio::chain::transaction_trace, (eosio::chain::transaction_receipt), (action_traces)(deferred_transactions) )
......
......@@ -137,6 +137,7 @@ namespace eosio { namespace chain {
proxy_vote_object_type, ///< Defined by native_contract library
key64x64x64_value_object_type,
keystr_value_object_type,
scope_serial_object_type,
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
};
......@@ -185,6 +186,7 @@ FC_REFLECT_ENUM(eosio::chain::object_type,
(proxy_vote_object_type)
(key64x64x64_value_object_type)
(keystr_value_object_type)
(scope_serial_object_type)
(OBJECT_TYPE_COUNT)
)
FC_REFLECT( eosio::chain::void_t, )
......@@ -8,6 +8,18 @@ using namespace eosio;
using namespace eosio::chain;
using namespace eosio::testing;
struct action_proof_data {
account_name receiver;
scope_name scope;
action_name name;
bytes data;
uint32_t region_id;
uint32_t cycle_index;
vector<data_access_info> data_access;
};
FC_REFLECT(action_proof_data, (receiver)(scope)(name)(data)(region_id)(cycle_index)(data_access));
struct merkle_node {
digest_type digest;
optional<size_t> left;
......@@ -160,9 +172,6 @@ struct action_proof_info {
action_trace trace;
size_t action_leaf;
size_t shard_leaf;
size_t cycle_leaf;
size_t region_leaf;
size_t block_leaf;
uint32_t cycle_index;
......@@ -186,63 +195,46 @@ BOOST_FIXTURE_TEST_CASE( prove_action_in_block, tester ) { try {
nodes.emplace_back(merkle_node{bt.block.id()});
size_t block_leaf = nodes.size() - 1;
block_leaves.push_back(block_leaf);
vector<size_t> region_leaves;
vector<size_t> shard_leaves;
for (uint32_t r_idx = 0; r_idx < bt.region_traces.size(); r_idx++) {
const auto& rt = bt.region_traces.at(r_idx);
nodes.emplace_back(merkle_node());
size_t region_leaf = nodes.size() - 1;
vector<size_t> cycle_leaves;
for (uint32_t c_idx = 0; c_idx < rt.cycle_traces.size(); c_idx++) {
const auto& ct = rt.cycle_traces.at(c_idx);
nodes.emplace_back(merkle_node());
size_t cycle_leaf = nodes.size() - 1;
vector<size_t> shard_leaves;
for (const auto& st: ct.shard_traces) {
nodes.emplace_back(merkle_node());
size_t shard_leaf = nodes.size() - 1;
vector<size_t> action_leaves;
for (const auto& tt: st.transaction_traces) {
for (const auto& at: tt.action_traces) {
digest_type::encoder enc;
fc::raw::pack(enc, at.receiver);
fc::raw::pack(enc, at.act.scope);
fc::raw::pack(enc, at.act.name);
fc::raw::pack(enc, at.act.data);
fc::raw::pack(enc, at.data_access);
auto a_data = action_proof_data {
at.receiver,
at.act.scope,
at.act.name,
at.act.data,
at.region_id,
at.cycle_index,
at.data_access
};
fc::raw::pack(enc, a_data);
nodes.emplace_back(merkle_node{enc.result()});
size_t action_leaf = nodes.size() - 1;
known_actions.emplace_back(action_proof_info{at, action_leaf, shard_leaf, cycle_leaf, region_leaf, block_leaf, c_idx, r_idx });
known_actions.emplace_back(action_proof_info{at, action_leaf, block_leaf, c_idx, r_idx });
action_leaves.emplace_back(action_leaf);
}
}
nodes[shard_leaf].digest = process_merkle(nodes, move(action_leaves));
shard_leaves.emplace_back(shard_leaf);
if (action_leaves.size() > 0) {
process_merkle(nodes, move(action_leaves));
shard_leaves.emplace_back(nodes.size() - 1);
}
}
digest_type cycle_root = process_merkle(nodes, move(shard_leaves));
digest_type::encoder enc;
fc::raw::pack(enc, c_idx);
fc::raw::pack(enc, cycle_root);
nodes[cycle_leaf].digest = enc.result();
cycle_leaves.emplace_back(cycle_leaf);
}
digest_type region_root = process_merkle(nodes, move(cycle_leaves));
digest_type::encoder enc;
fc::raw::pack(enc, r_idx);
fc::raw::pack(enc, region_root);
nodes[region_leaf].digest = enc.result();
region_leaves.emplace_back(region_leaf);
}
digest_type action_mroot = process_merkle(nodes, move(region_leaves));
digest_type action_mroot = process_merkle(nodes, move(shard_leaves));
BOOST_REQUIRE_EQUAL((std::string)bt.block.action_mroot, (std::string)action_mroot);
last_block_header = bt.block;
......@@ -264,65 +256,47 @@ BOOST_FIXTURE_TEST_CASE( prove_action_in_block, tester ) { try {
produce_block();
BOOST_REQUIRE_EQUAL((std::string)block_mroot, (std::string)last_block_header.block_mroot);
/* UNCOMMENT TO PRODUCE PROOFS TO STDOUT
std::cout << "Best Block ID: " << (std::string)last_block_id << std::endl;
std::cout << " Merkle Root: " << (std::string)last_block_header.block_mroot << std::endl;
for(const auto& ai : known_actions) {
auto shard_path = get_proof_path(nodes, ai.action_leaf);
auto cycle_path = get_proof_path(nodes, ai.shard_leaf);
auto region_path = get_proof_path(nodes, ai.cycle_leaf);
auto block_path = get_proof_path(nodes, ai.region_leaf);
auto block_path = get_proof_path(nodes, ai.action_leaf);
auto chain_path = get_proof_path(nodes, ai.block_leaf);
// prove action in shard
auto shard_root = apply_path(nodes[ai.action_leaf].digest, shard_path);
BOOST_REQUIRE_EQUAL((std::string)shard_root, (std::string)nodes[ai.shard_leaf].digest);
// prove its in the cycle
auto cycle_root = apply_path(shard_root, cycle_path);
auto cycle_digest = digest_type::hash(std::make_pair(ai.cycle_index, cycle_root));
BOOST_REQUIRE_EQUAL((std::string)cycle_digest, (std::string)nodes[ai.cycle_leaf].digest);
// prove that cycle is in the region
auto region_root = apply_path(cycle_digest, region_path);
auto region_digest = digest_type::hash(std::make_pair(ai.region_id, region_root));
BOOST_REQUIRE_EQUAL((std::string)region_digest, (std::string)nodes[ai.region_leaf].digest);
// prove that region is in the correct blocks action_mroot
auto action_mroot = apply_path(region_digest, block_path);
BOOST_REQUIRE_EQUAL((std::string)action_mroot, (std::string)block_action_mroots[nodes[ai.block_leaf].digest]);
// prove action in block
auto shard_root = apply_path(nodes[ai.action_leaf].digest, block_path);
BOOST_REQUIRE_EQUAL((std::string)shard_root, (std::string)block_action_mroots[nodes[ai.block_leaf].digest]);
// prove that block is part of the chain
auto expected_block_mroot = apply_path(nodes[ai.block_leaf].digest, chain_path);
BOOST_REQUIRE_EQUAL((std::string)expected_block_mroot, (std::string)last_block_header.block_mroot);
std::cout << "Proof for Action:" << std::endl;
std::cout << std::setw(10) << "reciever" << ":" << (std::string) ai.trace.receiver << std::endl;
std::cout << std::setw(10) << "scope" << ":" << (std::string) ai.trace.act.scope << std::endl;
std::cout << std::setw(10) << "name" << ":" << (std::string) ai.trace.act.name << std::endl;
std::cout << std::setw(10) << "data" << ":" << fc::json::to_string(ai.trace.act.as<contracts::transfer>()) << std::endl;
std::cout << std::setw(10) << "block" << ":" << (std::string)nodes[ai.block_leaf].digest << std::endl;
std::cout << std::setw(10) << "region" << ":" << ai.region_id << std::endl;
std::cout << std::setw(10) << "cycle" << ":" << ai.cycle_index << std::endl;
std::cout << std::endl;
std::cout << "Action Hash: " << (std::string)nodes[ai.action_leaf].digest << std::endl;
std::cout << "Shard Path: ";
for (const auto& p: shard_path) {
std::cout << (std::string)p << " ";
}
std::cout << std::endl;
std::cout << "Cycle Path: ";
for (const auto& p: cycle_path) {
std::cout << (std::string)p << " ";
}
std::cout << std::setw(14) << "reciever" << ":" << (std::string) ai.trace.receiver << std::endl;
std::cout << std::setw(14) << "scope" << ":" << (std::string) ai.trace.act.scope << std::endl;
std::cout << std::setw(14) << "name" << ":" << (std::string) ai.trace.act.name << std::endl;
std::cout << std::setw(14) << "data" << ":" << fc::json::to_string(ai.trace.act.as<contracts::transfer>()) << std::endl;
std::cout << std::setw(14) << "data_access" << ":" << fc::json::to_string(ai.trace.data_access) << std::endl;
std::cout << std::setw(14) << "region" << ":" << ai.region_id << std::endl;
std::cout << std::setw(14) << "cycle" << ":" << ai.cycle_index << std::endl;
std::cout << std::setw(14) << "block" << ":" << (std::string)nodes[ai.block_leaf].digest << std::endl;
std::cout << std::setw(14) << "am_root" << ":" << (std::string)block_action_mroots[nodes[ai.block_leaf].digest] << std::endl;
std::cout << std::endl;
std::cout << "Region Path: ";
for (const auto& p: region_path) {
std::cout << (std::string)p << " ";
}
std::cout << std::endl;
auto a_data = action_proof_data {
ai.trace.receiver,
ai.trace.act.scope,
ai.trace.act.name,
ai.trace.act.data,
ai.trace.region_id,
ai.trace.cycle_index,
ai.trace.data_access
};
auto action_data = fc::raw::pack(a_data);
std::cout << "Action Hex: " << fc::to_hex(action_data) << std::endl;
std::cout << "Action Hash: " << (std::string)nodes[ai.action_leaf].digest << std::endl;
std::cout << "Block Path: ";
for (const auto& p: block_path) {
......@@ -335,7 +309,7 @@ BOOST_FIXTURE_TEST_CASE( prove_action_in_block, tester ) { try {
std::cout << (std::string)p << " ";
}
std::cout << std::endl;
}
}*/
} FC_LOG_AND_RETHROW() }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册