From 7e52d3f6452f8c8363d9926d5ece20f579461708 Mon Sep 17 00:00:00 2001 From: Chetan Phirke Date: Tue, 9 Jul 2024 12:41:19 +0800 Subject: [PATCH 1/2] Filter duplicate Eth logs at api level --- src/libServer/EthRpcMethods.cpp | 10 +++-- src/libUtils/JsonUtils.h | 43 ++++++++++++++++---- tests/EvmAcceptanceTests/contracts/Event.sol | 8 ++++ tests/EvmAcceptanceTests/test/EventsLogs.ts | 15 ++++--- 4 files changed, 60 insertions(+), 16 deletions(-) diff --git a/src/libServer/EthRpcMethods.cpp b/src/libServer/EthRpcMethods.cpp index be12e02910..eebfa43262 100644 --- a/src/libServer/EthRpcMethods.cpp +++ b/src/libServer/EthRpcMethods.cpp @@ -1800,6 +1800,8 @@ Json::Value EthRpcMethods::GetEthTransactionReceipt( Eth::GetLogsFromReceipt(transactionBodyPtr->GetTransactionReceipt()); logs = Eth::ConvertScillaEventsToEvm(logs); + Json::Value filteredLogs = + JSONUtils::GetInstance().FilterDuplicateLogs(logs); const auto [errors, exceptions] = Eth::GetErrorsAndExceptionsFromReceipt( transactionBodyPtr->GetTransactionReceipt()); @@ -1808,24 +1810,24 @@ Json::Value EthRpcMethods::GetEthTransactionReceipt( Eth::ConvertScillaExceptionsToEvm(exceptions); for (const auto &error : convertedErrors) { - logs.append(error); + filteredLogs.append(error); } for (const auto &exception : convertedExceptions) { - logs.append(exception); + filteredLogs.append(exception); } const auto baselogIndex = Eth::GetBaseLogIndexForReceiptInBlock(argHash, txBlock); - Eth::DecorateReceiptLogs(logs, txnhash, blockHash, blockNumber, + Eth::DecorateReceiptLogs(filteredLogs, 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, + blockNumber, contractAddress, filteredLogs, bloomLogs, transactionIndex, transactionBodyPtr->GetTransaction()); return res; diff --git a/src/libUtils/JsonUtils.h b/src/libUtils/JsonUtils.h index 1b7f4d10c4..c0686a5c7c 100644 --- a/src/libUtils/JsonUtils.h +++ b/src/libUtils/JsonUtils.h @@ -45,7 +45,7 @@ class JSONUtils { std::unique_ptr(writeBuilder.newStreamWriter()); } - ~JSONUtils(){}; + ~JSONUtils() {}; public: static JSONUtils& GetInstance() { @@ -53,20 +53,22 @@ class JSONUtils { return jsonutils; } - bool getUint128FromObject(const Json::Value& obj, const std::string& key, uint128_t &result) const { + bool getUint128FromObject(const Json::Value& obj, const std::string& key, + uint128_t& result) const { return this->getUint128FromObject(obj, key.c_str(), result); } - + /// Get an object value as a uint128_t. /// @return false if we failed, true if we succeeded. - bool getUint128FromObject(const Json::Value& obj, const char* key, uint128_t &result) const { - if (obj.isObject() && - obj.isMember(key)) { + bool getUint128FromObject(const Json::Value& obj, const char* key, + uint128_t& result) const { + if (obj.isObject() && obj.isMember(key)) { Json::Value member = obj[key]; if (member.isString()) { // Parse it. try { - result = DataConversion::ConvertStrToInt(member.asString()); + result = + DataConversion::ConvertStrToInt(member.asString()); return true; } catch (...) { return false; @@ -118,6 +120,33 @@ class JSONUtils { std::lock_guard g(m_mutexWriter); m_writer->write(_json, &os); } + + static std::size_t hashJsonValue(const Json::Value& log) { + Json::StreamWriterBuilder writer; + std::string logStr = Json::writeString(writer, log); + return std::hash{}(logStr); + } + + static bool equalJsonValue(const Json::Value& lhs, const Json::Value& rhs) { + return lhs == rhs; + } + + Json::Value FilterDuplicateLogs(const Json::Value& logs) { + using CustomHash = std::function; + using CustomEqual = + std::function; + + std::unordered_set uniqueLogs( + 10, hashJsonValue, equalJsonValue); + Json::Value filteredLogs(Json::arrayValue); + + for (const auto& log : logs) { + if (uniqueLogs.insert(log).second) { + filteredLogs.append(log); + } + } + return filteredLogs; + } }; #endif // ZILLIQA_SRC_LIBUTILS_JSONUTILS_H_ diff --git a/tests/EvmAcceptanceTests/contracts/Event.sol b/tests/EvmAcceptanceTests/contracts/Event.sol index ec7ebe210f..bf7fe248dc 100644 --- a/tests/EvmAcceptanceTests/contracts/Event.sol +++ b/tests/EvmAcceptanceTests/contracts/Event.sol @@ -32,4 +32,12 @@ contract Event { child.one_log(); revert(); } + function duplicate_one_log() public { + emit Log(msg.sender, "Hello World!"); + emit Log(msg.sender, "Hello World!"); + emit Log(msg.sender, "Hello World!"); + emit Log(msg.sender, "Hello World!"); + emit Log(msg.sender, "Hello World2!"); + emit Log(msg.sender, "Hello World3!"); + } } \ No newline at end of file diff --git a/tests/EvmAcceptanceTests/test/EventsLogs.ts b/tests/EvmAcceptanceTests/test/EventsLogs.ts index f7b16d1a80..c7ac7e2dd0 100644 --- a/tests/EvmAcceptanceTests/test/EventsLogs.ts +++ b/tests/EvmAcceptanceTests/test/EventsLogs.ts @@ -1,6 +1,6 @@ -import {expect} from "chai"; -import {Contract} from "ethers"; -import hre, {ethers} from "hardhat"; +import { expect } from "chai"; +import { Contract } from "ethers"; +import hre, { ethers } from "hardhat"; const FUND = ethers.utils.parseUnits("1", "gwei"); @@ -28,9 +28,14 @@ describe("Events and logs #parallel", function () { }); it("Should return log from child contract even if function failed @block-2", async function () { - const tx = await contract.one_log_and_fail({gasLimit: 250000}); + const tx = await contract.one_log_and_fail({ gasLimit: 250000 }); const receipt = await ethers.provider.getTransactionReceipt(tx.hash); - console.log("Receipt: " + JSON.stringify(receipt)); expect(receipt.logs.length).to.be.eq(1); }); + it("Should return 3 log whenever a function with duplicate one event is called @block-1", async function () { + const tx = await contract.duplicate_one_log(); + const receipt = await ethers.provider.getTransactionReceipt(tx.hash); + //console.log("Receipt = ", JSON.stringify(receipt)); + expect(receipt.logs.length).to.be.eq(3); + }); }); From c87467aa4b920c46e2064e9b98766bddb327dcac Mon Sep 17 00:00:00 2001 From: Chetan Phirke Date: Thu, 12 Sep 2024 12:17:41 +0800 Subject: [PATCH 2/2] Fix docker build breakage --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 77b54a69da..54b61950b4 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -71,7 +71,7 @@ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o install_script. sh install_script.sh -y ENV PATH="/root/.cargo/bin:${PATH}" -RUN cargo install --git https://github.com/rrw-zilliqa/sccache --branch main sccache --locked +RUN cargo install --git https://github.com/mozilla/sccache --branch main sccache --locked ENV SCCACHE_CACHE_SIZE="1G" ENV SCCACHE_DIR="/sccache" ENV RUSTC_WRAPPER="/root/.cargo/bin/sccache"