Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve tracing #2462

Merged
merged 5 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,14 @@ class FinalChain {
std::optional<EthBlockNumber> blk_n = {}) const = 0;

/**
* @brief Trace execution of a new message call immediately without creating a transaction on the block chain. That
* @brief Trace execution of a new message call immediately without creating a transactions on the block chain. That
* means that state would be reverted and not saved anywhere
* @param trx state_api::EVMTransaction
* @param trxs std::vector<state_api::EVMTransaction> vector of transaction to trace
* @param blk_n EthBlockNumber number of block we are getting state from
* @return std::string
*/
virtual std::string trace_trx(const state_api::EVMTransaction& trx, EthBlockNumber blk_n,
std::optional<state_api::Tracing> params = {}) const = 0;
virtual std::string trace(std::vector<state_api::EVMTransaction> trx, EthBlockNumber blk_n,
std::optional<state_api::Tracing> params = {}) const = 0;

/**
* @brief total count of eligible votes are in DPOS precompiled contract
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ class StateAPI {
u256 get_account_storage(EthBlockNumber blk_num, const addr_t& addr, const u256& key) const;
bytes get_code_by_address(EthBlockNumber blk_num, const addr_t& addr) const;
ExecutionResult dry_run_transaction(EthBlockNumber blk_num, const EVMBlock& blk, const EVMTransaction& trx) const;
bytes trace_transaction(EthBlockNumber blk_num, const EVMBlock& blk, const EVMTransaction& trx,
std::optional<Tracing> params = {}) const;
bytes trace(EthBlockNumber blk_num, const EVMBlock& blk, const std::vector<EVMTransaction> trx,
std::optional<Tracing> params = {}) const;
StateDescriptor get_last_committed_state_descriptor() const;
const StateTransitionResult& transition_state(const EVMBlock& block,
const util::RangeView<EVMTransaction>& transactions,
Expand Down
20 changes: 10 additions & 10 deletions libraries/core_libs/consensus/src/final_chain/final_chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -407,17 +407,17 @@ class FinalChainImpl final : public FinalChain {
trx);
}

std::string trace_trx(const state_api::EVMTransaction& trx, EthBlockNumber blk_n,
std::optional<state_api::Tracing> params = {}) const override {
std::string trace(std::vector<state_api::EVMTransaction> trxs, EthBlockNumber blk_n,
std::optional<state_api::Tracing> params = {}) const override {
const auto blk_header = block_header(last_if_absent(blk_n));
return dev::asString(state_api_.trace_transaction(blk_header->number,
{
blk_header->author,
blk_header->gas_limit,
blk_header->timestamp,
BlockHeader::difficulty(),
},
trx, params));
return dev::asString(state_api_.trace(blk_header->number,
{
blk_header->author,
blk_header->gas_limit,
blk_header->timestamp,
BlockHeader::difficulty(),
},
trxs, params));
}

uint64_t dpos_eligible_total_vote_count(EthBlockNumber blk_num) const override {
Expand Down
12 changes: 4 additions & 8 deletions libraries/core_libs/consensus/src/final_chain/state_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,10 @@ ExecutionResult StateAPI::dry_run_transaction(EthBlockNumber blk_num, const EVMB
trx);
}

bytes StateAPI::trace_transaction(EthBlockNumber blk_num, const EVMBlock& blk, const EVMTransaction& trx,
std::optional<Tracing> params) const {
if (params) {
return c_method_args_rlp<bytes, from_rlp, taraxa_evm_state_api_trace_transaction>(this_c_, blk_num, blk, trx,
*params);
} else {
return c_method_args_rlp<bytes, from_rlp, taraxa_evm_state_api_debug_transaction>(this_c_, blk_num, blk, trx);
}
bytes StateAPI::trace(EthBlockNumber blk_num, const EVMBlock& blk, const std::vector<EVMTransaction> trxs,
std::optional<Tracing> params) const {
return c_method_args_rlp<bytes, from_rlp, taraxa_evm_state_api_trace_transactions>(this_c_, blk_num, blk, trxs,
params);
}

StateDescriptor StateAPI::get_last_committed_state_descriptor() const {
Expand Down
91 changes: 72 additions & 19 deletions libraries/core_libs/network/rpc/Debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@ using namespace jsonrpc;
using namespace taraxa;

namespace taraxa::net {

inline EthBlockNumber get_ctx_block_num(EthBlockNumber block_number) {
return (block_number >= 1) ? block_number - 1 : 0;
}

Json::Value Debug::debug_traceTransaction(const std::string& transaction_hash) {
Json::Value res;
try {
auto [trx, loc] = get_transaction_with_location(transaction_hash);
if (!trx || !loc) {
res["status"] = "Transaction not found";
return res;
}
if (auto node = full_node_.lock()) {
const auto hash = jsToFixed<32>(transaction_hash);
const auto trx = node->getDB()->getTransaction(hash);
if (!trx) {
res["status"] = "Transaction not found";
return res;
}
const auto loc = node->getFinalChain()->transaction_location(hash);
if (!loc) {
res["status"] = "Transaction not found";
return res;
}
return util::readJsonFromString(node->getFinalChain()->trace_trx(to_eth_trx(trx), loc->blk_n));
return util::readJsonFromString(
node->getFinalChain()->trace({to_eth_trx(std::move(trx))}, get_ctx_block_num(loc->blk_n)));
}
} catch (std::exception& e) {
res["status"] = e.what();
Expand All @@ -41,7 +41,7 @@ Json::Value Debug::debug_traceCall(const Json::Value& call_params, const std::st
const auto block = parse_blk_num(blk_num);
auto trx = to_eth_trx(call_params, block);
if (auto node = full_node_.lock()) {
return util::readJsonFromString(node->getFinalChain()->trace_trx(std::move(trx), block));
return util::readJsonFromString(node->getFinalChain()->trace({std::move(trx)}, block));
}
} catch (std::exception& e) {
res["status"] = e.what();
Expand All @@ -54,10 +54,53 @@ Json::Value Debug::trace_call(const Json::Value& call_params, const Json::Value&
Json::Value res;
try {
const auto block = parse_blk_num(blk_num);
auto trx = to_eth_trx(call_params, block);
auto params = parse_tracking_parms(trace_params);
if (auto node = full_node_.lock()) {
return util::readJsonFromString(node->getFinalChain()->trace_trx(std::move(trx), block, std::move(params)));
return util::readJsonFromString(
node->getFinalChain()->trace({to_eth_trx(call_params, block)}, block, std::move(params)));
}
} catch (std::exception& e) {
res["status"] = e.what();
}
return res;
}

Json::Value Debug::trace_replayTransaction(const std::string& transaction_hash, const Json::Value& trace_params) {
Json::Value res;
try {
auto params = parse_tracking_parms(trace_params);
auto [trx, loc] = get_transaction_with_location(transaction_hash);
if (!trx || !loc) {
res["status"] = "Transaction not found";
return res;
}
if (auto node = full_node_.lock()) {
return util::readJsonFromString(
node->getFinalChain()->trace({to_eth_trx(std::move(trx))}, get_ctx_block_num(loc->blk_n), std::move(params)));
}
} catch (std::exception& e) {
res["status"] = e.what();
}
return res;
}

Json::Value Debug::trace_replayBlockTransactions(const std::string& block_num, const Json::Value& trace_params) {
Json::Value res;
try {
const auto block = parse_blk_num(block_num);
auto params = parse_tracking_parms(trace_params);
if (auto node = full_node_.lock()) {
auto transactions = node->getDB()->getPeriodTransactions(block);
if (!transactions.has_value() || transactions->empty()) {
res["status"] = "Block has no transactions";
return res;
}
std::vector<state_api::EVMTransaction> trxs;
trxs.reserve(transactions->size());
std::transform(transactions->begin(), transactions->end(), std::back_inserter(trxs),
[this](auto t) { return to_eth_trx(std::move(t)); });
return util::readJsonFromString(
node->getFinalChain()->trace(std::move(trxs), get_ctx_block_num(block), std::move(params)));
}
} catch (std::exception& e) {
res["status"] = e.what();
Expand All @@ -72,7 +115,8 @@ state_api::Tracing Debug::parse_tracking_parms(const Json::Value& json) const {
}
for (const auto& obj : json) {
if (obj.asString() == "trace") ret.trace = true;
if (obj.asString() == "stateDiff") ret.stateDiff = true;
// Disabled for now
// if (obj.asString() == "stateDiff") ret.stateDiff = true;
if (obj.asString() == "vmTrace") ret.vmTrace = true;
}
return ret;
Expand All @@ -91,13 +135,13 @@ state_api::EVMTransaction Debug::to_eth_trx(const Json::Value& json, EthBlockNum
}

if (!json["from"].empty()) {
trx.from = toAddress(json["from"].asString());
trx.from = to_address(json["from"].asString());
} else {
trx.from = ZeroAddress;
}

if (!json["to"].empty() && json["to"].asString() != "0x" && !json["to"].asString().empty()) {
trx.to = toAddress(json["to"].asString());
trx.to = to_address(json["to"].asString());
}

if (!json["value"].empty()) {
Expand Down Expand Up @@ -144,7 +188,7 @@ EthBlockNumber Debug::parse_blk_num(const string& blk_num_str) {
return jsToInt(blk_num_str);
}

Address Debug::toAddress(const string& s) const {
Address Debug::to_address(const string& s) const {
try {
if (auto b = fromHex(s.substr(0, 2) == "0x" ? s.substr(2) : s, WhenError::Throw); b.size() == Address::size) {
return Address(b);
Expand All @@ -154,4 +198,13 @@ Address Debug::toAddress(const string& s) const {
throw InvalidAddress();
}

std::pair<std::shared_ptr<Transaction>, std::optional<final_chain::TransactionLocation>>
Debug::get_transaction_with_location(const std::string& transaction_hash) const {
if (auto node = full_node_.lock()) {
const auto hash = jsToFixed<32>(transaction_hash);
return {node->getDB()->getTransaction(hash), node->getFinalChain()->transaction_location(hash)};
}
return {};
}

} // namespace taraxa::net
6 changes: 5 additions & 1 deletion libraries/core_libs/network/rpc/Debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,17 @@ class Debug : public DebugFace {
virtual Json::Value debug_traceCall(const Json::Value& param1, const std::string& param2) override;
virtual Json::Value trace_call(const Json::Value& param1, const Json::Value& param2,
const std::string& param3) override;
virtual Json::Value trace_replayTransaction(const std::string& param1, const Json::Value& param2) override;
virtual Json::Value trace_replayBlockTransactions(const std::string& param1, const Json::Value& param2) override;

private:
state_api::EVMTransaction to_eth_trx(std::shared_ptr<Transaction> t) const;
state_api::EVMTransaction to_eth_trx(const Json::Value& json, EthBlockNumber blk_num);
EthBlockNumber parse_blk_num(const string& blk_num_str);
state_api::Tracing parse_tracking_parms(const Json::Value& json) const;
Address toAddress(const string& s) const;
Address to_address(const string& s) const;
std::pair<std::shared_ptr<Transaction>, std::optional<final_chain::TransactionLocation>>
get_transaction_with_location(const std::string& transaction_hash) const;

std::weak_ptr<taraxa::FullNode> full_node_;
const uint64_t kGasLimit = ((uint64_t)1 << 53) - 1;
Expand Down
18 changes: 18 additions & 0 deletions libraries/core_libs/network/rpc/Debug.jsonrpc.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,23 @@
],
"order": [],
"returns": {}
},
{
"name": "trace_replayTransaction",
"params": [
"",
[]
],
"order": [],
"returns": {}
},
{
"name": "trace_replayBlockTransactions",
"params": [
"",
[]
],
"order": [],
"returns": {}
}
]
22 changes: 22 additions & 0 deletions libraries/core_libs/network/rpc/DebugClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,28 @@ class DebugClient : public jsonrpc::Client {
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value trace_replayTransaction(const std::string& param1,
const Json::Value& param2) throw(jsonrpc::JsonRpcException) {
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("trace_replayTransaction", p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value trace_replayBlockTransactions(const std::string& param1,
const Json::Value& param2) throw(jsonrpc::JsonRpcException) {
Json::Value p;
p.append(param1);
p.append(param2);
Json::Value result = this->CallMethod("trace_replayBlockTransactions", p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
};

} // namespace net
Expand Down
16 changes: 16 additions & 0 deletions libraries/core_libs/network/rpc/DebugFace.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ class DebugFace : public ServerInterface<DebugFace> {
jsonrpc::Procedure("trace_call", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",
jsonrpc::JSON_OBJECT, "param2", jsonrpc::JSON_ARRAY, "param3", jsonrpc::JSON_STRING, NULL),
&taraxa::net::DebugFace::trace_callI);
this->bindAndAddMethod(
jsonrpc::Procedure("trace_replayTransaction", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",
jsonrpc::JSON_STRING, "param2", jsonrpc::JSON_ARRAY, NULL),
&taraxa::net::DebugFace::trace_replayTransactionI);
this->bindAndAddMethod(
jsonrpc::Procedure("trace_replayBlockTransactions", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",
jsonrpc::JSON_STRING, "param2", jsonrpc::JSON_ARRAY, NULL),
&taraxa::net::DebugFace::trace_replayBlockTransactionsI);
}

inline virtual void debug_traceTransactionI(const Json::Value& request, Json::Value& response) {
Expand All @@ -33,9 +41,17 @@ class DebugFace : public ServerInterface<DebugFace> {
inline virtual void trace_callI(const Json::Value& request, Json::Value& response) {
response = this->trace_call(request[0u], request[1u], request[2u].asString());
}
inline virtual void trace_replayTransactionI(const Json::Value& request, Json::Value& response) {
response = this->trace_replayTransaction(request[0u].asString(), request[1u]);
}
inline virtual void trace_replayBlockTransactionsI(const Json::Value& request, Json::Value& response) {
response = this->trace_replayBlockTransactions(request[0u].asString(), request[1u]);
}
virtual Json::Value debug_traceTransaction(const std::string& param1) = 0;
virtual Json::Value debug_traceCall(const Json::Value& param1, const std::string& param2) = 0;
virtual Json::Value trace_call(const Json::Value& param1, const Json::Value& param2, const std::string& param3) = 0;
virtual Json::Value trace_replayTransaction(const std::string& param1, const Json::Value& param2) = 0;
virtual Json::Value trace_replayBlockTransactions(const std::string& param1, const Json::Value& param2) = 0;
};

} // namespace net
Expand Down