Skip to content

Commit

Permalink
<fix>(executor,scheduler): move update eoa nonce logic to scheduler.
Browse files Browse the repository at this point in the history
  • Loading branch information
kyonRay committed Feb 24, 2025
1 parent a461217 commit 80f42b1
Show file tree
Hide file tree
Showing 17 changed files with 132 additions and 96 deletions.
25 changes: 0 additions & 25 deletions bcos-executor/src/executive/TransactionExecutive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,33 +77,8 @@ 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
49 changes: 31 additions & 18 deletions bcos-executor/src/executor/SwitchExecutorManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,25 +255,26 @@ class SwitchExecutorManager : public executor::ParallelTransactionExecutorInterf
inputsVec->emplace_back(std::move(inputs[i]));
}
auto queryTime = utcTime();
m_pool.enqueue([queryTime, executor = m_executor, contractAddress = std::move(contractAddress),
inputsVec, callback = std::move(callback)] {
auto waitInPoolCost = utcTime() - queryTime;
// create a holder
auto _holdExecutorCallback =
[queryTime, waitInPoolCost ,executorHolder = executor, callback = std::move(callback)](
bcos::Error::UniquePtr error,
std::vector<bcos::protocol::ExecutionMessage::UniquePtr> outputs) {
EXECUTOR_LOG(TRACE) << "Release executor holder executeTransactions"
<< LOG_KV("ptr count", executorHolder.use_count())
<< LOG_KV("waitInPoolCost", waitInPoolCost)
<< LOG_KV("costFromQuery", utcTime() - queryTime);
callback(std::move(error), std::move(outputs));
};
m_pool.enqueue(
[queryTime, executor = m_executor, contractAddress = std::move(contractAddress),
inputsVec, callback = std::move(callback)] {
auto waitInPoolCost = utcTime() - queryTime;
// create a holder
auto _holdExecutorCallback =
[queryTime, waitInPoolCost, executorHolder = executor,
callback = std::move(callback)](bcos::Error::UniquePtr error,
std::vector<bcos::protocol::ExecutionMessage::UniquePtr> outputs) {
EXECUTOR_LOG(TRACE) << "Release executor holder executeTransactions"
<< LOG_KV("ptr count", executorHolder.use_count())
<< LOG_KV("waitInPoolCost", waitInPoolCost)
<< LOG_KV("costFromQuery", utcTime() - queryTime);
callback(std::move(error), std::move(outputs));
};

// execute the function
executor->executeTransactions(
contractAddress, *inputsVec, std::move(_holdExecutorCallback));
});
// execute the function
executor->executeTransactions(
contractAddress, *inputsVec, std::move(_holdExecutorCallback));
});
}

void preExecuteTransactions(int64_t schedulerTermId,
Expand Down Expand Up @@ -685,6 +686,18 @@ class SwitchExecutorManager : public executor::ParallelTransactionExecutorInterf
});
}

void updateEoaNonce(std::unordered_map<std::string, u256> const& nonceMap) override
{
if (hasStopped())
{
std::string message = "updateEoaNonce: executor has been stopped";
EXECUTOR_LOG(DEBUG) << message;
return;
}

getAndNewExecutorIfNotExists()->updateEoaNonce(std::move(nonceMap));
}

void stop() override
{
EXECUTOR_LOG(INFO) << "Try to stop SwitchExecutorManager";
Expand Down
18 changes: 18 additions & 0 deletions bcos-executor/src/executor/TransactionExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,24 @@ void TransactionExecutor::getHash(bcos::protocol::BlockNumber number,
callback(nullptr, std::move(hash));
}

void TransactionExecutor::updateEoaNonce(std::unordered_map<std::string, u256> const& eoa2Nonce)
{
if (m_blockContext->features().get(
ledger::Features::Flag::bugfix_nonce_not_increase_when_revert))
{
for (auto&& [sender, nonce] : eoa2Nonce)
{
LEDGER_LOG(TRACE) << METRIC << LOG_DESC("updateEoaNonce") << LOG_KV("sender", sender)
<< LOG_KV("nonce", nonce);
auto eoa = ledger::account::EVMAccount(*m_blockContext->storage(), sender,
m_blockContext->features().get(ledger::Features::Flag::feature_raw_address));
auto nonceInStorage = task::syncWait(ledger::account::nonce(eoa));
auto nonceToUpdate = std::max(u256(nonceInStorage.value_or("0")), u256(nonce)) + 1;
task::syncWait(ledger::account::setNonce(eoa, nonceToUpdate.convert_to<std::string>()));
}
}
}

void TransactionExecutor::dagExecuteTransactions(
gsl::span<bcos::protocol::ExecutionMessage::UniquePtr> inputs,
std::function<void(
Expand Down
2 changes: 2 additions & 0 deletions bcos-executor/src/executor/TransactionExecutor.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ class TransactionExecutor : public ParallelTransactionExecutorInterface,
void getABI(std::string_view contract,
std::function<void(bcos::Error::Ptr, std::string)> callback) override;

void updateEoaNonce(std::unordered_map<std::string, u256> const& nonceMap) override;

void start() override { m_isRunning = true; }
void stop() override;

Expand Down
31 changes: 29 additions & 2 deletions bcos-executor/test/unittest/libvm/TestTransactionExecutive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ class TransactionExecutiveFixture : public TransactionFixture
auto result = executePromise.get_future().get();

BOOST_CHECK_EQUAL(result->status(), 0);

if (type != TransactionType::BCOSTransaction)
{
std::unordered_map<std::string, u256> eoaNonceMap;
eoaNonceMap.emplace(sender.hex(), toQuantity(nonce));
executor->updateEoaNonce(std::move(eoaNonceMap));
}

commitBlock(blockNumber);

auto const nonceOfEoa = task::syncWait(bcos::ledger::account::nonce(eoa));
Expand All @@ -74,7 +82,6 @@ class TransactionExecutiveFixture : public TransactionFixture
auto const nonceOfContract = task::syncWait(bcos::ledger::account::nonce(contractAddress));
if (type == TransactionType::BCOSTransaction)
{
BOOST_CHECK_EQUAL(nonceOfEoa.has_value(), false);
BOOST_CHECK_EQUAL(nonceOfContract.has_value(), true);
BOOST_CHECK_EQUAL(nonceOfContract.value(), "1");
}
Expand Down Expand Up @@ -128,6 +135,13 @@ class TransactionExecutiveFixture : public TransactionFixture
auto result = executePromise.get_future().get();

BOOST_CHECK_EQUAL(result->status(), 0);

if (type != TransactionType::BCOSTransaction)
{
std::unordered_map<std::string, u256> eoaNonceMap;
eoaNonceMap.emplace(sender.hex(), toQuantity(nonce));
executor->updateEoaNonce(std::move(eoaNonceMap));
}
commitBlock(blockNumber);

auto const nonceOfEoa = task::syncWait(bcos::ledger::account::nonce(eoa));
Expand Down Expand Up @@ -188,6 +202,13 @@ class TransactionExecutiveFixture : public TransactionFixture
auto result = executePromise.get_future().get();

BOOST_CHECK_EQUAL(result->status(), 16);

if (type != TransactionType::BCOSTransaction)
{
std::unordered_map<std::string, u256> eoaNonceMap;
eoaNonceMap.emplace(sender.hex(), toQuantity(nonce));
executor->updateEoaNonce(std::move(eoaNonceMap));
}
commitBlock(blockNumber);

auto const nonceOfEoa = task::syncWait(bcos::ledger::account::nonce(eoa));
Expand All @@ -208,7 +229,6 @@ class TransactionExecutiveFixture : public TransactionFixture

auto transfer(uint blockNumber, TransactionType type, std::string toAddress,
uint64_t initBalance, uint64_t transferValue, uint64_t initNonce)

{
nextBlock(blockNumber, protocol::BlockVersion::MAX_VERSION, web3Features);
auto nonce = initNonce;
Expand Down Expand Up @@ -249,6 +269,13 @@ class TransactionExecutiveFixture : public TransactionFixture

auto result = executePromise.get_future().get();

if (type != TransactionType::BCOSTransaction)
{
std::unordered_map<std::string, u256> eoaNonceMap;
eoaNonceMap.emplace(sender, toQuantity(nonce));
executor->updateEoaNonce(std::move(eoaNonceMap));
}

commitBlock(blockNumber);

auto const nonceOfEoa = task::syncWait(bcos::ledger::account::nonce(eoa));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ class ParallelTransactionExecutorInterface
virtual void getHash(bcos::protocol::BlockNumber number,
std::function<void(bcos::Error::UniquePtr, crypto::HashType)> callback) = 0;

virtual void updateEoaNonce(std::unordered_map<std::string, u256> const& nonceMap) = 0;

/* ----- XA Transaction interface Start ----- */

// Write data to storage uncommitted
Expand Down
7 changes: 0 additions & 7 deletions bcos-framework/bcos-framework/ledger/LedgerInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,6 @@ class LedgerInterface
co_return std::nullopt;
}

virtual task::Task<void> batchInsertEoaNonce(bcos::storage::StorageInterface::Ptr storage,
std::unordered_map<std::string, uint64_t> eoa2Nonce,
std::unordered_map<std::string, uint64_t> fbEoa2Nonce)
{
co_return;
}

virtual task::Task<std::optional<ledger::StorageState>> getStorageState(
std::string_view _address, protocol::BlockNumber _blockNumber)
{
Expand Down
37 changes: 0 additions & 37 deletions bcos-ledger/bcos-ledger/Ledger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,6 @@ void Ledger::asyncPrewriteBlock(bcos::storage::StorageInterface::Ptr storage,
// number 2 nonce
auto nonceBlock = m_blockFactory->createBlock();
protocol::NonceList nonceList;
std::unordered_map<std::string, uint64_t> web3NonceMap{};
std::unordered_map<std::string, uint64_t> bcosNonceMap{};
// get nonce from _blockTxs
if (_blockTxs)
{
Expand Down Expand Up @@ -396,41 +394,6 @@ void Ledger::asyncPrewriteBlock(bcos::storage::StorageInterface::Ptr storage,
});
}

task::Task<void> Ledger::batchInsertEoaNonce(bcos::storage::StorageInterface::Ptr storage,
std::unordered_map<std::string, uint64_t> eoa2Nonce,
std::unordered_map<std::string, uint64_t> fbEoa2Nonce)
{
auto features = co_await ledger::getFeatures(*this);

for (auto&& [sender, nonce] : fbEoa2Nonce)
{
if (eoa2Nonce.contains(sender))
{
eoa2Nonce[sender] += nonce;
continue;
}
// write in storage
ledger::account::EVMAccount eoa(
*storage, sender, features.get(Features::Flag::feature_raw_address));
if (!co_await ledger::account::exists(eoa))
{
co_await ledger::account::create(eoa);
}
auto nonceInStorage = co_await ledger::account::nonce(eoa);
auto const newNonce = nonce + std::stoull(nonceInStorage.value_or("0"));
co_await ledger::account::setNonce(eoa, std::to_string(newNonce));
}

co_await bcos::storage2::writeSome(
*storage, ::ranges::views::transform(eoa2Nonce, [&](auto& item) {
auto&& [sender, nonce] = item;
return std::make_tuple(
transaction_executor::StateKey(
getContractTableName(SYS_DIRECTORY::USER_APPS, sender), "nonce"),
storage::Entry(std::to_string(nonce + 1)));
}));
}

task::Task<std::optional<ledger::StorageState>> Ledger::getStorageState(
std::string_view _address, protocol::BlockNumber _blockNumber)
{
Expand Down
4 changes: 0 additions & 4 deletions bcos-ledger/bcos-ledger/Ledger.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,6 @@ class Ledger : public LedgerInterface
return _s.substr(_s.find_last_of('/') + 1);
}

task::Task<void> batchInsertEoaNonce(bcos::storage::StorageInterface::Ptr storage,
std::unordered_map<std::string, uint64_t> eoa2Nonce,
std::unordered_map<std::string, uint64_t> fbEoa2Nonce) override;

task::Task<std::optional<ledger::StorageState>> getStorageState(
std::string_view _address, protocol::BlockNumber _blockNumber) override;

Expand Down
32 changes: 31 additions & 1 deletion bcos-scheduler/src/BlockExecutive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ bcos::protocol::ExecutionMessage::UniquePtr BlockExecutive::buildMessage(
if (tx->to().empty())
{
message->setCreate(true);
message->setNonce(std::string(tx->nonce()));
}
else
{
Expand All @@ -147,6 +146,7 @@ bcos::protocol::ExecutionMessage::UniquePtr BlockExecutive::buildMessage(
message->setTo(preprocessAddress(tx->to()));
}
}
message->setNonce(std::string(tx->nonce()));
message->setDepth(0);
message->setGasAvailable(m_gasLimit);
auto toAddress = tx->to();
Expand Down Expand Up @@ -691,9 +691,27 @@ void BlockExecutive::asyncNotify(
void BlockExecutive::saveMessage(
std::string address, protocol::ExecutionMessage::UniquePtr message, bool withDAG)
{
updateWeb3NonceMap(message);
registerAndGetDmcExecutor(std::move(address))->submit(std::move(message), withDAG);
}

void BlockExecutive::updateWeb3NonceMap(protocol::ExecutionMessage::UniquePtr const& msg)
{
if (msg->txType() != protocol::TransactionType::BCOSTransaction)
{
if (c_fileLogLevel == TRACE)
{
SCHEDULER_LOG(TRACE) << METRIC << LOG_DESC("fillNonceMap")
<< LOG_KV("sender", msg->from()) << LOG_KV("nonce", msg->nonce());
}
auto sender = std::string(msg->from());
if (auto const nonce = u256(msg->nonce()); m_web3NonceMap[sender] < nonce)
{
m_web3NonceMap.emplace(sender, nonce);
}
}
}

void BlockExecutive::DAGExecute(std::function<void(Error::UniquePtr)> callback)
{
if (!m_isRunning)
Expand Down Expand Up @@ -1026,6 +1044,18 @@ void BlockExecutive::onDmcExecuteFinish(
<< LOG_BADGE("DMCRecorder") << " DMCExecute for transaction finished "
<< LOG_KV("checksum", dmcChecksum);
}
std::unordered_map<std::string, std::unordered_map<std::string, u256>> executorUpdateMap = {};
if (m_scheduler->m_executorManager->size() == 1)
for (auto&& [sender, nonce] : m_web3NonceMap)
{
auto const info = m_scheduler->m_executorManager->getExecutorInfo(sender);
executorUpdateMap[info->name][sender] = nonce;
}
for (auto&& [name, map] : executorUpdateMap)
{
m_scheduler->m_executorManager->getExecutorInfoByName(name)->executor->updateEoaNonce(
std::move(map));
}

onExecuteFinish(std::move(callback));
}
Expand Down
2 changes: 2 additions & 0 deletions bcos-scheduler/src/BlockExecutive.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,11 @@ class BlockExecutive : public std::enable_shared_from_this<BlockExecutive>
bcos::protocol::ConstTransactionsPtr fetchBlockTxsFromTxPool(
bcos::protocol::Block::Ptr block, bcos::txpool::TxPoolInterface::Ptr txPool);
std::string preprocessAddress(const std::string_view& address);
void updateWeb3NonceMap(protocol::ExecutionMessage::UniquePtr const& msg);

std::map<std::string, std::shared_ptr<DmcExecutor>, std::less<>> m_dmcExecutors;
std::shared_ptr<DmcStepRecorder> m_dmcRecorder;
std::unordered_map<std::string, u256> m_web3NonceMap;

std::vector<ExecutiveResult> m_executiveResults;

Expand Down
3 changes: 3 additions & 0 deletions bcos-scheduler/src/SerialBlockExecutive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ void SerialBlockExecutive::prepare()
<< LOG_KV("block number", m_block->blockHeaderConst()->number());
}
m_transactions.resize(txSize);
m_web3NonceMap.clear();

if (m_executor == nullptr)
{
Expand Down Expand Up @@ -196,6 +197,7 @@ void SerialBlockExecutive::serialExecute(
}
}

updateWeb3NonceMap(tx);
SERIAL_EXECUTE_LOG(DEBUG) << BLOCK_NUMBER(number()) << "0.Send:\t >>>> ["
<< m_executorInfo->name << "]: " << tx->toString();
}
Expand Down Expand Up @@ -285,5 +287,6 @@ void SerialBlockExecutive::onExecuteFinish(
<< LOG_KV("receiptsSize", m_executiveResults.size())
<< LOG_KV("blockNumber", number());
}
m_executor->updateEoaNonce(m_web3NonceMap);
BlockExecutive::onExecuteFinish(std::move(callback));
}
Loading

0 comments on commit 80f42b1

Please sign in to comment.