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

<fix>(txpool,executor): change web3 nonce mem cache logic to avoid duplicate tx, add only web3 transaction store nonce logic. #4631

Merged
merged 4 commits into from
Sep 25, 2024
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
5 changes: 3 additions & 2 deletions bcos-boostssl/bcos-boostssl/httpserver/HttpSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,12 @@ class HttpSession : public std::enable_shared_from_this<HttpSession>

handleRequest(m_parser->release());
}
catch (std::exception const& e)
catch (...)
{
HTTP_SESSION(WARNING) << LOG_DESC("onRead exception")
<< LOG_KV("bytesSize", bytes_transferred)
<< LOG_KV("failed", boost::diagnostic_information(e));
<< LOG_KV("failed",
boost::current_exception_diagnostic_information());
}

if (!m_queue->isFull())
Expand Down
8 changes: 8 additions & 0 deletions bcos-executor/src/CallParameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ struct CallParameters
std::string abi; // common field, contract abi, json format

u256 nonce = 0; // for create
uint8_t transactionType = 0;
// balance
u256 value = 0;
u256 gasPrice = 0;
Expand Down Expand Up @@ -117,6 +118,13 @@ struct CallParameters
<< "origin:" << origin << "|"
<< "gas:" << gas << "|"
<< "value:" << value << "|"
<< "gasPrice:" << gasPrice << "|"
<< "effectiveGasPrice:" << effectiveGasPrice << "|"
<< "gasLimit:" << gasLimit << "|"
<< "maxFeePerGas:" << maxFeePerGas << "|"
<< "maxPriorityFeePerGas:" << maxPriorityFeePerGas << "|"
<< "nonce:" << nonce << "|"
<< "transactionType:" << std::to_string(transactionType) << "|"
<< "dataSize:" << data.size() << "|"
<< "abiSize:" << abi.size() << "|"
<< "acquireKeyLock:" << acquireKeyLock << "|"
Expand Down
8 changes: 7 additions & 1 deletion bcos-executor/src/executive/TransactionExecutive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,8 @@ CallParameters::UniquePtr TransactionExecutive::execute(CallParameters::UniquePt
// 如果是合约调用合约,那么只有在create场景下才更新nonce。
// If it is an EOA initiating a transaction, the nonce must be updated; if it is a contract
// calling a contract, the nonce is updated only in the creation scenario.
if ((callParameters->origin == callParameters->senderAddress) ||
if ((callParameters->origin == callParameters->senderAddress &&
callParameters->transactionType != 0) ||
(callParameters->create && !callParameters->internalCreate))
{
// TODO)): set nonce here will be better
Expand All @@ -318,6 +319,11 @@ CallParameters::UniquePtr TransactionExecutive::execute(CallParameters::UniquePt
auto const storageNonce = u256(nonceInStorage.value_or("0"));
auto const newNonce = std::max(callNonce, storageNonce) + 1;
co_await ledger::account::setNonce(addr, newNonce.convert_to<std::string>());
if (c_fileLogLevel == TRACE)
{
EXECUTIVE_LOG(TRACE) << "Web3Nonce: update address nonce to storage"
<< LOG_KV("address", addr) << LOG_KV("nonce", newNonce);
}
}(std::move(address), callParameters->nonce));
}
}
Expand Down
4 changes: 3 additions & 1 deletion bcos-executor/src/executor/TransactionExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2700,6 +2700,8 @@ std::unique_ptr<CallParameters> TransactionExecutor::createCallParameters(
callParameters->message = input.message();
callParameters->data = input.takeData();
callParameters->gas = input.gasAvailable();
callParameters->nonce = hex2u(input.nonce());
callParameters->transactionType = input.txType();
callParameters->staticCall = staticCall;
callParameters->newEVMContractAddress = input.newEVMContractAddress();
callParameters->keyLocks = input.takeKeyLocks();
Expand Down Expand Up @@ -2776,8 +2778,8 @@ std::unique_ptr<CallParameters> TransactionExecutor::createCallParameters(
callParameters->gasLimit = input.gasLimit();
callParameters->maxFeePerGas = u256(input.maxFeePerGas());
callParameters->maxPriorityFeePerGas = u256(input.maxPriorityFeePerGas());
// TODO: depends on whether web3 tx?
callParameters->nonce = hex2u(input.nonce());
callParameters->transactionType = input.txType();

if (!m_isWasm && !callParameters->create)
{
Expand Down
3 changes: 3 additions & 0 deletions bcos-framework/bcos-framework/executor/ExecutionMessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ class ExecutionMessage
virtual void setNonce(std::string nonce) = 0;
virtual std::string nonce() const = 0;

virtual uint8_t txType() const = 0;
virtual void setTxType(uint8_t txType) = 0;

// -----------------------------------------------
// Request / Response common fields
// -----------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ class NativeExecutionMessage : public protocol::ExecutionMessage
void setNonce(std::string nonce) override { m_nonce = std::move(nonce); }
std::string nonce() const override { return m_nonce; }

uint8_t txType() const override { return m_transactionType; }
void setTxType(uint8_t txType) override { m_transactionType = txType; }

int32_t depth() const override { return m_depth; }
void setDepth(int32_t depth) override { m_depth = depth; }

Expand Down Expand Up @@ -192,6 +195,7 @@ class NativeExecutionMessage : public protocol::ExecutionMessage
std::vector<std::string> m_keyLocks;
std::string m_keyLockAcquired;
std::string m_nonce;
uint8_t m_transactionType = static_cast<uint8_t>(protocol::TransactionType::BCOSTransaction);

int32_t m_status = 0;
int32_t m_depth = 0;
Expand Down
8 changes: 7 additions & 1 deletion bcos-framework/bcos-framework/ledger/EVMAccount.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,12 @@ class EVMAccount
m_tableName.append(address);
}
~EVMAccount() noexcept = default;
auto address() const { return this->m_tableName; }
};

template <class Storage>
inline std::ostream& operator<<(std::ostream& stream, EVMAccount<Storage> const& account)
{
stream << account.address();
return stream;
}
} // namespace bcos::ledger::account
1 change: 0 additions & 1 deletion bcos-framework/bcos-framework/ledger/Features.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ class Features
BOOST_THROW_EXCEPTION(NoSuchFeatureError{});
}

validate(flag);
m_flags[*index] = true;
// enableDependencyFeatures(flag);
}
Expand Down
4 changes: 2 additions & 2 deletions bcos-framework/bcos-framework/protocol/Transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace bcos::protocol
enum class TransactionType : uint8_t
{
BCOSTransaction = 0,
Web3Transacion = 1,
Web3Transaction = 1,
};

constexpr auto operator<=>(bcos::protocol::TransactionType const& _lhs, auto _rhs)
Expand Down Expand Up @@ -104,7 +104,7 @@ class Transaction
{
hashResult = hash();
}
else if (type() == static_cast<uint8_t>(TransactionType::Web3Transacion))
else if (type() == static_cast<uint8_t>(TransactionType::Web3Transaction))
{
auto bytes = extraTransactionBytes();
hashResult = bcos::crypto::keccak256Hash(bytes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ inline Transaction::Ptr fakeWeb3Tx(CryptoSuite::Ptr _cryptoSuite, std::string no
std::string inputStr = "testTransaction";
transaction.data.input.assign(inputStr.begin(), inputStr.end());
transaction.data.nonce = std::move(nonce);
transaction.type = static_cast<tars::Char>(TransactionType::Web3Transacion);
transaction.type = static_cast<tars::Char>(TransactionType::Web3Transaction);
std::mt19937 random(std::random_device{}());
std::string extraData = "extraData" + std::to_string(random());
auto hash = _cryptoSuite->hash(extraData);
Expand Down
2 changes: 1 addition & 1 deletion bcos-gateway/bcos-gateway/libp2p/Service.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ class Service : public P2PInterface, public std::enable_shared_from_this<Service
m_beforeMessageHandler;

std::function<std::optional<bcos::Error>(SessionFace::Ptr, Message::Ptr)> m_onMessageHandler;
bcos::LogLevel m_connectionLogLevel = bcos::LogLevel::WARNING;
// bcos::LogLevel m_connectionLogLevel = bcos::LogLevel::WARNING;
};

} // namespace gateway
Expand Down
2 changes: 1 addition & 1 deletion bcos-rpc/bcos-rpc/jsonrpc/JsonRpcImpl_2_0.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ void bcos::rpc::toJsonResp(Json::Value& jResp, bcos::protocol::Transaction const
jResp["extension"].append(ext);
}
}
if (transaction.type() == bcos::protocol::TransactionType::Web3Transacion) [[unlikely]]
if (transaction.type() == bcos::protocol::TransactionType::Web3Transaction) [[unlikely]]
{
Web3Transaction web3Tx;
auto extraBytesRef =
Expand Down
7 changes: 7 additions & 0 deletions bcos-rpc/bcos-rpc/jsonrpc/JsonRpcInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,13 @@ void JsonRpcInterface::onRPCRequest(std::string_view _requestBody, Sender _sende
response.error.code = JsonRpcError::InvalidRequest;
response.error.message = std::string(e.what());
}
catch (...)
{
RPC_IMPL_LOG(DEBUG) << LOG_BADGE("onRPCRequest")
<< LOG_DESC("response with unknown exception");
response.error.code = JsonRpcError::InternalError;
response.error.message = boost::current_exception_diagnostic_information();
}

auto strResp = toStringResponse(response);

Expand Down
2 changes: 1 addition & 1 deletion bcos-rpc/bcos-rpc/web3jsonrpc/Web3FilterSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Web3FilterSystem : public FilterSystem
filterTimeout, maxBlockProcessPerReq)
{}

virtual int32_t InvalidParamsCode() override { return Web3JsonRpcError::Web3DefautError; }
virtual int32_t InvalidParamsCode() override { return Web3JsonRpcError::Web3DefaultError; }
};

} // namespace rpc
Expand Down
13 changes: 10 additions & 3 deletions bcos-rpc/bcos-rpc/web3jsonrpc/Web3JsonRpcImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,10 @@ void Web3JsonRpcImpl::onRPCRequest(std::string_view _requestBody, Sender _sender
{
buildJsonError(_request, InternalError, e.errorMessage(), resp);
}
catch (const std::exception& e)
catch (...)
{
buildJsonError(_request, InternalError, boost::diagnostic_information(e), resp);
buildJsonError(_request, InternalError,
boost::current_exception_diagnostic_information(), resp);
}
auto&& respBytes = toBytesResponse(resp);
if (c_fileLogLevel == TRACE) [[unlikely]]
Expand All @@ -89,9 +90,15 @@ void Web3JsonRpcImpl::onRPCRequest(std::string_view _requestBody, Sender _sender
{
buildJsonError(request, e.code(), e.msg(), response);
}
catch (bcos::Error const& e)
{
buildJsonError(request, InternalError, e.errorMessage(), response);
}
catch (...)
{
buildJsonError(request, InternalError, "Internal error", response);
std::stringstream msg;
msg << "Internal error: " << boost::current_exception_diagnostic_information();
buildJsonError(request, InternalError, msg.str(), response);
}
auto&& resp = toBytesResponse(response);
WEB3_LOG(DEBUG) << LOG_BADGE("onRPCRequest") << LOG_DESC("response with exception")
Expand Down
17 changes: 10 additions & 7 deletions bcos-rpc/bcos-rpc/web3jsonrpc/endpoints/EthEndpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ using namespace bcos::rpc;

task::Task<void> EthEndpoint::protocolVersion(const Json::Value&, Json::Value&)
{
// TODO: impl this
// TODO: impl this, this returns eth p2p protocol version
BOOST_THROW_EXCEPTION(
JsonRpcException(MethodNotFound, "This API has not been implemented yet!"));
co_return;
Expand All @@ -68,10 +68,12 @@ task::Task<void> EthEndpoint::syncing(const Json::Value&, Json::Value& response)
buildJsonContent(result, response);
co_return;
}
task::Task<void> EthEndpoint::coinbase(const Json::Value&, Json::Value&)
task::Task<void> EthEndpoint::coinbase(const Json::Value&, Json::Value& response)
{
BOOST_THROW_EXCEPTION(
JsonRpcException(MethodNotFound, "This API has not been implemented yet!"));
auto const nodeId = m_nodeService->consensus()->consensusConfig()->nodeID();
auto const address = right160(crypto::keccak256Hash(ref(nodeId->data())));
Json::Value result = address.hexPrefixed();
buildJsonContent(result, response);
co_return;
}
task::Task<void> EthEndpoint::chainId(const Json::Value&, Json::Value& response)
Expand Down Expand Up @@ -114,6 +116,7 @@ task::Task<void> EthEndpoint::gasPrice(const Json::Value&, Json::Value& response
{
// result: gasPrice(QTY)
auto const ledger = m_nodeService->ledger();
// TODO)): gas price can wrap in a class
auto config = co_await ledger::getSystemConfig(*ledger, ledger::SYSTEM_KEY_TX_GAS_PRICE);
Json::Value result;
if (config.has_value())
Expand Down Expand Up @@ -245,12 +248,12 @@ task::Task<void> EthEndpoint::getTransactionCount(const Json::Value& request, Js
<< LOG_KV("blockTag", blockTag) << LOG_KV("blockNumber", blockNumber);
}
auto const ledger = m_nodeService->ledger();
uint64_t nonce = 0;
u256 nonce = 0;
if (auto const entry = co_await ledger::getStorageAt(
*ledger, addressStr, bcos::ledger::ACCOUNT_TABLE_FIELDS::NONCE, /*blockNumber*/ 0);
entry.has_value())
{
nonce = std::stoull(std::string(entry.value().get()));
nonce = u256(entry.value().get());
}
// else
// {
Expand Down Expand Up @@ -723,7 +726,7 @@ task::Task<void> EthEndpoint::getTransactionReceipt(
JsonRpcException(InvalidParams, "Invalid transaction hash: " + hash.hexPrefixed()));
}
auto block = co_await ledger::getBlockData(*ledger, receipt->blockNumber(),
bcos::ledger::HEADER | bcos::ledger::TRANSACTIONS_HASH);
bcos::ledger::HEADER | bcos::ledger::TRANSACTIONS_HASH | bcos::ledger::RECEIPTS);
combineReceiptResponse(result, std::move(receipt), txs->at(0), std::move(block));
}
catch (...)
Expand Down
3 changes: 2 additions & 1 deletion bcos-rpc/bcos-rpc/web3jsonrpc/model/BlockResponse.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ namespace bcos::rpc
result["parentHash"] = info.blockHash.hexPrefixed();
}
result["nonce"] = "0x0000000000000000";
// result["sha3Uncles"] = "0x";
// empty uncle hash: keccak256(RLP([]))
result["sha3Uncles"] = "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347";
result["logsBloom"] = "0x";
result["transactionsRoot"] = block->blockHeader()->txsRoot().hexPrefixed();
result["stateRoot"] = block->blockHeader()->stateRoot().hexPrefixed();
Expand Down
6 changes: 4 additions & 2 deletions bcos-rpc/bcos-rpc/web3jsonrpc/model/CallRequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,14 @@ std::tuple<bool, CallRequest> rpc::decodeCallRequest(Json::Value const& _root) n
{
return {false, _request};
}
if (!_root.isMember("data"))
if (!_root.isMember("data") && !_root.isMember("input"))
{
return {false, _request};
}
auto const& data = _root.isMember("data") ? _root["data"] : _root["input"];

_request.to = _root.isMember("to") ? _root["to"].asString() : "";
_request.data = bcos::fromHexWithPrefix(_root["data"].asString());
_request.data = bcos::fromHexWithPrefix(data.asString());
if (_root.isMember("from"))
{
_request.from = _root["from"].asString();
Expand Down
9 changes: 7 additions & 2 deletions bcos-rpc/bcos-rpc/web3jsonrpc/model/ReceiptResponse.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ namespace bcos::rpc
size_t transactionIndex = 0;
crypto::HashType blockHash;
uint64_t blockNumber = 0;
u256 cumulativeGasUsed = 0;
if (block)
{
blockHash = block->blockHeader()->hash();
Expand All @@ -58,6 +59,10 @@ namespace bcos::rpc
{
break;
}
if (transactionIndex <= block->receiptsSize())
{
cumulativeGasUsed += block->receipt(transactionIndex)->gasUsed();
}
}
}
result["transactionIndex"] = toQuantity(transactionIndex);
Expand All @@ -77,10 +82,10 @@ namespace bcos::rpc
toChecksumAddress(to, bcos::crypto::keccak256Hash(bcos::bytesConstRef(to)).hex());
result["to"] = "0x" + std::move(to);
}
result["cumulativeGasUsed"] = "0x0";
result["cumulativeGasUsed"] = toQuantity(cumulativeGasUsed);
result["effectiveGasPrice"] =
receipt->effectiveGasPrice().empty() ? "0x0" : std::string(receipt->effectiveGasPrice());
result["gasUsed"] = toQuantity((uint64_t)receipt->gasUsed());
result["gasUsed"] = toQuantity(receipt->gasUsed());
if (receipt->contractAddress().empty())
{
result["contractAddress"] = Json::nullValue;
Expand Down
2 changes: 1 addition & 1 deletion bcos-rpc/bcos-rpc/web3jsonrpc/model/Web3FilterRequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Web3FilterRequest : public FilterRequest
Web3FilterRequest() = default;
~Web3FilterRequest() = default;
Web3FilterRequest(const FilterRequest& oth) : FilterRequest(oth) {}
virtual int32_t InvalidParamsCode() override { return Web3JsonRpcError::Web3DefautError; }
virtual int32_t InvalidParamsCode() override { return Web3JsonRpcError::Web3DefaultError; }
};

class Web3FilterRequestFactory : public FilterRequestFactory
Expand Down
2 changes: 1 addition & 1 deletion bcos-rpc/bcos-rpc/web3jsonrpc/model/Web3Transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ bcostars::Transaction Web3Transaction::takeToTarsTransaction()
{
tarsTx.data.gasPrice = "0x" + this->maxPriorityFeePerGas.str(0, std::ios_base::hex);
}
tarsTx.type = static_cast<tars::Char>(bcos::protocol::TransactionType::Web3Transacion);
tarsTx.type = static_cast<tars::Char>(bcos::protocol::TransactionType::Web3Transaction);
auto hashForSign = this->hashForSign();
auto encodedForSign = this->encodeForSign();
// FISCO BCOS signature is r||s||v
Expand Down
2 changes: 1 addition & 1 deletion bcos-rpc/bcos-rpc/web3jsonrpc/utils/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ constexpr const uint64_t LowestGasPrice{21000};
constexpr const uint64_t LowestGasUsed{21000};
enum Web3JsonRpcError : int32_t
{
Web3DefautError = -32000,
Web3DefaultError = -32000,
};
} // namespace bcos::rpc
11 changes: 0 additions & 11 deletions bcos-rpc/test/unittests/rpc/Web3RpcTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,17 +126,6 @@ BOOST_AUTO_TEST_CASE(handleInvalidTest)
BOOST_CHECK(response["error"]["code"].asInt() == MethodNotFound);
BOOST_CHECK(response["error"]["message"].asString() == "Method not found");
}

// not impl method
{
const auto request = R"({"jsonrpc":"2.0","id":1, "method":"eth_coinbase","params":[]})";
auto response = onRPCRequestWrapper(request);
std::string s = response.toStyledString();
BOOST_CHECK(response.isMember("error"));
BOOST_CHECK(response["error"]["code"].asInt() == MethodNotFound);
BOOST_CHECK(
response["error"]["message"].asString() == "This API has not been implemented yet!");
}
}

BOOST_AUTO_TEST_CASE(handleValidTest)
Expand Down
2 changes: 1 addition & 1 deletion bcos-scheduler/src/BlockExecutive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ bcos::protocol::ExecutionMessage::UniquePtr BlockExecutive::buildMessage(
message->setTransactionHash(tx->hash());
message->setOrigin(toHex(tx->sender()));
message->setFrom(std::string(message->origin()));

message->setTxType(tx->type());
if (!m_isSysBlock)
{
auto toAddress = tx->to();
Expand Down
Loading
Loading