From 0076620097fab85a8f2dc07ad2c5d5a9eb8de044 Mon Sep 17 00:00:00 2001 From: wenlinli <1574249665@qq.com> Date: Tue, 21 May 2024 19:58:45 +0800 Subject: [PATCH 01/16] upgrade evm to cancun (#4332) --- .../workflows/workflow-self-hosted-mac.yml | 2 +- CMakeLists.txt | 1 + bcos-codec/bcos-codec/abi/ContractABIType.cpp | 2 +- bcos-crypto/test/unittests/HashTest.cpp | 14 + bcos-executor/src/Common.h | 10 + bcos-executor/src/executive/BlockContext.cpp | 29 +- bcos-executor/src/executive/BlockContext.h | 14 +- .../src/executive/TransactionExecutive.cpp | 39 + .../src/executive/TransactionExecutive.h | 9 +- .../src/executor/TransactionExecutor.cpp | 9 +- .../src/executor/TransactionExecutor.h | 8 - bcos-executor/src/vm/EVMHostInterface.cpp | 22 + bcos-executor/src/vm/HostContext.cpp | 80 ++ bcos-executor/src/vm/HostContext.h | 2 + bcos-executor/src/vm/Precompiled.cpp | 34 +- bcos-executor/src/vm/VMInstance.cpp | 11 +- bcos-executor/src/vm/kzgPrecompiled.h | 197 +++++ .../unittest/libexecutor/TestBlockContext.cpp | 2 +- .../unittest/libexecutor/TestEVMExecutor.cpp | 768 +++++++++++++++++- .../libexecutor/TestExecutiveStackFlow.cpp | 2 +- .../libexecutor/TestExecutiveState.cpp | 2 +- .../libprecompiled/CryptoPrecompiledTest.cpp | 7 +- .../GroupSigPrecompiledTest.cpp | 4 +- .../libprecompiled/RingSigPrecompiledTest.cpp | 4 +- .../SystemConfigPrecompileTest.cpp | 10 +- .../libprecompiled/VRFPrecompiledTest.cpp | 5 +- .../test/unittest/mock/MockExecutiveFactory.h | 2 +- .../bcos-framework/ledger/Features.h | 1 + .../bcos-framework/storage2/MemoryStorage.h | 3 +- .../unittests/interfaces/FeaturesTest.cpp | 3 +- cmake/ProjectBLST.cmake | 43 + .../TransactionExecutorImpl.h | 20 +- .../precompiled/Precompiled.h | 2 +- .../precompiled/PrecompiledManager.cpp | 3 + .../vm/EVMHostInterface.h | 20 + .../vm/HostContext.cpp | 4 - .../vm/HostContext.h | 105 ++- .../vm/VMInstance.cpp | 11 +- .../tests/StorageContract.sol | 113 +++ transaction-executor/tests/StorageSlot.sol | 193 +++++ transaction-executor/tests/TestBytecode.h | 93 +++ .../tests/TestHostContext.cpp | 39 +- .../tests/TestTransactionExecutor.cpp | 93 +++ vcpkg-configuration.json | 2 +- vcpkg.json | 4 +- 45 files changed, 1933 insertions(+), 108 deletions(-) create mode 100644 bcos-executor/src/vm/kzgPrecompiled.h create mode 100644 cmake/ProjectBLST.cmake create mode 100644 transaction-executor/tests/StorageContract.sol create mode 100644 transaction-executor/tests/StorageSlot.sol diff --git a/.github/workflows/workflow-self-hosted-mac.yml b/.github/workflows/workflow-self-hosted-mac.yml index b871e7c518..7fe7376f18 100644 --- a/.github/workflows/workflow-self-hosted-mac.yml +++ b/.github/workflows/workflow-self-hosted-mac.yml @@ -7,7 +7,7 @@ on: - "README.md" branches: - release-3.* - - feature-3.* + - feature-* - master release: types: [push] diff --git a/CMakeLists.txt b/CMakeLists.txt index cc6956295d..9b825e9a59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,6 +62,7 @@ if(FULLNODE) endif() include(ProjectGroupSig) include(ProjectPaillier) + include(ProjectBLST) add_subdirectory(bcos-sealer) add_subdirectory(bcos-security) diff --git a/bcos-codec/bcos-codec/abi/ContractABIType.cpp b/bcos-codec/bcos-codec/abi/ContractABIType.cpp index a5ea8907ad..3796efb045 100644 --- a/bcos-codec/bcos-codec/abi/ContractABIType.cpp +++ b/bcos-codec/bcos-codec/abi/ContractABIType.cpp @@ -273,7 +273,7 @@ bool ABIFunc::parser(const std::string& _sig) // set function name this->strFuncName = strFuncName; - // set function sigature + // set function signature this->strFuncSignature = sig; return true; diff --git a/bcos-crypto/test/unittests/HashTest.cpp b/bcos-crypto/test/unittests/HashTest.cpp index a7d70d78b3..c612b036e9 100644 --- a/bcos-crypto/test/unittests/HashTest.cpp +++ b/bcos-crypto/test/unittests/HashTest.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -122,6 +123,19 @@ BOOST_AUTO_TEST_CASE(testSha3) BOOST_REQUIRE_EQUAL(cryptoSuite->hash("hello"sv), h256("3338be694f50c5f338814986cdf0686453a888b84f424d792af4b9202398f392")); } + +BOOST_AUTO_TEST_CASE(SHA256_test) { + HashType hash; + auto sha256 = std::make_shared(); + bcos::bytes input{}; + hash = sha256->hash(bcos::ref(input)); + BOOST_CHECK_EQUAL(hash.hex(), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + + std::string data = "1234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678"; + input += bcos::fromHex(data); + hash = sha256->hash(bcos::ref(input)); + BOOST_REQUIRE_EQUAL(hash.hex(), "7303caef875be8c39b2c2f1905ea24adcc024bef6830a965fe05370f3170dc52"); +} BOOST_AUTO_TEST_SUITE_END() } // namespace test } // namespace bcos diff --git a/bcos-executor/src/Common.h b/bcos-executor/src/Common.h index df30634814..bffe69b923 100644 --- a/bcos-executor/src/Common.h +++ b/bcos-executor/src/Common.h @@ -167,6 +167,7 @@ struct VMSchedule bool exceptionalFailedCodeDeposit = true; bool enableLondon = true; bool enablePairs = false; + bool enableCanCun = false; unsigned sstoreRefundGas = 15000; unsigned suicideRefundGas = 24000; unsigned createDataGas = 20; @@ -187,6 +188,15 @@ static const VMSchedule FiscoBcosScheduleV320 = [] { return schedule; }(); +static const VMSchedule FiscoBcosScheduleCancun = [] { + VMSchedule schedule = VMSchedule(); + schedule.enablePairs = false; + schedule.enableCanCun = true; + schedule.maxEvmCodeSize = 0x100000; // 1MB + schedule.maxWasmCodeSize = 0xF00000; // 15MB + return schedule; +}(); + static const int64_t BALANCE_TRANSFER_GAS = 21000; constexpr evmc_gas_metrics ethMetrics{32000, 20000, 5000, 200, 9000, 2300, 25000}; diff --git a/bcos-executor/src/executive/BlockContext.cpp b/bcos-executor/src/executive/BlockContext.cpp index a5ae418167..847c3ec8c4 100644 --- a/bcos-executor/src/executive/BlockContext.cpp +++ b/bcos-executor/src/executive/BlockContext.cpp @@ -45,16 +45,16 @@ using namespace std; BlockContext::BlockContext(std::shared_ptr storage, LedgerCache::Ptr ledgerCache, crypto::Hash::Ptr _hashImpl, bcos::protocol::BlockNumber blockNumber, h256 blockHash, uint64_t timestamp, - uint32_t blockVersion, const VMSchedule& _schedule, bool _isWasm, bool _isAuthCheck, + uint32_t blockVersion, bool _isWasm, bool _isAuthCheck, storage::StorageInterface::Ptr backendStorage) : m_blockNumber(blockNumber), m_blockHash(blockHash), m_timeStamp(timestamp), m_blockVersion(blockVersion), - m_schedule(_schedule), m_isWasm(_isWasm), m_isAuthCheck(_isAuthCheck), m_storage(std::move(storage)), + m_transientStorageMap(std::make_shared(10)), m_hashImpl(std::move(_hashImpl)), m_ledgerCache(std::move(ledgerCache)), m_backendStorage(std::move(backendStorage)) @@ -66,16 +66,17 @@ BlockContext::BlockContext(std::shared_ptr stora } task::syncWait(m_features.readFromStorage(*m_storage, m_blockNumber)); + setVMSchedule(); } BlockContext::BlockContext(std::shared_ptr storage, LedgerCache::Ptr ledgerCache, crypto::Hash::Ptr _hashImpl, - protocol::BlockHeader::ConstPtr _current, const VMSchedule& _schedule, bool _isWasm, - bool _isAuthCheck, storage::StorageInterface::Ptr backendStorage, + protocol::BlockHeader::ConstPtr _current, bool _isWasm, bool _isAuthCheck, + storage::StorageInterface::Ptr backendStorage, std::shared_ptr>> _keyPageIgnoreTables) : BlockContext(std::move(storage), std::move(ledgerCache), std::move(_hashImpl), - _current->number(), _current->hash(), _current->timestamp(), _current->version(), _schedule, - _isWasm, _isAuthCheck, std::move(backendStorage)) + _current->number(), _current->hash(), _current->timestamp(), _current->version(), _isWasm, + _isAuthCheck, std::move(backendStorage)) { if (_current->number() > 0 && !_current->parentInfo().empty()) { @@ -102,6 +103,7 @@ BlockContext::BlockContext(std::shared_ptr stora } } } + setVMSchedule(); } @@ -128,6 +130,21 @@ void BlockContext::setExecutiveFlow( bcos::ReadGuard l(x_executiveFlows); m_executiveFlows.emplace(codeAddress, executiveFlow); } +void BlockContext::setVMSchedule() +{ + if (m_features.get(ledger::Features::Flag::feature_evm_cancun)) + { + m_schedule = FiscoBcosScheduleCancun; + } + else if (m_blockVersion >= (uint32_t)bcos::protocol::BlockVersion::V3_2_VERSION) + { + m_schedule = FiscoBcosScheduleV320; + } + else + { + m_schedule = FiscoBcosSchedule; + } +} void BlockContext::suicide(std::string_view contract2Suicide) { diff --git a/bcos-executor/src/executive/BlockContext.h b/bcos-executor/src/executive/BlockContext.h index 0764a51896..305042cd30 100644 --- a/bcos-executor/src/executive/BlockContext.h +++ b/bcos-executor/src/executive/BlockContext.h @@ -32,6 +32,7 @@ #include "bcos-framework/storage/EntryCache.h" #include "bcos-framework/storage/Table.h" #include "bcos-table/src/StateStorage.h" +#include "bcos-utilities/BucketMap.h" #include #include #include @@ -52,13 +53,13 @@ class BlockContext : public std::enable_shared_from_this BlockContext(std::shared_ptr storage, LedgerCache::Ptr ledgerCache, crypto::Hash::Ptr _hashImpl, bcos::protocol::BlockNumber blockNumber, h256 blockHash, uint64_t timestamp, - uint32_t blockVersion, const VMSchedule& _schedule, bool _isWasm, bool _isAuthCheck, + uint32_t blockVersion, bool _isWasm, bool _isAuthCheck, storage::StorageInterface::Ptr backendStorage = nullptr); BlockContext(std::shared_ptr storage, LedgerCache::Ptr ledgerCache, crypto::Hash::Ptr _hashImpl, - protocol::BlockHeader::ConstPtr _current, const VMSchedule& _schedule, bool _isWasm, - bool _isAuthCheck, storage::StorageInterface::Ptr backendStorage = nullptr, + protocol::BlockHeader::ConstPtr _current, bool _isWasm, bool _isAuthCheck, + storage::StorageInterface::Ptr backendStorage = nullptr, std::shared_ptr>> = nullptr); using getTxCriticalsHandler = std::function>( @@ -66,6 +67,11 @@ class BlockContext : public std::enable_shared_from_this virtual ~BlockContext() = default; std::shared_ptr storage() const { return m_storage; } + using transientStorageMap = BucketMap>; + std::shared_ptr getTransientStorageMap() const + { + return m_transientStorageMap; + } uint64_t txGasLimit() const { return m_ledgerCache->fetchTxGasLimit(); } @@ -90,6 +96,7 @@ class BlockContext : public std::enable_shared_from_this void setExecutiveFlow(std::string codeAddress, ExecutiveFlowInterface::Ptr executiveFlow); std::shared_ptr getVMFactory() const { return m_vmFactory; } + void setVMSchedule(); void setVMFactory(std::shared_ptr factory) { m_vmFactory = factory; } void stop() @@ -151,6 +158,7 @@ class BlockContext : public std::enable_shared_from_this bool m_isWasm = false; bool m_isAuthCheck = false; std::shared_ptr m_storage; + transientStorageMap::Ptr m_transientStorageMap; crypto::Hash::Ptr m_hashImpl; std::function f_onNeedSwitchEvent; std::shared_ptr>> m_keyPageIgnoreTables; diff --git a/bcos-executor/src/executive/TransactionExecutive.cpp b/bcos-executor/src/executive/TransactionExecutive.cpp index 86adf23b2c..598e33ac9d 100644 --- a/bcos-executor/src/executive/TransactionExecutive.cpp +++ b/bcos-executor/src/executive/TransactionExecutive.cpp @@ -216,6 +216,8 @@ CallParameters::UniquePtr TransactionExecutive::execute(CallParameters::UniquePt << LOG_KV("blockNumber", m_blockContext.number()); } m_storageWrapper->setRecoder(m_recoder); + auto transientStorage = getTransientStateStorage(m_contextID); + transientStorage->setRecoder(m_transientRecoder); std::unique_ptr hostContext; CallParameters::UniquePtr callResults; if (c_fileLogLevel <= LogLevel::TRACE) @@ -1374,6 +1376,8 @@ void TransactionExecutive::revert() } m_blockContext.storage()->rollback(*m_recoder); + auto transientStateStorage = getTransientStateStorage(m_contextID); + transientStateStorage->rollback(*m_transientRecoder); m_recoder->clear(); } @@ -1875,3 +1879,38 @@ std::string TransactionExecutive::getContractTableName( return std::string(USER_APPS_PREFIX).append(formatAddress); } + +std::shared_ptr TransactionExecutive::getTransientStateStorage( + int64_t contextID) +{ + auto transientStorageMap = blockContext().getTransientStorageMap(); + bcos::storage::StateStorageInterface::Ptr transientStorage; + bool has; + { + tssMap::ReadAccessor::Ptr readAccessor; + has = transientStorageMap->find(readAccessor, contextID); + if (has) + { + transientStorage = readAccessor->value(); + } + } + if (!has) + { + { + tssMap::WriteAccessor::Ptr writeAccessor; + auto hasWrite = + transientStorageMap->find(writeAccessor, contextID); + + if (!hasWrite) + { + transientStorage = std::make_shared(nullptr); + transientStorageMap->insert(writeAccessor, {contextID, transientStorage}); + } + else + { + transientStorage = writeAccessor->value(); + } + } + } + return transientStorage; +} diff --git a/bcos-executor/src/executive/TransactionExecutive.h b/bcos-executor/src/executive/TransactionExecutive.h index 131b307d34..ebee2e9cdc 100644 --- a/bcos-executor/src/executive/TransactionExecutive.h +++ b/bcos-executor/src/executive/TransactionExecutive.h @@ -32,6 +32,7 @@ #include "bcos-framework/protocol/BlockHeader.h" #include "bcos-framework/protocol/Transaction.h" #include "bcos-protocol/TransactionStatus.h" +#include "bcos-table/src/StateStorage.h" #include #include #include @@ -65,10 +66,11 @@ class TransactionExecutive : public std::enable_shared_from_this()), + m_transientRecoder(std::make_shared()), m_storageWrapperObj(m_blockContext.storage(), m_recoder), m_storageWrapper(&m_storageWrapperObj) { - m_recoder = std::make_shared(); m_hashImpl = m_blockContext.hashHandler(); m_storageWrapperObj.setCodeCache(m_blockContext.getCodeCache()); m_storageWrapperObj.setCodeHashCache(m_blockContext.getCodeHashCache()); @@ -92,6 +94,7 @@ class TransactionExecutive : public std::enable_shared_from_this execPrecompiled( precompiled::PrecompiledExecResult::Ptr const& _precompiledParams); + using tssMap = bcos::BucketMap>; VMSchedule const& vmSchedule() const { return m_blockContext.vmSchedule(); } @@ -166,6 +170,8 @@ class TransactionExecutive : public std::enable_shared_from_this getTransientStateStorage(int64_t contextID); + std::shared_ptr getRecoder() { return m_recoder; } protected: @@ -224,6 +230,7 @@ class TransactionExecutive : public std::enable_shared_from_this m_childExecutives; storage::StorageWrapper m_storageWrapperObj; diff --git a/bcos-executor/src/executor/TransactionExecutor.cpp b/bcos-executor/src/executor/TransactionExecutor.cpp index c059b380f5..4fda0a262a 100644 --- a/bcos-executor/src/executor/TransactionExecutor.cpp +++ b/bcos-executor/src/executor/TransactionExecutor.cpp @@ -60,8 +60,10 @@ #include "../vm/gas_meter/GasInjector.h" #endif +#include "../Common.h" #include "ExecuteOutputs.h" #include "bcos-codec/abi/ContractABIType.h" +#include "bcos-executor/src/executive/BlockContext.h" #include "bcos-executor/src/precompiled/common/Common.h" #include "bcos-executor/src/precompiled/common/PrecompiledResult.h" #include "bcos-executor/src/precompiled/common/Utilities.h" @@ -76,6 +78,7 @@ #include "bcos-table/src/KeyPageStorage.h" #include "bcos-table/src/StateStorage.h" #include "bcos-table/src/StateStorageFactory.h" +#include "bcos-task/Wait.h" #include "bcos-tool/BfsFileFactory.h" #include "tbb/flow_graph.h" #include @@ -401,8 +404,7 @@ BlockContext::Ptr TransactionExecutor::createBlockContext( backend = m_cachedStorage; } BlockContext::Ptr context = make_shared(storage, m_ledgerCache, m_hashImpl, - currentHeader, getVMSchedule((uint32_t)currentHeader->version()), m_isWasm, m_isAuthCheck, - std::move(backend), m_keyPageIgnoreTables); + currentHeader, m_isWasm, m_isAuthCheck, std::move(backend), m_keyPageIgnoreTables); context->setVMFactory(m_vmFactory); if (f_onNeedSwitchEvent) { @@ -417,8 +419,7 @@ std::shared_ptr TransactionExecutor::createBlockContextForCall( int32_t blockVersion, storage::StateStorageInterface::Ptr storage) { BlockContext::Ptr context = make_shared(storage, m_ledgerCache, m_hashImpl, - blockNumber, blockHash, timestamp, blockVersion, getVMSchedule((uint32_t)blockVersion), - m_isWasm, m_isAuthCheck); + blockNumber, blockHash, timestamp, blockVersion, m_isWasm, m_isAuthCheck); context->setVMFactory(m_vmFactory); return context; } diff --git a/bcos-executor/src/executor/TransactionExecutor.h b/bcos-executor/src/executor/TransactionExecutor.h index 25bb568f47..cee15dee12 100644 --- a/bcos-executor/src/executor/TransactionExecutor.h +++ b/bcos-executor/src/executor/TransactionExecutor.h @@ -333,14 +333,6 @@ class TransactionExecutor : public ParallelTransactionExecutorInterface, void initWasmEnvironment(); void resetEnvironment(); void initTestPrecompiledTable(storage::StorageInterface::Ptr storage); - VMSchedule getVMSchedule(uint32_t currentVersion) const - { - if (currentVersion >= (uint32_t)bcos::protocol::BlockVersion::V3_2_VERSION) - { - return FiscoBcosScheduleV320; - } - return FiscoBcosSchedule; - } std::function f_onNeedSwitchEvent; LedgerCache::Ptr m_ledgerCache; diff --git a/bcos-executor/src/vm/EVMHostInterface.cpp b/bcos-executor/src/vm/EVMHostInterface.cpp index affe1ff404..1cbcb49e9e 100644 --- a/bcos-executor/src/vm/EVMHostInterface.cpp +++ b/bcos-executor/src/vm/EVMHostInterface.cpp @@ -68,6 +68,18 @@ evmc_bytes32 getStorage( return hostContext.store(key); } +evmc_bytes32 getTransientStorage( + evmc_host_context* context, [[maybe_unused]] const evmc_address* addr, const evmc_bytes32* key) +{ + auto& hostContext = static_cast(*context); + + // programming assert for debug + assert(fromEvmC(*addr) == boost::algorithm::unhex(std::string(hostContext.myAddress()))); + + return hostContext.getTransientStorage(key); +} + + evmc_storage_status setStorage(evmc_host_context* context, [[maybe_unused]] const evmc_address* addr, const evmc_bytes32* key, const evmc_bytes32* value) { @@ -85,6 +97,14 @@ evmc_storage_status setStorage(evmc_host_context* context, return status; } +void setTransientStorage(evmc_host_context* context, [[maybe_unused]] const evmc_address* addr, + const evmc_bytes32* key, const evmc_bytes32* value) +{ + auto& hostContext = static_cast(*context); + hostContext.setTransientStorage(key, value); // Interface uses native endianness +} + + evmc_bytes32 getBalance(evmc_host_context* _context, const evmc_address* _addr) noexcept { auto& hostContext = static_cast(*_context); @@ -281,6 +301,8 @@ evmc_host_interface const fnTable = { log, access_account, access_storage, + getTransientStorage, + setTransientStorage, }; // clang-format on diff --git a/bcos-executor/src/vm/HostContext.cpp b/bcos-executor/src/vm/HostContext.cpp index 9f0369406f..0b2542f1f1 100644 --- a/bcos-executor/src/vm/HostContext.cpp +++ b/bcos-executor/src/vm/HostContext.cpp @@ -559,6 +559,36 @@ evmc_bytes32 HostContext::store(const evmc_bytes32* key) } return result; } +evmc_bytes32 HostContext::getTransientStorage(const evmc_bytes32* key) +{ + evmc_bytes32 result; + auto keyView = std::string_view((char*)key->bytes, sizeof(key->bytes)); + + auto transientStorageMap = m_executive->blockContext().getTransientStorageMap(); + using TSMap = bcos::BucketMap>; + TSMap::ReadAccessor::Ptr readAccessor; + auto has = + transientStorageMap->find(readAccessor, m_executive->contextID()); + if (!has) + { + EXECUTOR_LOG(DEBUG) << LOG_DESC("get transient storage failed") + << LOG_KV("transientStorageMapKey", m_executive->contextID()) + << LOG_KV("key", keyView); + std::uninitialized_fill_n(result.bytes, sizeof(result), 0); + return result; + } + auto entry = readAccessor->value()->getRow(m_tableName, keyView); + if (!entry.first) + { + auto field = entry.second->getField(0); + std::uninitialized_copy_n(field.data(), sizeof(result), result.bytes); + } + else + { + std::uninitialized_fill_n(result.bytes, sizeof(result), 0); + } + return result; +} void HostContext::setStore(const evmc_bytes32* key, const evmc_bytes32* value) { @@ -570,6 +600,56 @@ void HostContext::setStore(const evmc_bytes32* key, const evmc_bytes32* value) m_executive->storage().setRow(m_tableName, keyView, std::move(entry)); } +void HostContext::setTransientStorage(const evmc_bytes32* key, const evmc_bytes32* value) +{ + auto keyView = std::string_view((char*)key->bytes, sizeof(key->bytes)); + bytes valueBytes(value->bytes, value->bytes + sizeof(value->bytes)); + + Entry entry; + entry.importFields({std::move(valueBytes)}); + + auto transientStorageMap = m_executive->blockContext().getTransientStorageMap(); + using TSMap = bcos::BucketMap>; + bcos::storage::StateStorageInterface::Ptr transientStorage; + + bool has; + { + TSMap::ReadAccessor::Ptr readAccessor; + has = + transientStorageMap->find(readAccessor, m_executive->contextID()); + if (has) + { + transientStorage = readAccessor->value(); + } + } + if (!has) + { + { + TSMap::WriteAccessor::Ptr writeAccessor; + auto hasWrite = transientStorageMap->find( + writeAccessor, m_executive->contextID()); + if (!hasWrite) // if not another write access, create a new one + { + transientStorage = std::make_shared(nullptr); + transientStorageMap->insert( + writeAccessor, {m_executive->contextID(), transientStorage}); + } + else // if another write access, use the same storage + { + transientStorage = writeAccessor->value(); + } + } + } + + transientStorage->asyncSetRow(m_tableName, keyView, std::move(entry), [](auto&& error) { + if (error) + { + EXECUTOR_LOG(ERROR) << LOG_DESC("set transient storage failed") + << LOG_KV("error", error); + } + }); +} + void HostContext::log(h256s&& _topics, bytesConstRef _data) { // if (m_isWasm || myAddress().empty()) diff --git a/bcos-executor/src/vm/HostContext.h b/bcos-executor/src/vm/HostContext.h index 2384228118..851fbf0c32 100644 --- a/bcos-executor/src/vm/HostContext.h +++ b/bcos-executor/src/vm/HostContext.h @@ -64,10 +64,12 @@ class HostContext : public evmc_host_context /// Read storage location. evmc_bytes32 store(const evmc_bytes32* key); + evmc_bytes32 getTransientStorage(const evmc_bytes32* key); /// Write a value in storage. // void setStore(const u256& _n, const u256& _v); void setStore(const evmc_bytes32* key, const evmc_bytes32* value); + void setTransientStorage(const evmc_bytes32* key, const evmc_bytes32* value); /// Create a new contract. evmc_result externalRequest(const evmc_message* _msg); diff --git a/bcos-executor/src/vm/Precompiled.cpp b/bcos-executor/src/vm/Precompiled.cpp index ad50d97b7a..c3930dc63e 100644 --- a/bcos-executor/src/vm/Precompiled.cpp +++ b/bcos-executor/src/vm/Precompiled.cpp @@ -24,12 +24,12 @@ #include "bcos-crypto/hash/Keccak256.h" #include "bcos-crypto/signature/codec/SignatureDataWithV.h" #include "bcos-crypto/signature/secp256k1/Secp256k1Crypto.h" +#include "kzgPrecompiled.h" #include "wedpr-crypto/WedprBn128.h" #include "wedpr-crypto/WedprCrypto.h" #include #include - using namespace std; using namespace bcos; using namespace bcos::crypto; @@ -287,6 +287,37 @@ ETH_REGISTER_PRECOMPILED_PRICER(blake2_compression) return rounds; } +// ETH_REGISTER_PRECOMPILED(point_evaluation)(bytesConstRef _in) +//{ +// static constexpr size_t versioned_hash_size = 32; +// static constexpr size_t z_end_bound = 64; +// static constexpr size_t y_end_bound = 96; +// static constexpr size_t commitment_end_bound = 144; +// static constexpr size_t proof_end_bound = 192; +// +// if(_in.size() != 192) +// return {false, {}}; +// +// auto const versioned_hash = _in.getCroppedData(0, versioned_hash_size); +// auto const z = _in.getCroppedData(versioned_hash_size, z_end_bound); +// auto const y = _in.getCroppedData(z_end_bound, y_end_bound); +// auto const commitment = _in.getCroppedData(y_end_bound, commitment_end_bound); +// auto const proof = _in.getCroppedData(commitment_end_bound, proof_end_bound); +// +// auto kzg = make_shared(); +// if(kzg->kzg2VersionedHash(commitment) != sha256(versioned_hash)) +// return {false, {}}; +// +// if(!kzg->verifyKZGProof(proof, commitment, z, y)) +// return {false, {}}; +// +// return {true, {}}; +// } +// +// ETH_REGISTER_PRECOMPILED_PRICER(point_evaluation)(bytesConstRef _in) +//{ +// return 45000; +// } } // namespace @@ -346,6 +377,7 @@ struct blake2b_state uint8_t last_node; }; + // clang-format off constexpr uint64_t blake2b_IV[8] = { diff --git a/bcos-executor/src/vm/VMInstance.cpp b/bcos-executor/src/vm/VMInstance.cpp index 1f9dc3d262..ac96fe3e0d 100644 --- a/bcos-executor/src/vm/VMInstance.cpp +++ b/bcos-executor/src/vm/VMInstance.cpp @@ -20,10 +20,9 @@ */ #include "VMInstance.h" - #include "HostContext.h" -#include "evmone/advanced_analysis.hpp" #include "evmone/advanced_execution.hpp" +#include "evmone/execution_state.hpp" #include using namespace std; @@ -60,8 +59,8 @@ Result VMInstance::execute(HostContext& _hostContext, evmc_message* _msg) return Result(m_instance->execute(m_instance, _hostContext.interface, &_hostContext, m_revision, _msg, m_code.data(), m_code.size())); } - auto state = std::make_unique( - *_msg, m_revision, *_hostContext.interface, &_hostContext, m_code); + auto state = std::unique_ptr(new evmone::ExecutionState( + *_msg, m_revision, *_hostContext.interface, &_hostContext, m_code, {})); { // baseline static auto* evm = evmc_create_evmone(); // baseline use the vm to get options return Result(evmone::baseline::execute( @@ -77,6 +76,10 @@ evmc_revision toRevision(VMSchedule const& _schedule) { return EVMC_PARIS; } + if (_schedule.enableCanCun) + { + return EVMC_CANCUN; + } return EVMC_LONDON; } } // namespace bcos::executor diff --git a/bcos-executor/src/vm/kzgPrecompiled.h b/bcos-executor/src/vm/kzgPrecompiled.h new file mode 100644 index 0000000000..7f79332b8f --- /dev/null +++ b/bcos-executor/src/vm/kzgPrecompiled.h @@ -0,0 +1,197 @@ +///* +//* Copyright (C) 2021 FISCO BCOS. +//* SPDX-License-Identifier: Apache-2.0 +//* Licensed under the Apache License, Version 2.0 (the "License"); +//* you may not use this file except in compliance with the License. +//* You may obtain a copy of the License at +//* +//* http://www.apache.org/licenses/LICENSE-2.0 +//* +//* Unless required by applicable law or agreed to in writing, software +//* distributed under the License is distributed on an "AS IS" BASIS, +//* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//* See the License for the specific language governing permissions and +//* limitations under the License. +//* +//* @brief factory of vm +//* @file KZGPrecompiled.h +//* @author: wenlinli +//* @date: 2024-04-29 +// */ +// +// #pragma once +// #include +// #include +// #include +// #include +// #include +// #include +// +// +// namespace bcos::executor +//{ +// +// inline constexpr uint8_t kBlobCommitmentVersionKzg{1}; +// +// namespace crypto +//{ +// +// class kzgPrecompiled +//{ +// public: +// using Ptr = std::shared_ptr; +// using G1 = blst_p1; +// using G2 = blst_p2; +// using Fr = blst_fr; +// +// +// static bool pairings_verify( +// const G1* a1, const G2* a2, const G1* b1, const G2* b2) { +// blst_fp12 loop0, loop1, gt_point; +// blst_p1_affine aa1, bb1; +// blst_p2_affine aa2, bb2; +// +// G1 a1neg = *a1; +// blst_p1_cneg(&a1neg, true); +// +// blst_p1_to_affine(&aa1, &a1neg); +// blst_p1_to_affine(&bb1, b1); +// blst_p2_to_affine(&aa2, a2); +// blst_p2_to_affine(&bb2, b2); +// +// blst_miller_loop(&loop0, &aa2, &aa1); +// blst_miller_loop(&loop1, &bb2, &bb1); +// +// blst_fp12_mul(>_point, &loop0, &loop1); +// blst_final_exp(>_point, >_point); +// +// return blst_fp12_is_one(>_point); +// } +// +// static void g1_mul(G1* out, const G1* a, const Fr* b) { +// blst_scalar s; +// blst_scalar_from_fr(&s, b); +// blst_p1_mult(out, a, s.b, 8 * sizeof(blst_scalar)); +// } +// +// +// static void g2_mul(G2* out, const G2* a, const Fr* b) { +// blst_scalar s; +// blst_scalar_from_fr(&s, b); +// blst_p2_mult(out, a, s.b, 8 * sizeof(blst_scalar)); +// } +// +// +// static void g1_sub(G1* out, const G1* a, const G1* b) { +// G1 bneg = *b; +// blst_p1_cneg(&bneg, true); +// blst_p1_add_or_double(out, a, &bneg); +// } +// +// +// static void g2_sub(G2* out, const G2* a, const G2* b) { +// G2 bneg = *b; +// blst_p2_cneg(&bneg, true); +// blst_p2_add_or_double(out, a, &bneg); +// } +// +// constexpr static const G2 kKzgSetupG2_1{ +// {{{0x6120a2099b0379f9, 0xa2df815cb8210e4e, 0xcb57be5577bd3d4f, +// 0x62da0ea89a0c93f8, 0x02e0ee16968e150d, 0x171f09aea833acd5}, +// {0x11a3670749dfd455, 0x04991d7b3abffadc, 0x85446a8e14437f41, +// 0x27174e7b4e76e3f2, 0x7bfa6dd397f60a20, 0x02fcc329ac07080f}}}, +// {{{0xaa130838793b2317, 0xe236dd220f891637, 0x6502782925760980, +// 0xd05c25f60557ec89, 0x6095767a44064474, 0x185693917080d405}, +// {0x549f9e175b03dc0a, 0x32c0c95a77106cfe, 0x64a74eae5705d080, +// 0x53deeaf56659ed9e, 0x09a1d368508afb93, 0x12cf3a4525b5e9bd}}}, +// {{{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, +// 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}, +// {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, +// 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}} +// }; +// +// +// static bool validate_kzg_g1(G1* out, bytesConstRef b) { +// blst_p1_affine p1_affine; +// +// /* Convert the bytes to a p1 point */ +// /* The uncompress routine checks that the point is on the curve */ +// if (blst_p1_uncompress(&p1_affine, b.data()) != BLST_SUCCESS) { +// return false; +// } +// blst_p1_from_affine(out, &p1_affine); +// +// /* The point at infinity is accepted! */ +// if (blst_p1_is_inf(out)) { +// return true; +// } +// +// /* The point must be on the right subgroup */ +// return blst_p1_in_g1(out); +// } +// +// static bool bytes_to_bls_field(Fr* out, bytesConstRef b) { +// blst_scalar tmp; +// blst_scalar_from_bendian(&tmp, b.data()); +// if (!blst_scalar_fr_check(&tmp)) { +// return false; +// } +// blst_fr_from_scalar(out, &tmp); +// return true; +// } +// +// +// bcos::crypto::HashType kzg2VersionedHash(bytesConstRef input){ +// bcos::crypto::HashType hash; +// hash = bcos::crypto::sha256Hash(input); +// return hash; +// } +// +// bool verifyKZGProof(bytesConstRef commitment, +// bytesConstRef z, +// bytesConstRef y, +// bytesConstRef proof){ +// Fr z_fr, y_fr; +// G1 commitment_g1, proof_g1; +// +// if (!validate_kzg_g1(&commitment_g1, commitment)) { +// return false; +// } +// if (!bytes_to_bls_field(&z_fr, z)) { +// return false; +// } +// if (!bytes_to_bls_field(&y_fr, y)) { +// return false; +// } +// if (!validate_kzg_g1(&proof_g1, proof)) { +// return false; +// } +// +// return verifyKZGProofImpl( +// &commitment_g1, &z_fr, &y_fr, &proof_g1); +// } +// +// static bool verifyKZGProofImpl(const G1* commitment, +// const Fr* z, +// const Fr* y, +// const G1* proof){ +// G2 x_g2, X_minus_z; +// G1 y_g1, P_minus_y; +// +// /* Calculate: X_minus_z */ +// g2_mul(&x_g2, blst_p2_generator(), z); +// g2_sub(&X_minus_z, &kKzgSetupG2_1, &x_g2); +// +// /* Calculate: P_minus_y */ +// g1_mul(&y_g1, blst_p1_generator(), y); +// g1_sub(&P_minus_y, commitment, &y_g1); +// +// /* Verify: P - y = Q * (X - z) */ +// return pairings_verify(&P_minus_y, blst_p2_generator(), proof, &X_minus_z); +// } +//}; +// +//} // namespace crypto +//} // namespace bcos::executor +// +// diff --git a/bcos-executor/test/unittest/libexecutor/TestBlockContext.cpp b/bcos-executor/test/unittest/libexecutor/TestBlockContext.cpp index 8c707543b3..3b74d9c8d8 100644 --- a/bcos-executor/test/unittest/libexecutor/TestBlockContext.cpp +++ b/bcos-executor/test/unittest/libexecutor/TestBlockContext.cpp @@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE(BlockContextTest) LedgerCache::Ptr ledgerCache = std::make_shared(std::make_shared()); BlockContext::Ptr blockContext = std::make_shared( - nullptr, ledgerCache, nullptr, 0, h256(), 0, 0, FiscoBcosSchedule, false, false); + nullptr, ledgerCache, nullptr, 0, h256(), 0, 0, false, false); h256 blockhash = blockContext->hash(); EXECUTOR_LOG(DEBUG) << blockhash; diff --git a/bcos-executor/test/unittest/libexecutor/TestEVMExecutor.cpp b/bcos-executor/test/unittest/libexecutor/TestEVMExecutor.cpp index cf5db000d0..57a42e4117 100644 --- a/bcos-executor/test/unittest/libexecutor/TestEVMExecutor.cpp +++ b/bcos-executor/test/unittest/libexecutor/TestEVMExecutor.cpp @@ -27,10 +27,15 @@ #include "bcos-framework/bcos-framework/testutils/faker/FakeBlockHeader.h" #include "bcos-framework/bcos-framework/testutils/faker/FakeTransaction.h" #include "bcos-framework/executor/ExecutionMessage.h" +#include "bcos-framework/ledger/Features.h" +#include "bcos-framework/ledger/LedgerTypeDef.h" #include "bcos-framework/protocol/ProtocolTypeDef.h" #include "bcos-framework/protocol/Transaction.h" +#include "bcos-framework/storage/Entry.h" #include "bcos-table/src/StateStorage.h" #include "bcos-table/src/StateStorageFactory.h" +#include "bcos-task/Task.h" +#include "bcos-task/Wait.h" #include "evmc/evmc.h" #include "executor/TransactionExecutorFactory.h" #include @@ -86,7 +91,6 @@ struct TransactionExecutorFixture executor = bcos::executor::TransactionExecutorFactory::build(ledger, txpool, lruStorage, backend, executionResultFactory, stateStorageFactory, hashImpl, false, false); - keyPair = cryptoSuite->signatureImpl()->generateKeyPair(); memcpy(keyPair->secretKey()->mutableData(), fromHexString("ff6f30856ad3bae00b1169808488502786a13e3c174d85682135ffd51310310e") @@ -1809,6 +1813,768 @@ contract HelloWorld { executePromise3.get_future().get(); } +BOOST_AUTO_TEST_CASE(transientStorageTest) +{ + // test opcode tstore and tload, contracts: + // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/StorageSlot.sol + std::string transientCodeBin = + "60806040526100337fbad128a9c9f118267291de46fed9cb24d9fbbe19a927cfee43cdc3b8e4eba17161010e60" + "201b60201c565b5f556100647fe51529ae218841954601d43f697e9bb24b282c1a2ddf95745a7e79ee1b4b7b7d" + "61011760201b60201c565b6001556100967f5d4010ae4473cd3ede543746d54ec6f990232434c2d4884f06e3cc" + "4ac77168e561012060201b60201c565b6002556100c87fb734117ebc01eac75f020b05b2620ab71735dfa2175a" + "c8e98f85bd7f529bb96f61012960201b60201c565b6003556100fa7feb7753d6e9a22bf47d9682cdc6f111b5de" + "fde6c206047689bad23120af3743bd61013260201b60201c565b600455348015610108575f80fd5b5061013b56" + "5b5f819050919050565b5f819050919050565b5f819050919050565b5f819050919050565b5f81905091905056" + "5b6105e3806101485f395ff3fe608060405234801561000f575f80fd5b506004361061009c575f3560e01c8063" + "c2b12a7311610064578063c2b12a7314610134578063d2282dc514610150578063e30081a01461016c578063f5" + "b53e1714610188578063f8462a0f146101a65761009c565b80631f903037146100a05780632d1be94d146100be" + "57806338cc4831146100dc57806368895979146100fa578063a53b1c1e14610118575b5f80fd5b6100a86101c2" + "565b6040516100b591906102fa565b60405180910390f35b6100c66101d3565b6040516100d3919061032d565b" + "60405180910390f35b6100e46101e4565b6040516100f19190610385565b60405180910390f35b6101026101f4" + "565b60405161010f91906103b6565b60405180910390f35b610132600480360381019061012d9190610406565b" + "610205565b005b61014e6004803603810190610149919061045b565b61021d565b005b61016a60048036038101" + "9061016591906104b0565b610235565b005b61018660048036038101906101819190610505565b61024d565b00" + "5b610190610264565b60405161019d919061053f565b60405180910390f35b6101c060048036038101906101bb" + "9190610582565b610275565b005b5f6101ce60025461028d565b905090565b5f6101df600154610297565b9050" + "90565b5f6101ef5f546102a1565b905090565b5f6102006003546102ab565b905090565b61021a816004546102" + "b590919063ffffffff16565b50565b610232816002546102bc90919063ffffffff16565b50565b61024a816003" + "546102c390919063ffffffff16565b50565b610261815f546102ca90919063ffffffff16565b50565b5f610270" + "6004546102d1565b905090565b61028a816001546102db90919063ffffffff16565b50565b5f815c9050919050" + "565b5f815c9050919050565b5f815c9050919050565b5f815c9050919050565b80825d5050565b80825d505056" + "5b80825d5050565b80825d5050565b5f815c9050919050565b80825d5050565b5f819050919050565b6102f481" + "6102e2565b82525050565b5f60208201905061030d5f8301846102eb565b92915050565b5f8115159050919050" + "565b61032781610313565b82525050565b5f6020820190506103405f83018461031e565b92915050565b5f73ff" + "ffffffffffffffffffffffffffffffffffffff82169050919050565b5f61036f82610346565b9050919050565b" + "61037f81610365565b82525050565b5f6020820190506103985f830184610376565b92915050565b5f81905091" + "9050565b6103b08161039e565b82525050565b5f6020820190506103c95f8301846103a7565b92915050565b5f" + "80fd5b5f819050919050565b6103e5816103d3565b81146103ef575f80fd5b50565b5f81359050610400816103" + "dc565b92915050565b5f6020828403121561041b5761041a6103cf565b5b5f610428848285016103f2565b9150" + "5092915050565b61043a816102e2565b8114610444575f80fd5b50565b5f8135905061045581610431565b9291" + "5050565b5f602082840312156104705761046f6103cf565b5b5f61047d84828501610447565b91505092915050" + "565b61048f8161039e565b8114610499575f80fd5b50565b5f813590506104aa81610486565b92915050565b5f" + "602082840312156104c5576104c46103cf565b5b5f6104d28482850161049c565b91505092915050565b6104e4" + "81610365565b81146104ee575f80fd5b50565b5f813590506104ff816104db565b92915050565b5f6020828403" + "121561051a576105196103cf565b5b5f610527848285016104f1565b91505092915050565b610539816103d356" + "5b82525050565b5f6020820190506105525f830184610530565b92915050565b61056181610313565b81146105" + "6b575f80fd5b50565b5f8135905061057c81610558565b92915050565b5f602082840312156105975761059661" + "03cf565b5b5f6105a48482850161056e565b9150509291505056fea2646970667358221220c24f2807e50107ea" + "7f1b14927e683f13801dba0387067d73ff19776123092a7d64736f6c63430008190033"; + + bytes input; + boost::algorithm::unhex(transientCodeBin, std::back_inserter(input)); + + auto tx = + fakeTransaction(cryptoSuite, keyPair, "", input, std::to_string(101), 100001, "1", "1"); + auto sender = boost::algorithm::hex_lower(std::string(tx->sender())); + // The contract address + h256 addressCreate("ff6f30856ad3bae00b1169808488502786a13e3c174d85682135ffd51310310e"); + std::string address = addressCreate.hex().substr(0, 40); + + auto hash = tx->hash(); + txpool->hash2Transaction.emplace(hash, tx); + + auto params = std::make_unique(); + params->setContextID(100); + params->setSeq(1000); + params->setDepth(0); + + params->setOrigin(std::string(sender)); + params->setFrom(std::string(sender)); + + params->setTo(std::string(sender)); + params->setStaticCall(false); + params->setGasAvailable(gas); + params->setData(input); + params->setType(NativeExecutionMessage::TXHASH); + params->setTransactionHash(hash); + params->setCreate(true); + + NativeExecutionMessage paramsBak = *params; + auto blockHeader = std::make_shared( + [m_blockHeader = bcostars::BlockHeader()]() mutable { return &m_blockHeader; }); + blockHeader->setNumber(1); + + std::vector parentInfos{ + {{blockHeader->number() - 1, h256(blockHeader->number() - 1)}}}; + blockHeader->setParentInfo(parentInfos); + ledger->setBlockNumber(blockHeader->number() - 1); + blockHeader->calculateHash(*cryptoSuite->hashImpl()); + std::promise nextPromise; + executor->nextBlockHeader(0, blockHeader, [&](bcos::Error::Ptr&& error) { + BOOST_CHECK(!error); + nextPromise.set_value(); + }); + nextPromise.get_future().get(); + + // -------------------------- + // Deploy + // -------------------------- + std::promise executePromise; + executor->dmcExecuteTransaction(std::move(params), + [&](bcos::Error::UniquePtr&& error, bcos::protocol::ExecutionMessage::UniquePtr&& result) { + BOOST_CHECK(!error); + executePromise.set_value(std::move(result)); + }); + auto result = executePromise.get_future().get(); + BOOST_CHECK(result); + + // feature_evm_cancun is off + BOOST_CHECK_EQUAL(result->type(), NativeExecutionMessage::REVERT); + BOOST_CHECK_EQUAL(result->status(), 10); + BOOST_CHECK_EQUAL(result->evmStatus(), 5); +} + +BOOST_AUTO_TEST_CASE(transientStorageTest2) +{ + // turn on feature_evm_cuncan swtich + std::shared_ptr newStorage = + std::make_shared(hashImpl); + Entry entry; + bcos::protocol::BlockNumber blockNumber = 0; + entry.setObject( + ledger::SystemConfigEntry{boost::lexical_cast((int)1), blockNumber}); + newStorage->asyncSetRow(ledger::SYS_CONFIG, "feature_evm_cancun", entry, + [](Error::UniquePtr error) { BOOST_CHECK_EQUAL(error.get(), nullptr); }); + // check feature_evm_cancun whether is on + auto entry1 = newStorage->getRow(ledger::SYS_CONFIG, "feature_evm_cancun"); + // BOOST_CHECK_EQUAL(value, "1"); + // BOOST_CHECK_EQUAL(enableNumber, 0); + + auto executionResultFactory = std::make_shared(); + auto stateStorageFactory = std::make_shared(0); + auto lruStorage = std::make_shared(newStorage); + auto newExecutor = bcos::executor::TransactionExecutorFactory::build(ledger, txpool, lruStorage, + newStorage, executionResultFactory, stateStorageFactory, hashImpl, false, false); + + std::string transientCodeBin = + "6080604052348015600e575f80fd5b506108748061001c5f395ff3fe608060405234801561000f575f80fd5b50" + "60043610610029575f3560e01c8063fa3e317e1461002d575b5f80fd5b61004760048036038101906100429190" + "610194565b61005d565b60405161005491906101d9565b60405180910390f35b5f808260405161006c90610150" + "565b6100769190610201565b604051809103905ff08015801561008f573d5f803e3d5ffd5b5090505f8173ffff" + "ffffffffffffffffffffffffffffffffffff16636428f3dc6040518163ffffffff1660e01b8152600401602060" + "4051808303815f875af11580156100dd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060" + "405250810190610101919061022e565b9050838114610145576040517f08c379a0000000000000000000000000" + "00000000000000000000000000000000815260040161013c906102d9565b60405180910390fd5b600192505050" + "919050565b610547806102f883390190565b5f80fd5b5f819050919050565b61017381610161565b811461017d" + "575f80fd5b50565b5f8135905061018e8161016a565b92915050565b5f602082840312156101a9576101a86101" + "5d565b5b5f6101b684828501610180565b91505092915050565b5f8115159050919050565b6101d3816101bf56" + "5b82525050565b5f6020820190506101ec5f8301846101ca565b92915050565b6101fb81610161565b82525050" + "565b5f6020820190506102145f8301846101f2565b92915050565b5f815190506102288161016a565b92915050" + "565b5f602082840312156102435761024261015d565b5b5f6102508482850161021a565b91505092915050565b" + "5f82825260208201905092915050565b7f73746f72652076616c7565206e6f7420657175616c20746c6f616420" + "726573755f8201527f6c7400000000000000000000000000000000000000000000000000000000000060208201" + "5250565b5f6102c3602283610259565b91506102ce82610269565b604082019050919050565b5f602082019050" + "8181035f8301526102f0816102b7565b905091905056fe6080604052348015600e575f80fd5b50604051610547" + "3803806105478339818101604052810190602e9190607b565b603d5f5482604260201b60201c565b5060a1565b" + "80825d5050565b5f80fd5b5f819050919050565b605d81604d565b81146066575f80fd5b50565b5f8151905060" + "75816056565b92915050565b5f60208284031215608d57608c6049565b5b5f6098848285016069565b91505092" + "915050565b610499806100ae5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560" + "e01c80633bc5de30146100385780636428f3dc14610056575b5f80fd5b610040610074565b60405161004d9190" + "61015c565b60405180910390f35b61005e610084565b60405161006b919061015c565b60405180910390f35b5f" + "61007f5f5461012d565b905090565b5f8060405161009290610137565b604051809103905ff0801580156100ab" + "573d5f803e3d5ffd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663c1df0f483060405182" + "63ffffffff1660e01b81526004016100e791906101b4565b6020604051808303815f875af1158015610103573d" + "5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061012791906101fb565b9150" + "5090565b5f815c9050919050565b61023d8061022783390190565b5f819050919050565b61015681610144565b" + "82525050565b5f60208201905061016f5f83018461014d565b92915050565b5f73ffffffffffffffffffffffff" + "ffffffffffffffff82169050919050565b5f61019e82610175565b9050919050565b6101ae81610194565b8252" + "5050565b5f6020820190506101c75f8301846101a5565b92915050565b5f80fd5b6101da81610144565b811461" + "01e4575f80fd5b50565b5f815190506101f5816101d1565b92915050565b5f602082840312156102105761020f" + "6101cd565b5b5f61021d848285016101e7565b9150509291505056fe6080604052348015600e575f80fd5b5061" + "02218061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063c1df" + "0f481461002d575b5f80fd5b6100476004803603810190610042919061013a565b61005d565b60405161005491" + "9061017d565b60405180910390f35b5f808290505f8173ffffffffffffffffffffffffffffffffffffffff1663" + "3bc5de306040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100ac573d5f803e" + "3d5ffd5b505050506040513d601f19601f820116820180604052508101906100d091906101c0565b9050809250" + "5050919050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6101" + "09826100e0565b9050919050565b610119816100ff565b8114610123575f80fd5b50565b5f8135905061013481" + "610110565b92915050565b5f6020828403121561014f5761014e6100dc565b5b5f61015c84828501610126565b" + "91505092915050565b5f819050919050565b61017781610165565b82525050565b5f6020820190506101905f83" + "018461016e565b92915050565b61019f81610165565b81146101a9575f80fd5b50565b5f815190506101ba8161" + "0196565b92915050565b5f602082840312156101d5576101d46100dc565b5b5f6101e2848285016101ac565b91" + "50509291505056fea2646970667358221220b74855b53bcf2b3cc2261d3f57e16507da8b24f81ff519699191e3" + "4ce025bc8664736f6c63430008190033a26469706673582212201eb1e02998c84b08c3db1bdb2487184ca8357f" + "1d2739ec65daa47ffe3e89316a64736f6c63430008190033a2646970667358221220bad0e7bec379be9bb4f446" + "b845050f59959e8bd9da49d83f3c9f669a63e5e51e64736f6c63430008190033"; + bytes input; + boost::algorithm::unhex(transientCodeBin, std::back_inserter(input)); + + auto tx = + fakeTransaction(cryptoSuite, keyPair, "", input, std::to_string(100), 100000, "1", "1"); + auto sender = boost::algorithm::hex_lower(std::string(tx->sender())); + // The contract address + h256 addressCreate("ff6f30856ad3bae00b1169808488502786a13e3c174d85682135ffd51310310e"); + std::string address = addressCreate.hex().substr(0, 40); + + auto hash = tx->hash(); + txpool->hash2Transaction.emplace(hash, tx); + + + auto params1 = std::make_unique(); + params1->setContextID(101); + params1->setSeq(1001); + params1->setDepth(0); + params1->setOrigin(std::string(sender)); + params1->setFrom(std::string(sender)); + + // The contract address + params1->setTo(sender); + params1->setStaticCall(false); + params1->setGasAvailable(gas); + params1->setData(input); + params1->setType(NativeExecutionMessage::TXHASH); + params1->setTransactionHash(hash); + params1->setCreate(true); + + NativeExecutionMessage paramsBak1 = *params1; + + auto blockHeader = std::make_shared( + [m_blockHeader = bcostars::BlockHeader()]() mutable { return &m_blockHeader; }); + blockHeader->setNumber(1); + blockHeader->setVersion((uint32_t)bcos::protocol::BlockVersion::MAX_VERSION); + + std::vector parentInfos{ + {{blockHeader->number() - 1, h256(blockHeader->number() - 1)}}}; + blockHeader->setParentInfo(parentInfos); + ledger->setBlockNumber(blockHeader->number() - 1); + blockHeader->calculateHash(*cryptoSuite->hashImpl()); + std::promise nextPromise; + newExecutor->nextBlockHeader(0, blockHeader, [&](bcos::Error::Ptr&& error) { + BOOST_CHECK(!error); + nextPromise.set_value(); + }); + nextPromise.get_future().get(); + + // -------------------------- + // Deploy + // -------------------------- + std::promise executePromise; + newExecutor->executeTransaction(std::move(params1), + [&](bcos::Error::UniquePtr&& error, bcos::protocol::ExecutionMessage::UniquePtr&& result) { + BOOST_CHECK(!error); + executePromise.set_value(std::move(result)); + }); + auto result = executePromise.get_future().get(); + BOOST_CHECK(result); + + BOOST_CHECK_EQUAL(result->type(), NativeExecutionMessage::FINISHED); + BOOST_CHECK_EQUAL(result->status(), 0); + BOOST_CHECK_EQUAL(result->evmStatus(), 0); +} + +BOOST_AUTO_TEST_CASE(mcopy_opcode_test) +{ + // test opcode mcopy + /* solidity code + pragma solidity 0.8.25; + + contract mcopy { + function memoryCopy() external pure returns (bytes32 x) { + assembly { + mstore(0x20, 0x50) // Store 0x50 at word 1 in memory + mcopy(0, 0x20, 0x20) // Copies 0x50 to word 0 in memory + x := mload(0) // Returns 32 bytes "0x50" + } + } + }*/ + std::string mcopyCodeBin = + "6080604052348015600e575f80fd5b5060b980601a5f395ff3fe6080604052348015600e575f80fd5b50600436" + "106026575f3560e01c80632dbaeee914602a575b5f80fd5b60306044565b604051603b9190606c565b60405180" + "910390f35b5f60506020526020805f5e5f51905090565b5f819050919050565b6066816056565b82525050565b" + "5f602082019050607d5f830184605f565b9291505056fea2646970667358221220c16107fa00317d2d630d4d01" + "9754eb2bae42e96482d0050308e60ec21c69d7eb64736f6c63430008190033"; + + bytes input; + boost::algorithm::unhex(mcopyCodeBin, std::back_inserter(input)); + + auto tx = + fakeTransaction(cryptoSuite, keyPair, "", input, std::to_string(101), 100001, "1", "1"); + auto sender = boost::algorithm::hex_lower(std::string(tx->sender())); + // The contract address + h256 addressCreate("ff6f30856ad3bae00b1169808488502786a13e3c174d85682135ffd51310310e"); + std::string address = addressCreate.hex().substr(0, 40); + + auto hash = tx->hash(); + txpool->hash2Transaction.emplace(hash, tx); + + auto params = std::make_unique(); + params->setContextID(100); + params->setSeq(1000); + params->setDepth(0); + + params->setOrigin(std::string(sender)); + params->setFrom(std::string(sender)); + + params->setTo(std::string(sender)); + params->setStaticCall(false); + params->setGasAvailable(gas); + params->setData(input); + params->setType(NativeExecutionMessage::TXHASH); + params->setTransactionHash(hash); + params->setCreate(true); + + NativeExecutionMessage paramsBak = *params; + auto blockHeader = std::make_shared( + [m_blockHeader = bcostars::BlockHeader()]() mutable { return &m_blockHeader; }); + blockHeader->setNumber(1); + std::vector parentInfos{ + {{blockHeader->number() - 1, h256(blockHeader->number() - 1)}}}; + blockHeader->setParentInfo(parentInfos); + ledger->setBlockNumber(blockHeader->number() - 1); + blockHeader->calculateHash(*cryptoSuite->hashImpl()); + std::promise nextPromise; + executor->nextBlockHeader(0, blockHeader, [&](bcos::Error::Ptr&& error) { + BOOST_CHECK(!error); + nextPromise.set_value(); + }); + nextPromise.get_future().get(); + + // -------------------------- + // Deploy on executor which feature_evm_cancun is off + // -------------------------- + std::promise executePromise; + executor->dmcExecuteTransaction(std::move(params), + [&](bcos::Error::UniquePtr&& error, bcos::protocol::ExecutionMessage::UniquePtr&& result) { + BOOST_CHECK(!error); + executePromise.set_value(std::move(result)); + }); + auto result = executePromise.get_future().get(); + BOOST_CHECK(result); + + // feature_evm_cancun is off + BOOST_CHECK_EQUAL(result->type(), NativeExecutionMessage::REVERT); + BOOST_CHECK_EQUAL(result->status(), 10); + BOOST_CHECK_EQUAL(result->evmStatus(), 5); +} + +BOOST_AUTO_TEST_CASE(mcopy_opcode_test_1) +{ + // turn on feature_evm_cuncan swtich + std::shared_ptr newStorage = + std::make_shared(hashImpl); + Entry entry; + bcos::protocol::BlockNumber blockNumber = 0; + entry.setObject( + ledger::SystemConfigEntry{boost::lexical_cast((int)1), blockNumber}); + newStorage->asyncSetRow(ledger::SYS_CONFIG, "feature_evm_cancun", entry, + [](Error::UniquePtr error) { BOOST_CHECK_EQUAL(error.get(), nullptr); }); + // check feature_evm_cancun whether is on + auto entry1 = newStorage->getRow(ledger::SYS_CONFIG, "feature_evm_cancun"); + // BOOST_CHECK_EQUAL(value, "1"); + // BOOST_CHECK_EQUAL(enableNumber, 0); + + auto executionResultFactory = std::make_shared(); + auto stateStorageFactory = std::make_shared(0); + auto lruStorage = std::make_shared(newStorage); + auto newExecutor = bcos::executor::TransactionExecutorFactory::build(ledger, txpool, lruStorage, + newStorage, executionResultFactory, stateStorageFactory, hashImpl, false, false); + + std::string mcopyCodeBin = + "6080604052348015600e575f80fd5b5060b980601a5f395ff3fe6080604052348015600e575f80" + "fd5b50600436106026575f3560e01c80632dbaeee914602a575b5f80fd5b60306044565b604051603b9190606c" + "565b60405180" + "910390f35b5f60506020526020805f5e5f51905090565b5f819050919050565b6066816056565b82525050565b" + "5f6020820190" + "50607d5f830184605f565b9291505056fea2646970667358221220c16107fa00317d2d630d4d019754eb2bae42" + "e96482d00503" + "08e60ec21c69d7eb64736f6c63430008190033"; + + bytes input; + boost::algorithm::unhex(mcopyCodeBin, std::back_inserter(input)); + + auto tx = + fakeTransaction(cryptoSuite, keyPair, "", input, std::to_string(101), 100001, "1", "1"); + auto sender = boost::algorithm::hex_lower(std::string(tx->sender())); + // The contract address + h256 addressCreate("ff6f30856ad3bae00b1169808488502786a13e3c174d85682135ffd51310310e"); + std::string address = addressCreate.hex().substr(0, 40); + + auto hash = tx->hash(); + txpool->hash2Transaction.emplace(hash, tx); + + auto params = std::make_unique(); + params->setContextID(100); + params->setSeq(1000); + params->setDepth(0); + + params->setOrigin(std::string(sender)); + params->setFrom(std::string(sender)); + + params->setTo(std::string(sender)); + params->setStaticCall(false); + params->setGasAvailable(gas); + params->setData(input); + params->setType(NativeExecutionMessage::TXHASH); + params->setTransactionHash(hash); + params->setCreate(true); + + NativeExecutionMessage paramsBak = *params; + auto blockHeader = std::make_shared( + [m_blockHeader = bcostars::BlockHeader()]() mutable { return &m_blockHeader; }); + blockHeader->setNumber(1); + std::vector parentInfos{ + {{blockHeader->number() - 1, h256(blockHeader->number() - 1)}}}; + blockHeader->setParentInfo(parentInfos); + ledger->setBlockNumber(blockHeader->number() - 1); + blockHeader->calculateHash(*cryptoSuite->hashImpl()); + std::promise nextPromise; + newExecutor->nextBlockHeader(0, blockHeader, [&](bcos::Error::Ptr&& error) { + BOOST_CHECK(!error); + nextPromise.set_value(); + }); + nextPromise.get_future().get(); + + // -------------------------- + // Deploy on executor which feature_evm_cancun is off + // -------------------------- + std::promise executePromise; + newExecutor->dmcExecuteTransaction(std::move(params), + [&](bcos::Error::UniquePtr&& error, bcos::protocol::ExecutionMessage::UniquePtr&& result) { + BOOST_CHECK(!error); + executePromise.set_value(std::move(result)); + }); + auto result = executePromise.get_future().get(); + BOOST_CHECK(result); + BOOST_CHECK_EQUAL(result->type(), NativeExecutionMessage::FINISHED); + BOOST_CHECK_EQUAL(result->status(), 0); + BOOST_CHECK_EQUAL(result->evmStatus(), 0); +} + +BOOST_AUTO_TEST_CASE(blobBaseFee_test) +{ + /* + pragma solidity 0.8.25; + + contract blobBaseFee { + function getBlobBaseFeeYul() external view returns (uint256 blobBaseFee) { + assembly { + blobBaseFee := blobbasefee() + } + } + + function getBlobBaseFeeSolidity() external view returns (uint256 blobBaseFee) { + blobBaseFee = block.blobbasefee; + } + } + */ + // turn on feature_evm_cuncan swtich + std::shared_ptr newStorage = + std::make_shared(hashImpl); + Entry entry; + bcos::protocol::BlockNumber blockNumber = 0; + entry.setObject( + ledger::SystemConfigEntry{boost::lexical_cast((int)1), blockNumber}); + newStorage->asyncSetRow(ledger::SYS_CONFIG, "feature_evm_cancun", entry, + [](Error::UniquePtr error) { BOOST_CHECK_EQUAL(error.get(), nullptr); }); + // check feature_evm_cancun whether is on + auto entry1 = newStorage->getRow(ledger::SYS_CONFIG, "feature_evm_cancun"); + // BOOST_CHECK_EQUAL(value, "1"); + // BOOST_CHECK_EQUAL(enableNumber, 0); + + auto executionResultFactory = std::make_shared(); + auto stateStorageFactory = std::make_shared(0); + auto lruStorage = std::make_shared(newStorage); + auto newExecutor = bcos::executor::TransactionExecutorFactory::build(ledger, txpool, lruStorage, + newStorage, executionResultFactory, stateStorageFactory, hashImpl, false, false); + + std::string blobBaseFeeCodeBin = + "6080604052348015600e575f80fd5b5060d980601a5f395ff3fe6080" + "604052348015600e575f80fd5b50600436106030575f3560e01c806348a35d4e1460345780635b85fe9814" + "604e575b5f80fd5b603a6068565b60405160459190608c565b60405180910390f35b6054606f565b604051" + "605f9190608c565b60405180910390f35b5f4a905090565b5f4a905090565b5f819050919050565b608681" + "6076565b82525050565b5f602082019050609d5f830184607f565b9291505056fea2646970667358221220" + "954cfa4357894c6c07e251b6fe89f193c6348d4425388a3cae9a77548e09789964736f6c63430008190033"; + + bytes input; + boost::algorithm::unhex(blobBaseFeeCodeBin, std::back_inserter(input)); + + auto tx = + fakeTransaction(cryptoSuite, keyPair, "", input, std::to_string(101), 100001, "1", "1"); + auto sender = boost::algorithm::hex_lower(std::string(tx->sender())); + // The contract address + h256 addressCreate("ff6f30856ad3bae00b1169808488502786a13e3c174d85682135ffd51310310e"); + std::string address = addressCreate.hex().substr(0, 40); + + auto hash = tx->hash(); + txpool->hash2Transaction.emplace(hash, tx); + + auto params = std::make_unique(); + params->setContextID(100); + params->setSeq(1000); + params->setDepth(0); + + params->setOrigin(std::string(sender)); + params->setFrom(std::string(sender)); + + params->setTo(std::string(sender)); + params->setStaticCall(false); + params->setGasAvailable(gas); + params->setData(input); + params->setType(NativeExecutionMessage::TXHASH); + params->setTransactionHash(hash); + params->setCreate(true); + + NativeExecutionMessage paramsBak = *params; + auto blockHeader = std::make_shared( + [m_blockHeader = bcostars::BlockHeader()]() mutable { return &m_blockHeader; }); + blockHeader->setNumber(1); + std::vector parentInfos{ + {{blockHeader->number() - 1, h256(blockHeader->number() - 1)}}}; + blockHeader->setParentInfo(parentInfos); + ledger->setBlockNumber(blockHeader->number() - 1); + blockHeader->calculateHash(*cryptoSuite->hashImpl()); + std::promise nextPromise; + newExecutor->nextBlockHeader(0, blockHeader, [&](bcos::Error::Ptr&& error) { + BOOST_CHECK(!error); + nextPromise.set_value(); + }); + nextPromise.get_future().get(); + + // -------------------------- + // Deploy on executor which feature_evm_cancun is off + // -------------------------- + std::promise executePromise; + newExecutor->dmcExecuteTransaction(std::move(params), + [&](bcos::Error::UniquePtr&& error, bcos::protocol::ExecutionMessage::UniquePtr&& result) { + BOOST_CHECK(!error); + executePromise.set_value(std::move(result)); + }); + auto result = executePromise.get_future().get(); + BOOST_CHECK(result); + BOOST_CHECK_EQUAL(result->type(), NativeExecutionMessage::FINISHED); + BOOST_CHECK_EQUAL(result->status(), 0); + BOOST_CHECK_EQUAL(result->evmStatus(), 0); +} + +BOOST_AUTO_TEST_CASE(blobHash_test) +{ + /* + pragma solidity 0.8.25; + contract blobhash { + function storeBlobHash(uint256 index) external { + assembly { + sstore(0, blobhash(index)) + } + } + } + */ + + // turn on feature_evm_cuncan swtich + std::shared_ptr newStorage = + std::make_shared(hashImpl); + Entry entry; + bcos::protocol::BlockNumber blockNumber = 0; + entry.setObject( + ledger::SystemConfigEntry{boost::lexical_cast((int)1), blockNumber}); + newStorage->asyncSetRow(ledger::SYS_CONFIG, "feature_evm_cancun", entry, + [](Error::UniquePtr error) { BOOST_CHECK_EQUAL(error.get(), nullptr); }); + // check feature_evm_cancun whether is on + auto entry1 = newStorage->getRow(ledger::SYS_CONFIG, "feature_evm_cancun"); + // BOOST_CHECK_EQUAL(value, "1"); + // BOOST_CHECK_EQUAL(enableNumber, 0); + + auto executionResultFactory = std::make_shared(); + auto stateStorageFactory = std::make_shared(0); + auto lruStorage = std::make_shared(newStorage); + auto newExecutor = bcos::executor::TransactionExecutorFactory::build(ledger, txpool, lruStorage, + newStorage, executionResultFactory, stateStorageFactory, hashImpl, false, false); + + std::string blobHashCodeBin = + "6080604052348015600e575f80fd5b5060d780601a5f395ff3fe6080604052348015600e575f80fd5b50600436" + "106026575f3560e01c8063ae67ac9b14602a575b5f80fd5b60406004803603810190603c9190607b565b604256" + "5b005b80495f5550565b5f80fd5b5f819050919050565b605d81604d565b81146066575f80fd5b50565b5f8135" + "90506075816056565b92915050565b5f60208284031215608d57608c6049565b5b5f6098848285016069565b91" + "50509291505056fea2646970667358221220ad2b619fbd8e82b272adfa7e9278d31e0c2f6e109361b2206b5b03" + "84aee5700f64736f6c63430008190033"; + bytes input; + boost::algorithm::unhex(blobHashCodeBin, std::back_inserter(input)); + + auto tx = + fakeTransaction(cryptoSuite, keyPair, "", input, std::to_string(101), 100001, "1", "1"); + auto sender = boost::algorithm::hex_lower(std::string(tx->sender())); + // The contract address + h256 addressCreate("ff6f30856ad3bae00b1169808488502786a13e3c174d85682135ffd51310310e"); + std::string address = addressCreate.hex().substr(0, 40); + + auto hash = tx->hash(); + txpool->hash2Transaction.emplace(hash, tx); + + auto params = std::make_unique(); + params->setContextID(100); + params->setSeq(1000); + params->setDepth(0); + + params->setOrigin(std::string(sender)); + params->setFrom(std::string(sender)); + + params->setTo(std::string(sender)); + params->setStaticCall(false); + params->setGasAvailable(gas); + params->setData(input); + params->setType(NativeExecutionMessage::TXHASH); + params->setTransactionHash(hash); + params->setCreate(true); + + NativeExecutionMessage paramsBak = *params; + auto blockHeader = std::make_shared( + [m_blockHeader = bcostars::BlockHeader()]() mutable { return &m_blockHeader; }); + blockHeader->setNumber(1); + std::vector parentInfos{ + {{blockHeader->number() - 1, h256(blockHeader->number() - 1)}}}; + blockHeader->setParentInfo(parentInfos); + ledger->setBlockNumber(blockHeader->number() - 1); + blockHeader->calculateHash(*cryptoSuite->hashImpl()); + std::promise nextPromise; + newExecutor->nextBlockHeader(0, blockHeader, [&](bcos::Error::Ptr&& error) { + BOOST_CHECK(!error); + nextPromise.set_value(); + }); + nextPromise.get_future().get(); + + // -------------------------- + // Deploy on executor which feature_evm_cancun is off + // -------------------------- + std::promise executePromise; + newExecutor->dmcExecuteTransaction(std::move(params), + [&](bcos::Error::UniquePtr&& error, bcos::protocol::ExecutionMessage::UniquePtr&& result) { + BOOST_CHECK(!error); + executePromise.set_value(std::move(result)); + }); + auto result = executePromise.get_future().get(); + BOOST_CHECK(result); + BOOST_CHECK_EQUAL(result->type(), NativeExecutionMessage::FINISHED); + BOOST_CHECK_EQUAL(result->status(), 0); + BOOST_CHECK_EQUAL(result->evmStatus(), 0); +} + +BOOST_AUTO_TEST_CASE(getTransientStorageTest) +{ + // turn on feature_evm_cuncan swtich + std::shared_ptr newStorage = + std::make_shared(hashImpl); + Entry entry; + bcos::protocol::BlockNumber blockNumber = 0; + entry.setObject( + ledger::SystemConfigEntry{boost::lexical_cast((int)1), blockNumber}); + newStorage->asyncSetRow(ledger::SYS_CONFIG, "feature_evm_cancun", entry, + [](Error::UniquePtr error) { BOOST_CHECK_EQUAL(error.get(), nullptr); }); + // check feature_evm_cancun whether is on + auto entry1 = newStorage->getRow(ledger::SYS_CONFIG, "feature_evm_cancun"); + // BOOST_CHECK_EQUAL(value, "1"); + // BOOST_CHECK_EQUAL(enableNumber, 0); + + auto executionResultFactory = std::make_shared(); + auto stateStorageFactory = std::make_shared(0); + auto lruStorage = std::make_shared(newStorage); + auto newExecutor = bcos::executor::TransactionExecutorFactory::build(ledger, txpool, lruStorage, + newStorage, executionResultFactory, stateStorageFactory, hashImpl, false, false); + + std::string transientCodeBin = + "60806040527fe3598e46f24394be411dcf68a978c22ef80d97a0ef7c630d9b8e35d241c0210060015534801560" + "32575f80fd5b506106a9806100405f395ff3fe608060405234801561000f575f80fd5b5060043610610055575f" + "3560e01c806320965255146100595780632a130724146100775780635524107714610093578063613d81e11461" + "00af57806374f7ca87146100b9575b5f80fd5b6100616100d7565b60405161006e91906103a4565b6040518091" + "0390f35b610091600480360381019061008c919061041b565b6100eb565b005b6100ad60048036038101906100" + "a89190610470565b61012d565b005b6100b761013a565b005b6100c1610369565b6040516100ce91906104aa56" + "5b60405180910390f35b5f8060015490505f815c9050809250505090565b805f806101000a81548173ffffffff" + "ffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217" + "90555050565b5f600154905081815d5050565b5f73ffffffffffffffffffffffffffffffffffffffff165f8054" + "906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffff" + "ffffffffff16036101c7576040517f08c379a00000000000000000000000000000000000000000000000000000" + "000081526004016101be9061051d565b60405180910390fd5b5f805f9054906101000a900473ffffffffffffff" + "ffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16604051602401604051" + "6020818303038152906040527fb7fd278600000000000000000000000000000000000000000000000000000000" + "7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffff" + "ffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161028f919061058d565b" + "5f604051808303815f865af19150503d805f81146102c8576040519150601f19603f3d011682016040523d8252" + "3d5f602084013e6102cd565b606091505b5050905080610311576040517f08c379a00000000000000000000000" + "00000000000000000000000000000000008152600401610308906105ed565b60405180910390fd5b5f61031a61" + "00d7565b90506103246100d7565b8114610365576040517f08c379a00000000000000000000000000000000000" + "0000000000000000000000815260040161035c90610655565b60405180910390fd5b5050565b5f805490610100" + "0a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f819050919050565b61039e8161038c56" + "5b82525050565b5f6020820190506103b75f830184610395565b92915050565b5f80fd5b5f73ffffffffffffff" + "ffffffffffffffffffffffffff82169050919050565b5f6103ea826103c1565b9050919050565b6103fa816103" + "e0565b8114610404575f80fd5b50565b5f81359050610415816103f1565b92915050565b5f6020828403121561" + "04305761042f6103bd565b5b5f61043d84828501610407565b91505092915050565b61044f8161038c565b8114" + "610459575f80fd5b50565b5f8135905061046a81610446565b92915050565b5f60208284031215610485576104" + "846103bd565b5b5f6104928482850161045c565b91505092915050565b6104a4816103e0565b82525050565b5f" + "6020820190506104bd5f83018461049b565b92915050565b5f82825260208201905092915050565b7f4220636f" + "6e74726163742061646472657373206e6f74207365740000000000005f82015250565b5f610507601a836104c3" + "565b9150610512826104d3565b602082019050919050565b5f6020820190508181035f830152610534816104fb" + "565b9050919050565b5f81519050919050565b5f81905092915050565b8281835e5f83830152505050565b5f61" + "05678261053b565b6105718185610545565b935061058181856020860161054f565b8084019150509291505056" + "5b5f610598828461055d565b915081905092915050565b7f43616c6c20746f204220636f6e7472616374206661" + "696c6564000000000000005f82015250565b5f6105d76019836104c3565b91506105e2826105a3565b60208201" + "9050919050565b5f6020820190508181035f830152610604816105cb565b9050919050565b7f53746f72656420" + "76616c756520646f6573206e6f74206d6174636800000000005f82015250565b5f61063f601b836104c3565b91" + "5061064a8261060b565b602082019050919050565b5f6020820190508181035f83015261066c81610633565b90" + "5091905056fea264697066735822122032dafff81aab17ab191d852a4391e85e6339bf0c051c273ddc9ac41348" + "25fb5464736f6c63430008190033"; + bytes input; + boost::algorithm::unhex(transientCodeBin, std::back_inserter(input)); + + auto tx = + fakeTransaction(cryptoSuite, keyPair, "", input, std::to_string(100), 100000, "1", "1"); + auto sender = boost::algorithm::hex_lower(std::string(tx->sender())); + // The contract address + h256 addressCreate("ff6f30856ad3bae00b1169808488502786a13e3c174d85682135ffd51310310e"); + std::string address = addressCreate.hex().substr(0, 40); + + auto hash = tx->hash(); + txpool->hash2Transaction.emplace(hash, tx); + + + auto params1 = std::make_unique(); + params1->setContextID(101); + params1->setSeq(1001); + params1->setDepth(0); + params1->setOrigin(std::string(sender)); + params1->setFrom(std::string(sender)); + + // The contract address + params1->setTo(sender); + params1->setStaticCall(false); + params1->setGasAvailable(gas); + params1->setData(input); + params1->setType(NativeExecutionMessage::TXHASH); + params1->setTransactionHash(hash); + params1->setCreate(true); + + NativeExecutionMessage paramsBak1 = *params1; + + auto blockHeader = std::make_shared( + [m_blockHeader = bcostars::BlockHeader()]() mutable { return &m_blockHeader; }); + blockHeader->setNumber(1); + blockHeader->setVersion((uint32_t)bcos::protocol::BlockVersion::MAX_VERSION); + + std::vector parentInfos{ + {{blockHeader->number() - 1, h256(blockHeader->number() - 1)}}}; + blockHeader->setParentInfo(parentInfos); + ledger->setBlockNumber(blockHeader->number() - 1); + blockHeader->calculateHash(*cryptoSuite->hashImpl()); + std::promise nextPromise; + newExecutor->nextBlockHeader(0, blockHeader, [&](bcos::Error::Ptr&& error) { + BOOST_CHECK(!error); + nextPromise.set_value(); + }); + nextPromise.get_future().get(); + + // -------------------------- + // Deploy + // -------------------------- + std::promise executePromise; + newExecutor->executeTransaction(std::move(params1), + [&](bcos::Error::UniquePtr&& error, bcos::protocol::ExecutionMessage::UniquePtr&& result) { + BOOST_CHECK(!error); + executePromise.set_value(std::move(result)); + }); + auto result = executePromise.get_future().get(); + BOOST_CHECK(result); + + BOOST_CHECK_EQUAL(result->type(), NativeExecutionMessage::FINISHED); + BOOST_CHECK_EQUAL(result->status(), 0); + BOOST_CHECK_EQUAL(result->evmStatus(), 0); +} BOOST_AUTO_TEST_SUITE_END() } // namespace test diff --git a/bcos-executor/test/unittest/libexecutor/TestExecutiveStackFlow.cpp b/bcos-executor/test/unittest/libexecutor/TestExecutiveStackFlow.cpp index 6fc0785b9d..ba2d0af6d0 100644 --- a/bcos-executor/test/unittest/libexecutor/TestExecutiveStackFlow.cpp +++ b/bcos-executor/test/unittest/libexecutor/TestExecutiveStackFlow.cpp @@ -83,7 +83,7 @@ struct ExecutiveStackFlowFixture LedgerCache::Ptr ledgerCache = std::make_shared(std::make_shared()); blockContext = std::make_shared( - nullptr, ledgerCache, nullptr, 0, h256(), 0, 0, FiscoBcosSchedule, false, false); + nullptr, ledgerCache, nullptr, 0, h256(), 0, 0, false, false); executiveFactory = std::make_shared( *blockContext, nullptr, nullptr, nullptr, nullptr); diff --git a/bcos-executor/test/unittest/libexecutor/TestExecutiveState.cpp b/bcos-executor/test/unittest/libexecutor/TestExecutiveState.cpp index fec3b2c5d7..53a0e59b69 100644 --- a/bcos-executor/test/unittest/libexecutor/TestExecutiveState.cpp +++ b/bcos-executor/test/unittest/libexecutor/TestExecutiveState.cpp @@ -28,7 +28,7 @@ struct ExecutiveStateFixture input->contextID = 1; input->seq = 1; blockContext = std::make_shared( - nullptr, ledgerCache, nullptr, 0, h256(), 0, 0, FiscoBcosSchedule, false, false); + nullptr, ledgerCache, nullptr, 0, h256(), 0, 0, false, false); executiveFactory = std::make_shared( *blockContext, nullptr, nullptr, nullptr, nullptr); diff --git a/bcos-executor/test/unittest/libprecompiled/CryptoPrecompiledTest.cpp b/bcos-executor/test/unittest/libprecompiled/CryptoPrecompiledTest.cpp index d9b4513655..e23a2f110a 100644 --- a/bcos-executor/test/unittest/libprecompiled/CryptoPrecompiledTest.cpp +++ b/bcos-executor/test/unittest/libprecompiled/CryptoPrecompiledTest.cpp @@ -303,10 +303,9 @@ class SM2VerifyPrecompiledFixture m_cryptoSuite = std::make_shared( std::make_shared(), std::make_shared(), nullptr); m_cryptoPrecompiled = std::make_shared(m_cryptoSuite->hashImpl()); - m_blockContext = - std::make_shared(nullptr, m_ledgerCache, m_cryptoSuite->hashImpl(), 0, - h256(), utcTime(), (uint32_t)(bcos::protocol::BlockVersion::V3_0_VERSION), - FiscoBcosSchedule, false, false); + m_blockContext = std::make_shared(nullptr, m_ledgerCache, + m_cryptoSuite->hashImpl(), 0, h256(), utcTime(), + (uint32_t)(bcos::protocol::BlockVersion::V3_0_VERSION), false, false); m_executive = std::make_shared(*m_blockContext, "", 100, 0, m_gasInjector); m_abi = std::make_shared(m_cryptoSuite->hashImpl()); diff --git a/bcos-executor/test/unittest/libprecompiled/GroupSigPrecompiledTest.cpp b/bcos-executor/test/unittest/libprecompiled/GroupSigPrecompiledTest.cpp index 8789715273..7c4ed84322 100644 --- a/bcos-executor/test/unittest/libprecompiled/GroupSigPrecompiledTest.cpp +++ b/bcos-executor/test/unittest/libprecompiled/GroupSigPrecompiledTest.cpp @@ -49,8 +49,8 @@ struct GroupSigPrecompiledFixture m_hashImpl = std::make_shared(); m_groupSigPrecompiled = std::make_shared(m_hashImpl); m_ledgerCache = std::make_shared(std::make_shared()); - m_blockContext = std::make_shared(nullptr, m_ledgerCache, m_hashImpl, 0, - h256(), utcTime(), 0, FiscoBcosSchedule, false, false); + m_blockContext = std::make_shared( + nullptr, m_ledgerCache, m_hashImpl, 0, h256(), utcTime(), 0, false, false); m_executive = std::make_shared(*m_blockContext, "", 100, 0, m_gasInjector); } diff --git a/bcos-executor/test/unittest/libprecompiled/RingSigPrecompiledTest.cpp b/bcos-executor/test/unittest/libprecompiled/RingSigPrecompiledTest.cpp index f356d9af06..3f3dbd4241 100644 --- a/bcos-executor/test/unittest/libprecompiled/RingSigPrecompiledTest.cpp +++ b/bcos-executor/test/unittest/libprecompiled/RingSigPrecompiledTest.cpp @@ -49,8 +49,8 @@ struct RingSigPrecompiledFixture m_hashImpl = std::make_shared(); m_ringSigPrecompiled = std::make_shared(m_hashImpl); m_ledgerCache = std::make_shared(std::make_shared()); - m_blockContext = std::make_shared(nullptr, m_ledgerCache, m_hashImpl, 0, - h256(), utcTime(), 0, FiscoBcosSchedule, false, false); + m_blockContext = std::make_shared( + nullptr, m_ledgerCache, m_hashImpl, 0, h256(), utcTime(), 0, false, false); m_executive = std::make_shared(*m_blockContext, "", 100, 0, m_gasInjector); } diff --git a/bcos-executor/test/unittest/libprecompiled/SystemConfigPrecompileTest.cpp b/bcos-executor/test/unittest/libprecompiled/SystemConfigPrecompileTest.cpp index c86b9c3931..fcbd72963d 100644 --- a/bcos-executor/test/unittest/libprecompiled/SystemConfigPrecompileTest.cpp +++ b/bcos-executor/test/unittest/libprecompiled/SystemConfigPrecompileTest.cpp @@ -47,9 +47,9 @@ struct SystemConfigPrecompiledFixture : public bcos::test::PrecompiledFixture std::shared_ptr backendStorage = std::make_shared(nullptr); std::shared_ptr stateStorage = std::make_shared(backendStorage); std::shared_ptr blockContext = - std::make_shared(stateStorage, ledgerCache, hashImpl, 0, h256(), utcTime(), - static_cast(protocol::BlockVersion::V3_1_VERSION), FiscoBcosSchedule, false, - false, backendStorage); + std::make_shared(stateStorage, + ledgerCache, hashImpl, 0, h256(), utcTime(), + static_cast(protocol::BlockVersion::V3_1_VERSION), false, false, backendStorage); std::shared_ptr executive = std::make_shared(*blockContext, "", 100, 0, *gasInjector); }; @@ -113,8 +113,8 @@ BOOST_AUTO_TEST_CASE(getAndSetFeature) std::make_shared(std::make_shared()); std::shared_ptr newBlockContext = std::make_shared( executive->blockContext().storage(), ledgerCache, executive->blockContext().hashHandler(), - 1, h256(), utcTime(), static_cast(protocol::BlockVersion::V3_1_VERSION), - FiscoBcosSchedule, false, false, backendStorage); + 1, h256(), utcTime(), static_cast(protocol::BlockVersion::V3_1_VERSION), false, + false, backendStorage); std::shared_ptr newExecutive = std::make_shared(*newBlockContext, "", 100, 0, *gasInjector); setInput = codec.encodeWithSig("setValueByKey(string,string)", diff --git a/bcos-executor/test/unittest/libprecompiled/VRFPrecompiledTest.cpp b/bcos-executor/test/unittest/libprecompiled/VRFPrecompiledTest.cpp index ac4c8b9d9b..2094a9b777 100644 --- a/bcos-executor/test/unittest/libprecompiled/VRFPrecompiledTest.cpp +++ b/bcos-executor/test/unittest/libprecompiled/VRFPrecompiledTest.cpp @@ -67,9 +67,8 @@ class VRFPrecompiledFixture } m_cryptoPrecompiled = std::make_shared(m_cryptoSuite->hashImpl()); m_ledgerCache = std::make_shared(std::make_shared()); - m_blockContext = - std::make_shared(nullptr, m_ledgerCache, m_cryptoSuite->hashImpl(), 0, - h256(), utcTime(), _blockVersion, FiscoBcosSchedule, false, false); + m_blockContext = std::make_shared(nullptr, m_ledgerCache, + m_cryptoSuite->hashImpl(), 0, h256(), utcTime(), _blockVersion, false, false); m_executive = std::make_shared(*m_blockContext, "", 100, 0, m_gasInjector); m_abi = std::make_shared(m_cryptoSuite->hashImpl()); diff --git a/bcos-executor/test/unittest/mock/MockExecutiveFactory.h b/bcos-executor/test/unittest/mock/MockExecutiveFactory.h index 6969e21255..b7a4149a64 100644 --- a/bcos-executor/test/unittest/mock/MockExecutiveFactory.h +++ b/bcos-executor/test/unittest/mock/MockExecutiveFactory.h @@ -31,7 +31,7 @@ class MockExecutiveFactory : public bcos::executor::ExecutiveFactory { auto ledgerCache = std::make_shared(std::make_shared()); blockContext = std::make_shared( - nullptr, ledgerCache, nullptr, 0, h256(), 0, 0, FiscoBcosSchedule, false, false); + nullptr, ledgerCache, nullptr, 0, h256(), 0, 0, false, false); auto executive = std::make_shared(*blockContext, "0x00", 0, 0, instruction); return executive; diff --git a/bcos-framework/bcos-framework/ledger/Features.h b/bcos-framework/bcos-framework/ledger/Features.h index 15bc1ae9ba..e4f6ccb09d 100644 --- a/bcos-framework/bcos-framework/ledger/Features.h +++ b/bcos-framework/bcos-framework/ledger/Features.h @@ -49,6 +49,7 @@ class Features feature_balance_precompiled, feature_balance_policy1, feature_paillier_add_raw, + feature_evm_cancun, }; private: diff --git a/bcos-framework/bcos-framework/storage2/MemoryStorage.h b/bcos-framework/bcos-framework/storage2/MemoryStorage.h index 7ac9c33dc3..9d1e809671 100644 --- a/bcos-framework/bcos-framework/storage2/MemoryStorage.h +++ b/bcos-framework/bcos-framework/storage2/MemoryStorage.h @@ -241,7 +241,8 @@ class MemoryStorage } friend task::AwaitableValue> tag_invoke( - storage2::tag_t /*unused*/, MemoryStorage& storage, auto&& key) + storage2::tag_t /*unused*/, MemoryStorage& storage, auto&& key, + auto&&... args) { task::AwaitableValue> result({}); auto& bucket = storage.getBucket(key); diff --git a/bcos-framework/test/unittests/interfaces/FeaturesTest.cpp b/bcos-framework/test/unittests/interfaces/FeaturesTest.cpp index 93f5d7bbfd..3cbea29b20 100644 --- a/bcos-framework/test/unittests/interfaces/FeaturesTest.cpp +++ b/bcos-framework/test/unittests/interfaces/FeaturesTest.cpp @@ -148,7 +148,8 @@ BOOST_AUTO_TEST_CASE(feature) "feature_balance", "feature_balance_precompiled", "feature_balance_policy1", - "feature_paillier_add_raw" + "feature_paillier_add_raw", + "feature_evm_cancun" }; // clang-format on for (size_t i = 0; i < keys.size(); ++i) diff --git a/cmake/ProjectBLST.cmake b/cmake/ProjectBLST.cmake new file mode 100644 index 0000000000..4bd2bd0bdc --- /dev/null +++ b/cmake/ProjectBLST.cmake @@ -0,0 +1,43 @@ +include(ExternalProject) +include(GNUInstallDirs) + +find_program(BASH_COMMAND NAMES bash REQUIRED PATHS "/bin") +set(BLST_BUILD_COMMAND "${BASH_COMMAND}" build.sh) + +if (NOT BASH_COMMAND) + message(FATAL_ERROR "bash not found") +endif () + +ExternalProject_Add(blst_project + PREFIX ${CMAKE_SOURCE_DIR}/deps + GIT_REPOSITORY https://${URL_BASE}/supranational/blst.git + GIT_TAG 3dd0f804b1819e5d03fb22ca2e6fac105932043a + GIT_SHALLOW 0 + + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX= + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND "" + BUILD_COMMAND ${BLST_BUILD_COMMAND} + INSTALL_COMMAND sh -c "cp /bindings/blst.h /include/ && cp /bindings/blst_aux.h /include/ && cp /libblst.a /lib/" + LOG_BUILD true + LOG_INSTALL true + LOG_CONFIGURE true + BUILD_BYPRODUCTS libblst.a + ) + +ExternalProject_Get_Property(blst_project INSTALL_DIR) +add_library(blst STATIC IMPORTED) + +set(BLST_LIBRARY ${INSTALL_DIR}/lib/libblst.a) +set(BLST_INCLUDE_DIR ${INSTALL_DIR}/include) +file(MAKE_DIRECTORY ${INSTALL_DIR}/lib/) +file(MAKE_DIRECTORY ${BLST_INCLUDE_DIR}) + +set_property(TARGET blst PROPERTY IMPORTED_LOCATION ${BLST_LIBRARY}) +set_property(TARGET blst PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${BLST_INCLUDE_DIR}) +add_dependencies(blst blst_project) +unset(INSTALL_DIR) + + + + diff --git a/transaction-executor/bcos-transaction-executor/TransactionExecutorImpl.h b/transaction-executor/bcos-transaction-executor/TransactionExecutorImpl.h index 1d6c68c8a7..1f196f20d1 100644 --- a/transaction-executor/bcos-transaction-executor/TransactionExecutorImpl.h +++ b/transaction-executor/bcos-transaction-executor/TransactionExecutorImpl.h @@ -54,10 +54,19 @@ class TransactionExecutorImpl if (c_fileLogLevel <= LogLevel::TRACE) { TRANSACTION_EXECUTOR_LOG(TRACE) - << "Execte transaction: " << transaction.hash().hex(); + << "Execute transaction: " << transaction.hash().hex(); } Rollbackable> rollbackableStorage(storage); + // create a transient storage + using MemoryStorageType = + bcos::storage2::memory_storage::MemoryStorage; + MemoryStorageType transientStorage; + Rollbackable rollbackableTransientStorage(transientStorage); auto gasLimit = static_cast(std::get<0>(ledgerConfig.gasLimit())); auto toAddress = unhexAddress(transaction.to()); @@ -87,10 +96,11 @@ class TransactionExecutorImpl } int64_t seq = 0; - HostContext hostContext(rollbackableStorage, blockHeader, - evmcMessage, evmcMessage.sender, transaction.abi(), contextID, seq, - executor.m_precompiledManager, ledgerConfig, *executor.m_hashImpl, - std::forward(waitOperator)); + HostContext + hostContext(rollbackableStorage, rollbackableTransientStorage, blockHeader, + evmcMessage, evmcMessage.sender, transaction.abi(), contextID, seq, + executor.m_precompiledManager, ledgerConfig, *executor.m_hashImpl, + std::forward(waitOperator)); waitOperator(hostContext.prepare()); co_yield receipt; // 完成第一步 Complete the first step diff --git a/transaction-executor/bcos-transaction-executor/precompiled/Precompiled.h b/transaction-executor/bcos-transaction-executor/precompiled/Precompiled.h index 978f900f2a..914601e759 100644 --- a/transaction-executor/bcos-transaction-executor/precompiled/Precompiled.h +++ b/transaction-executor/bcos-transaction-executor/precompiled/Precompiled.h @@ -35,7 +35,7 @@ inline auto buildLegacyExecutive(auto& storage, protocol::BlockHeader const& blo auto blockContext = std::make_unique(storageWrapper, nullptr, executor::GlobalHashImpl::g_hashImpl, blockHeader.number(), blockHeader.hash(), - blockHeader.timestamp(), blockHeader.version(), bcos::executor::VMSchedule{}, false, false); + blockHeader.timestamp(), blockHeader.version(), false, false); return std::make_shared< ExecutiveWrapper>>( std::move(blockContext), std::move(contractAddress), 0, 0, wasm::GasInjector{}, diff --git a/transaction-executor/bcos-transaction-executor/precompiled/PrecompiledManager.cpp b/transaction-executor/bcos-transaction-executor/precompiled/PrecompiledManager.cpp index 0ebbcb5ddd..35b818a850 100644 --- a/transaction-executor/bcos-transaction-executor/precompiled/PrecompiledManager.cpp +++ b/transaction-executor/bcos-transaction-executor/precompiled/PrecompiledManager.cpp @@ -49,6 +49,9 @@ bcos::transaction_executor::PrecompiledManager::PrecompiledManager(crypto::Hash: m_address2Precompiled.emplace_back(9, executor::PrecompiledContract(executor::PrecompiledRegistrar::pricer("blake2_compression"), executor::PrecompiledRegistrar::executor("blake2_compression"))); + // m_address2Precompiled.emplace_back(10, + // executor::PrecompiledContract(executor::PrecompiledRegistrar::pricer("point_evaluation"), + // executor::PrecompiledRegistrar::executor("point_evaluation"))); m_address2Precompiled.emplace_back( 0x1000, std::make_shared(m_hashImpl)); diff --git a/transaction-executor/bcos-transaction-executor/vm/EVMHostInterface.h b/transaction-executor/bcos-transaction-executor/vm/EVMHostInterface.h index 93f09fc7bf..e1a3336709 100644 --- a/transaction-executor/bcos-transaction-executor/vm/EVMHostInterface.h +++ b/transaction-executor/bcos-transaction-executor/vm/EVMHostInterface.h @@ -53,6 +53,13 @@ struct EVMHostInterface return waitOperator(hostContext.get(key)); } + static evmc_bytes32 getTransientStorage(evmc_host_context* context, + [[maybe_unused]] const evmc_address* addr, const evmc_bytes32* key) noexcept + { + auto& hostContext = static_cast(*context); + return waitOperator(hostContext.getTransientStorage(key)); + } + static evmc_storage_status setStorage(evmc_host_context* context, [[maybe_unused]] const evmc_address* addr, const evmc_bytes32* key, const evmc_bytes32* value) noexcept @@ -68,6 +75,14 @@ struct EVMHostInterface return status; } + static void setTransientStorage(evmc_host_context* context, + [[maybe_unused]] const evmc_address* addr, const evmc_bytes32* key, + const evmc_bytes32* value) noexcept + { + auto& hostContext = static_cast(*context); + waitOperator(hostContext.setTransientStorage(key, value)); + } + static evmc_bytes32 getBalance([[maybe_unused]] evmc_host_context* context, [[maybe_unused]] const evmc_address* addr) noexcept { @@ -155,6 +170,9 @@ struct EVMHostInterface .block_prev_randao = {}, .chain_id = {}, .block_base_fee = {}, + .blob_base_fee = {}, + .blob_hashes = {}, + .blob_hashes_count = 0, }; return result; } @@ -202,6 +220,8 @@ const evmc_host_interface* getHostInterface(auto&& waitOperator) HostContextImpl::log, HostContextImpl::access_account, HostContextImpl::access_storage, + HostContextImpl::getTransientStorage, + HostContextImpl::setTransientStorage, }; return &fnTable; } diff --git a/transaction-executor/bcos-transaction-executor/vm/HostContext.cpp b/transaction-executor/bcos-transaction-executor/vm/HostContext.cpp index 25ba879df8..2dfd5b7789 100644 --- a/transaction-executor/bcos-transaction-executor/vm/HostContext.cpp +++ b/transaction-executor/bcos-transaction-executor/vm/HostContext.cpp @@ -4,7 +4,3 @@ evmc_bytes32 bcos::transaction_executor::evm_hash_fn(const uint8_t* data, size_t { return toEvmC(executor::GlobalHashImpl::g_hashImpl->hash(bytesConstRef(data, size))); } -bcos::executor::VMSchedule const& bcos::transaction_executor::vmSchedule() -{ - return executor::FiscoBcosScheduleV320; -} diff --git a/transaction-executor/bcos-transaction-executor/vm/HostContext.h b/transaction-executor/bcos-transaction-executor/vm/HostContext.h index a6669cbba2..869eca2c70 100644 --- a/transaction-executor/bcos-transaction-executor/vm/HostContext.h +++ b/transaction-executor/bcos-transaction-executor/vm/HostContext.h @@ -68,29 +68,31 @@ struct NotFoundCodeError : public bcos::Error {}; // clang-format on evmc_bytes32 evm_hash_fn(const uint8_t* data, size_t size); -executor::VMSchedule const& vmSchedule(); -static const auto mode = toRevision(vmSchedule()); -template +template class HostContext : public evmc_host_context { private: using Account = ledger::account::EVMAccount; struct Executable { - Executable(storage::Entry code) + Executable(storage::Entry code, evmc_revision revision) : m_code(std::make_optional(std::move(code))), + m_revision(revision), m_vmInstance(VMFactory::create(VMKind::evmone, - bytesConstRef((const uint8_t*)m_code->data(), m_code->size()), mode)) + bytesConstRef((const uint8_t*)m_code->data(), m_code->size()), m_revision)) {} - Executable(bytesConstRef code) : m_vmInstance(VMFactory::create(VMKind::evmone, code, mode)) + Executable(bytesConstRef code, evmc_revision mode) + : m_vmInstance(VMFactory::create(VMKind::evmone, code, mode)) {} std::optional m_code; + evmc_revision m_revision; VMInstance m_vmInstance; }; Storage& m_rollbackableStorage; + TransientStorage& m_rollbackableTransientStorage; protocol::BlockHeader const& m_blockHeader; const evmc_message& m_message; const evmc_address& m_origin; @@ -103,6 +105,7 @@ class HostContext : public evmc_host_context Account m_myAccount; evmc_address m_newContractAddress; // Set by getMyContractTable, no need initialize value! + evmc_revision m_mode; std::vector m_logs; std::shared_ptr m_executable; @@ -161,7 +164,7 @@ class HostContext : public evmc_host_context { } innerConstructor{}; - HostContext(InnerConstructor /*unused*/, Storage& storage, + HostContext(InnerConstructor /*unused*/, Storage& storage, TransientStorage& transientStorage, protocol::BlockHeader const& blockHeader, const evmc_message& message, const evmc_address& origin, std::string_view abi, int contextID, int64_t& seq, PrecompiledManager const& precompiledManager, ledger::LedgerConfig const& ledgerConfig, @@ -173,6 +176,7 @@ class HostContext : public evmc_host_context .version = 0, .metrics = std::addressof(executor::ethMetrics)}, m_rollbackableStorage(storage), + m_rollbackableTransientStorage(transientStorage), m_blockHeader(blockHeader), m_message(message), m_origin(origin), @@ -183,15 +187,25 @@ class HostContext : public evmc_host_context m_ledgerConfig(ledgerConfig), m_hashImpl(hashImpl), m_myAccount(getMyAccount(blockHeader, message)) - {} + { + if (m_ledgerConfig.features().get(ledger::Features::Flag::feature_evm_cancun)) + { + m_mode = EVMC_CANCUN; + } + else + { + m_mode = EVMC_PARIS; + } + } public: - HostContext(Storage& storage, protocol::BlockHeader const& blockHeader, - const evmc_message& message, const evmc_address& origin, std::string_view abi, - int contextID, int64_t& seq, PrecompiledManager const& precompiledManager, - ledger::LedgerConfig const& ledgerConfig, crypto::Hash const& hashImpl, auto&& waitOperator) - : HostContext(innerConstructor, storage, blockHeader, message, origin, abi, contextID, seq, - precompiledManager, ledgerConfig, hashImpl, + HostContext(Storage& storage, TransientStorage& transientStorage, + protocol::BlockHeader const& blockHeader, const evmc_message& message, + const evmc_address& origin, std::string_view abi, int contextID, int64_t& seq, + PrecompiledManager const& precompiledManager, ledger::LedgerConfig const& ledgerConfig, + crypto::Hash const& hashImpl, auto&& waitOperator) + : HostContext(innerConstructor, storage, transientStorage, blockHeader, message, origin, abi, + contextID, seq, precompiledManager, ledgerConfig, hashImpl, getHostInterface(std::forward(waitOperator))) {} @@ -212,6 +226,46 @@ class HostContext : public evmc_host_context co_await ledger::account::setStorage(m_myAccount, *key, *value); } + task::Task getTransientStorage(const evmc_bytes32* key) + { + auto valueEntry = co_await storage2::readOne(m_rollbackableTransientStorage, + transaction_executor::StateKeyView{ + concepts::bytebuffer::toView(co_await ledger::account::path(m_myAccount)), + concepts::bytebuffer::toView(key->bytes)}); + evmc_bytes32 value; + if (valueEntry) + { + auto field = valueEntry->get(); + std::uninitialized_copy_n(field.data(), sizeof(value), value.bytes); + } + else + { + std::uninitialized_fill_n(value.bytes, sizeof(value), 0); + } + if (c_fileLogLevel <= LogLevel::TRACE) + { + HOST_CONTEXT_LOG(TRACE) + << "getTransientStorage:" << LOG_KV("key", concepts::bytebuffer::toView(key->bytes)) + << LOG_KV("value", concepts::bytebuffer::toView(value.bytes)); + } + co_return value; + } + + task::Task setTransientStorage(const evmc_bytes32* key, const evmc_bytes32* value) + { + storage::Entry valueEntry(concepts::bytebuffer::toView(value->bytes)); + StateKey stateKey = + StateKey{concepts::bytebuffer::toView(co_await ledger::account::path(m_myAccount)), + concepts::bytebuffer::toView(key->bytes)}; + if (c_fileLogLevel <= LogLevel::TRACE) + { + HOST_CONTEXT_LOG(TRACE) << "setTransientStorage:" + << LOG_KV("key", concepts::bytebuffer::toView(key->bytes)); + } + co_await storage2::writeOne( + m_rollbackableTransientStorage, stateKey, std::move(valueEntry)); + } + task::Task> code(const evmc_address& address) { auto executable = co_await getExecutable(m_rollbackableStorage, address); @@ -327,9 +381,9 @@ class HostContext : public evmc_host_context messagePtr = std::addressof(*messageWithSender); } - HostContext hostcontext(innerConstructor, m_rollbackableStorage, m_blockHeader, *messagePtr, - m_origin, {}, m_contextID, m_seq, m_precompiledManager, m_ledgerConfig, m_hashImpl, - interface); + HostContext hostcontext(innerConstructor, m_rollbackableStorage, + m_rollbackableTransientStorage, m_blockHeader, *messagePtr, m_origin, {}, m_contextID, + m_seq, m_precompiledManager, m_ledgerConfig, m_hashImpl, interface); co_await hostcontext.prepare(); auto result = co_await hostcontext.execute(); @@ -368,7 +422,7 @@ class HostContext : public evmc_host_context co_return std::shared_ptr{}; } - executable.emplace(std::make_shared(Executable(std::move(*codeEntry)))); + executable.emplace(std::make_shared(Executable(std::move(*codeEntry), m_mode))); co_await storage2::writeOne(cachedExecutables, address, *executable); co_return std::move(*executable); } @@ -376,21 +430,21 @@ class HostContext : public evmc_host_context void prepareCreate() { bytesConstRef createCode(m_message.input_data, m_message.input_size); - m_executable = std::make_shared(createCode); + m_executable = std::make_shared(createCode, m_mode); } task::Task executeCreate() { auto savepoint = m_rollbackableStorage.current(); + auto transientSavepoint = m_rollbackableTransientStorage.current(); if (m_ledgerConfig.authCheckStatus() != 0U) { createAuthTable(m_rollbackableStorage, m_blockHeader, m_message, m_origin, co_await ledger::account::path(m_myAccount), buildLegacyExternalCaller(), m_precompiledManager); } - auto result = m_executable->m_vmInstance.execute( - interface, this, mode, &m_message, m_message.input_data, m_message.input_size); + interface, this, m_mode, &m_message, m_message.input_data, m_message.input_size); if (result.status_code == 0) { auto code = bytesConstRef(result.output_data, result.output_size); @@ -399,13 +453,14 @@ class HostContext : public evmc_host_context co_await ledger::account::create(m_myAccount); co_await ledger::account::setCode( m_myAccount, code.toBytes(), std::string(m_abi), codeHash); - - result.gas_left -= result.output_size * vmSchedule().createDataGas; + auto schedule = bcos::executor::VMSchedule(); + result.gas_left -= result.output_size * schedule.createDataGas; result.create_address = m_newContractAddress; } else { co_await m_rollbackableStorage.rollback(savepoint); + co_await m_rollbackableTransientStorage.rollback(transientSavepoint); } co_return result; @@ -433,6 +488,7 @@ class HostContext : public evmc_host_context task::Task executeCall() { auto savepoint = m_rollbackableStorage.current(); + auto transientSavepoint = m_rollbackableTransientStorage.current(); if (m_preparedPrecompiled != nullptr) { co_return transaction_executor::callPrecompiled(*m_preparedPrecompiled, @@ -444,12 +500,13 @@ class HostContext : public evmc_host_context { m_executable = co_await getExecutable(m_rollbackableStorage, m_message.code_address); } - auto result = m_executable->m_vmInstance.execute(interface, this, mode, &m_message, + auto result = m_executable->m_vmInstance.execute(interface, this, m_mode, &m_message, (const uint8_t*)m_executable->m_code->data(), m_executable->m_code->size()); if (result.status_code != 0) { HOST_CONTEXT_LOG(DEBUG) << "Execute transaction failed, status: " << result.status_code; co_await m_rollbackableStorage.rollback(savepoint); + co_await m_rollbackableTransientStorage.rollback(transientSavepoint); } co_return result; diff --git a/transaction-executor/bcos-transaction-executor/vm/VMInstance.cpp b/transaction-executor/bcos-transaction-executor/vm/VMInstance.cpp index 1610096b85..1dedbe1629 100644 --- a/transaction-executor/bcos-transaction-executor/vm/VMInstance.cpp +++ b/transaction-executor/bcos-transaction-executor/vm/VMInstance.cpp @@ -1,4 +1,6 @@ #include "VMInstance.h" +#include "bcos-transaction-executor/TransactionExecutorImpl.h" +using bytes_view = std::basic_string_view; bcos::transaction_executor::VMInstance::VMInstance( std::shared_ptr instance) noexcept @@ -10,20 +12,17 @@ bcos::transaction_executor::EVMCResult bcos::transaction_executor::VMInstance::e const evmc_message* msg, const uint8_t* code, size_t codeSize) { static auto const* evm = evmc_create_evmone(); - static thread_local std::unique_ptr - localExecutionState; + static thread_local std::unique_ptr localExecutionState; auto executionState = std::move(localExecutionState); if (!executionState) { - executionState = std::make_unique(); + executionState = std::make_unique(); } - executionState->reset( - *msg, rev, *host, context, std::basic_string_view(code, codeSize)); + *msg, rev, *host, context, std::basic_string_view(code, codeSize), {}); auto result = EVMCResult(evmone::baseline::execute( *static_cast(evm), msg->gas, *executionState, *m_instance)); - if (!localExecutionState) { localExecutionState = std::move(executionState); diff --git a/transaction-executor/tests/StorageContract.sol b/transaction-executor/tests/StorageContract.sol new file mode 100644 index 0000000000..a34a8a7685 --- /dev/null +++ b/transaction-executor/tests/StorageContract.sol @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "./StorageSlot.sol"; + +contract StorageContract { + using StorageSlot for *; + + StorageSlot.AddressSlotType private addressSlot = StorageSlot.asAddress(keccak256("address_slot")); + StorageSlot.BooleanSlotType private booleanSlot = StorageSlot.asBoolean(keccak256("boolean_slot")); + StorageSlot.Bytes32SlotType private bytes32Slot = StorageSlot.asBytes32(keccak256("bytes32_slot")); + StorageSlot.Uint256SlotType private uint256Slot = StorageSlot.asUint256(keccak256("uint256_slot")); + StorageSlot.Int256SlotType private int256Slot = StorageSlot.asInt256(keccak256("int256_slot")); + + function setAddress(address _value) public { + addressSlot.tstore(_value); + } + + function getAddress() public view returns (address) { + return addressSlot.tload(); + } + + function setBoolean(bool _value) public { + booleanSlot.tstore(_value); + } + + function getBoolean() public view returns (bool) { + return booleanSlot.tload(); + } + + function setBytes32(bytes32 _value) public { + bytes32Slot.tstore(_value); + } + + function getBytes32() public view returns (bytes32) { + return bytes32Slot.tload(); + } + + function setUint256(uint256 _value) public { + uint256Slot.tstore(_value); + } + + function getUint256() public view returns (uint256) { + return uint256Slot.tload(); + } + + function setInt256(int256 _value) public { + int256Slot.tstore(_value); + } + + function getInt256() public view returns (int256) { + return int256Slot.tload(); + } + + function storeIntTest(int256 _value) public returns (int256) { + int256Slot.tstore(_value); + return int256Slot.tload(); + } +} +// Path: transaction-executor/tests/ContractA.sol +pragma solidity ^0.8.25; + +import "./StorageSlot.sol"; +import "./ContractB.sol"; + +contract ContractA { + using StorageSlot for *; + + StorageSlot.Int256SlotType private intSlot; + constructor(int256 value){ + StorageSlot.tstore(intSlot, value); + } + + function getData() public view returns (int256) { + return StorageSlot.tload(intSlot); + } + + function callContractB() public returns (int256){ + ContractB b = new ContractB(); + return b.callContractA(address(this)); + } + +} + +// Path: transaction-executor/tests/ContractA.sol +import "./StorageSlot.sol"; +import "./ContractA.sol"; + + +contract ContractB { + + function callContractA(address a) public returns (int256){ + ContractA a = ContractA(a); + int256 result = a.getData(); + return result; + } + +} +// Path: transaction-executor/tests/MainContract.sol +import "./StorageSlot.sol"; +import "./ContractA.sol"; +import "./ContractB.sol"; + +contract MainContract { + + + function checkAndVerifyIntValue(int256 value) public returns (bool) { + ContractA a = new ContractA(value); + int256 result = a.callContractB(); + require(result == value, "store value not equal tload result"); + return true; + } +} \ No newline at end of file diff --git a/transaction-executor/tests/StorageSlot.sol b/transaction-executor/tests/StorageSlot.sol new file mode 100644 index 0000000000..56c13ef290 --- /dev/null +++ b/transaction-executor/tests/StorageSlot.sol @@ -0,0 +1,193 @@ +pragma solidity ^0.8.24; + +library StorageSlot { + struct AddressSlot { + address value; + } + + struct BooleanSlot { + bool value; + } + + struct Bytes32Slot { + bytes32 value; + } + + struct Uint256Slot { + uint256 value; + } + + struct Int256Slot { + int256 value; + } + + struct StringSlot { + string value; + } + + struct BytesSlot { + bytes value; + } + + function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { + assembly { + r.slot := slot + } + } + + function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := store.slot + } + } + + function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := store.slot + } + } + + type AddressSlotType is bytes32; + + function asAddress(bytes32 slot) internal pure returns (AddressSlotType) { + return AddressSlotType.wrap(slot); + } + + type BooleanSlotType is bytes32; + + function asBoolean(bytes32 slot) internal pure returns (BooleanSlotType) { + return BooleanSlotType.wrap(slot); + } + + type Bytes32SlotType is bytes32; + + function asBytes32(bytes32 slot) internal pure returns (Bytes32SlotType) { + return Bytes32SlotType.wrap(slot); + } + + type Uint256SlotType is bytes32; + + function asUint256(bytes32 slot) internal pure returns (Uint256SlotType) { + return Uint256SlotType.wrap(slot); + } + + type Int256SlotType is bytes32; + + function asInt256(bytes32 slot) internal pure returns (Int256SlotType) { + return Int256SlotType.wrap(slot); + } + + function tload(AddressSlotType slot) internal view returns (address value) { + /// @solidity memory-safe-assembly + assembly { + value := tload(slot) + } + } + + function tstore(AddressSlotType slot, address value) internal { + /// @solidity memory-safe-assembly + assembly { + tstore(slot, value) + } + } + + function tload(BooleanSlotType slot) internal view returns (bool value) { + /// @solidity memory-safe-assembly + assembly { + value := tload(slot) + } + } + + function tstore(BooleanSlotType slot, bool value) internal { + /// @solidity memory-safe-assembly + assembly { + tstore(slot, value) + } + } + + function tload(Bytes32SlotType slot) internal view returns (bytes32 value) { + /// @solidity memory-safe-assembly + assembly { + value := tload(slot) + } + } + + function tstore(Bytes32SlotType slot, bytes32 value) internal { + /// @solidity memory-safe-assembly + assembly { + tstore(slot, value) + } + } + + function tload(Uint256SlotType slot) internal view returns (uint256 value) { + /// @solidity memory-safe-assembly + assembly { + value := tload(slot) + } + } + + function tstore(Uint256SlotType slot, uint256 value) internal { + /// @solidity memory-safe-assembly + assembly { + tstore(slot, value) + } + } + + function tload(Int256SlotType slot) internal view returns (int256 value) { + /// @solidity memory-safe-assembly + assembly { + value := tload(slot) + } + } + + function tstore(Int256SlotType slot, int256 value) internal { + /// @solidity memory-safe-assembly + assembly { + tstore(slot, value) + } + } +} \ No newline at end of file diff --git a/transaction-executor/tests/TestBytecode.h b/transaction-executor/tests/TestBytecode.h index 9242bff940..29884662c3 100644 --- a/transaction-executor/tests/TestBytecode.h +++ b/transaction-executor/tests/TestBytecode.h @@ -129,3 +129,96 @@ constexpr static std::string_view helloworldBytecode = "6970667358221220fa853e743e1e2a844a7a788534a46c2dce6fbff27bef6a64ac3c15c67549f2e164736f6c634300" "08120033a26469706673582212207f4fa2554331e8c5ef4917fea82fc88828584fb34b5f7a57d6d48d7b832d5cf564" "736f6c63430008120033"; + +constexpr static std::string_view transientStorageBytecode = + "60806040526100337fbad128a9c9f118267291de46fed9cb24d9fbbe19a927cfee43cdc3b8e4eba17161010e60201b" + "60201c565b5f556100647fe51529ae218841954601d43f697e9bb24b282c1a2ddf95745a7e79ee1b4b7b7d61011760" + "201b60201c565b6001556100967f5d4010ae4473cd3ede543746d54ec6f990232434c2d4884f06e3cc4ac77168e561" + "012060201b60201c565b6002556100c87fb734117ebc01eac75f020b05b2620ab71735dfa2175ac8e98f85bd7f529b" + "b96f61012960201b60201c565b6003556100fa7feb7753d6e9a22bf47d9682cdc6f111b5defde6c206047689bad231" + "20af3743bd61013260201b60201c565b600455348015610108575f80fd5b5061013b565b5f819050919050565b5f81" + "9050919050565b5f819050919050565b5f819050919050565b5f819050919050565b610653806101485f395ff3fe60" + "8060405234801561000f575f80fd5b50600436106100a7575f3560e01c8063a65e939e1161006f578063a65e939e14" + "610153578063c2b12a7314610183578063d2282dc51461019f578063e30081a0146101bb578063f5b53e17146101d7" + "578063f8462a0f146101f5576100a7565b80631f903037146100ab5780632d1be94d146100c957806338cc48311461" + "00e75780636889597914610105578063a53b1c1e14610123575b5f80fd5b6100b3610211565b6040516100c0919061" + "036a565b60405180910390f35b6100d1610222565b6040516100de919061039d565b60405180910390f35b6100ef61" + "0233565b6040516100fc91906103f5565b60405180910390f35b61010d610243565b60405161011a9190610426565b" + "60405180910390f35b61013d60048036038101906101389190610476565b610254565b60405161014a919061039d56" + "5b60405180910390f35b61016d60048036038101906101689190610476565b610273565b60405161017a91906104b0" + "565b60405180910390f35b61019d600480360381019061019891906104f3565b61028d565b005b6101b96004803603" + "8101906101b49190610548565b6102a5565b005b6101d560048036038101906101d0919061059d565b6102bd565b00" + "5b6101df6102d4565b6040516101ec91906104b0565b60405180910390f35b61020f600480360381019061020a9190" + "6105f2565b6102e5565b005b5f61021d6002546102fd565b905090565b5f61022e600154610307565b905090565b5f" + "61023e5f54610311565b905090565b5f61024f60035461031b565b905090565b5f61026a8260045461032590919063" + "ffffffff16565b60019050919050565b5f61027d82610254565b506102866102d4565b9050919050565b6102a28160" + "025461032c90919063ffffffff16565b50565b6102ba8160035461033390919063ffffffff16565b50565b6102d181" + "5f5461033a90919063ffffffff16565b50565b5f6102e0600454610341565b905090565b6102fa8160015461034b90" + "919063ffffffff16565b50565b5f815c9050919050565b5f815c9050919050565b5f815c9050919050565b5f815c90" + "50919050565b80825d5050565b80825d5050565b80825d5050565b80825d5050565b5f815c9050919050565b80825d" + "5050565b5f819050919050565b61036481610352565b82525050565b5f60208201905061037d5f83018461035b565b" + "92915050565b5f8115159050919050565b61039781610383565b82525050565b5f6020820190506103b05f83018461" + "038e565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6103df8261" + "03b6565b9050919050565b6103ef816103d5565b82525050565b5f6020820190506104085f8301846103e6565b9291" + "5050565b5f819050919050565b6104208161040e565b82525050565b5f6020820190506104395f830184610417565b" + "92915050565b5f80fd5b5f819050919050565b61045581610443565b811461045f575f80fd5b50565b5f8135905061" + "04708161044c565b92915050565b5f6020828403121561048b5761048a61043f565b5b5f6104988482850161046256" + "5b91505092915050565b6104aa81610443565b82525050565b5f6020820190506104c35f8301846104a1565b929150" + "50565b6104d281610352565b81146104dc575f80fd5b50565b5f813590506104ed816104c9565b92915050565b5f60" + "2082840312156105085761050761043f565b5b5f610515848285016104df565b91505092915050565b610527816104" + "0e565b8114610531575f80fd5b50565b5f813590506105428161051e565b92915050565b5f6020828403121561055d" + "5761055c61043f565b5b5f61056a84828501610534565b91505092915050565b61057c816103d5565b811461058657" + "5f80fd5b50565b5f8135905061059781610573565b92915050565b5f602082840312156105b2576105b161043f565b" + "5b5f6105bf84828501610589565b91505092915050565b6105d181610383565b81146105db575f80fd5b50565b5f81" + "3590506105ec816105c8565b92915050565b5f602082840312156106075761060661043f565b5b5f61061484828501" + "6105de565b9150509291505056fea2646970667358221220d88517d2dffabcb325b3b34f932814eb3c9b3a6167aa58" + "814fcc57b116d57fbb64736f6c63430008190033"; + +constexpr static std::string_view transientStorageContractTestByteCode = + "6080604052348015600e575f80fd5b506108748061001c5f395ff3fe608060405234801561000f575f80fd5b506004" + "3610610029575f3560e01c8063fa3e317e1461002d575b5f80fd5b6100476004803603810190610042919061019456" + "5b61005d565b60405161005491906101d9565b60405180910390f35b5f808260405161006c90610150565b61007691" + "90610201565b604051809103905ff08015801561008f573d5f803e3d5ffd5b5090505f8173ffffffffffffffffffff" + "ffffffffffffffffffff16636428f3dc6040518163ffffffff1660e01b81526004016020604051808303815f875af1" + "1580156100dd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610101919061" + "022e565b9050838114610145576040517f08c379a00000000000000000000000000000000000000000000000000000" + "0000815260040161013c906102d9565b60405180910390fd5b600192505050919050565b610547806102f883390190" + "565b5f80fd5b5f819050919050565b61017381610161565b811461017d575f80fd5b50565b5f8135905061018e8161" + "016a565b92915050565b5f602082840312156101a9576101a861015d565b5b5f6101b684828501610180565b915050" + "92915050565b5f8115159050919050565b6101d3816101bf565b82525050565b5f6020820190506101ec5f83018461" + "01ca565b92915050565b6101fb81610161565b82525050565b5f6020820190506102145f8301846101f2565b929150" + "50565b5f815190506102288161016a565b92915050565b5f602082840312156102435761024261015d565b5b5f6102" + "508482850161021a565b91505092915050565b5f82825260208201905092915050565b7f73746f72652076616c7565" + "206e6f7420657175616c20746c6f616420726573755f8201527f6c7400000000000000000000000000000000000000" + "0000000000000000000000602082015250565b5f6102c3602283610259565b91506102ce82610269565b6040820190" + "50919050565b5f6020820190508181035f8301526102f0816102b7565b905091905056fe6080604052348015600e57" + "5f80fd5b506040516105473803806105478339818101604052810190602e9190607b565b603d5f5482604260201b60" + "201c565b5060a1565b80825d5050565b5f80fd5b5f819050919050565b605d81604d565b81146066575f80fd5b5056" + "5b5f815190506075816056565b92915050565b5f60208284031215608d57608c6049565b5b5f609884828501606956" + "5b91505092915050565b610499806100ae5f395ff3fe608060405234801561000f575f80fd5b506004361061003457" + "5f3560e01c80633bc5de30146100385780636428f3dc14610056575b5f80fd5b610040610074565b60405161004d91" + "9061015c565b60405180910390f35b61005e610084565b60405161006b919061015c565b60405180910390f35b5f61" + "007f5f5461012d565b905090565b5f8060405161009290610137565b604051809103905ff0801580156100ab573d5f" + "803e3d5ffd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663c1df0f48306040518263ffffffff" + "1660e01b81526004016100e791906101b4565b6020604051808303815f875af1158015610103573d5f803e3d5ffd5b" + "505050506040513d601f19601f8201168201806040525081019061012791906101fb565b91505090565b5f815c9050" + "919050565b61023d8061022783390190565b5f819050919050565b61015681610144565b82525050565b5f60208201" + "905061016f5f83018461014d565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff8216905091" + "9050565b5f61019e82610175565b9050919050565b6101ae81610194565b82525050565b5f6020820190506101c75f" + "8301846101a5565b92915050565b5f80fd5b6101da81610144565b81146101e4575f80fd5b50565b5f815190506101" + "f5816101d1565b92915050565b5f602082840312156102105761020f6101cd565b5b5f61021d848285016101e7565b" + "9150509291505056fe6080604052348015600e575f80fd5b506102218061001c5f395ff3fe60806040523480156100" + "0f575f80fd5b5060043610610029575f3560e01c8063c1df0f481461002d575b5f80fd5b6100476004803603810190" + "610042919061013a565b61005d565b604051610054919061017d565b60405180910390f35b5f808290505f8173ffff" + "ffffffffffffffffffffffffffffffffffff16633bc5de306040518163ffffffff1660e01b81526004016020604051" + "80830381865afa1580156100ac573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101" + "906100d091906101c0565b90508092505050919050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffff" + "ffff82169050919050565b5f610109826100e0565b9050919050565b610119816100ff565b8114610123575f80fd5b" + "50565b5f8135905061013481610110565b92915050565b5f6020828403121561014f5761014e6100dc565b5b5f6101" + "5c84828501610126565b91505092915050565b5f819050919050565b61017781610165565b82525050565b5f602082" + "0190506101905f83018461016e565b92915050565b61019f81610165565b81146101a9575f80fd5b50565b5f815190" + "506101ba81610196565b92915050565b5f602082840312156101d5576101d46100dc565b5b5f6101e2848285016101" + "ac565b9150509291505056fea2646970667358221220b74855b53bcf2b3cc2261d3f57e16507da8b24f81ff5196991" + "91e34ce025bc8664736f6c63430008190033a26469706673582212201eb1e02998c84b08c3db1bdb2487184ca8357f" + "1d2739ec65daa47ffe3e89316a64736f6c63430008190033a2646970667358221220bad0e7bec379be9bb4f446b845" + "050f59959e8bd9da49d83f3c9f669a63e5e51e64736f6c63430008190033"; \ No newline at end of file diff --git a/transaction-executor/tests/TestHostContext.cpp b/transaction-executor/tests/TestHostContext.cpp index 90bbd19e5b..c3dc9a7b31 100644 --- a/transaction-executor/tests/TestHostContext.cpp +++ b/transaction-executor/tests/TestHostContext.cpp @@ -40,12 +40,21 @@ class TestHostContextFixture bcos::crypto::Hash::Ptr hashImpl = std::make_shared(); MutableStorage storage; Rollbackable rollbackableStorage; + using MemoryStorageType = + bcos::storage2::memory_storage::MemoryStorage; + MemoryStorageType transientStorage; + Rollbackable rollbackableTransientStorage; evmc_address helloworldAddress; int64_t seq = 0; std::optional precompiledManager; bcos::ledger::LedgerConfig ledgerConfig; - TestHostContextFixture() : rollbackableStorage(storage) + TestHostContextFixture() + : rollbackableStorage(storage), rollbackableTransientStorage(transientStorage) { bcos::executor::GlobalHashImpl::g_hashImpl = std::make_shared(); precompiledManager.emplace(hashImpl); @@ -76,9 +85,10 @@ class TestHostContextFixture .code_address = {}}; evmc_address origin = {}; - HostContext hostContext(rollbackableStorage, blockHeader, - message, origin, "", 0, seq, *precompiledManager, ledgerConfig, *hashImpl, - bcos::task::syncWait); + HostContext + hostContext(rollbackableStorage, rollbackableTransientStorage, blockHeader, message, + origin, "", 0, seq, *precompiledManager, ledgerConfig, *hashImpl, + bcos::task::syncWait); syncWait(hostContext.prepare()); auto result = syncWait(hostContext.execute()); @@ -118,9 +128,10 @@ class TestHostContextFixture .code_address = helloworldAddress}; evmc_address origin = {}; - HostContext hostContext(rollbackableStorage, blockHeader, - message, origin, "", 0, seq, *precompiledManager, ledgerConfig, *hashImpl, - bcos::task::syncWait); + HostContext + hostContext(rollbackableStorage, rollbackableTransientStorage, blockHeader, message, + origin, "", 0, seq, *precompiledManager, ledgerConfig, *hashImpl, + bcos::task::syncWait); co_await hostContext.prepare(); auto result = co_await hostContext.execute(); @@ -335,9 +346,10 @@ BOOST_AUTO_TEST_CASE(precompiled) .code_address = callAddress}; evmc_address origin = {}; - HostContext hostContext(rollbackableStorage, blockHeader, - message, origin, "", 0, seq, *precompiledManager, ledgerConfig, *hashImpl, - bcos::task::syncWait); + HostContext + hostContext(rollbackableStorage, rollbackableTransientStorage, blockHeader, message, + origin, "", 0, seq, *precompiledManager, ledgerConfig, *hashImpl, + bcos::task::syncWait); syncWait(hostContext.prepare()); auto result = syncWait(hostContext.execute()); } @@ -366,9 +378,10 @@ BOOST_AUTO_TEST_CASE(precompiled) .code_address = callAddress}; evmc_address origin = {}; - HostContext hostContext(rollbackableStorage, blockHeader, - message, origin, "", 0, seq, *precompiledManager, ledgerConfig, *hashImpl, - bcos::task::syncWait); + HostContext + hostContext(rollbackableStorage, rollbackableTransientStorage, blockHeader, message, + origin, "", 0, seq, *precompiledManager, ledgerConfig, *hashImpl, + bcos::task::syncWait); syncWait(hostContext.prepare()); result.emplace(syncWait(hostContext.execute())); } diff --git a/transaction-executor/tests/TestTransactionExecutor.cpp b/transaction-executor/tests/TestTransactionExecutor.cpp index 7f1db7fdf3..cd4d9868bf 100644 --- a/transaction-executor/tests/TestTransactionExecutor.cpp +++ b/transaction-executor/tests/TestTransactionExecutor.cpp @@ -73,5 +73,98 @@ BOOST_AUTO_TEST_CASE(execute) BOOST_CHECK_EQUAL(getIntResult, 10099); }()); } +BOOST_AUTO_TEST_CASE(transientStorageTest) +{ + task::syncWait([this]() mutable -> task::Task { + MutableStorage storage; + + auto cryptoSuite = std::make_shared( + bcos::executor::GlobalHashImpl::g_hashImpl, nullptr, nullptr); + bcostars::protocol::TransactionReceiptFactoryImpl receiptFactory(cryptoSuite); + + bcos::transaction_executor::TransactionExecutorImpl executor( + receiptFactory, bcos::executor::GlobalHashImpl::g_hashImpl); + bcostars::protocol::BlockHeaderImpl blockHeader( + [inner = bcostars::BlockHeader()]() mutable { return std::addressof(inner); }); + blockHeader.setVersion((uint32_t)bcos::protocol::BlockVersion::V3_7_0_VERSION); + blockHeader.calculateHash(*bcos::executor::GlobalHashImpl::g_hashImpl); + + bcostars::protocol::TransactionFactoryImpl transactionFactory(cryptoSuite); + + // turn on evm_cancun feature + ledger::Features features; + features.set(ledger::Features::Flag::feature_evm_cancun); + ledgerConfig.setFeatures(features); + + bcos::bytes transientStorageBinary; + boost::algorithm::unhex( + transientStorageBytecode, std::back_inserter(transientStorageBinary)); + // First deploy + auto transaction = + transactionFactory.createTransaction(0, "", transientStorageBinary, {}, 0, "", "", 0); + auto receipt = co_await bcos::transaction_executor::executeTransaction( + executor, storage, blockHeader, *transaction, 3, ledgerConfig, task::syncWait); + BOOST_CHECK_EQUAL(receipt->status(), 0); + + // test read and write transient storage + bcos::codec::abi::ContractABICodec abiCodec(bcos::executor::GlobalHashImpl::g_hashImpl); + auto input = abiCodec.abiIn("storeIntTest(int256)", bcos::s256(10000)); + auto transaction2 = transactionFactory.createTransaction( + 0, std::string(receipt->contractAddress()), input, {}, 0, "", "", 0); + auto receipt2 = co_await bcos::transaction_executor::executeTransaction( + executor, storage, blockHeader, *transaction2, 4, ledgerConfig, task::syncWait); + BOOST_CHECK_EQUAL(receipt2->status(), 0); + bcos::s256 getIntResult = -1; + abiCodec.abiOut(receipt2->output(), getIntResult); + BOOST_CHECK_EQUAL(getIntResult, 10000); + }()); +} + +BOOST_AUTO_TEST_CASE(transientStorageContractTest) +{ + task::syncWait([this]() mutable -> task::Task { + MutableStorage storage; + + auto cryptoSuite = std::make_shared( + bcos::executor::GlobalHashImpl::g_hashImpl, nullptr, nullptr); + bcostars::protocol::TransactionReceiptFactoryImpl receiptFactory(cryptoSuite); + + bcos::transaction_executor::TransactionExecutorImpl executor( + receiptFactory, bcos::executor::GlobalHashImpl::g_hashImpl); + bcostars::protocol::BlockHeaderImpl blockHeader( + [inner = bcostars::BlockHeader()]() mutable { return std::addressof(inner); }); + blockHeader.setVersion((uint32_t)bcos::protocol::BlockVersion::V3_1_VERSION); + blockHeader.calculateHash(*bcos::executor::GlobalHashImpl::g_hashImpl); + + bcostars::protocol::TransactionFactoryImpl transactionFactory(cryptoSuite); + + // turn on evm_cancun feature + ledger::Features features; + features.set(ledger::Features::Flag::feature_evm_cancun); + ledgerConfig.setFeatures(features); + + bcos::bytes transientStorageBinary; + boost::algorithm::unhex( + transientStorageContractTestByteCode, std::back_inserter(transientStorageBinary)); + // First deploy + auto transaction = + transactionFactory.createTransaction(0, "", transientStorageBinary, {}, 0, "", "", 0); + auto receipt = co_await bcos::transaction_executor::executeTransaction( + executor, storage, blockHeader, *transaction, 5, ledgerConfig, task::syncWait); + BOOST_CHECK_EQUAL(receipt->status(), 0); + + // test read and write transient storage + bcos::codec::abi::ContractABICodec abiCodec(bcos::executor::GlobalHashImpl::g_hashImpl); + auto input = abiCodec.abiIn("checkAndVerifyIntValue(int256)", bcos::h256(12345)); + auto transaction2 = transactionFactory.createTransaction( + 0, std::string(receipt->contractAddress()), input, {}, 0, "", "", 0); + auto receipt2 = co_await bcos::transaction_executor::executeTransaction( + executor, storage, blockHeader, *transaction2, 6, ledgerConfig, task::syncWait); + BOOST_CHECK_EQUAL(receipt2->status(), 0); + bool checkResult = false; + abiCodec.abiOut(receipt2->output(), checkResult); + BOOST_CHECK_EQUAL(checkResult, true); + }()); +} BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json index fb7837cceb..4d87f8172c 100644 --- a/vcpkg-configuration.json +++ b/vcpkg-configuration.json @@ -3,7 +3,7 @@ { "kind": "git", "repository": "https://github.com/FISCO-BCOS/registry", - "baseline": "d9d17621556f919cab688e8d60cb76ceca24f5bb", + "baseline": "e2d5ceff3836b83c1f606fcc2afaae3e236baa30", "packages": [ "openssl", "evmone", diff --git a/vcpkg.json b/vcpkg.json index 9d6c8e85fb..2b12240daa 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -56,11 +56,11 @@ "dependencies": [ { "name": "evmone", - "version>=": "0.10.0" + "version>=": "0.11.0" }, { "name": "evmc", - "version>=": "10.1.0" + "version>=": "11.0.1" }, { "name": "boost-coroutine2", From 7301b8feb64fbaf2616b17235c0c27c07b9104da Mon Sep 17 00:00:00 2001 From: wenlinli <1574249665@qq.com> Date: Thu, 30 May 2024 10:10:47 +0800 Subject: [PATCH 02/16] add point_evaluation Precompiled.cpp and add ut (#4489) --- bcos-crypto/test/unittests/HashTest.cpp | 15 +- bcos-executor/CMakeLists.txt | 4 +- bcos-executor/src/vm/Precompiled.cpp | 78 ++-- bcos-executor/src/vm/kzgPrecompiled.h | 409 +++++++++--------- .../libprecompiled/PrecompiledTest.cpp | 83 ++++ 5 files changed, 355 insertions(+), 234 deletions(-) create mode 100644 bcos-executor/test/unittest/libprecompiled/PrecompiledTest.cpp diff --git a/bcos-crypto/test/unittests/HashTest.cpp b/bcos-crypto/test/unittests/HashTest.cpp index edc3892649..71f3b648d3 100644 --- a/bcos-crypto/test/unittests/HashTest.cpp +++ b/bcos-crypto/test/unittests/HashTest.cpp @@ -124,17 +124,24 @@ BOOST_AUTO_TEST_CASE(testSha3) h256("3338be694f50c5f338814986cdf0686453a888b84f424d792af4b9202398f392")); } -BOOST_AUTO_TEST_CASE(SHA256_test) { +BOOST_AUTO_TEST_CASE(SHA256_test) +{ HashType hash; auto sha256 = std::make_shared(); bcos::bytes input{}; hash = sha256->hash(bcos::ref(input)); - BOOST_CHECK_EQUAL(hash.hex(), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + BCOS_LOG(DEBUG) << "hash: " << hash.hex(); + BOOST_CHECK_EQUAL( + hash.hex(), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); - std::string data = "1234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678"; + std::string data = + "123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812" + "3456781234567812345678"; input += bcos::fromHex(data); hash = sha256->hash(bcos::ref(input)); - BOOST_REQUIRE_EQUAL(hash.hex(), "7303caef875be8c39b2c2f1905ea24adcc024bef6830a965fe05370f3170dc52"); + BCOS_LOG(DEBUG) << "hash: " << hash.hex(); + BOOST_REQUIRE_EQUAL( + hash.hex(), "7303caef875be8c39b2c2f1905ea24adcc024bef6830a965fe05370f3170dc52"); } BOOST_AUTO_TEST_SUITE_END() } // namespace test diff --git a/bcos-executor/CMakeLists.txt b/bcos-executor/CMakeLists.txt index 67ab42ad33..17da9a85f9 100644 --- a/bcos-executor/CMakeLists.txt +++ b/bcos-executor/CMakeLists.txt @@ -18,10 +18,10 @@ file(GLOB_RECURSE SRCS src/*.cpp) add_library(${EXECUTOR_TARGET} ${SRCS}) if(WITH_WASM) target_link_libraries(${EXECUTOR_TARGET} PUBLIC jsoncpp_static ${CODEC_TARGET} ${TOOL_TARGET} ${CRYPTO_TARGET} ${TABLE_TARGET} wedprcrypto::fisco-bcos bcos-protocol - Boost::context evmone fbwasm evmc::loader evmc::instructions wabt GroupSig Paillier) + Boost::context evmone fbwasm evmc::loader evmc::instructions wabt GroupSig Paillier blst) else() target_link_libraries(${EXECUTOR_TARGET} PUBLIC jsoncpp_static ${CODEC_TARGET} ${TOOL_TARGET} ${CRYPTO_TARGET} ${TABLE_TARGET} wedprcrypto::fisco-bcos bcos-protocol - Boost::context evmone evmc::loader evmc::instructions GroupSig Paillier) + Boost::context evmone evmc::loader evmc::instructions GroupSig Paillier blst) endif() if (TOOLS) diff --git a/bcos-executor/src/vm/Precompiled.cpp b/bcos-executor/src/vm/Precompiled.cpp index c3930dc63e..79b77caac4 100644 --- a/bcos-executor/src/vm/Precompiled.cpp +++ b/bcos-executor/src/vm/Precompiled.cpp @@ -287,37 +287,53 @@ ETH_REGISTER_PRECOMPILED_PRICER(blake2_compression) return rounds; } -// ETH_REGISTER_PRECOMPILED(point_evaluation)(bytesConstRef _in) -//{ -// static constexpr size_t versioned_hash_size = 32; -// static constexpr size_t z_end_bound = 64; -// static constexpr size_t y_end_bound = 96; -// static constexpr size_t commitment_end_bound = 144; -// static constexpr size_t proof_end_bound = 192; -// -// if(_in.size() != 192) -// return {false, {}}; -// -// auto const versioned_hash = _in.getCroppedData(0, versioned_hash_size); -// auto const z = _in.getCroppedData(versioned_hash_size, z_end_bound); -// auto const y = _in.getCroppedData(z_end_bound, y_end_bound); -// auto const commitment = _in.getCroppedData(y_end_bound, commitment_end_bound); -// auto const proof = _in.getCroppedData(commitment_end_bound, proof_end_bound); -// -// auto kzg = make_shared(); -// if(kzg->kzg2VersionedHash(commitment) != sha256(versioned_hash)) -// return {false, {}}; -// -// if(!kzg->verifyKZGProof(proof, commitment, z, y)) -// return {false, {}}; -// -// return {true, {}}; -// } -// -// ETH_REGISTER_PRECOMPILED_PRICER(point_evaluation)(bytesConstRef _in) -//{ -// return 45000; -// } +// The precompiled contract for point evaluation, EIP-4844: +// https://eips.ethereum.org/EIPS/eip-4844#point-evaluation-precompile +ETH_REGISTER_PRECOMPILED(point_evaluation)(bytesConstRef _in) +{ + static constexpr size_t versioned_hash_size = 32; + static constexpr size_t z_end_bound = 64; + static constexpr size_t y_end_bound = 96; + static constexpr size_t commitment_end_bound = 144; + static constexpr size_t proof_end_bound = 192; + + if (_in.size() != 192) + return {false, {}}; + + auto const versioned_hash = _in.getCroppedData(0, versioned_hash_size); + auto const z = _in.getCroppedData(versioned_hash_size, z_end_bound - versioned_hash_size); + auto const y = _in.getCroppedData(z_end_bound, y_end_bound - z_end_bound); + auto const commitment = _in.getCroppedData(y_end_bound, commitment_end_bound - y_end_bound); + auto const proof = + _in.getCroppedData(commitment_end_bound, proof_end_bound - commitment_end_bound); + + auto kzg = make_shared(); + + if (kzg->kzg2VersionedHash(commitment) != h256(versioned_hash)) + { + BCOS_LOG(ERROR) << LOG_DESC("versioned_hash not equal"); + return {false, {}}; + } + + if (!kzg->verifyKZGProof(commitment, z, y, proof)) + { + BCOS_LOG(ERROR) << LOG_DESC("verifyKZGProof failed"); + return {false, {}}; + } + + // Return FIELD_ELEMENTS_PER_BLOB and BLS_MODULUS as padded 32 byte big endian values + // return turn and Bytes(U256(FIELD_ELEMENTS_PER_BLOB).to_be_bytes32() + + // U256(BLS_MODULUS).to_be_bytes32()) refer to + // https://github.com/erigontech/silkworm/blob/85ba5171e88855a6702602d38f102aae9b896f9c/silkworm/core/execution/precompile.cpp#L502-L524 + return {true, + *bcos::fromHexString("000000000000000000000000000000000000000000000000000000000000100073eda" + "753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001")}; +} + +ETH_REGISTER_PRECOMPILED_PRICER(point_evaluation)(bytesConstRef _in) +{ + return 50000; +} } // namespace diff --git a/bcos-executor/src/vm/kzgPrecompiled.h b/bcos-executor/src/vm/kzgPrecompiled.h index 7f79332b8f..894b0091a8 100644 --- a/bcos-executor/src/vm/kzgPrecompiled.h +++ b/bcos-executor/src/vm/kzgPrecompiled.h @@ -1,197 +1,212 @@ -///* -//* Copyright (C) 2021 FISCO BCOS. -//* SPDX-License-Identifier: Apache-2.0 -//* Licensed under the Apache License, Version 2.0 (the "License"); -//* you may not use this file except in compliance with the License. -//* You may obtain a copy of the License at -//* -//* http://www.apache.org/licenses/LICENSE-2.0 -//* -//* Unless required by applicable law or agreed to in writing, software -//* distributed under the License is distributed on an "AS IS" BASIS, -//* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -//* See the License for the specific language governing permissions and -//* limitations under the License. -//* -//* @brief factory of vm -//* @file KZGPrecompiled.h -//* @author: wenlinli -//* @date: 2024-04-29 -// */ -// -// #pragma once -// #include -// #include -// #include -// #include -// #include -// #include -// -// -// namespace bcos::executor -//{ -// -// inline constexpr uint8_t kBlobCommitmentVersionKzg{1}; -// -// namespace crypto -//{ -// -// class kzgPrecompiled -//{ -// public: -// using Ptr = std::shared_ptr; -// using G1 = blst_p1; -// using G2 = blst_p2; -// using Fr = blst_fr; -// -// -// static bool pairings_verify( -// const G1* a1, const G2* a2, const G1* b1, const G2* b2) { -// blst_fp12 loop0, loop1, gt_point; -// blst_p1_affine aa1, bb1; -// blst_p2_affine aa2, bb2; -// -// G1 a1neg = *a1; -// blst_p1_cneg(&a1neg, true); -// -// blst_p1_to_affine(&aa1, &a1neg); -// blst_p1_to_affine(&bb1, b1); -// blst_p2_to_affine(&aa2, a2); -// blst_p2_to_affine(&bb2, b2); -// -// blst_miller_loop(&loop0, &aa2, &aa1); -// blst_miller_loop(&loop1, &bb2, &bb1); -// -// blst_fp12_mul(>_point, &loop0, &loop1); -// blst_final_exp(>_point, >_point); -// -// return blst_fp12_is_one(>_point); -// } -// -// static void g1_mul(G1* out, const G1* a, const Fr* b) { -// blst_scalar s; -// blst_scalar_from_fr(&s, b); -// blst_p1_mult(out, a, s.b, 8 * sizeof(blst_scalar)); -// } -// -// -// static void g2_mul(G2* out, const G2* a, const Fr* b) { -// blst_scalar s; -// blst_scalar_from_fr(&s, b); -// blst_p2_mult(out, a, s.b, 8 * sizeof(blst_scalar)); -// } -// -// -// static void g1_sub(G1* out, const G1* a, const G1* b) { -// G1 bneg = *b; -// blst_p1_cneg(&bneg, true); -// blst_p1_add_or_double(out, a, &bneg); -// } -// -// -// static void g2_sub(G2* out, const G2* a, const G2* b) { -// G2 bneg = *b; -// blst_p2_cneg(&bneg, true); -// blst_p2_add_or_double(out, a, &bneg); -// } -// -// constexpr static const G2 kKzgSetupG2_1{ -// {{{0x6120a2099b0379f9, 0xa2df815cb8210e4e, 0xcb57be5577bd3d4f, -// 0x62da0ea89a0c93f8, 0x02e0ee16968e150d, 0x171f09aea833acd5}, -// {0x11a3670749dfd455, 0x04991d7b3abffadc, 0x85446a8e14437f41, -// 0x27174e7b4e76e3f2, 0x7bfa6dd397f60a20, 0x02fcc329ac07080f}}}, -// {{{0xaa130838793b2317, 0xe236dd220f891637, 0x6502782925760980, -// 0xd05c25f60557ec89, 0x6095767a44064474, 0x185693917080d405}, -// {0x549f9e175b03dc0a, 0x32c0c95a77106cfe, 0x64a74eae5705d080, -// 0x53deeaf56659ed9e, 0x09a1d368508afb93, 0x12cf3a4525b5e9bd}}}, -// {{{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, -// 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}, -// {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, -// 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}} -// }; -// -// -// static bool validate_kzg_g1(G1* out, bytesConstRef b) { -// blst_p1_affine p1_affine; -// -// /* Convert the bytes to a p1 point */ -// /* The uncompress routine checks that the point is on the curve */ -// if (blst_p1_uncompress(&p1_affine, b.data()) != BLST_SUCCESS) { -// return false; -// } -// blst_p1_from_affine(out, &p1_affine); -// -// /* The point at infinity is accepted! */ -// if (blst_p1_is_inf(out)) { -// return true; -// } -// -// /* The point must be on the right subgroup */ -// return blst_p1_in_g1(out); -// } -// -// static bool bytes_to_bls_field(Fr* out, bytesConstRef b) { -// blst_scalar tmp; -// blst_scalar_from_bendian(&tmp, b.data()); -// if (!blst_scalar_fr_check(&tmp)) { -// return false; -// } -// blst_fr_from_scalar(out, &tmp); -// return true; -// } -// -// -// bcos::crypto::HashType kzg2VersionedHash(bytesConstRef input){ -// bcos::crypto::HashType hash; -// hash = bcos::crypto::sha256Hash(input); -// return hash; -// } -// -// bool verifyKZGProof(bytesConstRef commitment, -// bytesConstRef z, -// bytesConstRef y, -// bytesConstRef proof){ -// Fr z_fr, y_fr; -// G1 commitment_g1, proof_g1; -// -// if (!validate_kzg_g1(&commitment_g1, commitment)) { -// return false; -// } -// if (!bytes_to_bls_field(&z_fr, z)) { -// return false; -// } -// if (!bytes_to_bls_field(&y_fr, y)) { -// return false; -// } -// if (!validate_kzg_g1(&proof_g1, proof)) { -// return false; -// } -// -// return verifyKZGProofImpl( -// &commitment_g1, &z_fr, &y_fr, &proof_g1); -// } -// -// static bool verifyKZGProofImpl(const G1* commitment, -// const Fr* z, -// const Fr* y, -// const G1* proof){ -// G2 x_g2, X_minus_z; -// G1 y_g1, P_minus_y; -// -// /* Calculate: X_minus_z */ -// g2_mul(&x_g2, blst_p2_generator(), z); -// g2_sub(&X_minus_z, &kKzgSetupG2_1, &x_g2); -// -// /* Calculate: P_minus_y */ -// g1_mul(&y_g1, blst_p1_generator(), y); -// g1_sub(&P_minus_y, commitment, &y_g1); -// -// /* Verify: P - y = Q * (X - z) */ -// return pairings_verify(&P_minus_y, blst_p2_generator(), proof, &X_minus_z); -// } -//}; -// -//} // namespace crypto -//} // namespace bcos::executor -// -// +/* + * Copyright (C) 2021 FISCO BCOS. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + * @file KZGPrecompiled.h + * @author: wenlinli + * @date: 2024-04-29 + */ + +#pragma once +#include +#include +#include +#include +#include +#include + + +namespace bcos::executor +{ + +inline constexpr uint8_t kBlobCommitmentVersionKzg{1}; + +namespace crypto +{ + +class kzgPrecompiled +{ +public: + using Ptr = std::shared_ptr; + using ConstPtr = std::shared_ptr; + using G1 = blst_p1; + using G2 = blst_p2; + using Fr = blst_fr; + + kzgPrecompiled() = default; + ~kzgPrecompiled() = default; + + + static bool pairings_verify(const G1* a1, const G2* a2, const G1* b1, const G2* b2) + { + blst_fp12 loop0, loop1, gt_point; + blst_p1_affine aa1, bb1; + blst_p2_affine aa2, bb2; + + G1 a1neg = *a1; + blst_p1_cneg(&a1neg, true); + + blst_p1_to_affine(&aa1, &a1neg); + blst_p1_to_affine(&bb1, b1); + blst_p2_to_affine(&aa2, a2); + blst_p2_to_affine(&bb2, b2); + + blst_miller_loop(&loop0, &aa2, &aa1); + blst_miller_loop(&loop1, &bb2, &bb1); + + blst_fp12_mul(>_point, &loop0, &loop1); + blst_final_exp(>_point, >_point); + + return blst_fp12_is_one(>_point); + } + + static void g1_mul(G1* out, const G1* a, const Fr* b) + { + blst_scalar s; + blst_scalar_from_fr(&s, b); + blst_p1_mult(out, a, s.b, 8 * sizeof(blst_scalar)); + } + + + static void g2_mul(G2* out, const G2* a, const Fr* b) + { + blst_scalar s; + blst_scalar_from_fr(&s, b); + blst_p2_mult(out, a, s.b, 8 * sizeof(blst_scalar)); + } + + + static void g1_sub(G1* out, const G1* a, const G1* b) + { + G1 bneg = *b; + blst_p1_cneg(&bneg, true); + blst_p1_add_or_double(out, a, &bneg); + } + + + static void g2_sub(G2* out, const G2* a, const G2* b) + { + G2 bneg = *b; + blst_p2_cneg(&bneg, true); + blst_p2_add_or_double(out, a, &bneg); + } + + constexpr static const G2 kKzgSetupG2_1{ + {{{0x6120a2099b0379f9, 0xa2df815cb8210e4e, 0xcb57be5577bd3d4f, 0x62da0ea89a0c93f8, + 0x02e0ee16968e150d, 0x171f09aea833acd5}, + {0x11a3670749dfd455, 0x04991d7b3abffadc, 0x85446a8e14437f41, 0x27174e7b4e76e3f2, + 0x7bfa6dd397f60a20, 0x02fcc329ac07080f}}}, + {{{0xaa130838793b2317, 0xe236dd220f891637, 0x6502782925760980, 0xd05c25f60557ec89, + 0x6095767a44064474, 0x185693917080d405}, + {0x549f9e175b03dc0a, 0x32c0c95a77106cfe, 0x64a74eae5705d080, 0x53deeaf56659ed9e, + 0x09a1d368508afb93, 0x12cf3a4525b5e9bd}}}, + {{{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, + 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000}}}}; + + + static bool validate_kzg_g1(G1* out, bytesConstRef b) + { + blst_p1_affine p1_affine; + + /* Convert the bytes to a p1 point */ + /* The uncompress routine checks that the point is on the curve */ + if (blst_p1_uncompress(&p1_affine, b.data()) != BLST_SUCCESS) + { + return false; + } + blst_p1_from_affine(out, &p1_affine); + + /* The point at infinity is accepted! */ + if (blst_p1_is_inf(out)) + { + return true; + } + + /* The point must be on the right subgroup */ + return blst_p1_in_g1(out); + } + + static bool bytes_to_bls_field(Fr* out, bytesConstRef b) + { + blst_scalar tmp; + blst_scalar_from_bendian(&tmp, b.data()); + if (!blst_scalar_fr_check(&tmp)) + { + return false; + } + blst_fr_from_scalar(out, &tmp); + return true; + } + + + bcos::crypto::HashType kzg2VersionedHash(bytesConstRef input) + { + auto sha256 = std::make_shared(); + auto hash = sha256->hash(input); + BCOS_LOG(DEBUG) << LOG_DESC("hash") << LOG_KV("hash", hash) + << LOG_KV("hash hex", hash.hex()); + hash[0] = kBlobCommitmentVersionKzg; + BCOS_LOG(DEBUG) << LOG_DESC("a") << LOG_KV("a", hash) << LOG_KV("a hex", hash.hex()); + return hash; + } + + bool verifyKZGProof( + bytesConstRef commitment, bytesConstRef z, bytesConstRef y, bytesConstRef proof) + { + Fr z_fr, y_fr; + G1 commitment_g1, proof_g1; + + if (!validate_kzg_g1(&commitment_g1, commitment)) + { + return false; + } + if (!bytes_to_bls_field(&z_fr, z)) + { + return false; + } + if (!bytes_to_bls_field(&y_fr, y)) + { + return false; + } + if (!validate_kzg_g1(&proof_g1, proof)) + { + return false; + } + + return verifyKZGProofImpl(&commitment_g1, &z_fr, &y_fr, &proof_g1); + } + + static bool verifyKZGProofImpl(const G1* commitment, const Fr* z, const Fr* y, const G1* proof) + { + G2 x_g2, X_minus_z; + G1 y_g1, P_minus_y; + + /* Calculate: X_minus_z */ + g2_mul(&x_g2, blst_p2_generator(), z); + g2_sub(&X_minus_z, &kKzgSetupG2_1, &x_g2); + + /* Calculate: P_minus_y */ + g1_mul(&y_g1, blst_p1_generator(), y); + g1_sub(&P_minus_y, commitment, &y_g1); + + /* Verify: P - y = Q * (X - z) */ + return pairings_verify(&P_minus_y, blst_p2_generator(), proof, &X_minus_z); + } +}; + +} // namespace crypto +} // namespace bcos::executor diff --git a/bcos-executor/test/unittest/libprecompiled/PrecompiledTest.cpp b/bcos-executor/test/unittest/libprecompiled/PrecompiledTest.cpp new file mode 100644 index 0000000000..ad682fa82d --- /dev/null +++ b/bcos-executor/test/unittest/libprecompiled/PrecompiledTest.cpp @@ -0,0 +1,83 @@ +/** + * Copyright (C) 2021 FISCO BCOS. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +using namespace bcos; +using namespace bcos::precompiled; +using namespace bcos::executor; +using namespace bcos::storage; + +namespace bcos::test +{ +BOOST_AUTO_TEST_SUITE(PrecompiledTest) + +BOOST_AUTO_TEST_CASE(PointEvaluatePrecompiledTest) +{ + static constexpr intx::uint256 kBlsModulus{intx::from_string( + "52435875175126190479447740508185965837690552500527637822603658699938581184513")}; + + bytes in = *bcos::fromHexString( + "014edfed8547661f6cb416eba53061a2f6dce872c0497e6dd485a876fe2567f1564c0a11a0f704f4fc3e8acfe0" + "f8245f0ad1347b378fbf96e206da11a5d363066d928e13fe443e957d82e3e71d48cb65d51028eb4483e719bf8e" + "fcdf12f7c321a421e229565952cfff4ef3517100a97da1d4fe57956fa50a442f92af03b1bf37adacc8ad4ed209" + "b31287ea5bb94d9d06a444d6bb5aadc3ceb615b50d6606bd54bfe529f59247987cd1ab848d19de599a9052f183" + "5fb0d0d44cf70183e19a68c9"); + PrecompiledExecutor const& executor = PrecompiledRegistrar::executor("point_evaluation"); + bytesConstRef input_ref(in.data(), in.size()); + std::pair out = executor(input_ref); + BOOST_CHECK(out.first); + BOOST_CHECK((out.second.size() == 64)); + intx::uint256 fieldElementsPerBlob{intx::be::unsafe::load(out.second.data())}; + BOOST_CHECK(fieldElementsPerBlob == 4096); + intx::uint256 blsModulus{intx::be::unsafe::load(out.second.data() + 32)}; + BOOST_CHECK(blsModulus == kBlsModulus); + + // change hash version + in[0] = 0x2; + bytesConstRef input_ref1(in.data(), in.size()); + auto out1 = executor(input_ref1); + BOOST_CHECK(!out1.first); + in[0] = 0x1; + + // truncate input + in.pop_back(); + bytesConstRef input_ref2(in.data(), in.size()); + auto out2 = executor(input_ref2); + BOOST_CHECK(!out2.first); + in.push_back(0xba); + + // extra input + in.push_back(0); + bytesConstRef input_ref3(in.data(), in.size()); + auto out3 = executor(input_ref3); + BOOST_CHECK(!out3.first); + in.pop_back(); + + // Try z > BLS_MODULUS + intx::uint256 z{intx::le::unsafe::load(&in[32])}; + z += kBlsModulus; + intx::le::unsafe::store(&in[32], z); + bytesConstRef input_ref4(in.data(), in.size()); + auto out4 = executor(input_ref4); + BOOST_CHECK(!out4.first); +} + +BOOST_AUTO_TEST_SUITE_END() + +} // namespace bcos::test \ No newline at end of file From 70a59ded4769c0e2dd4e6e737ffc72b21c9b7417 Mon Sep 17 00:00:00 2001 From: MO NAN <651932351@qq.com> Date: Mon, 15 Jul 2024 15:01:00 +0800 Subject: [PATCH 03/16] Fix code not found status code and output (#4512) --- .../TransactionExecutorImpl.h | 154 ++++++++---------- .../vm/HostContext.h | 88 ++++++---- .../tests/TestHostContext.cpp | 11 +- 3 files changed, 126 insertions(+), 127 deletions(-) diff --git a/transaction-executor/bcos-transaction-executor/TransactionExecutorImpl.h b/transaction-executor/bcos-transaction-executor/TransactionExecutorImpl.h index dff0253572..567bebe6d7 100644 --- a/transaction-executor/bcos-transaction-executor/TransactionExecutorImpl.h +++ b/transaction-executor/bcos-transaction-executor/TransactionExecutorImpl.h @@ -38,112 +38,86 @@ class TransactionExecutorImpl protocol::BlockHeader const& blockHeader, protocol::Transaction const& transaction, int contextID, ledger::LedgerConfig const& ledgerConfig, auto&& waitOperator) { - int64_t gasLimit{}; protocol::TransactionReceipt::Ptr receipt; - try + if (c_fileLogLevel <= LogLevel::TRACE) { - if (c_fileLogLevel <= LogLevel::TRACE) - { - TRANSACTION_EXECUTOR_LOG(TRACE) - << "Execute transaction: " << toHex(transaction.hash()); - } - - Rollbackable> rollbackableStorage(storage); - // create a transient storage - using MemoryStorageType = - bcos::storage2::memory_storage::MemoryStorage; - MemoryStorageType transientStorage; - Rollbackable rollbackableTransientStorage(transientStorage); - auto gasLimit = static_cast(std::get<0>(ledgerConfig.gasLimit())); - auto evmcMessage = newEVMCMessage(transaction, gasLimit); - - if (blockHeader.number() == 0 && - transaction.to() == precompiled::AUTH_COMMITTEE_ADDRESS) - { - evmcMessage.kind = EVMC_CREATE; - } + TRANSACTION_EXECUTOR_LOG(TRACE) << "Execute transaction: " << toHex(transaction.hash()); + } - int64_t seq = 0; - HostContext - hostContext(rollbackableStorage, rollbackableTransientStorage, blockHeader, - evmcMessage, evmcMessage.sender, transaction.abi(), contextID, seq, - executor.m_precompiledManager, ledgerConfig, *executor.m_hashImpl, - std::forward(waitOperator)); + Rollbackable> rollbackableStorage(storage); + // create a transient storage + using MemoryStorageType = + bcos::storage2::memory_storage::MemoryStorage; + MemoryStorageType transientStorage; + Rollbackable rollbackableTransientStorage(transientStorage); + auto gasLimit = static_cast(std::get<0>(ledgerConfig.gasLimit())); + auto evmcMessage = newEVMCMessage(transaction, gasLimit); + + if (blockHeader.number() == 0 && transaction.to() == precompiled::AUTH_COMMITTEE_ADDRESS) + { + evmcMessage.kind = EVMC_CREATE; + } - waitOperator(hostContext.prepare()); - co_yield receipt; // 完成第一步 Complete the first step + int64_t seq = 0; + HostContext + hostContext(rollbackableStorage, rollbackableTransientStorage, blockHeader, evmcMessage, + evmcMessage.sender, transaction.abi(), contextID, seq, + executor.m_precompiledManager, ledgerConfig, *executor.m_hashImpl, + std::forward(waitOperator)); - auto evmcResult = waitOperator(hostContext.execute()); - co_yield receipt; // 完成第二步 Complete the second step + waitOperator(hostContext.prepare()); + co_yield receipt; // 完成第一步 Complete the first step - std::string newContractAddress; - if (evmcMessage.kind == EVMC_CREATE && evmcResult.status_code == EVMC_SUCCESS) - { - newContractAddress.reserve(sizeof(evmcResult.create_address) * 2); - boost::algorithm::hex_lower(evmcResult.create_address.bytes, - evmcResult.create_address.bytes + sizeof(evmcResult.create_address.bytes), - std::back_inserter(newContractAddress)); - } - auto output = bcos::bytesConstRef{evmcResult.output_data, evmcResult.output_size}; + auto evmcResult = waitOperator(hostContext.execute()); + co_yield receipt; // 完成第二步 Complete the second step - if (evmcResult.status_code != 0) - { - TRANSACTION_EXECUTOR_LOG(DEBUG) << "Transaction revert: " << evmcResult.status_code; - } - - int32_t receiptStatus = - evmcResult.status_code == EVMC_REVERT ? - static_cast(protocol::TransactionStatus::RevertInstruction) : - evmcResult.status_code; - auto const& logEntries = hostContext.logs(); - auto transactionVersion = - static_cast(transaction.version()); - switch (transactionVersion) - { - case bcos::protocol::TransactionVersion::V0_VERSION: - receipt = executor.m_receiptFactory.get().createReceipt( - gasLimit - evmcResult.gas_left, newContractAddress, logEntries, receiptStatus, - output, blockHeader.number()); - break; - case bcos::protocol::TransactionVersion::V1_VERSION: - case bcos::protocol::TransactionVersion::V2_VERSION: - receipt = executor.m_receiptFactory.get().createReceipt2( - gasLimit - evmcResult.gas_left, newContractAddress, logEntries, receiptStatus, - output, blockHeader.number(), "", transactionVersion); - break; - default: - BOOST_THROW_EXCEPTION(std::runtime_error( - "Invalid receipt version: " + std::to_string(transaction.version()))); - } - } - catch (NotFoundCodeError& e) + std::string newContractAddress; + if (evmcMessage.kind == EVMC_CREATE && evmcResult.status_code == EVMC_SUCCESS) { - TRANSACTION_EXECUTOR_LOG(DEBUG) - << "Not found code exception: " << boost::diagnostic_information(e); - - receipt = executor.m_receiptFactory.get().createReceipt( - 0, {}, {}, EVMC_REVERT, {}, blockHeader.number()); - receipt->setMessage(boost::diagnostic_information(e)); + newContractAddress.reserve(sizeof(evmcResult.create_address) * 2); + boost::algorithm::hex_lower(evmcResult.create_address.bytes, + evmcResult.create_address.bytes + sizeof(evmcResult.create_address.bytes), + std::back_inserter(newContractAddress)); } - catch (std::exception& e) + auto output = bcos::bytesConstRef{evmcResult.output_data, evmcResult.output_size}; + + if (evmcResult.status_code != 0) { - TRANSACTION_EXECUTOR_LOG(DEBUG) - << "Execute exception: " << boost::diagnostic_information(e); + TRANSACTION_EXECUTOR_LOG(DEBUG) << "Transaction revert: " << evmcResult.status_code; + } - receipt = executor.m_receiptFactory.get().createReceipt( - 0, {}, {}, EVMC_INTERNAL_ERROR, {}, blockHeader.number()); - receipt->setMessage(boost::diagnostic_information(e)); + int32_t receiptStatus = + evmcResult.status_code == EVMC_REVERT ? + static_cast(protocol::TransactionStatus::RevertInstruction) : + evmcResult.status_code; + auto const& logEntries = hostContext.logs(); + auto transactionVersion = + static_cast(transaction.version()); + switch (transactionVersion) + { + case bcos::protocol::TransactionVersion::V0_VERSION: + receipt = executor.m_receiptFactory.get().createReceipt(gasLimit - evmcResult.gas_left, + newContractAddress, logEntries, receiptStatus, output, blockHeader.number()); + break; + case bcos::protocol::TransactionVersion::V1_VERSION: + case bcos::protocol::TransactionVersion::V2_VERSION: + receipt = executor.m_receiptFactory.get().createReceipt2(gasLimit - evmcResult.gas_left, + newContractAddress, logEntries, receiptStatus, output, blockHeader.number(), "", + transactionVersion); + break; + default: + BOOST_THROW_EXCEPTION(std::runtime_error( + "Invalid receipt version: " + std::to_string(transaction.version()))); } if (c_fileLogLevel <= LogLevel::TRACE) { TRANSACTION_EXECUTOR_LOG(TRACE) - << "Execte transaction finished" - << ", gasUsed: " << receipt->gasUsed() + << "Execte transaction finished" << ", gasUsed: " << receipt->gasUsed() << ", newContractAddress: " << receipt->contractAddress() << ", logEntries: " << receipt->logEntries().size() << ", status: " << receipt->status() << ", output: " << toHex(receipt->output()) diff --git a/transaction-executor/bcos-transaction-executor/vm/HostContext.h b/transaction-executor/bcos-transaction-executor/vm/HostContext.h index af338fcdf6..e9a552c9ab 100644 --- a/transaction-executor/bcos-transaction-executor/vm/HostContext.h +++ b/transaction-executor/bcos-transaction-executor/vm/HostContext.h @@ -384,17 +384,56 @@ class HostContext : public evmc_host_context }; } - if (!evmResult) + try { - if (ref.kind == EVMC_CREATE || ref.kind == EVMC_CREATE2) - { - evmResult.emplace(co_await executeCreate()); - } - else + if (!evmResult) { - evmResult.emplace(co_await executeCall()); + if (ref.kind == EVMC_CREATE || ref.kind == EVMC_CREATE2) + { + evmResult.emplace(co_await executeCreate()); + } + else + { + evmResult.emplace(co_await executeCall()); + } } } + catch (NotFoundCodeError& e) + { + HOST_CONTEXT_LOG(DEBUG) + << "Not found code exception: " << boost::diagnostic_information(e); + bcos::codec::abi::ContractABICodec abi(m_hashImpl); + auto codecOutput = abi.abiIn("Error(string)", std::string("Call address error.")); + auto errorBuffer = std::unique_ptr(new uint8_t[codecOutput.size()]); + std::uninitialized_copy(codecOutput.begin(), codecOutput.end(), errorBuffer.get()); + + // Static call或delegate call时,合约不存在要返回EVMC_SUCCESS + // STATIC_CALL or DELEGATE_CALL, the EVMC_SUCCESS is returned when the contract does not + // exist + co_return EVMCResult{evmc_result{ + .status_code = (ref.flags == EVMC_STATIC || ref.kind == EVMC_DELEGATECALL) ? + EVMC_SUCCESS : + (evmc_status_code)protocol::TransactionStatus::CallAddressError, + .gas_left = ref.gas, + .gas_refund = 0, + .output_data = errorBuffer.release(), + .output_size = codecOutput.size(), + .release = [](const struct evmc_result* result) { delete[] result->output_data; }, + .create_address = {}, + .padding = {}}}; + } + catch (std::exception& e) + { + HOST_CONTEXT_LOG(DEBUG) << "Execute exception: " << boost::diagnostic_information(e); + co_return EVMCResult{evmc_result{.status_code = EVMC_INTERNAL_ERROR, + .gas_left = ref.gas, + .gas_refund = 0, + .output_data = nullptr, + .output_size = 0, + .release = nullptr, + .create_address = {}, + .padding = {}}}; + } // 如果本次调用系统合约失败,不消耗gas // If the call to system contract failed, the gasUsed is cleared to zero @@ -452,36 +491,15 @@ class HostContext : public evmc_host_context m_rollbackableTransientStorage.get(), m_blockHeader, message, m_origin, {}, m_contextID, m_seq, m_precompiledManager.get(), m_ledgerConfig, m_hashImpl, interface); - try - { - co_await hostcontext.prepare(); - auto result = co_await hostcontext.execute(); - auto& logs = hostcontext.logs(); - if (result.status_code == EVMC_SUCCESS && !logs.empty()) - { - m_logs.reserve(m_logs.size() + RANGES::size(logs)); - RANGES::move(logs, std::back_inserter(m_logs)); - } - co_return result; - } - catch (NotFoundCodeError& e) + co_await hostcontext.prepare(); + auto result = co_await hostcontext.execute(); + auto& logs = hostcontext.logs(); + if (result.status_code == EVMC_SUCCESS && !logs.empty()) { - // Static call或delegate call时,合约不存在要返回EVMC_SUCCESS - // STATIC_CALL or DELEGATE_CALL, the EVMC_SUCCESS is returned when the contract does not - // exist - co_return EVMCResult{evmc_result{ - .status_code = - ((message.flags == EVMC_STATIC || message.kind == EVMC_DELEGATECALL) ? - EVMC_SUCCESS : - EVMC_REVERT), - .gas_left = message.gas, - .gas_refund = 0, - .output_data = nullptr, - .output_size = 0, - .release = nullptr, - .create_address = {}, - .padding = {}}}; + m_logs.reserve(m_logs.size() + RANGES::size(logs)); + RANGES::move(logs, std::back_inserter(m_logs)); } + co_return result; } std::vector& logs() & { return m_logs; } diff --git a/transaction-executor/tests/TestHostContext.cpp b/transaction-executor/tests/TestHostContext.cpp index 6c9647323d..ceb05f55fe 100644 --- a/transaction-executor/tests/TestHostContext.cpp +++ b/transaction-executor/tests/TestHostContext.cpp @@ -396,9 +396,16 @@ BOOST_AUTO_TEST_CASE(precompiled) origin, "", 0, seq, *precompiledManager, ledgerConfig, *hashImpl, bcos::task::syncWait); syncWait(hostContext.prepare()); - BOOST_CHECK_THROW(result.emplace(syncWait(hostContext.execute())), - bcos::transaction_executor::NotFoundCodeError); + auto notFoundResult = syncWait(hostContext.execute()); + BOOST_CHECK_EQUAL(notFoundResult.status_code, + (evmc_status_code)bcos::protocol::TransactionStatus::CallAddressError); + + bcos::codec::abi::ContractABICodec abi(*hashImpl); + std::string errorMessage; + BOOST_REQUIRE_GT(notFoundResult.output_size, 4); + abi.abiOut({notFoundResult.output_data + 4, notFoundResult.output_size - 4}, errorMessage); + BOOST_CHECK_EQUAL(errorMessage, "Call address error."); auto& features = const_cast(ledgerConfig.features()); features.set(bcos::ledger::Features::Flag::feature_sharding); From 2c2046256d7580ec2d6c3ca5b32038a23726f564 Mon Sep 17 00:00:00 2001 From: MO NAN <651932351@qq.com> Date: Tue, 16 Jul 2024 16:30:07 +0800 Subject: [PATCH 04/16] Fix code to pass gcc 14.1 (#4533) --- .../test/unittest/libprecompiled/PrecompiledTest.cpp | 3 ++- .../bcos-framework/testutils/faker/FakeTransactionReceipt.h | 3 ++- bcos-txpool/bcos-txpool/txpool/storage/MemoryStorage.cpp | 2 +- libinitializer/StorageInitializer.h | 1 + vcpkg-configuration.json | 2 +- vcpkg.json | 6 +++--- 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/bcos-executor/test/unittest/libprecompiled/PrecompiledTest.cpp b/bcos-executor/test/unittest/libprecompiled/PrecompiledTest.cpp index ad682fa82d..901f8e0efa 100644 --- a/bcos-executor/test/unittest/libprecompiled/PrecompiledTest.cpp +++ b/bcos-executor/test/unittest/libprecompiled/PrecompiledTest.cpp @@ -38,7 +38,8 @@ BOOST_AUTO_TEST_CASE(PointEvaluatePrecompiledTest) "fcdf12f7c321a421e229565952cfff4ef3517100a97da1d4fe57956fa50a442f92af03b1bf37adacc8ad4ed209" "b31287ea5bb94d9d06a444d6bb5aadc3ceb615b50d6606bd54bfe529f59247987cd1ab848d19de599a9052f183" "5fb0d0d44cf70183e19a68c9"); - PrecompiledExecutor const& executor = PrecompiledRegistrar::executor("point_evaluation"); + static std::string pointE("point_evaluation"); + PrecompiledExecutor const& executor = PrecompiledRegistrar::executor(pointE); bytesConstRef input_ref(in.data(), in.size()); std::pair out = executor(input_ref); BOOST_CHECK(out.first); diff --git a/bcos-framework/bcos-framework/testutils/faker/FakeTransactionReceipt.h b/bcos-framework/bcos-framework/testutils/faker/FakeTransactionReceipt.h index 62e7529063..55c7b6f92e 100644 --- a/bcos-framework/bcos-framework/testutils/faker/FakeTransactionReceipt.h +++ b/bcos-framework/bcos-framework/testutils/faker/FakeTransactionReceipt.h @@ -65,7 +65,8 @@ inline void checkReceipts(Hash::Ptr hashImpl, bcos::protocol::TransactionReceipt // check LogEntries BOOST_CHECK(decodedReceipt->logEntries().size() == 2); BOOST_CHECK(decodedReceipt->logEntries().size() == receipt->logEntries().size()); - auto& logEntry = (decodedReceipt->logEntries())[1]; + auto logEntries = decodedReceipt->logEntries(); + const auto& logEntry = logEntries[1]; auto expectedTopic = hashImpl->hash(std::to_string(1)); BOOST_CHECK(logEntry.topics()[0] == expectedTopic); diff --git a/bcos-txpool/bcos-txpool/txpool/storage/MemoryStorage.cpp b/bcos-txpool/bcos-txpool/txpool/storage/MemoryStorage.cpp index 6c2ec4de75..bf66b9016c 100644 --- a/bcos-txpool/bcos-txpool/txpool/storage/MemoryStorage.cpp +++ b/bcos-txpool/bcos-txpool/txpool/storage/MemoryStorage.cpp @@ -468,7 +468,7 @@ TransactionStatus MemoryStorage::insertWithoutLock(Transaction::Ptr transaction) { if (transaction->submitCallback() && !accessor->value()->submitCallback()) { - accessor->value()->setSubmitCallback(std::move(transaction->submitCallback())); + accessor->value()->setSubmitCallback(transaction->submitCallback()); return TransactionStatus::None; } return TransactionStatus::AlreadyInTxPool; diff --git a/libinitializer/StorageInitializer.h b/libinitializer/StorageInitializer.h index 8428dd5ff0..7c6f153f81 100644 --- a/libinitializer/StorageInitializer.h +++ b/libinitializer/StorageInitializer.h @@ -24,6 +24,7 @@ */ #pragma once #include "bcos-storage/RocksDBStorage.h" +#include #ifdef WITH_TIKV #include "bcos-storage/TiKVStorage.h" #endif diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json index 9f06c28d2b..3cc3a2ad93 100644 --- a/vcpkg-configuration.json +++ b/vcpkg-configuration.json @@ -3,7 +3,7 @@ { "kind": "git", "repository": "https://github.com/FISCO-BCOS/registry", - "baseline": "f08e2b4c2907bdfafa383dded27c3d484cc35f5f", + "baseline": "748c50ba0a5e69297b9527d64a6b2ca76447b7a7", "packages": [ "openssl", "evmone", diff --git a/vcpkg.json b/vcpkg.json index cae34be679..84728e19da 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -220,7 +220,7 @@ }, { "name": "rocksdb", - "version": "6.27.3" + "version": "8.5.3" }, { "name": "magic-enum", @@ -280,7 +280,7 @@ }, { "name": "redis-plus-plus", - "version": "1.3.2" + "version": "1.3.10" }, { "name": "protobuf", @@ -296,7 +296,7 @@ }, { "name": "tarscpp", - "version": "3.0.3-1#1" + "version": "3.0.3-2" }, { "name": "wedprcrypto", From 52b65142e82f4a11c3e736d9249933074d0fe1c9 Mon Sep 17 00:00:00 2001 From: wenlinli <1574249665@qq.com> Date: Tue, 16 Jul 2024 17:32:00 +0800 Subject: [PATCH 05/16] update version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f3d389811..089454615e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ endif() list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) -set(VERSION "3.9.0") +set(VERSION "3.10.0") set(VERSION_SUFFIX "") include(Options) configure_project() From 05e412e0f5946caf0f94906396ff96ab255b7b36 Mon Sep 17 00:00:00 2001 From: wenlinli <1574249665@qq.com> Date: Wed, 17 Jul 2024 16:35:00 +0800 Subject: [PATCH 06/16] upgrade version --- tools/BcosAirBuilder/build_chain.sh | 6 +++--- tools/BcosBuilder/max/conf/config-build-example.toml | 2 +- tools/BcosBuilder/max/conf/config-deploy-example.toml | 2 +- tools/BcosBuilder/pro/conf/config-build-example.toml | 2 +- tools/BcosBuilder/pro/conf/config-deploy-example.toml | 2 +- tools/BcosBuilder/src/common/utilities.py | 2 +- tools/BcosBuilder/src/tpl/config.genesis | 2 +- vcpkg.json | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/BcosAirBuilder/build_chain.sh b/tools/BcosAirBuilder/build_chain.sh index 3aa1478a1f..760e820a01 100755 --- a/tools/BcosAirBuilder/build_chain.sh +++ b/tools/BcosAirBuilder/build_chain.sh @@ -39,7 +39,7 @@ ca_dir="" prometheus_dir="" config_path="" docker_mode= -default_version="v3.9.0" +default_version="v3.10.0" compatibility_version=${default_version} default_mtail_version="3.0.0-rc49" compatibility_mtail_version=${default_mtail_version} @@ -71,11 +71,11 @@ log_level="info" # for pro or max default setting bcos_builder_package=BcosBuilder.tgz -bcos_builder_version=v3.9.0 +bcos_builder_version=v3.10.0 use_exist_binary="false" download_specific_binary_flag="false" download_service_binary_type="cdn" -service_binary_version="v3.9.0" +service_binary_version="v3.10.0" download_service_binary_path="binary" download_service_binary_path_flag="false" service_type="all" diff --git a/tools/BcosBuilder/max/conf/config-build-example.toml b/tools/BcosBuilder/max/conf/config-build-example.toml index 17a9df5429..fe89d61191 100644 --- a/tools/BcosBuilder/max/conf/config-build-example.toml +++ b/tools/BcosBuilder/max/conf/config-build-example.toml @@ -36,7 +36,7 @@ consensus_type = "pbft" # transaction gas limit gas_limit = "3000000000" # compatible version, can be dynamically upgraded through setSystemConfig -compatibility_version = "3.9.0" +compatibility_version = "3.10.0" [[agency]] name = "agencyA" diff --git a/tools/BcosBuilder/max/conf/config-deploy-example.toml b/tools/BcosBuilder/max/conf/config-deploy-example.toml index aed6633223..2e07ff7adf 100644 --- a/tools/BcosBuilder/max/conf/config-deploy-example.toml +++ b/tools/BcosBuilder/max/conf/config-deploy-example.toml @@ -36,7 +36,7 @@ consensus_type = "pbft" # transaction gas limit gas_limit = "3000000000" # compatible version, can be dynamically upgraded through setSystemConfig -compatibility_version = "3.9.0" +compatibility_version = "3.10.0" [[agency]] name = "agencyA" diff --git a/tools/BcosBuilder/pro/conf/config-build-example.toml b/tools/BcosBuilder/pro/conf/config-build-example.toml index a9e4430a19..50eb5d0979 100644 --- a/tools/BcosBuilder/pro/conf/config-build-example.toml +++ b/tools/BcosBuilder/pro/conf/config-build-example.toml @@ -34,7 +34,7 @@ consensus_type = "pbft" # transaction gas limit gas_limit = "3000000000" # compatible version, can be dynamically upgraded through setSystemConfig -compatibility_version = "3.9.0" +compatibility_version = "3.10.0" [[agency]] name = "agencyA" diff --git a/tools/BcosBuilder/pro/conf/config-deploy-example.toml b/tools/BcosBuilder/pro/conf/config-deploy-example.toml index 2090dd04a3..2158b6c5ac 100644 --- a/tools/BcosBuilder/pro/conf/config-deploy-example.toml +++ b/tools/BcosBuilder/pro/conf/config-deploy-example.toml @@ -36,7 +36,7 @@ consensus_type = "pbft" # transaction gas limit gas_limit = "3000000000" # compatible version, can be dynamically upgraded through setSystemConfig -compatibility_version = "3.9.0" +compatibility_version = "3.10.0" [[agency]] name = "agencyA" diff --git a/tools/BcosBuilder/src/common/utilities.py b/tools/BcosBuilder/src/common/utilities.py index 3fc63d01f0..054585de27 100644 --- a/tools/BcosBuilder/src/common/utilities.py +++ b/tools/BcosBuilder/src/common/utilities.py @@ -99,7 +99,7 @@ class CommandInfo: network_add_vxlan = "add-vxlan" download_binary = "download_binary" download_type = ["cdn", "git"] - default_binary_version = "v3.9.0" + default_binary_version = "v3.10.0" command_list = [gen_config, upload, deploy, upgrade, undeploy, expand, start, stop] service_command_list_str = ', '.join(command_list) diff --git a/tools/BcosBuilder/src/tpl/config.genesis b/tools/BcosBuilder/src/tpl/config.genesis index 8f10bd9e81..84738bc33a 100644 --- a/tools/BcosBuilder/src/tpl/config.genesis +++ b/tools/BcosBuilder/src/tpl/config.genesis @@ -22,7 +22,7 @@ [version] ; compatible version, can be dynamically upgraded through setSystemConfig - compatibility_version=3.9.0 + compatibility_version=3.10.0 [tx] ; transaction gas limit diff --git a/vcpkg.json b/vcpkg.json index cae34be679..88df787e49 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,6 +1,6 @@ { "name": "fiscobcos", - "version-string": "3.9.0", + "version-string": "3.10.0", "homepage": "https://github.com/FISCO-BCOS/FISCO-BCOS", "description": "FISCO BCOS", "dependencies": [ From 04e435718015279f451d58907775a0d4eeb3b9af Mon Sep 17 00:00:00 2001 From: wenlinli <1574249665@qq.com> Date: Thu, 18 Jul 2024 19:37:23 +0800 Subject: [PATCH 07/16] update rpcapi_ci_prepare.sh --- tools/.ci/rpcapi_ci_prepare.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/.ci/rpcapi_ci_prepare.sh b/tools/.ci/rpcapi_ci_prepare.sh index bf2f3b828d..732b96aa19 100644 --- a/tools/.ci/rpcapi_ci_prepare.sh +++ b/tools/.ci/rpcapi_ci_prepare.sh @@ -35,12 +35,11 @@ wait_and_start() init() { - sm_option="${1}" cd ${current_path} echo " ==> fisco-bcos version: " ${fisco_bcos_path} -v clear_node - bash ${build_chain_path} -l "127.0.0.1:4" -e ${fisco_bcos_path} "${sm_option}" + bash ${build_chain_path} -p 30300,20200 -l "127.0.0.1:4" -e ${fisco_bcos_path} open_disablessl cd .. wait_and_start @@ -79,4 +78,4 @@ open_disablessl(){ -init "" \ No newline at end of file +init \ No newline at end of file From 3f57b47dc20111d45a4f9a911632144295c95b8a Mon Sep 17 00:00:00 2001 From: wenlinli <1574249665@qq.com> Date: Thu, 18 Jul 2024 20:02:47 +0800 Subject: [PATCH 08/16] update max_version --- bcos-framework/bcos-framework/protocol/Protocol.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bcos-framework/bcos-framework/protocol/Protocol.h b/bcos-framework/bcos-framework/protocol/Protocol.h index f8332650ff..528ddae4c6 100644 --- a/bcos-framework/bcos-framework/protocol/Protocol.h +++ b/bcos-framework/bcos-framework/protocol/Protocol.h @@ -114,6 +114,7 @@ enum ProtocolVersion : uint32_t enum class BlockVersion : uint32_t { + V3_10_0_VERSION = 0x030a0000, V3_9_0_VERSION = 0x03090000, V3_8_0_VERSION = 0x03080000, V3_7_3_VERSION = 0x03070300, @@ -136,7 +137,7 @@ enum class BlockVersion : uint32_t V3_0_VERSION = 0x03000000, RC4_VERSION = 4, MIN_VERSION = RC4_VERSION, - MAX_VERSION = V3_9_0_VERSION, + MAX_VERSION = V3_10_0_VERSION, }; enum class TransactionVersion : uint32_t @@ -151,7 +152,7 @@ const std::string RC4_VERSION_STR = "3.0.0-rc4"; const std::string RC_VERSION_PREFIX = "3.0.0-rc"; const std::string V3_9_VERSION_STR = "3.9.0"; -const BlockVersion DEFAULT_VERSION = bcos::protocol::BlockVersion::V3_9_0_VERSION; +const BlockVersion DEFAULT_VERSION = bcos::protocol::BlockVersion::V3_10_0_VERSION; const std::string DEFAULT_VERSION_STR = V3_9_VERSION_STR; const uint8_t MAX_MAJOR_VERSION = std::numeric_limits::max(); const uint8_t MIN_MAJOR_VERSION = 3; From 02d9bee1ef7c589f7ad9443a6bd19fc4540234ff Mon Sep 17 00:00:00 2001 From: MO NAN <651932351@qq.com> Date: Fri, 19 Jul 2024 08:10:50 +0800 Subject: [PATCH 09/16] Remove mp11, Coroutine.h and precompiledheader, use std::generator (#4538) --- CMakeLists.txt | 1 - bcos-framework/CMakeLists.txt | 8 +- .../bcos-framework/ledger/LedgerInterface.h | 1 - .../storage/LegacyStorageMethods.h | 4 +- bcos-front/bcos-front/FrontImpl.h | 4 +- bcos-ledger/src/libledger/LedgerMethods.cpp | 20 ++-- .../web3jsonrpc/endpoints/EthEndpoint.cpp | 4 +- bcos-sdk/bcos-cpp-sdk/tarsRPC/CoRPCClient.cpp | 10 +- bcos-sdk/bcos-cpp-sdk/tarsRPC/CoRPCClient.h | 9 +- bcos-sync/bcos-sync/state/SyncPeerStatus.h | 4 +- .../client/TxPoolServiceClient.h | 4 +- .../txpool/storage/MemoryStorage.cpp | 4 +- cmake/CompilerSettings.cmake | 10 +- cmake/Options.cmake | 2 - cmake/PrecompiledHeaders.cmake | 104 ------------------ libtask/bcos-task/AwaitableValue.h | 6 +- libtask/bcos-task/Coroutine.h | 9 -- libtask/bcos-task/Generator.h | 41 ++++--- libtask/bcos-task/TBBScheduler.h | 6 +- libtask/bcos-task/Task.h | 27 +++-- libtask/tests/TestTask.cpp | 8 +- .../scheduler/SchedulerWrapperImpl.h | 4 +- .../client/P2PClientImpl.h | 6 +- .../SchedulerParallelImpl.h | 16 +-- .../SchedulerSerialImpl.h | 10 +- vcpkg.json | 1 - 26 files changed, 103 insertions(+), 220 deletions(-) delete mode 100644 cmake/PrecompiledHeaders.cmake delete mode 100644 libtask/bcos-task/Coroutine.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f3d389811..3593f56111 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,6 @@ include(BuildInfoGenerator) include(IncludeDirectories) include(TargetSettings) -include(PrecompiledHeaders) add_subdirectory(bcos-boostssl) add_subdirectory(bcos-framework) diff --git a/bcos-framework/CMakeLists.txt b/bcos-framework/CMakeLists.txt index d5aa1c7e3f..a37d3e4ac3 100644 --- a/bcos-framework/CMakeLists.txt +++ b/bcos-framework/CMakeLists.txt @@ -27,13 +27,7 @@ add_library(bcos-framework INTERFACE) target_include_directories(bcos-framework INTERFACE $ $) - -if (PRECOMPILED_HEADER) - target_link_libraries(bcos-framework INTERFACE bcos-task Microsoft.GSL::GSL precompiled-headers) - target_precompile_headers(bcos-framework REUSE_FROM precompiled-headers) -else() - target_link_libraries(bcos-framework INTERFACE bcos-task Microsoft.GSL::GSL fmt::fmt) -endif() +target_link_libraries(bcos-framework INTERFACE bcos-task Microsoft.GSL::GSL fmt::fmt) if (TESTS) enable_testing() diff --git a/bcos-framework/bcos-framework/ledger/LedgerInterface.h b/bcos-framework/bcos-framework/ledger/LedgerInterface.h index da86497aab..c55797e099 100644 --- a/bcos-framework/bcos-framework/ledger/LedgerInterface.h +++ b/bcos-framework/bcos-framework/ledger/LedgerInterface.h @@ -28,7 +28,6 @@ #include "../storage/StorageInterface.h" #include "LedgerTypeDef.h" #include -#include #include #include #include diff --git a/bcos-framework/bcos-framework/storage/LegacyStorageMethods.h b/bcos-framework/bcos-framework/storage/LegacyStorageMethods.h index 1e3d703f8e..4e1034b699 100644 --- a/bcos-framework/bcos-framework/storage/LegacyStorageMethods.h +++ b/bcos-framework/bcos-framework/storage/LegacyStorageMethods.h @@ -20,7 +20,7 @@ inline task::Task> tag_invoke(storage2::tag_t, std::exception_ptr> m_result; constexpr static bool await_ready() noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { m_storage.asyncGetRow(m_table, m_key, [this, handle](Error::UniquePtr error, std::optional entry) mutable { @@ -98,7 +98,7 @@ inline task::Task tag_invoke(storage2::tag_t /*unused* std::variant m_result; constexpr static bool await_ready() noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { m_storage.asyncSetRow( m_table, m_key, std::move(m_entry), [this, handle](Error::UniquePtr error) mutable { diff --git a/bcos-front/bcos-front/FrontImpl.h b/bcos-front/bcos-front/FrontImpl.h index df93ab2e00..19239433a3 100644 --- a/bcos-front/bcos-front/FrontImpl.h +++ b/bcos-front/bcos-front/FrontImpl.h @@ -40,7 +40,7 @@ class FrontImpl : public bcos::concepts::front::FrontBase {} constexpr bool await_ready() const noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { bcos::concepts::getRef(m_gateway).asyncGetPeers( [this, m_handle = handle](Error::Ptr error, const gateway::GatewayInfo::Ptr&, @@ -123,7 +123,7 @@ class FrontImpl : public bcos::concepts::front::FrontBase { constexpr bool await_ready() const { return false; } - void await_suspend(CO_STD::coroutine_handle::promise_type> handle) + void await_suspend(std::coroutine_handle::promise_type> handle) { FRONT_LOG(DEBUG) << "P2P client send message: " << m_moduleID << " | " << m_nodeID->hex() << " | " << m_requestBuffer.size(); diff --git a/bcos-ledger/src/libledger/LedgerMethods.cpp b/bcos-ledger/src/libledger/LedgerMethods.cpp index 5a932c9728..44a0b0dc32 100644 --- a/bcos-ledger/src/libledger/LedgerMethods.cpp +++ b/bcos-ledger/src/libledger/LedgerMethods.cpp @@ -22,7 +22,7 @@ bcos::task::Task bcos::ledger::prewriteBlockToStorage(LedgerInterface& led Error::Ptr m_error; constexpr static bool await_ready() noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { m_ledger.asyncPrewriteBlock( m_storage, std::move(m_transactions), std::move(m_block), @@ -74,7 +74,7 @@ bcos::task::Task bcos::ledger::tag_invoke( std::variant m_result; constexpr static bool await_ready() noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { m_ledger.asyncGetBlockDataByNumber(m_blockNumber, m_blockFlag, [this, handle](Error::Ptr error, bcos::protocol::Block::Ptr block) { @@ -113,7 +113,7 @@ bcos::task::Task bcos::ledger::tag_invoke( std::variant m_result; constexpr static bool await_ready() noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { m_ledger.asyncGetTotalTransactionCount( [this, handle](Error::Ptr error, int64_t total, int64_t failed, @@ -155,7 +155,7 @@ bcos::task::Task bcos::ledger::tag_invoke( std::variant m_result; constexpr static bool await_ready() noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { m_ledger.asyncGetBlockNumber( [this, handle](Error::Ptr error, bcos::protocol::BlockNumber blockNumber) { @@ -195,7 +195,7 @@ bcos::task::Task bcos::ledger::tag_invoke( std::variant m_result; constexpr static bool await_ready() noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { m_ledger.asyncGetBlockHashByNumber( m_blockNumber, [this, handle](Error::Ptr error, crypto::HashType hash) { @@ -236,7 +236,7 @@ bcos::task::Task bcos::ledger::tag_invoke( std::variant m_result; constexpr static bool await_ready() noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { m_ledger.asyncGetBlockNumberByHash( m_hash, [this, handle](bcos::Error::Ptr error, bcos::protocol::BlockNumber number) { @@ -275,7 +275,7 @@ bcos::task::Task> bcos::ledger::t std::variant> m_result; constexpr static bool await_ready() noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { m_ledger.asyncGetSystemConfigByKey( m_key, [this, handle](Error::Ptr error, std::string value, @@ -325,7 +325,7 @@ bcos::task::Task bcos::ledger::tag_invoke( std::variant m_result; constexpr static bool await_ready() noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { m_ledger.asyncGetNodeListByType( m_type, [this, handle](Error::Ptr error, @@ -485,7 +485,7 @@ bcos::task::Task bcos::ledger::tag std::variant m_result; constexpr static bool await_ready() noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { m_ledger.asyncGetTransactionReceiptByHash(m_hash, false, [this, handle](bcos::Error::Ptr error, @@ -526,7 +526,7 @@ bcos::task::Task bcos::ledger::tag_invoke( std::variant m_result; constexpr static bool await_ready() noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { m_ledger.asyncGetBatchTxsByHashList( std::move(m_hashes), false, [this, handle](auto&& error, auto&& txs, auto&&) { diff --git a/bcos-rpc/bcos-rpc/web3jsonrpc/endpoints/EthEndpoint.cpp b/bcos-rpc/bcos-rpc/web3jsonrpc/endpoints/EthEndpoint.cpp index decf6d9a53..80de36de15 100644 --- a/bcos-rpc/bcos-rpc/web3jsonrpc/endpoints/EthEndpoint.cpp +++ b/bcos-rpc/bcos-rpc/web3jsonrpc/endpoints/EthEndpoint.cpp @@ -351,7 +351,7 @@ task::Task EthEndpoint::getCode(const Json::Value& request, Json::Value& r std::string m_address; std::variant m_result{}; constexpr static bool await_ready() noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) noexcept + void await_suspend(std::coroutine_handle<> handle) noexcept { m_scheduler->getCode(m_address, [this, handle](auto&& error, auto&& code) { if (error) @@ -497,7 +497,7 @@ task::Task EthEndpoint::call(const Json::Value& request, Json::Value& resp bcos::protocol::Transaction::Ptr m_tx; std::variant m_result{}; constexpr static bool await_ready() noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) noexcept + void await_suspend(std::coroutine_handle<> handle) noexcept { m_scheduler.call(m_tx, [this, handle](Error::Ptr&& error, auto&& result) { if (error) diff --git a/bcos-sdk/bcos-cpp-sdk/tarsRPC/CoRPCClient.cpp b/bcos-sdk/bcos-cpp-sdk/tarsRPC/CoRPCClient.cpp index c7bf216b36..e787c839aa 100644 --- a/bcos-sdk/bcos-cpp-sdk/tarsRPC/CoRPCClient.cpp +++ b/bcos-sdk/bcos-cpp-sdk/tarsRPC/CoRPCClient.cpp @@ -4,10 +4,10 @@ class CoCallback : public bcos::sdk::Callback { private: - CO_STD::coroutine_handle<> m_handle; + std::coroutine_handle<> m_handle; public: - CoCallback(CO_STD::coroutine_handle<> handle) : m_handle(handle) {} + CoCallback(std::coroutine_handle<> handle) : m_handle(handle) {} void onMessage([[maybe_unused]] int seq) override { // Make sure we are in the io thread of tars! @@ -18,7 +18,7 @@ class CoCallback : public bcos::sdk::Callback bcos::sdk::async::Awaitable bcos::sdk::async::sendTransaction( RPCClient& rpcClient, const bcos::protocol::Transaction& transaction) { - return {[&](CO_STD::coroutine_handle<> handle) { + return {[&](std::coroutine_handle<> handle) { bcos::sdk::SendTransaction sendTransaction(rpcClient); sendTransaction.setCallback(std::make_shared(handle)); sendTransaction.send(transaction); @@ -29,7 +29,7 @@ bcos::sdk::async::Awaitable bcos::sdk::async::sendTr bcos::sdk::async::Awaitable bcos::sdk::async::call( RPCClient& rpcClient, const bcos::protocol::Transaction& transaction) { - return {[&](CO_STD::coroutine_handle<> handle) { + return {[&](std::coroutine_handle<> handle) { bcos::sdk::Call call(rpcClient); call.setCallback(std::make_shared(handle)); call.send(transaction); @@ -40,7 +40,7 @@ bcos::sdk::async::Awaitable bcos::sdk::async::call( bcos::sdk::async::Awaitable bcos::sdk::async::blockNumber( RPCClient& rpcClient) { - return {[&](CO_STD::coroutine_handle<> handle) { + return {[&](std::coroutine_handle<> handle) { bcos::sdk::BlockNumber blockNumber(rpcClient); blockNumber.setCallback(std::make_shared(handle)); blockNumber.send(); diff --git a/bcos-sdk/bcos-cpp-sdk/tarsRPC/CoRPCClient.h b/bcos-sdk/bcos-cpp-sdk/tarsRPC/CoRPCClient.h index d56acf37bb..71e8437cf6 100644 --- a/bcos-sdk/bcos-cpp-sdk/tarsRPC/CoRPCClient.h +++ b/bcos-sdk/bcos-cpp-sdk/tarsRPC/CoRPCClient.h @@ -1,9 +1,6 @@ #pragma once #include "RPCClient.h" -#include -#include -#include -#include +#include namespace bcos::sdk::async { @@ -12,14 +9,14 @@ template class Awaitable { private: - std::function)> m_applyCall; + std::function)> m_applyCall; std::optional m_handle; public: Awaitable(decltype(m_applyCall) applyCall) : m_applyCall(std::move(applyCall)) {} constexpr bool await_ready() const { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) { m_handle.emplace(m_applyCall(handle)); } + void await_suspend(std::coroutine_handle<> handle) { m_handle.emplace(m_applyCall(handle)); } Handle await_resume() { return std::move(*m_handle); } }; diff --git a/bcos-sync/bcos-sync/state/SyncPeerStatus.h b/bcos-sync/bcos-sync/state/SyncPeerStatus.h index 7b6c0035ec..cf2c62f1f5 100644 --- a/bcos-sync/bcos-sync/state/SyncPeerStatus.h +++ b/bcos-sync/bcos-sync/state/SyncPeerStatus.h @@ -77,8 +77,8 @@ class PeerStatus private: bcos::crypto::PublicPtr m_nodeId; - bcos::protocol::BlockNumber m_number; - bcos::protocol::BlockNumber m_archivedNumber; + bcos::protocol::BlockNumber m_number{}; + bcos::protocol::BlockNumber m_archivedNumber{}; bcos::crypto::HashType m_hash; bcos::crypto::HashType m_genesisHash; diff --git a/bcos-tars-protocol/bcos-tars-protocol/client/TxPoolServiceClient.h b/bcos-tars-protocol/bcos-tars-protocol/client/TxPoolServiceClient.h index f0b56df6c2..0045ede0d1 100644 --- a/bcos-tars-protocol/bcos-tars-protocol/client/TxPoolServiceClient.h +++ b/bcos-tars-protocol/bcos-tars-protocol/client/TxPoolServiceClient.h @@ -57,7 +57,7 @@ class TxPoolServiceClient : public bcos::txpool::TxPoolInterface m_handle.resume(); } - CO_STD::coroutine_handle<> m_handle; + std::coroutine_handle<> m_handle; std::variant m_submitResult; @@ -67,7 +67,7 @@ class TxPoolServiceClient : public bcos::txpool::TxPoolInterface struct Awaitable { constexpr bool await_ready() { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { m_callback->m_handle = handle; m_proxy->tars_set_timeout(600000)->async_submit(m_callback, diff --git a/bcos-txpool/bcos-txpool/txpool/storage/MemoryStorage.cpp b/bcos-txpool/bcos-txpool/txpool/storage/MemoryStorage.cpp index bf66b9016c..245d5c88e5 100644 --- a/bcos-txpool/bcos-txpool/txpool/storage/MemoryStorage.cpp +++ b/bcos-txpool/bcos-txpool/txpool/storage/MemoryStorage.cpp @@ -99,7 +99,7 @@ task::Task MemoryStorage::submitTransact struct Awaitable { [[maybe_unused]] constexpr bool await_ready() { return false; } - [[maybe_unused]] void await_suspend(CO_STD::coroutine_handle<> handle) + [[maybe_unused]] void await_suspend(std::coroutine_handle<> handle) { try { @@ -180,7 +180,7 @@ task::Task MemoryStorage::submitTransact struct Awaitable { [[maybe_unused]] constexpr bool await_ready() { return false; } - [[maybe_unused]] void await_suspend(CO_STD::coroutine_handle<> handle) + [[maybe_unused]] void await_suspend(std::coroutine_handle<> handle) { try { diff --git a/cmake/CompilerSettings.cmake b/cmake/CompilerSettings.cmake index d55cff939d..051f6fd207 100644 --- a/cmake/CompilerSettings.cmake +++ b/cmake/CompilerSettings.cmake @@ -107,7 +107,6 @@ if(("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR("${CMAKE_CXX_COMPILER_ID}" MATC add_compile_options(-fstack-protector-strong) add_compile_options(-fstack-protector) - add_compile_options(-fno-omit-frame-pointer) if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0) add_compile_options(-fcoroutines) @@ -116,7 +115,7 @@ if(("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR("${CMAKE_CXX_COMPILER_ID}" MATC add_compile_options(-fPIC) add_compile_options(-Wno-error=nonnull) - add_compile_options(-foptimize-sibling-calls) + # add_compile_options(-foptimize-sibling-calls) add_compile_options(-Wno-stringop-overflow) add_compile_options(-Wno-restrict) add_compile_options(-Wno-error=format-truncation) @@ -127,7 +126,11 @@ if(("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR("${CMAKE_CXX_COMPILER_ID}" MATC add_compile_options(-Wno-array-bounds) add_compile_options(-Wno-aggressive-loop-optimizations) endif() - # add_compile_options(-fconcepts-diagnostics-depth=10) + + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 14.0) + set(CMAKE_CXX_STANDARD 23) + add_compile_options(-Wno-error=uninitialized) + endif() elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.0) set(CMAKE_CXX_FLAGS_DEBUG "-O -g") @@ -172,7 +175,6 @@ if(("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR("${CMAKE_CXX_COMPILER_ID}" MATC endif() elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC") add_compile_definitions(NOMINMAX) - #add_definitions(-DUSE_STD_RANGES) add_compile_options(/std:c++latest) add_compile_options(-bigobj) diff --git a/cmake/Options.cmake b/cmake/Options.cmake index 0d589906aa..54e1332356 100644 --- a/cmake/Options.cmake +++ b/cmake/Options.cmake @@ -56,7 +56,6 @@ macro(configure_project) default_option(SANITIZE_ADDRESS OFF) default_option(SANITIZE_THREAD OFF) default_option(IPO OFF) - default_option(PRECOMPILED_HEADER OFF) if(IPO) set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) endif() @@ -156,7 +155,6 @@ macro(print_config NAME) message("-- TESTS Build tests ${TESTS}") message("-- NATIVE Build native binary ${NATIVE}") message("-- IPO Enable IPO optimization ${IPO}") - message("-- PRECOMPILED_HEADER Enable precompiled header ${PRECOMPILED_HEADER}") message("-- SANITIZE_ADDRESS Enable sanitize ${SANITIZE_ADDRESS}") message("-- SANITIZE_THREAD Enable sanitize ${SANITIZE_THREAD}") message("-- TOOLCHAIN_FILE CMake toolchain file ${CMAKE_TOOLCHAIN_FILE}") diff --git a/cmake/PrecompiledHeaders.cmake b/cmake/PrecompiledHeaders.cmake deleted file mode 100644 index fb74029a87..0000000000 --- a/cmake/PrecompiledHeaders.cmake +++ /dev/null @@ -1,104 +0,0 @@ -if (PRECOMPILED_HEADER) - add_library(precompiled-headers INTERFACE) - target_precompile_headers(precompiled-headers - INTERFACE - # STL - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Boost - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # gsl - - - # fmt - - - # tbb - - - - - - - - - - - - - - # range - - ) - - include(GNUInstallDirs) - install(TARGETS precompiled-headers EXPORT fiscobcosTargets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}") - install(DIRECTORY "precompiled-headers" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" FILES_MATCHING PATTERN "*.h") -endif() \ No newline at end of file diff --git a/libtask/bcos-task/AwaitableValue.h b/libtask/bcos-task/AwaitableValue.h index 0c6bef4b38..6456130b60 100644 --- a/libtask/bcos-task/AwaitableValue.h +++ b/libtask/bcos-task/AwaitableValue.h @@ -1,6 +1,6 @@ #pragma once -#include "Coroutine.h" +#include #include namespace bcos::task @@ -13,7 +13,7 @@ class [[nodiscard]] AwaitableValue AwaitableValue() = default; AwaitableValue(Value&& value) : m_value(std::forward(value)) {} constexpr static bool await_ready() noexcept { return true; } - constexpr static bool await_suspend([[maybe_unused]] CO_STD::coroutine_handle<> handle) noexcept + constexpr static bool await_suspend([[maybe_unused]] std::coroutine_handle<> handle) noexcept { return false; } @@ -30,7 +30,7 @@ struct [[nodiscard]] AwaitableValue { AwaitableValue() = default; static constexpr bool await_ready() noexcept { return true; } - static constexpr bool await_suspend([[maybe_unused]] CO_STD::coroutine_handle<> handle) noexcept + static constexpr bool await_suspend([[maybe_unused]] std::coroutine_handle<> handle) noexcept { return false; } diff --git a/libtask/bcos-task/Coroutine.h b/libtask/bcos-task/Coroutine.h deleted file mode 100644 index e4388affd4..0000000000 --- a/libtask/bcos-task/Coroutine.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#if !__cpp_impl_coroutine -#include -namespace CO_STD = std::experimental; -#else -#include -namespace CO_STD = std; -#endif \ No newline at end of file diff --git a/libtask/bcos-task/Generator.h b/libtask/bcos-task/Generator.h index 8ba59c8647..9cb550e30f 100644 --- a/libtask/bcos-task/Generator.h +++ b/libtask/bcos-task/Generator.h @@ -1,16 +1,26 @@ #pragma once -// Fork from https://open-std.org/JTC1/SC22/WG21/docs/papers/2020/p2168r0.pdf -// Can be replace with std::generator +#include -#include "Coroutine.h" +#if __cpp_lib_generator >= 202207L +#include +namespace bcos::task +{ +template +using Generator = std::generator; +} +#else +#include #include #include +#include #include - namespace bcos::task { -template > +// Fork from https://open-std.org/JTC1/SC22/WG21/docs/papers/2020/p2168r0.pdf +// Can be replace with std::generator + +template , typename Alloc = void> class Generator { public: @@ -20,7 +30,7 @@ class Generator promise_type() : m_promise(this) {} Generator get_return_object() noexcept { - return Generator{CO_STD::coroutine_handle::from_promise(*this)}; + return Generator{std::coroutine_handle::from_promise(*this)}; } void unhandled_exception() @@ -34,21 +44,20 @@ class Generator void return_void() noexcept {} - CO_STD::suspend_always initial_suspend() noexcept { return {}; } + std::suspend_always initial_suspend() noexcept { return {}; } // Transfers control back to the parent of a nested coroutine struct final_awaiter { bool await_ready() noexcept { return false; } - CO_STD::coroutine_handle<> await_suspend( - CO_STD::coroutine_handle h) noexcept + std::coroutine_handle<> await_suspend(std::coroutine_handle h) noexcept { auto& promise = h.promise(); auto parent = h.promise().m_parent; if (parent) { promise.m_promise = parent; - return CO_STD::coroutine_handle::from_promise(*parent); + return std::coroutine_handle::from_promise(*parent); } return std::noop_coroutine(); } @@ -57,12 +66,12 @@ class Generator final_awaiter final_suspend() noexcept { return {}; } - CO_STD::suspend_always yield_value(Ref&& x) noexcept + std::suspend_always yield_value(Ref&& x) noexcept { m_promise->m_value = std::addressof(x); return {}; } - CO_STD::suspend_always yield_value(Ref& x) noexcept + std::suspend_always yield_value(Ref& x) noexcept { m_promise->m_value = std::addressof(x); return {}; @@ -83,7 +92,7 @@ class Generator // set the parent, root and exceptions pointer and // resume the nested coroutine - CO_STD::coroutine_handle<> await_suspend( + std::coroutine_handle<> await_suspend( std::coroutine_handle handle) noexcept { auto& current = handle.promise(); @@ -156,7 +165,7 @@ class Generator class Iterator { - using coroutine_handle = CO_STD::coroutine_handle; + using coroutine_handle = std::coroutine_handle; public: using iterator_category = std::input_iterator_tag; @@ -165,7 +174,6 @@ class Generator using reference = Ref; using pointer = std::add_pointer_t; - Iterator() noexcept = default; Iterator& operator=(const Iterator&) = delete; Iterator(const Iterator&) = delete; Iterator(Iterator&& o) noexcept { std::swap(coro_, o.coro_); } @@ -225,4 +233,5 @@ class Generator std::coroutine_handle coro_; }; -} // namespace bcos::task \ No newline at end of file +} // namespace bcos::task +#endif \ No newline at end of file diff --git a/libtask/bcos-task/TBBScheduler.h b/libtask/bcos-task/TBBScheduler.h index 1d34a4c46e..546735675f 100644 --- a/libtask/bcos-task/TBBScheduler.h +++ b/libtask/bcos-task/TBBScheduler.h @@ -1,6 +1,6 @@ #pragma once -#include "Coroutine.h" #include +#include namespace bcos::task::tbb { @@ -14,9 +14,9 @@ class TBBScheduler TBBScheduler(oneapi::tbb::task_group& taskGroup) : m_taskGroup(taskGroup) {} constexpr static bool await_ready() noexcept { return false; } - void await_suspend([[maybe_unused]] CO_STD::coroutine_handle<> handle) noexcept + void await_suspend([[maybe_unused]] std::coroutine_handle<> handle) noexcept { - m_taskGroup.run([handle]() { const_cast&>(handle).resume(); }); + m_taskGroup.run([handle]() { const_cast&>(handle).resume(); }); } constexpr static void await_resume() noexcept {} }; diff --git a/libtask/bcos-task/Task.h b/libtask/bcos-task/Task.h index 9963238782..f8d28496cd 100644 --- a/libtask/bcos-task/Task.h +++ b/libtask/bcos-task/Task.h @@ -1,10 +1,9 @@ #pragma once -#include "Coroutine.h" #include "bcos-concepts/Exception.h" #include #include +#include #include -#include #include #include @@ -26,30 +25,30 @@ class [[nodiscard]] Task struct Continuation { - CO_STD::coroutine_handle<> handle; + std::coroutine_handle<> handle; VariantType value; }; template struct PromiseBase { - constexpr CO_STD::suspend_always initial_suspend() noexcept { return {}; } + constexpr std::suspend_always initial_suspend() noexcept { return {}; } constexpr auto final_suspend() noexcept { struct FinalAwaitable { constexpr bool await_ready() noexcept { return false; } - constexpr CO_STD::coroutine_handle<> await_suspend( - CO_STD::coroutine_handle handle) noexcept + constexpr std::coroutine_handle<> await_suspend( + std::coroutine_handle handle) noexcept { - CO_STD::coroutine_handle<> continuationHandle; + std::coroutine_handle<> continuationHandle; if (handle.promise().m_continuation) { continuationHandle = handle.promise().m_continuation->handle; } handle.destroy(); - return continuationHandle ? continuationHandle : CO_STD::noop_coroutine(); + return continuationHandle ? continuationHandle : std::noop_coroutine(); } constexpr void await_resume() noexcept {} }; @@ -57,8 +56,8 @@ class [[nodiscard]] Task } Task get_return_object() { - auto handle = CO_STD::coroutine_handle::from_promise( - *static_cast(this)); + auto handle = + std::coroutine_handle::from_promise(*static_cast(this)); return Task(handle); } void unhandled_exception() @@ -100,7 +99,7 @@ class [[nodiscard]] Task bool await_ready() const noexcept { return !m_handle || m_handle.done(); } template - CO_STD::coroutine_handle<> await_suspend(CO_STD::coroutine_handle handle) + std::coroutine_handle<> await_suspend(std::coroutine_handle handle) { m_continuation.handle = handle; m_handle.promise().m_continuation = std::addressof(m_continuation); @@ -124,12 +123,12 @@ class [[nodiscard]] Task } } - CO_STD::coroutine_handle m_handle; + std::coroutine_handle m_handle; Continuation m_continuation; }; Awaitable operator co_await() { return Awaitable(*static_cast(this)); } - explicit Task(CO_STD::coroutine_handle handle) : m_handle(handle) {} + explicit Task(std::coroutine_handle handle) : m_handle(handle) {} Task(const Task&) = delete; Task(Task&& task) noexcept : m_handle(task.m_handle) { task.m_handle = nullptr; } Task& operator=(const Task&) = delete; @@ -142,7 +141,7 @@ class [[nodiscard]] Task void start() { m_handle.resume(); } private: - CO_STD::coroutine_handle m_handle; + std::coroutine_handle m_handle; }; } // namespace bcos::task \ No newline at end of file diff --git a/libtask/tests/TestTask.cpp b/libtask/tests/TestTask.cpp index 33733059fa..ef5a7fddea 100644 --- a/libtask/tests/TestTask.cpp +++ b/libtask/tests/TestTask.cpp @@ -99,7 +99,7 @@ Task asyncLevel2(oneapi::tbb::task_group& taskGroup) { constexpr bool await_ready() const { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { std::cout << "Start run async thread: " << handle.address() << std::endl; taskGroup.run([this, m_handle = handle]() { @@ -169,7 +169,7 @@ struct SleepTask inline static oneapi::tbb::concurrent_vector> futures; constexpr static bool await_ready() { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { futures.emplace_back(std::async([m_handle = handle]() mutable { using namespace std::chrono_literals; @@ -207,10 +207,10 @@ struct ResumableTask ResumableTask& operator=(ResumableTask&&) = default; ~ResumableTask() noexcept = default; - CO_STD::coroutine_handle<> m_handle; + std::coroutine_handle<> m_handle; constexpr bool static await_ready() { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { std::cout << "Task suspend!" << std::endl; m_handle = handle; diff --git a/lightnode/bcos-lightnode/scheduler/SchedulerWrapperImpl.h b/lightnode/bcos-lightnode/scheduler/SchedulerWrapperImpl.h index 835eefae52..056994407e 100644 --- a/lightnode/bcos-lightnode/scheduler/SchedulerWrapperImpl.h +++ b/lightnode/bcos-lightnode/scheduler/SchedulerWrapperImpl.h @@ -29,14 +29,14 @@ class SchedulerWrapperImpl auto transactionImpl = std::make_shared( [&transaction]() { return const_cast(&transaction); }); - struct Awaitable : public CO_STD::suspend_always + struct Awaitable : public std::suspend_always { Awaitable(decltype(transactionImpl)& transactionImpl, SchedulerType& scheduler, std::remove_cvref_t& receipt) : m_transactionImpl(transactionImpl), m_scheduler(scheduler), m_receipt(receipt) {} - void await_suspend(CO_STD::coroutine_handle::promise_type> handle) + void await_suspend(std::coroutine_handle::promise_type> handle) { bcos::concepts::getRef(m_scheduler) .call(std::move(m_transactionImpl), diff --git a/lightnode/fisco-bcos-lightnode/client/P2PClientImpl.h b/lightnode/fisco-bcos-lightnode/client/P2PClientImpl.h index 42a059a149..480031c451 100644 --- a/lightnode/fisco-bcos-lightnode/client/P2PClientImpl.h +++ b/lightnode/fisco-bcos-lightnode/client/P2PClientImpl.h @@ -52,7 +52,7 @@ class P2PClientImpl {} constexpr bool await_ready() const { return false; } - void await_suspend(CO_STD::coroutine_handle::promise_type> handle) + void await_suspend(std::coroutine_handle::promise_type> handle) { LIGHTNODE_LOG(DEBUG) << "P2P client send message: " << m_moduleID << " | " << m_nodeID->hex() << " | " << m_requestBuffer.size(); @@ -112,7 +112,7 @@ class P2PClientImpl {} constexpr bool await_ready() const noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { bcos::concepts::getRef(m_gateway).asyncGetPeers( [this, m_handle = handle](Error::Ptr error, const gateway::GatewayInfo::Ptr&, @@ -212,7 +212,7 @@ class P2PClientImpl {} constexpr bool await_ready() const noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { bcos::concepts::getRef(m_gateway).asyncGetPeers( [this, m_handle = handle](Error::Ptr error, const gateway::GatewayInfo::Ptr&, diff --git a/transaction-scheduler/bcos-transaction-scheduler/SchedulerParallelImpl.h b/transaction-scheduler/bcos-transaction-scheduler/SchedulerParallelImpl.h index d1d29d3aa0..4d84243676 100644 --- a/transaction-scheduler/bcos-transaction-scheduler/SchedulerParallelImpl.h +++ b/transaction-scheduler/bcos-transaction-scheduler/SchedulerParallelImpl.h @@ -40,7 +40,7 @@ struct ExecutionContext { ExecutionContext(int contextID, std::reference_wrapper transaction, std::reference_wrapper receipt, - std::optional coro, typename CoroType::Iterator iterator) + std::optional coro, std::optionalbegin())> iterator) : contextID(contextID), transaction(transaction), receipt(receipt), @@ -51,7 +51,7 @@ struct ExecutionContext std::reference_wrapper transaction; std::reference_wrapper receipt; std::optional coro; - typename CoroType::Iterator iterator; + std::optionalbegin())> iterator; }; template @@ -101,8 +101,8 @@ class ChunkStatus context.coro.emplace(transaction_executor::execute3Step(m_executor.get(), m_readWriteSetStorage, blockHeader, context.transaction.get(), context.contextID, ledgerConfig, task::tbb::syncWait)); - context.iterator = context.coro->begin(); - context.receipt.get() = *context.iterator; + context.iterator.emplace(context.coro->begin()); + context.receipt.get() = *(*context.iterator); } } @@ -119,9 +119,9 @@ class ChunkStatus << " transactions"; break; } - if (!context.receipt.get() && context.iterator != context.coro->end()) + if (!context.receipt.get() && *context.iterator != context.coro->end()) { - context.receipt.get() = *(++context.iterator); + context.receipt.get() = *(++(*context.iterator)); } } } @@ -132,9 +132,9 @@ class ChunkStatus ittapi::ITT_DOMAINS::instance().EXECUTE_CHUNK3); for (auto& context : m_contextRange) { - if (!context.receipt.get() && context.iterator != context.coro->end()) + if (!context.receipt.get() && *context.iterator != context.coro->end()) { - context.receipt.get() = *(++context.iterator); + context.receipt.get() = *(++(*context.iterator)); } } } diff --git a/transaction-scheduler/bcos-transaction-scheduler/SchedulerSerialImpl.h b/transaction-scheduler/bcos-transaction-scheduler/SchedulerSerialImpl.h index a729ea013b..4a1947833d 100644 --- a/transaction-scheduler/bcos-transaction-scheduler/SchedulerSerialImpl.h +++ b/transaction-scheduler/bcos-transaction-scheduler/SchedulerSerialImpl.h @@ -38,7 +38,7 @@ class SchedulerSerialImpl struct ExecutionContext { std::optional coro; - typename CoroType::Iterator iterator; + std::optionalbegin())> iterator; protocol::TransactionReceipt::Ptr receipt; }; @@ -76,8 +76,8 @@ class SchedulerSerialImpl coro.emplace( transaction_executor::execute3Step(executor, storage, blockHeader, transactions[i], i, ledgerConfig, task::tbb::syncWait)); - iterator = coro->begin(); - receipt = *iterator; + iterator.emplace(coro->begin()); + receipt = *(*iterator); } return range; }) & @@ -90,7 +90,7 @@ class SchedulerSerialImpl auto& [coro, iterator, receipt] = contexts[i]; if (!receipt) { - receipt = *(++iterator); + receipt = *(++(*iterator)); } } return range; @@ -104,7 +104,7 @@ class SchedulerSerialImpl auto& [coro, iterator, receipt] = contexts[i]; if (!receipt) { - receipt = *(++iterator); + receipt = *(++(*iterator)); } coro.reset(); } diff --git a/vcpkg.json b/vcpkg.json index 84728e19da..9f1324ced0 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -28,7 +28,6 @@ "boost-container-hash", "boost-multiprecision", "boost-program-options", - "boost-mp11", "ms-gsl", "tbb", { From fb6a18714a40e67d75895f08613f8f6977e2e7b9 Mon Sep 17 00:00:00 2001 From: MO NAN <651932351@qq.com> Date: Wed, 24 Jul 2024 15:11:20 +0800 Subject: [PATCH 10/16] Add optimize-sibling-calls (#4545) --- cmake/CompilerSettings.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/CompilerSettings.cmake b/cmake/CompilerSettings.cmake index 051f6fd207..f3005533f4 100644 --- a/cmake/CompilerSettings.cmake +++ b/cmake/CompilerSettings.cmake @@ -115,7 +115,7 @@ if(("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR("${CMAKE_CXX_COMPILER_ID}" MATC add_compile_options(-fPIC) add_compile_options(-Wno-error=nonnull) - # add_compile_options(-foptimize-sibling-calls) + add_compile_options(-foptimize-sibling-calls) add_compile_options(-Wno-stringop-overflow) add_compile_options(-Wno-restrict) add_compile_options(-Wno-error=format-truncation) From 8f67833f8f685bccd0399c22999f683a46ace2a2 Mon Sep 17 00:00:00 2001 From: Kyon <32325790+kyonRay@users.noreply.github.com> Date: Thu, 25 Jul 2024 14:05:47 +0800 Subject: [PATCH 11/16] (rpc): fix web3 rpc block tag null param bug. (#4547) --- bcos-rpc/bcos-rpc/util.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bcos-rpc/bcos-rpc/util.cpp b/bcos-rpc/bcos-rpc/util.cpp index 3d8ded0329..c2f6f24e3b 100644 --- a/bcos-rpc/bcos-rpc/util.cpp +++ b/bcos-rpc/bcos-rpc/util.cpp @@ -31,6 +31,10 @@ using namespace bcos::rpc; std::tuple bcos::rpc::getBlockNumberByTag( protocol::BlockNumber latest, std::string_view blockTag) { + if (blockTag.data() == nullptr || blockTag.empty()) + { + return std::make_tuple(latest, true); + } if (blockTag == EarliestBlock) { return std::make_tuple(0, false); From 99d16a69f5ffa93fab5cf8540905b88adf121952 Mon Sep 17 00:00:00 2001 From: MO NAN <651932351@qq.com> Date: Mon, 29 Jul 2024 10:48:08 +0800 Subject: [PATCH 12/16] Fix rollback and task memory leak (#4554) --- bcos-table/src/LegacyStorageWrapper.h | 22 ++-- cmake/CompilerSettings.cmake | 1 + libtask/bcos-task/TBBWait.h | 4 +- libtask/bcos-task/Task.h | 147 ++++++++++++++------------ libtask/bcos-task/Trait.h | 8 +- libtask/bcos-task/Wait.h | 6 +- libtask/tests/TestTask.cpp | 57 ++-------- 7 files changed, 114 insertions(+), 131 deletions(-) diff --git a/bcos-table/src/LegacyStorageWrapper.h b/bcos-table/src/LegacyStorageWrapper.h index a4ae7161ec..2784ae9045 100644 --- a/bcos-table/src/LegacyStorageWrapper.h +++ b/bcos-table/src/LegacyStorageWrapper.h @@ -9,6 +9,7 @@ #include "bcos-utilities/Error.h" #include #include +#include #include #include @@ -19,10 +20,10 @@ template class LegacyStorageWrapper : public virtual bcos::storage::StorageInterface { private: - Storage* m_storage; + std::reference_wrapper m_storage; public: - explicit LegacyStorageWrapper(Storage& m_storage) : m_storage(std::addressof(m_storage)) {} + explicit LegacyStorageWrapper(Storage& m_storage) : m_storage(m_storage) {} void asyncGetPrimaryKeys(std::string_view table, const std::optional& condition, @@ -35,7 +36,7 @@ class LegacyStorageWrapper : public virtual bcos::storage::StorageInterface size_t index = 0; auto [start, count] = condition->getLimit(); - auto range = co_await storage2::range(*self->m_storage); + auto range = co_await storage2::range(self->m_storage.get()); while (auto keyValue = co_await range.next()) { auto&& [key, value] = *keyValue; @@ -80,7 +81,7 @@ class LegacyStorageWrapper : public virtual bcos::storage::StorageInterface try { auto value = co_await storage2::readOne( - *self->m_storage, transaction_executor::StateKeyView{table, key}); + self->m_storage.get(), transaction_executor::StateKeyView{table, key}); callback(nullptr, std::move(value)); } catch (std::exception& e) @@ -105,7 +106,7 @@ class LegacyStorageWrapper : public virtual bcos::storage::StorageInterface return transaction_executor::StateKeyView{ table, std::forward(key)}; }) | RANGES::to(); - auto values = co_await storage2::readSome(*self->m_storage, stateKeys); + auto values = co_await storage2::readSome(self->m_storage.get(), stateKeys); std::vector> vectorValues( std::make_move_iterator(values.begin()), std::make_move_iterator(values.end())); @@ -128,11 +129,11 @@ class LegacyStorageWrapper : public virtual bcos::storage::StorageInterface if (entry.status() == storage::Entry::Status::DELETED) { co_await storage2::removeOne( - *self->m_storage, transaction_executor::StateKeyView(table, key)); + self->m_storage.get(), transaction_executor::StateKeyView(table, key)); } else { - co_await storage2::writeOne(*self->m_storage, + co_await storage2::writeOne(self->m_storage, transaction_executor::StateKey(table, key), std::move(entry)); } callback(nullptr); @@ -157,7 +158,7 @@ class LegacyStorageWrapper : public virtual bcos::storage::StorageInterface decltype(values)& values) -> task::Task { try { - co_await storage2::writeSome(*self->m_storage, + co_await storage2::writeSome(self->m_storage.get(), keys | RANGES::views::transform([&](std::string_view key) { return transaction_executor::StateKey{tableName, key}; }), @@ -195,7 +196,10 @@ class LegacyStateStorageWrapper : public virtual storage::StateStorageInterface, void rollback(const storage::Recoder& recoder) override { - BOOST_THROW_EXCEPTION(std::runtime_error("Unimplemented!")); + // 不要抛出异常,会导致TransactionExecutive::revert()后续的transientStateStorage->rollback无法执行 + // Do not throw an exception that will cause Tra::Revert () to follow the Trancintztat + // Stolag-> Rohrbak not to be executed + // BOOST_THROW_EXCEPTION(std::runtime_error("Unimplemented!")); } crypto::HashType hash( diff --git a/cmake/CompilerSettings.cmake b/cmake/CompilerSettings.cmake index f3005533f4..9a9c44d24d 100644 --- a/cmake/CompilerSettings.cmake +++ b/cmake/CompilerSettings.cmake @@ -131,6 +131,7 @@ if(("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR("${CMAKE_CXX_COMPILER_ID}" MATC set(CMAKE_CXX_STANDARD 23) add_compile_options(-Wno-error=uninitialized) endif() + # add_compile_options(-fconcepts-diagnostics-depth=10) elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.0) set(CMAKE_CXX_FLAGS_DEBUG "-O -g") diff --git a/libtask/bcos-task/TBBWait.h b/libtask/bcos-task/TBBWait.h index 5b5e4e31e9..3758bbf1f2 100644 --- a/libtask/bcos-task/TBBWait.h +++ b/libtask/bcos-task/TBBWait.h @@ -43,7 +43,7 @@ constexpr inline struct SyncWait { if constexpr (std::is_void_v) { - co_await task; + co_await std::forward(task); } else { @@ -54,7 +54,7 @@ constexpr inline struct SyncWait } else { - result.template emplace(co_await task); + result.template emplace(co_await std::forward(task)); } } } diff --git a/libtask/bcos-task/Task.h b/libtask/bcos-task/Task.h index f8d28496cd..ea23cec4f7 100644 --- a/libtask/bcos-task/Task.h +++ b/libtask/bcos-task/Task.h @@ -14,83 +14,94 @@ struct NoReturnValue : public bcos::error::Exception { }; -template - requires(!std::is_reference_v) -class [[nodiscard]] Task +template +struct FinalAwaitable { -public: - using VariantType = - std::conditional_t, std::variant, - std::variant>; - - struct Continuation - { - std::coroutine_handle<> handle; - VariantType value; - }; - - template - struct PromiseBase + static constexpr bool await_ready() noexcept { return false; } + static constexpr std::coroutine_handle<> await_suspend( + std::coroutine_handle handle) noexcept { - constexpr std::suspend_always initial_suspend() noexcept { return {}; } - constexpr auto final_suspend() noexcept + std::coroutine_handle<> continuationHandle; + if (handle.promise().m_continuation) { - struct FinalAwaitable - { - constexpr bool await_ready() noexcept { return false; } - constexpr std::coroutine_handle<> await_suspend( - std::coroutine_handle handle) noexcept - { - std::coroutine_handle<> continuationHandle; - if (handle.promise().m_continuation) - { - continuationHandle = handle.promise().m_continuation->handle; - } - handle.destroy(); - - return continuationHandle ? continuationHandle : std::noop_coroutine(); - } - constexpr void await_resume() noexcept {} - }; - return FinalAwaitable{}; + continuationHandle = handle.promise().m_continuation->handle; } - Task get_return_object() + handle.destroy(); + + return continuationHandle ? continuationHandle : std::noop_coroutine(); + } + constexpr void await_resume() noexcept {} +}; + +template +struct Continuation +{ + std::coroutine_handle<> handle; + VariantType value; +}; + +template +struct PromiseBase +{ + static constexpr std::suspend_always initial_suspend() noexcept { return {}; } + static constexpr auto final_suspend() noexcept { return FinalAwaitable{}; } + Task get_return_object() + { + auto handle = + std::coroutine_handle::from_promise(*static_cast(this)); + return Task{handle}; + } + void unhandled_exception() + { + if (!m_continuation) { auto handle = std::coroutine_handle::from_promise(*static_cast(this)); - return Task(handle); - } - void unhandled_exception() - { - if (!m_continuation) - { - std::rethrow_exception(std::current_exception()); - } - m_continuation->value.template emplace(std::current_exception()); + handle.destroy(); + std::rethrow_exception(std::current_exception()); } + m_continuation->value.template emplace(std::current_exception()); + } - Continuation* m_continuation = nullptr; - }; - struct PromiseVoid : public PromiseBase - { - constexpr void return_void() noexcept {} - }; - struct PromiseValue : public PromiseBase + Continuation* m_continuation{}; +}; + +template +struct PromiseVoid : public PromiseBase> +{ + static constexpr void return_void() noexcept {} +}; + +template +struct PromiseValue : public PromiseBase> +{ + void return_value(auto&& value) { - void return_value(auto&& value) + if (PromiseBase>::m_continuation) { - if (PromiseBase::m_continuation) - { - PromiseBase::m_continuation->value.template emplace( - std::forward(value)); - } + PromiseBase>::m_continuation->value + .template emplace(std::forward(value)); } - }; - using promise_type = std::conditional_t, PromiseVoid, PromiseValue>; + } +}; + +template + requires(!std::is_reference_v) +class [[nodiscard]] Task +{ +public: + using Value = ValueType; + using VariantType = std::conditional_t, + std::variant, + std::variant>; + + using promise_type = + std::conditional_t, PromiseVoid, PromiseValue>; struct Awaitable { - explicit Awaitable(Task const& task) : m_handle(task.m_handle){}; + explicit Awaitable(std::coroutine_handle handle) + : m_handle(std::move(handle)){}; Awaitable(const Awaitable&) = delete; Awaitable(Awaitable&&) noexcept = default; Awaitable& operator=(const Awaitable&) = delete; @@ -105,14 +116,14 @@ class [[nodiscard]] Task m_handle.promise().m_continuation = std::addressof(m_continuation); return m_handle; } - Value await_resume() + ValueType await_resume() { if (std::holds_alternative(m_continuation.value)) { std::rethrow_exception(std::get(m_continuation.value)); } - if constexpr (!std::is_void_v) + if constexpr (!std::is_void_v) { if (!std::holds_alternative(m_continuation.value)) { @@ -124,9 +135,9 @@ class [[nodiscard]] Task } std::coroutine_handle m_handle; - Continuation m_continuation; + Continuation m_continuation; }; - Awaitable operator co_await() { return Awaitable(*static_cast(this)); } + Awaitable operator co_await() const&& { return Awaitable(m_handle); } explicit Task(std::coroutine_handle handle) : m_handle(handle) {} Task(const Task&) = delete; @@ -134,6 +145,10 @@ class [[nodiscard]] Task Task& operator=(const Task&) = delete; Task& operator=(Task&& task) noexcept { + if (m_handle) + { + m_handle.destroy(); + } m_handle = task.m_handle; task.m_handle = nullptr; } diff --git a/libtask/bcos-task/Trait.h b/libtask/bcos-task/Trait.h index 9e4d2d84e7..f96405907f 100644 --- a/libtask/bcos-task/Trait.h +++ b/libtask/bcos-task/Trait.h @@ -7,11 +7,11 @@ namespace bcos::task { template -concept HasADLCoAwait = requires(Task task) { operator co_await(task); }; +concept HasADLCoAwait = requires(Task&& task) { operator co_await(task); }; template -concept HasMemberCoAwait = requires(Task task) { task.operator co_await(); }; +concept HasMemberCoAwait = requires(Task&& task) { std::forward(task).operator co_await(); }; template -concept HasAwaitable = requires(Awaitable awaitable) { awaitable.await_resume(); }; +concept HasAwaitable = requires(Awaitable&& awaitable) { awaitable.await_resume(); }; auto getAwaitable(auto&& task) { @@ -22,7 +22,7 @@ auto getAwaitable(auto&& task) } else if constexpr (HasMemberCoAwait) { - return task.operator co_await(); + return std::forward(task).operator co_await(); } else if constexpr (HasAwaitable) { diff --git a/libtask/bcos-task/Wait.h b/libtask/bcos-task/Wait.h index efb7309d28..de29ee5047 100644 --- a/libtask/bcos-task/Wait.h +++ b/libtask/bcos-task/Wait.h @@ -15,7 +15,7 @@ constexpr inline struct Wait void operator()(auto&& task) const requires std::is_rvalue_reference_v { - task.start(); + std::forward(task).start(); } } wait{}; @@ -41,7 +41,7 @@ constexpr inline struct SyncWait { if constexpr (std::is_void_v) { - co_await task; + co_await std::forward(task); } else { @@ -52,7 +52,7 @@ constexpr inline struct SyncWait } else { - result.template emplace(co_await task); + result.template emplace(co_await std::forward(task)); } } } diff --git a/libtask/tests/TestTask.cpp b/libtask/tests/TestTask.cpp index ef5a7fddea..e25e2e267c 100644 --- a/libtask/tests/TestTask.cpp +++ b/libtask/tests/TestTask.cpp @@ -1,6 +1,7 @@ #include "bcos-task/Generator.h" #include "bcos-task/TBBWait.h" #include "bcos-task/Task.h" +#include "bcos-task/Trait.h" #include "bcos-task/Wait.h" #include #include @@ -198,57 +199,19 @@ BOOST_AUTO_TEST_CASE(generator) std::cout << "All outputed" << std::endl; } -struct ResumableTask +Task taskWithThrow() { - ResumableTask() = default; - ResumableTask(const ResumableTask&) = delete; - ResumableTask& operator=(const ResumableTask&) = delete; - ResumableTask(ResumableTask&&) = default; - ResumableTask& operator=(ResumableTask&&) = default; - ~ResumableTask() noexcept = default; - - std::coroutine_handle<> m_handle; - - constexpr bool static await_ready() { return false; } - void await_suspend(std::coroutine_handle<> handle) - { - std::cout << "Task suspend!" << std::endl; - m_handle = handle; - } - constexpr void await_resume() const {} -}; + throw std::runtime_error("error"); + co_return 0; +} -BOOST_AUTO_TEST_CASE(tbbWait) +BOOST_AUTO_TEST_CASE(memoryLeak) { - constexpr static auto count = 20; - std::vector tasks(count); - - ::tbb::task_arena arena(2); - ::tbb::task_group group1; - arena.execute([&]() { - for (auto i = 0; i < count; ++i) - { - group1.run([&tasks, i]() { - std::cout << "Task " << i << " started" << std::endl; - bcos::task::tbb::syncWait(tasks[i]); - std::cout << "Task " << i << " ended" << std::endl; - }); - } - - group1.run([&]() { - using namespace std::chrono_literals; - std::this_thread::sleep_for(1s); - - for (auto& task : tasks) - { - BOOST_REQUIRE(task.m_handle); - task.m_handle.resume(); - } - }); - }); - + bcos::task::syncWait( + []() -> Task { BOOST_CHECK_THROW(co_await taskWithThrow(), std::runtime_error); }()); - group1.wait(); + bcos::task::wait( + []() -> Task { BOOST_CHECK_THROW(co_await taskWithThrow(), std::runtime_error); }()); } BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file From f1693aa1cfcdabb0774d0683c998f589cef38a97 Mon Sep 17 00:00:00 2001 From: Kyon <32325790+kyonRay@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:32:07 +0800 Subject: [PATCH 13/16] (CI): fix CI upload compile error. (#4551) --- .../workflow-self-hosted-centos-upload.yml | 3 +- .../src/executor/TransactionExecutor.cpp | 11 +++---- .../src/precompiled/common/Utilities.h | 5 ++-- .../web3jsonrpc/endpoints/EthEndpoint.cpp | 29 ++++++++++--------- .../web3jsonrpc/model/BlockResponse.h | 2 +- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/.github/workflows/workflow-self-hosted-centos-upload.yml b/.github/workflows/workflow-self-hosted-centos-upload.yml index ba38f4f3e2..76ee393459 100644 --- a/.github/workflows/workflow-self-hosted-centos-upload.yml +++ b/.github/workflows/workflow-self-hosted-centos-upload.yml @@ -9,6 +9,7 @@ on: branches: - release-3.* - feature-3.* + - bugfix-3.* - master release: types: [push] @@ -73,7 +74,7 @@ jobs: . /opt/rh/rh-perl530/enable export LIBCLANG_PATH=/opt/rh/llvm-toolset-7.0/root/lib64/ . /opt/rh/llvm-toolset-7.0/enable - cd build && cmake -DALLOCATOR=jemalloc -DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake -DTESTS=ON -DWITH_LIGHTNODE=OFF -DWITH_CPPSDK=OFF -DWITH_TIKV=OFF -DWITH_TARS_SERVICES=OFF .. || cat *.log + cd build && cmake -DALLOCATOR=defalut -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake -DTESTS=ON -DWITH_LIGHTNODE=OFF -DWITH_CPPSDK=OFF -DWITH_TIKV=OFF -DWITH_TARS_SERVICES=OFF .. || cat *.log make -j8 chmod +x ./fisco-bcos-air/fisco-bcos ./fisco-bcos-air/fisco-bcos -v diff --git a/bcos-executor/src/executor/TransactionExecutor.cpp b/bcos-executor/src/executor/TransactionExecutor.cpp index c0ea6cad99..5b5e3a47ca 100644 --- a/bcos-executor/src/executor/TransactionExecutor.cpp +++ b/bcos-executor/src/executor/TransactionExecutor.cpp @@ -2053,9 +2053,12 @@ void TransactionExecutor::getCode( // asyncGetRow key should not be empty auto codeKey = codeHash.empty() ? ACCOUNT_CODE : codeHash; // try to get abi from SYS_CODE_BINARY first + ledger::Features features; + task::syncWait(features.readFromStorage(*stateStorage, m_lastCommittedBlockNumber)); stateStorage->asyncGetRow(bcos::ledger::SYS_CODE_BINARY, codeKey, [this, contractTableName, callback = std::move(callback), - getCodeFromContractTable = std::move(getCodeFromContractTable)]( + getCodeFromContractTable = std::move(getCodeFromContractTable), + features = std::move(features)]( Error::UniquePtr error, std::optional entry) { if (!m_isRunning) { @@ -2082,11 +2085,9 @@ void TransactionExecutor::getCode( } auto code = entry->getField(0); - if ((m_blockContext->features().get( - ledger::Features::Flag::bugfix_eoa_as_contract) && + if ((features.get(ledger::Features::Flag::bugfix_eoa_as_contract) && bcos::precompiled::isDynamicPrecompiledAccountCode(code)) || - (m_blockContext->features().get( - ledger::Features::Flag::bugfix_eoa_match_failed) && + (features.get(ledger::Features::Flag::bugfix_eoa_match_failed) && bcos::precompiled::matchDynamicAccountCode(code))) { EXECUTOR_NAME_LOG(DEBUG) << "Get eoa code success, return empty code to evm"; diff --git a/bcos-executor/src/precompiled/common/Utilities.h b/bcos-executor/src/precompiled/common/Utilities.h index 9b06a5f401..a8c90d9c58 100644 --- a/bcos-executor/src/precompiled/common/Utilities.h +++ b/bcos-executor/src/precompiled/common/Utilities.h @@ -89,13 +89,14 @@ inline std::string getDynamicPrecompiledCodeString( inline bool matchDynamicAccountCode(std::string_view code) { - return code.starts_with(getDynamicPrecompiledCodeString(ACCOUNT_ADDRESS, "")); + auto const prefix = getDynamicPrecompiledCodeString(ACCOUNT_ADDRESS, ""); + return code.starts_with(prefix); } // ERROR: this method match account precompiled in wrong logic, use matchDynamicAccountCode instead. inline bool isDynamicPrecompiledAccountCode(const std::string_view& _code) { - return std::string_view(getDynamicPrecompiledCodeString(ACCOUNT_ADDRESS, "")) == _code; + return getDynamicPrecompiledCodeString(ACCOUNT_ADDRESS, "") == _code; } inline std::string trimHexPrefix(const std::string& _hex) diff --git a/bcos-rpc/bcos-rpc/web3jsonrpc/endpoints/EthEndpoint.cpp b/bcos-rpc/bcos-rpc/web3jsonrpc/endpoints/EthEndpoint.cpp index decf6d9a53..1781e67309 100644 --- a/bcos-rpc/bcos-rpc/web3jsonrpc/endpoints/EthEndpoint.cpp +++ b/bcos-rpc/bcos-rpc/web3jsonrpc/endpoints/EthEndpoint.cpp @@ -348,35 +348,35 @@ task::Task EthEndpoint::getCode(const Json::Value& request, Json::Value& r struct Awaitable { bcos::scheduler::SchedulerInterface::Ptr m_scheduler; - std::string m_address; + std::string& m_address; std::variant m_result{}; constexpr static bool await_ready() noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) noexcept + void await_suspend(CO_STD::coroutine_handle<> handle) { m_scheduler->getCode(m_address, [this, handle](auto&& error, auto&& code) { if (error) { - m_result.emplace(std::move(error)); + m_result.emplace(std::forward(error)); } else { - m_result.emplace(std::move(code)); + m_result.emplace(std::forward(code)); } handle.resume(); }); } - bcos::bytes await_resume() noexcept + bcos::bytes await_resume() { if (std::holds_alternative(m_result)) { BOOST_THROW_EXCEPTION(*std::get(m_result)); } - return std::move(std::get(m_result)); + return std::get(m_result); } }; auto const code = co_await Awaitable{ .m_scheduler = scheduler, - .m_address = std::move(addressStr), + .m_address = addressStr, }; Json::Value result = toHexStringWithPrefix(code); buildJsonContent(result, response); @@ -487,17 +487,17 @@ task::Task EthEndpoint::call(const Json::Value& request, Json::Value& resp WEB3_LOG(TRACE) << LOG_DESC("eth_call") << LOG_KV("call", call) << LOG_KV("blockTag", blockTag) << LOG_KV("blockNumber", blockNumber); } - auto&& tx = call.takeToTransaction(m_nodeService->blockFactory()->transactionFactory()); + auto const tx = call.takeToTransaction(m_nodeService->blockFactory()->transactionFactory()); // TODO: ignore params blockNumber here, use it after historical data is available - + std::variant variantResult{}; // MOVE it into a new file struct Awaitable { bcos::scheduler::SchedulerInterface& m_scheduler; bcos::protocol::Transaction::Ptr m_tx; - std::variant m_result{}; + std::variant& m_result; constexpr static bool await_ready() noexcept { return false; } - void await_suspend(CO_STD::coroutine_handle<> handle) noexcept + void await_suspend(CO_STD::coroutine_handle<> handle) { m_scheduler.call(m_tx, [this, handle](Error::Ptr&& error, auto&& result) { if (error) @@ -511,16 +511,17 @@ task::Task EthEndpoint::call(const Json::Value& request, Json::Value& resp handle.resume(); }); } - protocol::TransactionReceipt::Ptr await_resume() noexcept + protocol::TransactionReceipt::Ptr await_resume() { if (std::holds_alternative(m_result)) { BOOST_THROW_EXCEPTION(*std::get(m_result)); } - return std::move(std::get(m_result)); + return std::get(m_result); } }; - auto const result = co_await Awaitable{.m_scheduler = *scheduler, .m_tx = std::move(tx)}; + auto const result = + co_await Awaitable{.m_scheduler = *scheduler, .m_tx = tx, .m_result = variantResult}; auto output = toHexStringWithPrefix(result->output()); if (result->status() == static_cast(protocol::TransactionStatus::None)) diff --git a/bcos-rpc/bcos-rpc/web3jsonrpc/model/BlockResponse.h b/bcos-rpc/bcos-rpc/web3jsonrpc/model/BlockResponse.h index f0b5a5476e..1957ceb200 100644 --- a/bcos-rpc/bcos-rpc/web3jsonrpc/model/BlockResponse.h +++ b/bcos-rpc/bcos-rpc/web3jsonrpc/model/BlockResponse.h @@ -48,7 +48,7 @@ namespace bcos::rpc result["totalDifficulty"] = "0x0"; result["extraData"] = toHexStringWithPrefix(block->blockHeader()->extraData()); result["size"] = "0xffff"; - result["gasLimit"] = toQuantity(3000000000ull); + result["gasLimit"] = toQuantity(30000000ull); result["gasUsed"] = toQuantity((uint64_t)block->blockHeader()->gasUsed()); result["timestamp"] = toQuantity(block->blockHeader()->timestamp()); if (fullTxs) From 6f62fadf08dc69bdd57859d54bb99e3ece4ad62e Mon Sep 17 00:00:00 2001 From: MO NAN <651932351@qq.com> Date: Wed, 31 Jul 2024 19:01:52 +0800 Subject: [PATCH 14/16] Add limit to cached executives (#4559) --- .../TransactionScheduler.h | 4 +- .../web3jsonrpc/endpoints/EthEndpoint.cpp | 68 +++++++++---------- .../vm/HostContext.cpp | 16 +++++ .../vm/HostContext.h | 26 ++++--- .../BaselineScheduler.h | 2 +- 5 files changed, 64 insertions(+), 52 deletions(-) diff --git a/bcos-framework/bcos-framework/transaction-scheduler/TransactionScheduler.h b/bcos-framework/bcos-framework/transaction-scheduler/TransactionScheduler.h index 7264bcb5b8..c56eb9409c 100644 --- a/bcos-framework/bcos-framework/transaction-scheduler/TransactionScheduler.h +++ b/bcos-framework/bcos-framework/transaction-scheduler/TransactionScheduler.h @@ -1,9 +1,9 @@ #pragma once -#include "../protocol/Block.h" +#include "../protocol/BlockHeader.h" +#include "../protocol/TransactionReceipt.h" #include "bcos-task/Task.h" #include "bcos-task/Trait.h" -#include "bcos-utilities/Ranges.h" namespace bcos::transaction_scheduler { diff --git a/bcos-rpc/bcos-rpc/web3jsonrpc/endpoints/EthEndpoint.cpp b/bcos-rpc/bcos-rpc/web3jsonrpc/endpoints/EthEndpoint.cpp index 62d509dd81..ea2d2e8098 100644 --- a/bcos-rpc/bcos-rpc/web3jsonrpc/endpoints/EthEndpoint.cpp +++ b/bcos-rpc/bcos-rpc/web3jsonrpc/endpoints/EthEndpoint.cpp @@ -36,6 +36,7 @@ #include #include #include +#include using namespace bcos; using namespace bcos::rpc; @@ -475,71 +476,68 @@ task::Task EthEndpoint::call(const Json::Value& request, Json::Value& resp BOOST_THROW_EXCEPTION( JsonRpcException(JsonRpcError::InternalError, "Scheduler not available!")); } - auto [valid, call] = decodeCallRequest(request[0u]); + auto [valid, call] = decodeCallRequest(request[0U]); if (!valid) { BOOST_THROW_EXCEPTION(JsonRpcException(InvalidParams, "Invalid call request!")); } - auto const blockTag = toView(request[1u]); + auto const blockTag = toView(request[1U]); auto [blockNumber, _] = co_await getBlockNumberByTag(blockTag); if (c_fileLogLevel == TRACE) { WEB3_LOG(TRACE) << LOG_DESC("eth_call") << LOG_KV("call", call) << LOG_KV("blockTag", blockTag) << LOG_KV("blockNumber", blockNumber); } - auto const tx = call.takeToTransaction(m_nodeService->blockFactory()->transactionFactory()); - // TODO: ignore params blockNumber here, use it after historical data is available - std::variant variantResult{}; - // MOVE it into a new file + auto tx = call.takeToTransaction(m_nodeService->blockFactory()->transactionFactory()); struct Awaitable { bcos::scheduler::SchedulerInterface& m_scheduler; - bcos::protocol::Transaction::Ptr m_tx; - std::variant& m_result; + bcos::protocol::Transaction::Ptr& m_tx; + Error::Ptr m_error; + Json::Value& m_response; + constexpr static bool await_ready() noexcept { return false; } - void await_suspend(std::coroutine_handle<> handle) noexcept + void await_suspend(std::coroutine_handle<> handle) { m_scheduler.call(m_tx, [this, handle](Error::Ptr&& error, auto&& result) { if (error) { - m_result.emplace(std::move(error)); + m_error = std::move(error); } else { - m_result.emplace(std::move(result)); + auto output = toHexStringWithPrefix(result->output()); + if (result->status() == static_cast(protocol::TransactionStatus::None)) + { + m_response["jsonrpc"] = "2.0"; + m_response["result"] = output; + } + else + { + // https://docs.infura.io/api/networks/ethereum/json-rpc-methods/eth_call#returns + Json::Value jsonResult = Json::objectValue; + jsonResult["code"] = result->status(); + jsonResult["message"] = result->message(); + jsonResult["data"] = output; + m_response["jsonrpc"] = "2.0"; + m_response["error"] = std::move(jsonResult); + } } + handle.resume(); }); } - protocol::TransactionReceipt::Ptr await_resume() + void await_resume() { - if (std::holds_alternative(m_result)) + if (m_error) { - BOOST_THROW_EXCEPTION(*std::get(m_result)); + BOOST_THROW_EXCEPTION(*m_error); } - return std::get(m_result); } }; - auto const result = - co_await Awaitable{.m_scheduler = *scheduler, .m_tx = tx, .m_result = variantResult}; - - auto output = toHexStringWithPrefix(result->output()); - if (result->status() == static_cast(protocol::TransactionStatus::None)) - { - response["jsonrpc"] = "2.0"; - response["result"] = std::move(output); - } - else - { - // https://docs.infura.io/api/networks/ethereum/json-rpc-methods/eth_call#returns - Json::Value jsonResult = Json::objectValue; - jsonResult["code"] = result->status(); - jsonResult["message"] = result->message(); - jsonResult["data"] = std::move(output); - response["jsonrpc"] = "2.0"; - response["error"] = std::move(jsonResult); - } - co_return; + Awaitable awaitable{ + .m_scheduler = *scheduler, .m_tx = tx, .m_error = {}, .m_response = response}; + co_await awaitable; } task::Task EthEndpoint::estimateGas(const Json::Value& request, Json::Value& response) { diff --git a/transaction-executor/bcos-transaction-executor/vm/HostContext.cpp b/transaction-executor/bcos-transaction-executor/vm/HostContext.cpp index 5e5f4abe55..95e34a5cf8 100644 --- a/transaction-executor/bcos-transaction-executor/vm/HostContext.cpp +++ b/transaction-executor/bcos-transaction-executor/vm/HostContext.cpp @@ -58,3 +58,19 @@ std::variant bcos::transaction_executor::getM } return message; } + +bcos::transaction_executor::CacheExecutables& bcos::transaction_executor::getCacheExecutables() +{ + struct CacheExecutables + { + bcos::transaction_executor::CacheExecutables m_cachedExecutables; + + CacheExecutables() + { + constexpr static auto maxContracts = 100; + m_cachedExecutables.setMaxCapacity(sizeof(std::shared_ptr) * maxContracts); + } + } static cachedExecutables; + + return cachedExecutables.m_cachedExecutables; +} diff --git a/transaction-executor/bcos-transaction-executor/vm/HostContext.h b/transaction-executor/bcos-transaction-executor/vm/HostContext.h index e9a552c9ab..cac96102b6 100644 --- a/transaction-executor/bcos-transaction-executor/vm/HostContext.h +++ b/transaction-executor/bcos-transaction-executor/vm/HostContext.h @@ -75,35 +75,34 @@ std::variant getMessage(const evmc_message& i struct Executable { - explicit Executable(storage::Entry code, evmc_revision revision) + Executable(storage::Entry code, evmc_revision revision) : m_code(std::make_optional(std::move(code))), - m_revision(revision), m_vmInstance(VMFactory::create(VMKind::evmone, bytesConstRef(reinterpret_cast(m_code->data()), m_code->size()), - m_revision)) + revision)) {} explicit Executable(bytesConstRef code, evmc_revision revision) : m_vmInstance(VMFactory::create(VMKind::evmone, code, revision)) {} std::optional m_code; - evmc_revision m_revision; VMInstance m_vmInstance; }; template using Account = ledger::account::EVMAccount; -inline task::Task> getExecutable( - auto& storage, const evmc_address& address, const evmc_revision& revision) -{ - static storage2::memory_storage::MemoryStorage, +using CacheExecutables = + storage2::memory_storage::MemoryStorage, storage2::memory_storage::Attribute( storage2::memory_storage::LRU | storage2::memory_storage::CONCURRENT), - std::hash> - cachedExecutables; + std::hash>; +CacheExecutables& getCacheExecutables(); - if (auto executable = co_await storage2::readOne(cachedExecutables, address)) +inline task::Task> getExecutable( + auto& storage, const evmc_address& address, const evmc_revision& revision) +{ + if (auto executable = co_await storage2::readOne(getCacheExecutables(), address)) { co_return std::move(*executable); } @@ -111,9 +110,8 @@ inline task::Task> getExecutable( Account> account(storage, address); if (auto codeEntry = co_await ledger::account::code(account)) { - auto executable = - std::make_shared(Executable(std::move(*codeEntry), std::move(revision))); - co_await storage2::writeOne(cachedExecutables, address, executable); + auto executable = std::make_shared(Executable(std::move(*codeEntry), revision)); + co_await storage2::writeOne(getCacheExecutables(), address, executable); co_return executable; } co_return std::shared_ptr{}; diff --git a/transaction-scheduler/bcos-transaction-scheduler/BaselineScheduler.h b/transaction-scheduler/bcos-transaction-scheduler/BaselineScheduler.h index 7df398a7da..a70f798464 100644 --- a/transaction-scheduler/bcos-transaction-scheduler/BaselineScheduler.h +++ b/transaction-scheduler/bcos-transaction-scheduler/BaselineScheduler.h @@ -661,7 +661,7 @@ class BaselineScheduler : public scheduler::SchedulerInterface callback(nullptr); } - void stop() override{}; + void stop() override {}; void registerTransactionNotifier(std::function)> From cc2483e70a8f712aa2a447d8f16fe4997db69953 Mon Sep 17 00:00:00 2001 From: Kyon <32325790+kyonRay@users.noreply.github.com> Date: Thu, 1 Aug 2024 19:31:47 +0800 Subject: [PATCH 15/16] (security): fix dataEncrtption decode bug. (#4561) --- bcos-executor/src/vm/gas_meter/Metric.cpp | 1 + .../bcos-security/DataEncryption.cpp | 26 +++++++------------ .../BaselineScheduler.h | 2 +- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/bcos-executor/src/vm/gas_meter/Metric.cpp b/bcos-executor/src/vm/gas_meter/Metric.cpp index 51c586a368..8e466e65c7 100644 --- a/bcos-executor/src/vm/gas_meter/Metric.cpp +++ b/bcos-executor/src/vm/gas_meter/Metric.cpp @@ -25,6 +25,7 @@ namespace bcos { namespace wasm { +using bcos::wasm::Instruction; InstructionTable GetInstructionTable() { auto defaultInstructionTable = InstructionTable{}; diff --git a/bcos-security/bcos-security/DataEncryption.cpp b/bcos-security/bcos-security/DataEncryption.cpp index 93a99ba60b..bedd846812 100644 --- a/bcos-security/bcos-security/DataEncryption.cpp +++ b/bcos-security/bcos-security/DataEncryption.cpp @@ -97,15 +97,12 @@ std::shared_ptr DataEncryption::decryptContents(const std::shared_ptr= static_cast(bcos::protocol::BlockVersion::V3_3_VERSION)) { - random_bytes_engine rbe; - std::vector ivData(16); - std::generate(std::begin(ivData), std::end(ivData), std::ref(rbe)); - + size_t const offsetIv = encFileBytes.size() - 16; + size_t const cipherDataSize = encFileBytes.size() - 16; decFileBytesBase64Ptr = m_symmetricEncrypt->symmetricDecrypt( - (const unsigned char*)encFileBytes.data(), encFileBytes.size(), - (const unsigned char*)m_dataKey.data(), m_dataKey.size(), ivData.data(), 16); - decFileBytesBase64Ptr->insert( - decFileBytesBase64Ptr->end(), ivData.begin(), ivData.end()); + reinterpret_cast(encFileBytes.data()), cipherDataSize, + reinterpret_cast(m_dataKey.data()), m_dataKey.size(), + reinterpret_cast(encFileBytes.data() + offsetIv), 16); } else { @@ -143,15 +140,12 @@ std::shared_ptr DataEncryption::decryptFile(const std::string& filename) if (m_compatibilityVersion >= static_cast(bcos::protocol::BlockVersion::V3_3_VERSION)) { - random_bytes_engine rbe; - std::vector ivData(16); - std::generate(std::begin(ivData), std::end(ivData), std::ref(rbe)); - + size_t const offsetIv = encFileBytes.size() - 16; + size_t const cipherDataSize = encFileBytes.size() - 16; decFileBytesBase64Ptr = m_symmetricEncrypt->symmetricDecrypt( - (const unsigned char*)encFileBytes.data(), encFileBytes.size(), - (const unsigned char*)m_dataKey.data(), m_dataKey.size(), ivData.data(), 16); - decFileBytesBase64Ptr->insert( - decFileBytesBase64Ptr->end(), ivData.begin(), ivData.end()); + reinterpret_cast(encFileBytes.data()), cipherDataSize, + reinterpret_cast(m_dataKey.data()), m_dataKey.size(), + reinterpret_cast(encFileBytes.data() + offsetIv), 16); } else { diff --git a/transaction-scheduler/bcos-transaction-scheduler/BaselineScheduler.h b/transaction-scheduler/bcos-transaction-scheduler/BaselineScheduler.h index a70f798464..7df398a7da 100644 --- a/transaction-scheduler/bcos-transaction-scheduler/BaselineScheduler.h +++ b/transaction-scheduler/bcos-transaction-scheduler/BaselineScheduler.h @@ -661,7 +661,7 @@ class BaselineScheduler : public scheduler::SchedulerInterface callback(nullptr); } - void stop() override {}; + void stop() override{}; void registerTransactionNotifier(std::function)> From 45f37a40079d5cba55ec7fa40d94e30d611738a6 Mon Sep 17 00:00:00 2001 From: wenlinli <1574249665@qq.com> Date: Fri, 2 Aug 2024 16:59:14 +0800 Subject: [PATCH 16/16] update README.md (#4563) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 57ab568fe0..d3da0d9a25 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ FISCO BCOS(读作/ˈfɪskl bi:ˈkɒz/) 是一个稳定、高效、安全的 ## 版本信息 - -稳定版本(生产环境使用):v3.2.7,版本内容可参考[《FISCO-BCOS v3.2.7版本说明》](https://github.com/FISCO-BCOS/FISCO-BCOS/releases/tag/v3.2.7) +稳定版本(生产环境使用):v3.7.3,版本内容可参考[《FISCO-BCOS v3.7.3版本说明》](https://github.com/FISCO-BCOS/FISCO-BCOS/releases/tag/v3.7.3) - -最新版本(用户体验新特性):v3.9.0,版本内容可参考 [《FISCO-BCOS v3.9.0版本说明》](https://github.com/FISCO-BCOS/FISCO-BCOS/releases/tag/v3.9.0) +最新版本(用户体验新特性):v3.10.0,版本内容可参考 [《FISCO-BCOS v3.10.0版本说明》](https://github.com/FISCO-BCOS/FISCO-BCOS/releases/tag/v3.10.0) ## 系统概述 FISCO BCOS系统架构包括基础层、核心层、服务层、用户层和接入层提供稳定、安全的区块链底层服务。中间件层通过可视化界面,简化了用户管理区块链系统的流程。右侧配套相关开发、运维、安全控制的组件,辅助应用落地过程中不同角色的需要;同时,提供隐私保护和跨链相关的技术组件,满足不同场景的应用诉求。