提交 25b02102 编写于 作者: T Todd Fleming

history plugin: rework contract tables

上级 7ea4135e
......@@ -18,10 +18,9 @@ using std::shared_ptr;
typedef shared_ptr<struct state_history_plugin_impl> state_history_ptr;
struct table_delta {
fc::unsigned_int struct_version = 0;
std::string name{};
std::vector<std::pair<uint64_t, bytes>> rows{};
std::vector<uint64_t> removed{};
fc::unsigned_int struct_version = 0;
std::string name{};
std::vector<std::pair<bool, bytes>> rows{};
};
struct get_status_request_v0 {};
......@@ -67,7 +66,7 @@ class state_history_plugin : public plugin<state_history_plugin> {
} // namespace eosio
FC_REFLECT(eosio::table_delta, (struct_version)(name)(rows)(removed));
FC_REFLECT(eosio::table_delta, (struct_version)(name)(rows));
FC_REFLECT_EMPTY(eosio::get_status_request_v0);
FC_REFLECT(eosio::get_status_result_v0,
(last_irreversible_block_num)(last_irreversible_block_id)(state_begin_block_num)(state_end_block_num));
......
......@@ -26,6 +26,17 @@ history_serial_wrapper<T> make_history_serial_wrapper(const T& obj) {
return {obj};
}
template <typename T>
struct history_table_wrapper {
const eosio::chain::table_id_object& table_id;
const T& obj;
};
template <typename T>
history_table_wrapper<T> make_history_table_wrapper(const eosio::chain::table_id_object& table_id, const T& obj) {
return {table_id, obj};
}
namespace fc {
template <typename T>
......@@ -66,7 +77,6 @@ datastream<ST>& operator<<(datastream<ST>& ds, const history_serial_wrapper<std:
template <typename ST>
datastream<ST>& operator<<(datastream<ST>& ds, const history_serial_wrapper<eosio::chain::account_object>& obj) {
fc::raw::pack(ds, fc::unsigned_int(0));
fc::raw::pack(ds, as_type<uint64_t>(obj.obj.id._id));
fc::raw::pack(ds, as_type<uint64_t>(obj.obj.name.value));
fc::raw::pack(ds, as_type<uint8_t>(obj.obj.vm_type));
fc::raw::pack(ds, as_type<uint8_t>(obj.obj.vm_version));
......@@ -82,20 +92,19 @@ datastream<ST>& operator<<(datastream<ST>& ds, const history_serial_wrapper<eosi
template <typename ST>
datastream<ST>& operator<<(datastream<ST>& ds, const history_serial_wrapper<eosio::chain::table_id_object>& obj) {
fc::raw::pack(ds, fc::unsigned_int(0));
fc::raw::pack(ds, as_type<uint64_t>(obj.obj.id._id));
fc::raw::pack(ds, as_type<uint64_t>(obj.obj.code.value));
fc::raw::pack(ds, as_type<uint64_t>(obj.obj.scope.value));
fc::raw::pack(ds, as_type<uint64_t>(obj.obj.table.value));
fc::raw::pack(ds, as_type<uint64_t>(obj.obj.payer.value));
fc::raw::pack(ds, as_type<uint32_t>(obj.obj.count));
return ds;
}
template <typename ST>
datastream<ST>& operator<<(datastream<ST>& ds, const history_serial_wrapper<eosio::chain::key_value_object>& obj) {
datastream<ST>& operator<<(datastream<ST>& ds, const history_table_wrapper<eosio::chain::key_value_object>& obj) {
fc::raw::pack(ds, fc::unsigned_int(0));
fc::raw::pack(ds, as_type<uint64_t>(obj.obj.id._id));
fc::raw::pack(ds, as_type<uint64_t>(obj.obj.t_id._id));
fc::raw::pack(ds, as_type<uint64_t>(obj.table_id.code.value));
fc::raw::pack(ds, as_type<uint64_t>(obj.table_id.scope.value));
fc::raw::pack(ds, as_type<uint64_t>(obj.table_id.table.value));
fc::raw::pack(ds, as_type<uint64_t>(obj.obj.primary_key));
fc::raw::pack(ds, as_type<uint64_t>(obj.obj.payer.value));
fc::raw::pack(ds, as_type<eosio::chain::shared_string>(obj.obj.value));
......@@ -128,10 +137,12 @@ void serialize_secondary_index_data(datastream<ST>& ds, const eosio::chain::key2
}
template <typename ST, typename T>
datastream<ST>& serialize_secondary_index(datastream<ST>& ds, const T& obj) {
datastream<ST>& serialize_secondary_index(datastream<ST>& ds, const eosio::chain::table_id_object& table_id,
const T& obj) {
fc::raw::pack(ds, fc::unsigned_int(0));
fc::raw::pack(ds, as_type<uint64_t>(obj.id._id));
fc::raw::pack(ds, as_type<uint64_t>(obj.t_id._id));
fc::raw::pack(ds, as_type<uint64_t>(table_id.code.value));
fc::raw::pack(ds, as_type<uint64_t>(table_id.scope.value));
fc::raw::pack(ds, as_type<uint64_t>(table_id.table.value));
fc::raw::pack(ds, as_type<uint64_t>(obj.primary_key));
fc::raw::pack(ds, as_type<uint64_t>(obj.payer.value));
serialize_secondary_index_data(ds, obj.secondary_key);
......@@ -139,29 +150,29 @@ datastream<ST>& serialize_secondary_index(datastream<ST>& ds, const T& obj) {
}
template <typename ST>
datastream<ST>& operator<<(datastream<ST>& ds, const history_serial_wrapper<eosio::chain::index64_object>& obj) {
return serialize_secondary_index(ds, obj.obj);
datastream<ST>& operator<<(datastream<ST>& ds, const history_table_wrapper<eosio::chain::index64_object>& obj) {
return serialize_secondary_index(ds, obj.table_id, obj.obj);
}
template <typename ST>
datastream<ST>& operator<<(datastream<ST>& ds, const history_serial_wrapper<eosio::chain::index128_object>& obj) {
return serialize_secondary_index(ds, obj.obj);
datastream<ST>& operator<<(datastream<ST>& ds, const history_table_wrapper<eosio::chain::index128_object>& obj) {
return serialize_secondary_index(ds, obj.table_id, obj.obj);
}
template <typename ST>
datastream<ST>& operator<<(datastream<ST>& ds, const history_serial_wrapper<eosio::chain::index256_object>& obj) {
return serialize_secondary_index(ds, obj.obj);
datastream<ST>& operator<<(datastream<ST>& ds, const history_table_wrapper<eosio::chain::index256_object>& obj) {
return serialize_secondary_index(ds, obj.table_id, obj.obj);
}
template <typename ST>
datastream<ST>& operator<<(datastream<ST>& ds, const history_serial_wrapper<eosio::chain::index_double_object>& obj) {
return serialize_secondary_index(ds, obj.obj);
datastream<ST>& operator<<(datastream<ST>& ds, const history_table_wrapper<eosio::chain::index_double_object>& obj) {
return serialize_secondary_index(ds, obj.table_id, obj.obj);
}
template <typename ST>
datastream<ST>& operator<<(datastream<ST>& ds,
const history_serial_wrapper<eosio::chain::index_long_double_object>& obj) {
return serialize_secondary_index(ds, obj.obj);
datastream<ST>& operator<<(datastream<ST>& ds,
const history_table_wrapper<eosio::chain::index_long_double_object>& obj) {
return serialize_secondary_index(ds, obj.table_id, obj.obj);
}
template <typename ST>
......
......@@ -26,31 +26,6 @@ using boost::signals2::scoped_connection;
static appbase::abstract_plugin& _state_history_plugin = app().register_plugin<state_history_plugin>();
template <typename F>
static void for_each_table(const chainbase::database& db, F f) {
f("account", db.get_index<account_index>(), [](auto&) { return true; });
f("table_id", db.get_index<table_id_multi_index>(), [](auto&) { return true; });
f("key_value", db.get_index<key_value_index>(), [](auto&) { return true; });
f("index64", db.get_index<index64_index>(), [](auto&) { return true; });
f("index128", db.get_index<index128_index>(), [](auto&) { return true; });
f("index256", db.get_index<index256_index>(), [](auto&) { return true; });
f("index_double", db.get_index<index_double_index>(), [](auto&) { return true; });
f("index_long_double", db.get_index<index_long_double_index>(), [](auto&) { return true; });
f("global_property", db.get_index<global_property_multi_index>(), [](auto&) { return true; });
f("generated_transaction", db.get_index<generated_transaction_multi_index>(), [](auto&) { return true; });
f("permission", db.get_index<permission_index>(), [](auto&) { return true; });
f("permission_link", db.get_index<permission_link_index>(), [](auto&) { return true; });
f("resource_limits", db.get_index<resource_limits::resource_limits_index>(), [](auto&) { return true; });
f("resource_usage", db.get_index<resource_limits::resource_usage_index>(), [](auto&) { return true; });
f("resource_limits_state", db.get_index<resource_limits::resource_limits_state_index>(), [](auto&) { return true; });
f("resource_limits_config", db.get_index<resource_limits::resource_limits_config_index>(),
[](auto&) { return true; });
}
template <typename F>
auto catch_and_log(F f) {
try {
......@@ -321,7 +296,29 @@ struct state_history_plugin_impl : std::enable_shared_from_this<state_history_pl
ilog("Placing initial state in block ${n}", ("n", block_state->block->block_num()));
std::vector<table_delta> deltas;
for_each_table(chain_plug->chain().db(), [&, this](auto* name, auto& index, auto filter) {
auto& db = chain_plug->chain().db();
const auto& table_id_index = db.get_index<table_id_multi_index>();
std::map<uint64_t, const table_id_object*> removed_table_id;
for (auto& rem : table_id_index.stack().back().removed_values)
removed_table_id[rem.first._id] = &rem.second;
auto get_table_id = [&](uint64_t tid) -> const table_id_object& {
auto obj = table_id_index.find(tid);
if (obj)
return *obj;
auto it = removed_table_id.find(tid);
EOS_ASSERT(it != removed_table_id.end(), chain::plugin_exception, "can not found table id ${tid}",
("tid", tid));
return *it->second;
};
auto pack_row = [](auto& row) { return fc::raw::pack(make_history_serial_wrapper(row)); };
auto pack_contract_row = [&](auto& row) {
return fc::raw::pack(make_history_table_wrapper(get_table_id(row.t_id._id), row));
};
auto process_table = [&](auto* name, auto& index, auto& pack_row) {
if (fresh) {
if (index.indices().empty())
return;
......@@ -329,8 +326,7 @@ struct state_history_plugin_impl : std::enable_shared_from_this<state_history_pl
auto& delta = deltas.back();
delta.name = name;
for (auto& row : index.indices())
if (filter(row))
delta.rows.emplace_back(row.id._id, fc::raw::pack(make_history_serial_wrapper(row)));
delta.rows.emplace_back(row.id._id, pack_row(row));
} else {
if (index.stack().empty())
return;
......@@ -342,19 +338,38 @@ struct state_history_plugin_impl : std::enable_shared_from_this<state_history_pl
delta.name = name;
for (auto& old : undo.old_values) {
auto& row = index.get(old.first);
if (filter(row))
delta.rows.emplace_back(old.first._id, fc::raw::pack(make_history_serial_wrapper(row)));
delta.rows.emplace_back(true, pack_row(row));
}
for (auto id : undo.new_ids) {
auto& row = index.get(id);
if (filter(row))
delta.rows.emplace_back(id._id, fc::raw::pack(make_history_serial_wrapper(row)));
delta.rows.emplace_back(true, pack_row(row));
}
for (auto& old : undo.removed_values)
if (filter(old.second))
delta.removed.push_back(old.first._id);
delta.rows.emplace_back(false, pack_row(old.second));
}
});
};
process_table("account", db.get_index<account_index>(), pack_row);
process_table("contract_table", db.get_index<table_id_multi_index>(), pack_row);
process_table("contract_row", db.get_index<key_value_index>(), pack_contract_row);
process_table("contract_index64", db.get_index<index64_index>(), pack_contract_row);
process_table("contract_index128", db.get_index<index128_index>(), pack_contract_row);
process_table("contract_index256", db.get_index<index256_index>(), pack_contract_row);
process_table("contract_index_double", db.get_index<index_double_index>(), pack_contract_row);
process_table("contract_index_long_double", db.get_index<index_long_double_index>(), pack_contract_row);
process_table("global_property", db.get_index<global_property_multi_index>(), pack_row);
process_table("generated_transaction", db.get_index<generated_transaction_multi_index>(), pack_row);
process_table("permission", db.get_index<permission_index>(), pack_row);
process_table("permission_link", db.get_index<permission_link_index>(), pack_row);
process_table("resource_limits", db.get_index<resource_limits::resource_limits_index>(), pack_row);
process_table("resource_usage", db.get_index<resource_limits::resource_usage_index>(), pack_row);
process_table("resource_limits_state", db.get_index<resource_limits::resource_limits_state_index>(), pack_row);
process_table("resource_limits_config", db.get_index<resource_limits::resource_limits_config_index>(), pack_row);
auto deltas_bin = fc::raw::pack(deltas);
EOS_ASSERT(deltas_bin.size() == (uint32_t)deltas_bin.size(), plugin_exception, "deltas is too big");
history_log_header header{.block_num = block_state->block->block_num(),
......
......@@ -28,15 +28,14 @@ extern const char* const state_history_plugin_abi = R"({
},
{
"name": "row", "fields": [
{ "name": "id", "type": "uint64" },
{ "name": "present", "type": "bool" },
{ "name": "data", "type": "bytes" }
]
},
{
"name": "table_delta_v0", "fields": [
{ "name": "name", "type": "string" },
{ "name": "rows", "type": "row[]" },
{ "name": "removed", "type": "uint64[]" }
{ "name": "rows", "type": "row[]" }
]
},
{
......@@ -148,7 +147,6 @@ extern const char* const state_history_plugin_abi = R"({
},
{
"name": "account_v0", "fields": [
{ "type": "uint64", "name": "id" },
{ "type": "name", "name": "name" },
{ "type": "uint8", "name": "vm_type" },
{ "type": "uint8", "name": "vm_version" },
......@@ -161,70 +159,74 @@ extern const char* const state_history_plugin_abi = R"({
]
},
{
"name": "table_id_v0", "fields": [
{ "type": "uint64", "name": "id" },
"name": "contract_table_v0", "fields": [
{ "type": "name", "name": "code" },
{ "type": "name", "name": "scope" },
{ "type": "name", "name": "table" },
{ "type": "name", "name": "payer" },
{ "type": "uint32", "name": "count" }
{ "type": "name", "name": "payer" }
]
},
{
"name": "key_value_v0", "fields": [
{ "type": "uint64", "name": "id" },
{ "type": "uint64", "name": "t_id" },
"name": "contract_row_v0", "fields": [
{ "type": "name", "name": "code" },
{ "type": "name", "name": "scope" },
{ "type": "name", "name": "table" },
{ "type": "uint64", "name": "primary_key" },
{ "type": "name", "name": "payer" },
{ "type": "bytes", "name": "value" }
]
},
{
"name": "index64_v0", "fields": [
{ "type": "uint64", "name": "id" },
{ "type": "uint64", "name": "t_id" },
"name": "contract_index64_v0", "fields": [
{ "type": "name", "name": "code" },
{ "type": "name", "name": "scope" },
{ "type": "name", "name": "table" },
{ "type": "uint64", "name": "primary_key" },
{ "type": "name", "name": "payer" },
{ "type": "uint64", "name": "secondary_key" }
]
},
{
"name": "index128_v0", "fields": [
{ "type": "uint64", "name": "id" },
{ "type": "uint64", "name": "t_id" },
"name": "contract_index128_v0", "fields": [
{ "type": "name", "name": "code" },
{ "type": "name", "name": "scope" },
{ "type": "name", "name": "table" },
{ "type": "uint64", "name": "primary_key" },
{ "type": "name", "name": "payer" },
{ "type": "uint128", "name": "secondary_key" }
]
},
{
"name": "index256_key", "fields": [
"name": "contract_index256_key", "fields": [
{ "type": "uint128", "name": "a0" },
{ "type": "uint128", "name": "a1" }
]
},
{
"name": "index256_v0", "fields": [
{ "type": "uint64", "name": "id" },
{ "type": "uint64", "name": "t_id" },
"name": "contract_index256_v0", "fields": [
{ "type": "name", "name": "code" },
{ "type": "name", "name": "scope" },
{ "type": "name", "name": "table" },
{ "type": "uint64", "name": "primary_key" },
{ "type": "name", "name": "payer" },
{ "type": "index256_key", "name": "secondary_key" }
{ "type": "contract_index256_key", "name": "secondary_key" }
]
},
{
"name": "index_double_v0", "fields": [
{ "type": "uint64", "name": "id" },
{ "type": "uint64", "name": "t_id" },
"name": "contract_index_double_v0", "fields": [
{ "type": "name", "name": "code" },
{ "type": "name", "name": "scope" },
{ "type": "name", "name": "table" },
{ "type": "uint64", "name": "primary_key" },
{ "type": "name", "name": "payer" },
{ "type": "float64", "name": "secondary_key" }
]
},
{
"name": "index_long_double_v0", "fields": [
{ "type": "uint64", "name": "id" },
{ "type": "uint64", "name": "t_id" },
"name": "contract_index_long_double_v0", "fields": [
{ "type": "name", "name": "code" },
{ "type": "name", "name": "scope" },
{ "type": "name", "name": "table" },
{ "type": "uint64", "name": "primary_key" },
{ "type": "name", "name": "payer" },
{ "type": "float128", "name": "secondary_key" }
......@@ -417,13 +419,13 @@ extern const char* const state_history_plugin_abi = R"({
{ "name": "table_delta", "types": ["table_delta_v0"] },
{ "name": "account", "types": ["account_v0"] },
{ "name": "table_id", "types": ["table_id_v0"] },
{ "name": "key_value", "types": ["key_value_v0"] },
{ "name": "index64", "types": ["index64_v0"] },
{ "name": "index128", "types": ["index128_v0"] },
{ "name": "index256", "types": ["index256_v0"] },
{ "name": "index_double", "types": ["index_double_v0"] },
{ "name": "index_long_double", "types": ["index_long_double_v0"] },
{ "name": "contract_table", "types": ["contract_table_v0"] },
{ "name": "contract_row", "types": ["contract_row_v0"] },
{ "name": "contract_index64", "types": ["contract_index64_v0"] },
{ "name": "contract_index128", "types": ["contract_index128_v0"] },
{ "name": "contract_index256", "types": ["contract_index256_v0"] },
{ "name": "contract_index_double", "types": ["contract_index_double_v0"] },
{ "name": "contract_index_long_double", "types": ["contract_index_long_double_v0"] },
{ "name": "chain_config", "types": ["chain_config_v0"] },
{ "name": "global_property", "types": ["global_property_v0"] },
{ "name": "generated_transaction", "types": ["generated_transaction_v0"] },
......@@ -443,22 +445,21 @@ extern const char* const state_history_plugin_abi = R"({
{ "name": "resource_limits_config", "types": ["resource_limits_config_v0"] }
],
"tables": [
{ "name": "account", "type": "account" },
{ "name": "table_id", "type": "table_id" },
{ "name": "key_value", "type": "key_value" },
{ "name": "index64", "type": "index64" },
{ "name": "index128", "type": "index128" },
{ "name": "index256", "type": "index256" },
{ "name": "index_double", "type": "index_double" },
{ "name": "index_long_double", "type": "index_long_double" },
{ "name": "global_property", "type": "global_property" },
{ "name": "transaction", "type": "transaction" },
{ "name": "generated_transaction", "type": "generated_transaction" },
{ "name": "permission", "type": "permission" },
{ "name": "permission_link", "type": "permission_link" },
{ "name": "resource_limits", "type": "resource_limits" },
{ "name": "resource_usage", "type": "resource_usage" },
{ "name": "resource_limits_state", "type": "resource_limits_state" },
{ "name": "resource_limits_config", "type": "resource_limits_config" }
{ "name": "account", "type": "account", "key_names": ["name"] },
{ "name": "contract_table", "type": "contract_table", "key_names": ["code", "scope", "table"] },
{ "name": "contract_row", "type": "contract_row", "key_names": ["code", "scope", "table", "primary_key"] },
{ "name": "contract_index64", "type": "contract_index64", "key_names": ["code", "scope", "table", "primary_key"] },
{ "name": "contract_index128", "type": "contract_index128", "key_names": ["code", "scope", "table", "primary_key"] },
{ "name": "contract_index256", "type": "contract_index256", "key_names": ["code", "scope", "table", "primary_key"] },
{ "name": "contract_index_double", "type": "contract_index_double", "key_names": ["code", "scope", "table", "primary_key"] },
{ "name": "contract_index_long_double", "type": "contract_index_long_double", "key_names": ["code", "scope", "table", "primary_key"] },
{ "name": "global_property", "type": "global_property", "key_names": ["id"] },
{ "name": "generated_transaction", "type": "generated_transaction", "key_names": ["id"] },
{ "name": "permission", "type": "permission", "key_names": ["id"] },
{ "name": "permission_link", "type": "permission_link", "key_names": ["id"] },
{ "name": "resource_limits", "type": "resource_limits", "key_names": ["id"] },
{ "name": "resource_usage", "type": "resource_usage", "key_names": ["id"] },
{ "name": "resource_limits_state", "type": "resource_limits_state", "key_names": ["id"] },
{ "name": "resource_limits_config", "type": "resource_limits_config", "key_names": ["id"] }
]
})";
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册