Skip to content

Commit

Permalink
<fix>(executor): fix nonce not increase when transaction revert, fix …
Browse files Browse the repository at this point in the history
…contract initial nonce not set issue.
  • Loading branch information
kyonRay committed Feb 18, 2025
1 parent e24682c commit 88ab013
Show file tree
Hide file tree
Showing 22 changed files with 993 additions and 98 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/workflow-self-hosted-ubuntu-upload.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ jobs:
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
cd build && cmake -DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DTESTS=OFF -DCOVERAGE=OFF -DWITH_LIGHTNODE=ON -DWITH_CPPSDK=ON -DWITH_TIKV=OFF -DWITH_TARS_SERVICES=OFF -DTOOLS=OFF -DBUILD_STATIC=ON -DALLOCATOR=default .. || cat *.log
make -j6
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: fisco-bcos.tar.gz
path: build/fisco-bcos-air/fisco-bcos
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ endif()

list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)

set(VERSION "3.13.0")
set(VERSION "3.14.0")
set(VERSION_SUFFIX "")
include(Options)
configure_project()
Expand Down
96 changes: 75 additions & 21 deletions bcos-executor/src/executive/TransactionExecutive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,33 @@ CallParameters::UniquePtr TransactionExecutive::start(CallParameters::UniquePtr

auto& callParameters = input;

bool updateEoaNonce = !callParameters->staticCall && callParameters->seq == 0 &&
callParameters->transactionType != TransactionType::BCOSTransaction &&
callParameters->origin == callParameters->senderAddress &&
m_blockContext.features().get(
ledger::Features::Flag::bugfix_nonce_not_increase_when_revert);
auto origin = callParameters->origin;
auto nonce = callParameters->nonce;

auto message = execute(std::move(callParameters));

if (updateEoaNonce)
{
// only increase the nonce of EOA
ledger::account::EVMAccount address(*m_blockContext.storage(), std::move(origin),
m_blockContext.features().get(ledger::Features::Flag::feature_raw_address));
task::wait([](decltype(address) addr, u256 callNonce) -> task::Task<void> {
if (!co_await ledger::account::exists(addr))
{
co_await ledger::account::create(addr);
}
auto const nonceInStorage = co_await ledger::account::nonce(addr);
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>());
}(std::move(address), nonce));
}

message->contextID = contextID();
message->seq = seq();
message->hasContractTableChanged = m_hasContractTableChanged;
Expand Down Expand Up @@ -310,32 +335,50 @@ CallParameters::UniquePtr TransactionExecutive::execute(CallParameters::UniquePt
}
}

if (!callParameters->staticCall &&
m_blockContext.features().get(ledger::Features::Flag::feature_evm_address)) [[unlikely]]
if (m_blockContext.features().get(
ledger::Features::Flag::bugfix_nonce_not_increase_when_revert))
{
// 如果是EOA发起交易,那么必须要更新nonce;
// 如果是合约调用合约,那么只有在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 &&
callParameters->transactionType != 0) ||
(callParameters->create && !callParameters->internalCreate))
// only update contract's nonce when contract create contract
if (callParameters->origin != callParameters->senderAddress && callParameters->create &&
!callParameters->internalCreate)
{
// TODO)): set nonce here will be better
ledger::account::EVMAccount address(*m_blockContext.storage(),
callParameters->senderAddress,
m_blockContext.features().get(ledger::Features::Flag::feature_raw_address));
task::wait([](decltype(address) addr, u256 callNonce) -> task::Task<void> {
if (!co_await ledger::account::exists(addr))
{
co_await ledger::account::create(addr);
}
auto const nonceInStorage = co_await ledger::account::nonce(addr);
// FIXME)) : only web3 tx use this
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>());
}(std::move(address), callParameters->nonce));
task::wait([](decltype(address) addr) -> task::Task<void> {
co_await ledger::account::increaseNonce(addr);
}(std::move(address)));
}
}
else
{
if (!callParameters->staticCall &&
m_blockContext.features().get(ledger::Features::Flag::feature_evm_address)) [[unlikely]]
{
// 如果是EOA发起交易,那么必须要更新nonce;
// 如果是合约调用合约,那么只有在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 &&
callParameters->transactionType != 0) ||
(callParameters->create && !callParameters->internalCreate))
{
// TODO)): set nonce here will be better
ledger::account::EVMAccount address(*m_blockContext.storage(),
callParameters->senderAddress,
m_blockContext.features().get(ledger::Features::Flag::feature_raw_address));
task::wait([](decltype(address) addr, u256 callNonce) -> task::Task<void> {
if (!co_await ledger::account::exists(addr))
{
co_await ledger::account::create(addr);
}
auto const nonceInStorage = co_await ledger::account::nonce(addr);
// FIXME)) : only web3 tx use this
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>());
}(std::move(address), callParameters->nonce));
}
}
}

Expand Down Expand Up @@ -751,6 +794,17 @@ std::tuple<std::unique_ptr<HostContext>, CallParameters::UniquePtr> TransactionE
<< LOG_KV("value", callParameters->value);
}

if (m_blockContext.features().get(
ledger::Features::Flag::bugfix_set_contract_nonce_when_create)) [[unlikely]]
{
// set nonce to 1 when create contract
ledger::account::EVMAccount account(
*m_blockContext.storage(), callParameters->codeAddress, false);
task::wait([](decltype(account) contract_account) -> task::Task<void> {
co_await ledger::account::setNonce(contract_account, "1");
}(std::move(account)));
}

if (m_blockContext.features().get(ledger::Features::Flag::feature_sharding))
{
if (callParameters->origin != callParameters->senderAddress)
Expand Down
2 changes: 2 additions & 0 deletions bcos-executor/src/vm/HostContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ evmc_result HostContext::externalRequest(const evmc_message* _msg)
}
}

request->transactionType = m_callParameters->transactionType;

if (request->create && features().get(ledger::Features::Flag::feature_evm_address)) [[unlikely]]
{
// account must exist
Expand Down
Loading

0 comments on commit 88ab013

Please sign in to comment.