Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Aug 27, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 0 additions & 3 deletions src/libCps/CpsExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ CpsExecuteResult CpsExecutor::RunFromScilla(
mTxReceipt.RemoveAllTransitions();
mTxReceipt.SetCumGas(0);
mTxReceipt.SetResult(false);
mTxReceipt.AddError(RUNNER_FAILED);
mTxReceipt.update();
mAccountStore.IncreaseNonceForAccount(clientContext.origin);
return preValidateResult;
Expand Down Expand Up @@ -211,7 +210,6 @@ CpsExecuteResult CpsExecutor::RunFromEvm(EvmProcessContext& clientContext) {
const auto preValidateResult = PreValidateEvmRun(clientContext);
if (!preValidateResult.isSuccess) {
mTxReceipt.SetResult(false);
mTxReceipt.AddError(RUNNER_FAILED);
mTxReceipt.SetCumGas(0);
mTxReceipt.update();
mAccountStore.IncreaseNonceForAccount(
Expand Down Expand Up @@ -292,7 +290,6 @@ CpsExecuteResult CpsExecutor::RunFromEvm(EvmProcessContext& clientContext) {
LOG_GENERAL(WARNING, "EVM call returned a Scilla result");
}
mTxReceipt.SetResult(false);
mTxReceipt.AddError(RUNNER_FAILED);
} else {
mTxReceipt.SetResult(true);
mTxReceipt.clear();
Expand Down
2 changes: 1 addition & 1 deletion src/libCps/CpsRunEvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ CpsExecuteResult CpsRunEvm::Run(TransactionReceipt& receipt) {

if (!invokeResult.has_value()) {
// Timeout
receipt.AddError(EXECUTE_CMD_TIMEOUT);
receipt.SetResult(false);
span.SetError("Evm-ds Invoke Error");
INC_STATUS(GetCPSMetric(), "error", "timeout");
LOG_GENERAL(WARNING, "Invoke EVM failed!");
Expand Down
41 changes: 40 additions & 1 deletion src/libData/AccountData/TransactionReceipt.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,48 @@ enum ReceiptError : unsigned int {
INTERNAL_ERROR = 22,
LIBRARY_AS_RECIPIENT = 23,
VERSION_INCONSISTENT = 24,
LIBRARY_EXTRACTION_FAILED = 25
LIBRARY_EXTRACTION_FAILED = 25,
MAX_LEN
};

// This is a perfect case for magic enum, however g3log messed up some macros
// disallowing magic enum to work...

namespace TransactionReceiptStr {

#define MAKE_RECEIPT_ERR_AS_STR(s) #s

constexpr std::array<std::string_view, static_cast<uint8_t>(MAX_LEN)>
TransactionReceiptErrorStr = {
MAKE_RECEIPT_ERR_AS_STR(CHECKER_FAILED),
MAKE_RECEIPT_ERR_AS_STR(RUNNER_FAILED),
MAKE_RECEIPT_ERR_AS_STR(BALANCE_TRANSFER_FAILED),
MAKE_RECEIPT_ERR_AS_STR(EXECUTE_CMD_FAILED),
MAKE_RECEIPT_ERR_AS_STR(EXECUTE_CMD_TIMEOUT),
MAKE_RECEIPT_ERR_AS_STR(NO_GAS_REMAINING_FOUND),
MAKE_RECEIPT_ERR_AS_STR(NO_ACCEPTED_FOUND),
MAKE_RECEIPT_ERR_AS_STR(CALL_CONTRACT_FAILED),
MAKE_RECEIPT_ERR_AS_STR(CREATE_CONTRACT_FAILED),
MAKE_RECEIPT_ERR_AS_STR(JSON_OUTPUT_CORRUPTED),
MAKE_RECEIPT_ERR_AS_STR(CONTRACT_NOT_EXIST),
MAKE_RECEIPT_ERR_AS_STR(STATE_CORRUPTED),
MAKE_RECEIPT_ERR_AS_STR(LOG_ENTRY_INSTALL_FAILED),
MAKE_RECEIPT_ERR_AS_STR(MESSAGE_CORRUPTED),
MAKE_RECEIPT_ERR_AS_STR(RECEIPT_IS_NULL),
MAKE_RECEIPT_ERR_AS_STR(MAX_EDGES_REACHED),
MAKE_RECEIPT_ERR_AS_STR(CHAIN_CALL_DIFF_SHARD),
MAKE_RECEIPT_ERR_AS_STR(PREPARATION_FAILED),
MAKE_RECEIPT_ERR_AS_STR(NO_OUTPUT),
MAKE_RECEIPT_ERR_AS_STR(OUTPUT_ILLEGAL),
MAKE_RECEIPT_ERR_AS_STR(MAP_DEPTH_MISSING),
MAKE_RECEIPT_ERR_AS_STR(GAS_NOT_SUFFICIENT),
MAKE_RECEIPT_ERR_AS_STR(INTERNAL_ERROR),
MAKE_RECEIPT_ERR_AS_STR(LIBRARY_AS_RECIPIENT),
MAKE_RECEIPT_ERR_AS_STR(VERSION_INCONSISTENT),
MAKE_RECEIPT_ERR_AS_STR(LIBRARY_EXTRACTION_FAILED)};

} // namespace TransactionReceiptStr

class TransactionReceipt : public SerializableDataBlock {
Json::Value m_tranReceiptObj = Json::nullValue;
std::string m_tranReceiptStr;
Expand Down
136 changes: 107 additions & 29 deletions src/libEth/Eth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@
*/

#include "Eth.h"

#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>
#include <boost/range.hpp>
#include <ethash/keccak.hpp>

#include "common/Constants.h"
#include "depends/common/RLP.h"
#include "json/value.h"
Expand All @@ -34,10 +37,21 @@

using namespace jsonrpc;

const char *ZEROES_HASH =
namespace Eth {

constexpr auto ZEROES_HASH =
"0x0000000000000000000000000000000000000000000000000000000000000";

namespace Eth {
constexpr auto ZEROES_ADDR = "0x0000000000000000000000000000000000000000";

std::string ConvertStrToHexEthSelector(const std::string &input) {
const auto ethhash = ethash_keccak256(
reinterpret_cast<const uint8_t *>(input.data()), std::size(input));
std::string selector = "0x";
boost::algorithm::hex(std::cbegin(ethhash.bytes), std::cend(ethhash.bytes),
std::back_inserter(selector));
return selector;
}

Json::Value populateReceiptHelper(
std::string const &txnhash, bool success, const std::string &from,
Expand Down Expand Up @@ -95,7 +109,7 @@ Json::Value populateReceiptHelper(
return ret;
}

EthFields parseLegacyTransaction(zbytes const& asBytes) {
EthFields parseLegacyTransaction(zbytes const &asBytes) {
EthFields ret;

dev::RLP rlpStream1(asBytes,
Expand Down Expand Up @@ -161,7 +175,7 @@ EthFields parseLegacyTransaction(zbytes const& asBytes) {
return ret;
}

EthFields parseEip2930Transaction(zbytes const& asBytes) {
EthFields parseEip2930Transaction(zbytes const &asBytes) {
EthFields ret;

dev::RLP rlpStream1(asBytes,
Expand All @@ -174,12 +188,14 @@ EthFields parseEip2930Transaction(zbytes const& asBytes) {

int i = 0;

ret.version = DataConversion::Pack(CHAIN_ID, TRANSACTION_VERSION_ETH_EIP_2930);
ret.version =
DataConversion::Pack(CHAIN_ID, TRANSACTION_VERSION_ETH_EIP_2930);

// RLP TX contains: chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, signatureYParity, signatureR, signatureS
for (const auto& it : rlpStream1) {
// RLP TX contains: chainId, nonce, gasPrice, gasLimit, to, value, data,
// accessList, signatureYParity, signatureR, signatureS
for (const auto &it : rlpStream1) {
switch (i) {
case 0: // Chain ID - validated earlier
case 0: // Chain ID - validated earlier
break;
case 1:
ret.nonce = uint32_t(it);
Expand Down Expand Up @@ -227,7 +243,7 @@ EthFields parseEip2930Transaction(zbytes const& asBytes) {
return ret;
}

EthFields parseEip1559Transaction(zbytes const& asBytes) {
EthFields parseEip1559Transaction(zbytes const &asBytes) {
EthFields ret;

dev::RLP rlpStream1(asBytes,
Expand All @@ -240,12 +256,15 @@ EthFields parseEip1559Transaction(zbytes const& asBytes) {

int i = 0;

ret.version = DataConversion::Pack(CHAIN_ID, TRANSACTION_VERSION_ETH_EIP_1559);
ret.version =
DataConversion::Pack(CHAIN_ID, TRANSACTION_VERSION_ETH_EIP_1559);

// RLP TX contains: chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list, signature_y_parity, signature_r, signature_s
for (const auto& it : rlpStream1) {
// RLP TX contains: chain_id, nonce, max_priority_fee_per_gas,
// max_fee_per_gas, gas_limit, destination, amount, data, access_list,
// signature_y_parity, signature_r, signature_s
for (const auto &it : rlpStream1) {
switch (i) {
case 0: // Chain ID - validated earlier
case 0: // Chain ID - validated earlier
break;
case 1:
ret.nonce = uint32_t(it);
Expand Down Expand Up @@ -290,8 +309,9 @@ EthFields parseEip1559Transaction(zbytes const& asBytes) {
++i;
}

// Set gas price now, based on `maxPriorityFeePerGas` and `maxFeePerGas`. This gas price is what will actually be
// used for all downstream transaction processing. We only need to keep around the two values from the request so
// Set gas price now, based on `maxPriorityFeePerGas` and `maxFeePerGas`. This
// gas price is what will actually be used for all downstream transaction
// processing. We only need to keep around the two values from the request so
// that we can reconstruct it later.
ret.gasPrice = ret.maxFeePerGas;

Expand All @@ -318,13 +338,14 @@ EthFields parseRawTxFields(std::string const &message) {
zbytes transaction(asBytes.begin() + 1, asBytes.end());
return parseEip1559Transaction(transaction);
} else if ((firstByte >= 0xc0) && (firstByte <= 0xfe)) {
// See https://eips.ethereum.org/EIPS/eip-2718 section "Backwards Compatibility"
// See https://eips.ethereum.org/EIPS/eip-2718 section "Backwards
// Compatibility"
return parseLegacyTransaction(asBytes);
} else {
LOG_GENERAL(WARNING, "invalid transaction. Tx: " << message << " First byte: " << firstByte);
LOG_GENERAL(WARNING, "invalid transaction. Tx: "
<< message << " First byte: " << firstByte);
return {};
}

}

bool ValidateEthTxn(const Transaction &tx, const Address &fromAddr,
Expand Down Expand Up @@ -456,26 +477,75 @@ Json::Value ConvertScillaEventsToEvm(const Json::Value &evmEvents) {

Json::Value converted{};
converted["address"] =
event.isMember("address") ? event["address"].asString() : "0x";
event.isMember("address") ? event["address"].asString() : ZEROES_ADDR;
converted["topics"] = Json::arrayValue;
const auto eventName =
event["_eventname"].asString() + std::string("(string)");
const auto ethhash =
ethash_keccak256(reinterpret_cast<const uint8_t *>(eventName.data()),
std::size(eventName));
std::string topic0 = "0x";
boost::algorithm::hex(std::cbegin(ethhash.bytes), std::cend(ethhash.bytes),
std::back_inserter(topic0));

const auto topic0 = ConvertStrToHexEthSelector(eventName);
converted["topics"].append(topic0);
converted["data"] = "0x" + ConvertScillaEventToEthAbi(
JSONUtils::GetInstance().convertJsontoStr(event));
converted["data"] =
"0x" +
ConvertStringToEthAbi(JSONUtils::GetInstance().convertJsontoStr(event));
convertedEvents.append(converted);
}

return convertedEvents;
}

std::string ConvertScillaEventToEthAbi(const std::string &scillaEventString) {
Json::Value ConvertScillaErrorsToEvm(const Json::Value &receiptErrors) {
Json::Value convertedErrors = Json::arrayValue;
const auto count =
std::size(TransactionReceiptStr::TransactionReceiptErrorStr);
for (const auto &arr : receiptErrors) {
for (const auto &error : arr) {
const auto errorInt = error.asUInt();
if (errorInt >= count) {
LOG_GENERAL(WARNING, "Receipt has unknown error code: " << errorInt);
continue;
}
const auto enumName = std::string{
TransactionReceiptStr::TransactionReceiptErrorStr[errorInt]};
Json::Value converted{};

converted["address"] = ZEROES_ADDR;

constexpr auto errorSignature = "ScillaError(string)";
const auto topic0 = ConvertStrToHexEthSelector(errorSignature);
converted["topics"] = Json::arrayValue;
converted["topics"].append(topic0);

converted["data"] = "0x" + ConvertStringToEthAbi(enumName);
convertedErrors.append(converted);
}
}
return convertedErrors;
}

Json::Value ConvertScillaExceptionsToEvm(const Json::Value &exceptions) {
Json::Value convertedErrors = Json::arrayValue;

for (const auto &entry : exceptions) {
const auto msg = entry["message"].asString();
const auto line = entry["line"].asString();

Json::Value converted{};

converted["address"] = ZEROES_ADDR;
constexpr auto errorSignature = "ScillaException(string)";
const auto topic0 = ConvertStrToHexEthSelector(errorSignature);
converted["topics"] = Json::arrayValue;
converted["topics"].append(topic0);

const std::string payload = msg + ", line: " + line;

converted["data"] = "0x" + ConvertStringToEthAbi(payload);
convertedErrors.append(converted);
}
return convertedErrors;
}

std::string ConvertStringToEthAbi(const std::string &scillaEventString) {
zbytes encoded;
constexpr auto OFFSET = 32;
// Specify offset where real data starts
Expand Down Expand Up @@ -516,6 +586,14 @@ Json::Value GetLogsFromReceipt(const TransactionReceipt &receipt) {
return logs;
}

std::pair<Json::Value, Json::Value> GetErrorsAndExceptionsFromReceipt(
const TransactionReceipt &receipt) {
const auto errors = receipt.GetJsonValue().get("errors", Json::arrayValue);
const auto exceptions =
receipt.GetJsonValue().get("exceptions", Json::arrayValue);
return {errors, exceptions};
}

LogBloom BuildBloomForLogObject(const Json::Value &logObject) {
const std::string addressStr =
logObject.get("address", Json::nullValue).asString();
Expand Down Expand Up @@ -626,7 +704,7 @@ Transaction GetTxFromFields(Eth::EthFields const &fields, zbytes const &pubKey,
fields.accessList,
fields.maxPriorityFeePerGas,
fields.maxFeePerGas,
fields.signature_validation };
fields.signature_validation};

hash = DataConversion::AddOXPrefix(tx.GetTranID().hex());

Expand Down
11 changes: 8 additions & 3 deletions src/libEth/Eth.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ Json::Value populateReceiptHelper(
const Json::Value &logs, const Json::Value &logsBloom,
const Json::Value &transactionIndex, const Transaction &txn);

EthFields parseEip2930Transaction(zbytes const& asBytes);
EthFields parseEip1559Transaction(zbytes const& asBytes);
EthFields parseEip2930Transaction(zbytes const &asBytes);
EthFields parseEip1559Transaction(zbytes const &asBytes);
EthFields parseRawTxFields(std::string const &message);

bool ValidateEthTxn(const Transaction &tx, const Address &fromAddr,
Expand All @@ -76,12 +76,17 @@ void DecorateReceiptLogs(Json::Value &logsArrayFromEvm,
uint32_t logIndex);

Json::Value ConvertScillaEventsToEvm(const Json::Value &evmEvents);
std::string ConvertScillaEventToEthAbi(const std::string &event);
Json::Value ConvertScillaErrorsToEvm(const Json::Value &evmEvents);
Json::Value ConvertScillaExceptionsToEvm(const Json::Value &evmEvents);

std::string ConvertStringToEthAbi(const std::string &event);

LogBloom GetBloomFromReceipt(const TransactionReceipt &receipt);
Json::Value GetBloomFromReceiptHex(const TransactionReceipt &receipt);

Json::Value GetLogsFromReceipt(const TransactionReceipt &receipt);
std::pair<Json::Value, Json::Value> GetErrorsAndExceptionsFromReceipt(
const TransactionReceipt &receipt);

LogBloom BuildBloomForLogObject(const Json::Value &logObject);
LogBloom BuildBloomForLogs(const Json::Value &logsArray);
Expand Down
15 changes: 15 additions & 0 deletions src/libServer/EthRpcMethods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1729,13 +1729,28 @@ Json::Value EthRpcMethods::GetEthTransactionReceipt(

logs = Eth::ConvertScillaEventsToEvm(logs);

const auto [errors, exceptions] = Eth::GetErrorsAndExceptionsFromReceipt(
transactionBodyPtr->GetTransactionReceipt());
const auto convertedErrors = Eth::ConvertScillaErrorsToEvm(errors);
const auto convertedExceptions =
Eth::ConvertScillaExceptionsToEvm(exceptions);

for (const auto &error : convertedErrors) {
logs.append(error);
}

for (const auto &exception : convertedExceptions) {
logs.append(exception);
}

const auto baselogIndex =
Eth::GetBaseLogIndexForReceiptInBlock(argHash, txBlock);

Eth::DecorateReceiptLogs(logs, txnhash, blockHash, blockNumber,
transactionIndex, baselogIndex);
const auto bloomLogs = Eth::GetBloomFromReceiptHex(
transactionBodyPtr->GetTransactionReceipt());

auto res = Eth::populateReceiptHelper(
hashId, success, sender, toAddr, cumGas, gasPrice, blockHash,
blockNumber, contractAddress, logs, bloomLogs, transactionIndex,
Expand Down
Loading