diff --git a/bcos-boostssl/CMakeLists.txt b/bcos-boostssl/CMakeLists.txt index 22d2f0ae36..68ea1aea3c 100644 --- a/bcos-boostssl/CMakeLists.txt +++ b/bcos-boostssl/CMakeLists.txt @@ -9,6 +9,7 @@ target_include_directories(bcos-boostssl PUBLIC $ $) target_link_libraries(bcos-boostssl PUBLIC bcos-framework bcos-utilities OpenSSL::SSL) +set_target_properties(bcos-boostssl PROPERTIES UNITY_BUILD "ON") if(TESTS) enable_testing() diff --git a/bcos-codec/CMakeLists.txt b/bcos-codec/CMakeLists.txt index 50ddd4e558..b8e4602e24 100644 --- a/bcos-codec/CMakeLists.txt +++ b/bcos-codec/CMakeLists.txt @@ -33,6 +33,7 @@ target_include_directories(${CODEC_TARGET} PUBLIC $ ) target_link_libraries(${CODEC_TARGET} PUBLIC bcos-crypto Microsoft.GSL::GSL) +set_target_properties(${CODEC_TARGET} PROPERTIES UNITY_BUILD "ON") if (TESTS) enable_testing() diff --git a/bcos-crypto/CMakeLists.txt b/bcos-crypto/CMakeLists.txt index fa83e78ff6..68298cff1a 100644 --- a/bcos-crypto/CMakeLists.txt +++ b/bcos-crypto/CMakeLists.txt @@ -15,6 +15,7 @@ find_package(HSM-CRYPTO REQUIRED) add_library(bcos-crypto STATIC ${ALL_SRCS}) target_link_libraries(bcos-crypto PUBLIC ${LIB_LIST}) +set_target_properties(bcos-crypto PROPERTIES UNITY_BUILD "ON") if(NOT WIN32) target_compile_options(bcos-crypto PUBLIC "-Wno-ignored-attributes") diff --git a/bcos-executor/CMakeLists.txt b/bcos-executor/CMakeLists.txt index 17da9a85f9..8d150eff15 100644 --- a/bcos-executor/CMakeLists.txt +++ b/bcos-executor/CMakeLists.txt @@ -24,6 +24,12 @@ else() Boost::context evmone evmc::loader evmc::instructions GroupSig Paillier blst) endif() +set_source_files_properties( + "src/vm/kzgPrecompiled.cpp" + "src/vm/VMFactory.cpp" + PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON) +set_target_properties(${EXECUTOR_TARGET} PROPERTIES UNITY_BUILD "ON") + if (TOOLS) add_subdirectory(tools) endif() diff --git a/bcos-executor/src/Common.cpp b/bcos-executor/src/Common.cpp index 80d9139a9e..8dcd487d36 100644 --- a/bcos-executor/src/Common.cpp +++ b/bcos-executor/src/Common.cpp @@ -21,6 +21,7 @@ #include "Common.h" #include "bcos-executor/src/precompiled/common/Common.h" +#include "bcos-framework/protocol/Exceptions.h" #include using namespace bcos::protocol; diff --git a/bcos-executor/src/Common.h b/bcos-executor/src/Common.h index 35a251a96d..684dcafd5b 100644 --- a/bcos-executor/src/Common.h +++ b/bcos-executor/src/Common.h @@ -26,9 +26,9 @@ #pragma once #include "bcos-crypto/interfaces/crypto/Hash.h" +#include "bcos-framework/protocol/LogEntry.h" #include "bcos-protocol/TransactionStatus.h" -#include -#include +#include "bcos-utilities/Exceptions.h" #include #include #include diff --git a/bcos-executor/src/precompiled/TableManagerPrecompiled.cpp b/bcos-executor/src/precompiled/TableManagerPrecompiled.cpp index 18de886e3d..3286089141 100644 --- a/bcos-executor/src/precompiled/TableManagerPrecompiled.cpp +++ b/bcos-executor/src/precompiled/TableManagerPrecompiled.cpp @@ -21,6 +21,7 @@ #include "TableManagerPrecompiled.h" #include "bcos-executor/src/precompiled/common/Common.h" +#include "bcos-executor/src/precompiled/common/PrecompiledAbi.h" #include "bcos-executor/src/precompiled/common/PrecompiledResult.h" #include "bcos-executor/src/precompiled/common/Utilities.h" #include @@ -93,7 +94,8 @@ std::shared_ptr TableManagerPrecompiled::call( if (selector != selector2Func.end()) { if (blockContext.isWasm() && func == name2Selector[TABLE_METHOD_OPEN]) - {} + { + } auto& [minVersion, execFunc] = selector->second; if (versionCompareTo(blockContext.blockVersion(), minVersion) >= 0) { diff --git a/bcos-executor/src/precompiled/common/Common.h b/bcos-executor/src/precompiled/common/Common.h index a810317190..286d047e27 100644 --- a/bcos-executor/src/precompiled/common/Common.h +++ b/bcos-executor/src/precompiled/common/Common.h @@ -20,19 +20,10 @@ #pragma once -#include "PrecompiledAbi.h" #include "bcos-executor/src/Common.h" -#include "bcos-framework/Common.h" -#include "bcos-framework/protocol/CommonError.h" -#include "bcos-framework/protocol/Exceptions.h" -#include "bcos-framework/storage/Common.h" -#include "bcos-framework/storage/Entry.h" -#include #include -namespace bcos -{ -namespace precompiled +namespace bcos::precompiled { #define PRECOMPILED_LOG(LEVEL) BCOS_LOG(LEVEL) << "[EXECUTOR][PRECOMPILED]" @@ -193,5 +184,4 @@ static constexpr inline ContractStatus StatusFromString(std::string_view _status } return ContractStatus::Available; } -} // namespace precompiled -} // namespace bcos \ No newline at end of file +} // namespace bcos::precompiled diff --git a/bcos-executor/src/precompiled/extension/AccountPrecompiled.cpp b/bcos-executor/src/precompiled/extension/AccountPrecompiled.cpp index f1d1e48c00..a604a38b26 100644 --- a/bcos-executor/src/precompiled/extension/AccountPrecompiled.cpp +++ b/bcos-executor/src/precompiled/extension/AccountPrecompiled.cpp @@ -28,8 +28,8 @@ using namespace bcos::executor; using namespace bcos::storage; using namespace bcos::protocol; -const char* const AM_METHOD_SET_ACCOUNT_STATUS = "setAccountStatus(uint8)"; -const char* const AM_METHOD_GET_ACCOUNT_STATUS = "getAccountStatus()"; +const char* const ACCOUNT_METHOD_SET_ACCOUNT_STATUS = "setAccountStatus(uint8)"; +const char* const ACCOUNT_METHOD_GET_ACCOUNT_STATUS = "getAccountStatus()"; const char* const AM_METHOD_GET_ACCOUNT_BALANCE = "getAccountBalance()"; const char* const AM_METHOD_ADD_ACCOUNT_BALANCE = "addAccountBalance(uint256)"; const char* const AM_METHOD_SUB_ACCOUNT_BALANCE = "subAccountBalance(uint256)"; @@ -38,10 +38,10 @@ const uint32_t AM_METHOD_RECEIVE_FALLBACK_SELECTOR = 1; AccountPrecompiled::AccountPrecompiled(crypto::Hash::Ptr hashImpl) : Precompiled(hashImpl) { - name2Selector[AM_METHOD_SET_ACCOUNT_STATUS] = - getFuncSelector(AM_METHOD_SET_ACCOUNT_STATUS, hashImpl); - name2Selector[AM_METHOD_GET_ACCOUNT_STATUS] = - getFuncSelector(AM_METHOD_GET_ACCOUNT_STATUS, hashImpl); + name2Selector[ACCOUNT_METHOD_SET_ACCOUNT_STATUS] = + getFuncSelector(ACCOUNT_METHOD_SET_ACCOUNT_STATUS, hashImpl); + name2Selector[ACCOUNT_METHOD_GET_ACCOUNT_STATUS] = + getFuncSelector(ACCOUNT_METHOD_GET_ACCOUNT_STATUS, hashImpl); name2Selector[AM_METHOD_GET_ACCOUNT_BALANCE] = getFuncSelector(AM_METHOD_GET_ACCOUNT_BALANCE, hashImpl); name2Selector[AM_METHOD_ADD_ACCOUNT_BALANCE] = @@ -78,11 +78,11 @@ std::shared_ptr AccountPrecompiled::call( bytesConstRef data = getParamData(originParam); auto table = _executive->storage().openTable(accountTableName); - if (func == name2Selector[AM_METHOD_SET_ACCOUNT_STATUS]) + if (func == name2Selector[ACCOUNT_METHOD_SET_ACCOUNT_STATUS]) { setAccountStatus(accountTableName, _executive, data, _callParameters); } - else if (func == name2Selector[AM_METHOD_GET_ACCOUNT_STATUS]) + else if (func == name2Selector[ACCOUNT_METHOD_GET_ACCOUNT_STATUS]) { getAccountStatus(accountTableName, _executive, _callParameters); } diff --git a/bcos-executor/src/precompiled/extension/ContractAuthMgrPrecompiled.cpp b/bcos-executor/src/precompiled/extension/ContractAuthMgrPrecompiled.cpp index c42aa81da4..9c608688f3 100644 --- a/bcos-executor/src/precompiled/extension/ContractAuthMgrPrecompiled.cpp +++ b/bcos-executor/src/precompiled/extension/ContractAuthMgrPrecompiled.cpp @@ -30,39 +30,39 @@ using namespace bcos::protocol; /// contract ACL /// wasm -constexpr const char* const AUTH_METHOD_GET_ADMIN = "getAdmin(string)"; -constexpr const char* const AUTH_METHOD_SET_ADMIN = "resetAdmin(string,string)"; -constexpr const char* const AUTH_METHOD_SET_AUTH_TYPE = "setMethodAuthType(string,bytes4,uint8)"; -constexpr const char* const AUTH_METHOD_OPEN_AUTH = "openMethodAuth(string,bytes4,string)"; -constexpr const char* const AUTH_METHOD_CLOSE_AUTH = "closeMethodAuth(string,bytes4,string)"; -constexpr const char* const AUTH_METHOD_CHECK_AUTH = "checkMethodAuth(string,bytes4,string)"; -constexpr const char* const AUTH_METHOD_GET_AUTH = "getMethodAuth(string,bytes4)"; +constexpr const char* const CONTRACT_AUTH_METHOD_GET_ADMIN = "getAdmin(string)"; +constexpr const char* const CONTRACT_AUTH_METHOD_SET_ADMIN = "resetAdmin(string,string)"; +constexpr const char* const CONTRACT_AUTH_METHOD_SET_AUTH_TYPE = "setMethodAuthType(string,bytes4,uint8)"; +constexpr const char* const CONTRACT_AUTH_METHOD_OPEN_AUTH = "openMethodAuth(string,bytes4,string)"; +constexpr const char* const CONTRACT_AUTH_METHOD_CLOSE_AUTH = "closeMethodAuth(string,bytes4,string)"; +constexpr const char* const CONTRACT_AUTH_METHOD_CHECK_AUTH = "checkMethodAuth(string,bytes4,string)"; +constexpr const char* const CONTRACT_AUTH_METHOD_GET_AUTH = "getMethodAuth(string,bytes4)"; /// evm -constexpr const char* const AUTH_METHOD_GET_ADMIN_ADD = "getAdmin(address)"; -constexpr const char* const AUTH_METHOD_SET_ADMIN_ADD = "resetAdmin(address,address)"; -constexpr const char* const AUTH_METHOD_SET_AUTH_TYPE_ADD = +constexpr const char* const CONTRACT_AUTH_METHOD_GET_ADMIN_ADD = "getAdmin(address)"; +constexpr const char* const CONTRACT_AUTH_METHOD_SET_ADMIN_ADD = "resetAdmin(address,address)"; +constexpr const char* const CONTRACT_AUTH_METHOD_SET_AUTH_TYPE_ADD = "setMethodAuthType(address,bytes4,uint8)"; -constexpr const char* const AUTH_METHOD_OPEN_AUTH_ADD = "openMethodAuth(address,bytes4,address)"; -constexpr const char* const AUTH_METHOD_CLOSE_AUTH_ADD = "closeMethodAuth(address,bytes4,address)"; -constexpr const char* const AUTH_METHOD_CHECK_AUTH_ADD = "checkMethodAuth(address,bytes4,address)"; -constexpr const char* const AUTH_METHOD_GET_AUTH_ADD = "getMethodAuth(address,bytes4)"; +constexpr const char* const CONTRACT_AUTH_METHOD_OPEN_AUTH_ADD = "openMethodAuth(address,bytes4,address)"; +constexpr const char* const CONTRACT_AUTH_METHOD_CLOSE_AUTH_ADD = "closeMethodAuth(address,bytes4,address)"; +constexpr const char* const CONTRACT_AUTH_METHOD_CHECK_AUTH_ADD = "checkMethodAuth(address,bytes4,address)"; +constexpr const char* const CONTRACT_AUTH_METHOD_GET_AUTH_ADD = "getMethodAuth(address,bytes4)"; /// contract status -constexpr const char* const AUTH_METHOD_SET_CONTRACT = "setContractStatus(address,bool)"; -constexpr const char* const AUTH_METHOD_SET_CONTRACT_32 = "setContractStatus(address,uint8)"; -constexpr const char* const AUTH_METHOD_GET_CONTRACT = "contractAvailable(address)"; +constexpr const char* const CONTRACT_AUTH_METHOD_SET_CONTRACT = "setContractStatus(address,bool)"; +constexpr const char* const CONTRACT_AUTH_METHOD_SET_CONTRACT_32 = "setContractStatus(address,uint8)"; +constexpr const char* const CONTRACT_AUTH_METHOD_GET_CONTRACT = "contractAvailable(address)"; ContractAuthMgrPrecompiled::ContractAuthMgrPrecompiled(crypto::Hash::Ptr _hashImpl, bool _isWasm) : bcos::precompiled::Precompiled(std::move(_hashImpl)) { - const auto* getAdminStr = _isWasm ? AUTH_METHOD_GET_ADMIN : AUTH_METHOD_GET_ADMIN_ADD; + const auto* getAdminStr = _isWasm ? CONTRACT_AUTH_METHOD_GET_ADMIN : CONTRACT_AUTH_METHOD_GET_ADMIN_ADD; registerFunc( getFuncSelector(getAdminStr, _hashImpl), [this](auto&& _executive, auto&& _callParameters) { getAdmin(std::forward(_executive), std::forward(_callParameters)); }); - const auto* resetAdminStr = _isWasm ? AUTH_METHOD_SET_ADMIN : AUTH_METHOD_SET_ADMIN_ADD; + const auto* resetAdminStr = _isWasm ? CONTRACT_AUTH_METHOD_SET_ADMIN : CONTRACT_AUTH_METHOD_SET_ADMIN_ADD; registerFunc(getFuncSelector(resetAdminStr, _hashImpl), [this](auto&& _executive, auto&& _callParameters) { resetAdmin(std::forward(_executive), @@ -70,35 +70,35 @@ ContractAuthMgrPrecompiled::ContractAuthMgrPrecompiled(crypto::Hash::Ptr _hashIm }); const auto* setMethodAuthTypeStr = - _isWasm ? AUTH_METHOD_SET_AUTH_TYPE : AUTH_METHOD_SET_AUTH_TYPE_ADD; + _isWasm ? CONTRACT_AUTH_METHOD_SET_AUTH_TYPE : CONTRACT_AUTH_METHOD_SET_AUTH_TYPE_ADD; registerFunc(getFuncSelector(setMethodAuthTypeStr, _hashImpl), [this](auto&& _executive, auto&& _callParameters) { setMethodAuthType(std::forward(_executive), std::forward(_callParameters)); }); - const auto* openMethodAuthStr = _isWasm ? AUTH_METHOD_OPEN_AUTH : AUTH_METHOD_OPEN_AUTH_ADD; + const auto* openMethodAuthStr = _isWasm ? CONTRACT_AUTH_METHOD_OPEN_AUTH : CONTRACT_AUTH_METHOD_OPEN_AUTH_ADD; registerFunc(getFuncSelector(openMethodAuthStr, _hashImpl), [this](auto&& _executive, auto&& _callParameters) { openMethodAuth(std::forward(_executive), std::forward(_callParameters)); }); - const auto* closeMethodAuthStr = _isWasm ? AUTH_METHOD_CLOSE_AUTH : AUTH_METHOD_CLOSE_AUTH_ADD; + const auto* closeMethodAuthStr = _isWasm ? CONTRACT_AUTH_METHOD_CLOSE_AUTH : CONTRACT_AUTH_METHOD_CLOSE_AUTH_ADD; registerFunc(getFuncSelector(closeMethodAuthStr, _hashImpl), [this](auto&& _executive, auto&& _callParameters) { closeMethodAuth(std::forward(_executive), std::forward(_callParameters)); }); - const auto* checkMethodAuthStr = _isWasm ? AUTH_METHOD_CHECK_AUTH : AUTH_METHOD_CHECK_AUTH_ADD; + const auto* checkMethodAuthStr = _isWasm ? CONTRACT_AUTH_METHOD_CHECK_AUTH : CONTRACT_AUTH_METHOD_CHECK_AUTH_ADD; registerFunc(getFuncSelector(checkMethodAuthStr, _hashImpl), [this](auto&& _executive, auto&& _callParameters) { checkMethodAuth(std::forward(_executive), std::forward(_callParameters)); }); - const auto* getMethodAuthStr = _isWasm ? AUTH_METHOD_GET_AUTH : AUTH_METHOD_GET_AUTH_ADD; + const auto* getMethodAuthStr = _isWasm ? CONTRACT_AUTH_METHOD_GET_AUTH : CONTRACT_AUTH_METHOD_GET_AUTH_ADD; registerFunc(getFuncSelector(getMethodAuthStr, _hashImpl), [this](auto&& _executive, auto&& _callParameters) { getMethodAuth(std::forward(_executive), @@ -106,19 +106,19 @@ ContractAuthMgrPrecompiled::ContractAuthMgrPrecompiled(crypto::Hash::Ptr _hashIm }); registerFunc( - getFuncSelector(AUTH_METHOD_SET_CONTRACT_32, _hashImpl), + getFuncSelector(CONTRACT_AUTH_METHOD_SET_CONTRACT_32, _hashImpl), [this](auto&& _executive, auto&& _callParameters) { setContractStatus32(std::forward(_executive), std::forward(_callParameters)); }, protocol::BlockVersion::V3_2_VERSION); - registerFunc(getFuncSelector(AUTH_METHOD_SET_CONTRACT, _hashImpl), + registerFunc(getFuncSelector(CONTRACT_AUTH_METHOD_SET_CONTRACT, _hashImpl), [this](auto&& _executive, auto&& _callParameters) { setContractStatus(std::forward(_executive), std::forward(_callParameters)); }); - registerFunc(getFuncSelector(AUTH_METHOD_GET_CONTRACT, _hashImpl), + registerFunc(getFuncSelector(CONTRACT_AUTH_METHOD_GET_CONTRACT, _hashImpl), [this](auto&& _executive, auto&& _callParameters) { contractAvailable(std::forward(_executive), std::forward(_callParameters)); diff --git a/bcos-executor/src/vm/kzgPrecompiled.cpp b/bcos-executor/src/vm/kzgPrecompiled.cpp new file mode 100644 index 0000000000..1055d0ca37 --- /dev/null +++ b/bcos-executor/src/vm/kzgPrecompiled.cpp @@ -0,0 +1,159 @@ +#include "kzgPrecompiled.h" +#include + +using G1 = blst_p1; +using G2 = blst_p2; +using Fr = blst_fr; + +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 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); +} + +static bool validate_kzg_g1(G1* out, bcos::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, bcos::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 bcos::executor::crypto::kzgPrecompiled::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; +} + +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); +} + +bool bcos::executor::crypto::kzgPrecompiled::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); +} diff --git a/bcos-executor/src/vm/kzgPrecompiled.h b/bcos-executor/src/vm/kzgPrecompiled.h index 894b0091a8..1a7dbfd997 100644 --- a/bcos-executor/src/vm/kzgPrecompiled.h +++ b/bcos-executor/src/vm/kzgPrecompiled.h @@ -22,11 +22,7 @@ #pragma once #include #include -#include #include -#include -#include - namespace bcos::executor { @@ -41,171 +37,13 @@ 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; - } + bcos::crypto::HashType kzg2VersionedHash(bytesConstRef input); 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); - } + bytesConstRef commitment, bytesConstRef z, bytesConstRef y, bytesConstRef proof); }; } // namespace crypto diff --git a/bcos-framework/bcos-framework/dispatcher/SchedulerInterface.h b/bcos-framework/bcos-framework/dispatcher/SchedulerInterface.h index e71090451e..c4d4bbd008 100644 --- a/bcos-framework/bcos-framework/dispatcher/SchedulerInterface.h +++ b/bcos-framework/bcos-framework/dispatcher/SchedulerInterface.h @@ -20,10 +20,9 @@ */ #pragma once -#include "../executor/ParallelTransactionExecutorInterface.h" #include "../ledger/LedgerConfig.h" #include "../protocol/Block.h" -#include "../protocol/ProtocolTypeDef.h" +#include "SchedulerTypeDef.h" #include #include #include @@ -68,6 +67,6 @@ class SchedulerInterface virtual void preExecuteBlock(bcos::protocol::Block::Ptr block, bool verify, std::function callback) = 0; - virtual void stop(){}; + virtual void stop() {}; }; } // namespace bcos::scheduler diff --git a/bcos-framework/bcos-framework/dispatcher/SchedulerTypeDef.h b/bcos-framework/bcos-framework/dispatcher/SchedulerTypeDef.h index 694130854e..ae2a63bbf1 100644 --- a/bcos-framework/bcos-framework/dispatcher/SchedulerTypeDef.h +++ b/bcos-framework/bcos-framework/dispatcher/SchedulerTypeDef.h @@ -19,9 +19,33 @@ * @date: 2021-04-9 */ #pragma once +#include "bcos-framework/protocol/ProtocolTypeDef.h" #include + namespace bcos { + +namespace protocol +{ +struct Session +{ + using Ptr = std::shared_ptr; + using ConstPtr = std::shared_ptr; + + enum Status + { + STARTED = 0, + DIRTY, + COMMITTED, + ROLLBACKED + }; + + long sessionID; + Status status; + bcos::protocol::BlockNumber beginNumber; // [ + bcos::protocol::BlockNumber endNumber; // ) +}; +} // namespace protocol namespace scheduler { enum SchedulerError @@ -48,5 +72,5 @@ enum SchedulerError InvalidTransactionVersion, BuildBlockError, }; -} // namespace scheduler -} // namespace bcos \ No newline at end of file +} +} // namespace bcos diff --git a/bcos-framework/bcos-framework/protocol/ProtocolTypeDef.h b/bcos-framework/bcos-framework/protocol/ProtocolTypeDef.h index ba77966c0d..e04a5ffa2d 100644 --- a/bcos-framework/bcos-framework/protocol/ProtocolTypeDef.h +++ b/bcos-framework/bcos-framework/protocol/ProtocolTypeDef.h @@ -80,25 +80,6 @@ using WeightListPtr = std::shared_ptr; int64_t constexpr InvalidSealerIndex = INT64_MAX; -struct Session -{ - using Ptr = std::shared_ptr; - using ConstPtr = std::shared_ptr; - - enum Status - { - STARTED = 0, - DIRTY, - COMMITTED, - ROLLBACKED - }; - - long sessionID; - Status status; - bcos::protocol::BlockNumber beginNumber; // [ - bcos::protocol::BlockNumber endNumber; // ) -}; - struct TwoPCParams { BlockNumber number = 0; diff --git a/bcos-framework/bcos-framework/storage2/MemoryStorage.h b/bcos-framework/bcos-framework/storage2/MemoryStorage.h index c27b937b39..3955eb88f3 100644 --- a/bcos-framework/bcos-framework/storage2/MemoryStorage.h +++ b/bcos-framework/bcos-framework/storage2/MemoryStorage.h @@ -35,19 +35,20 @@ enum Attribute : int }; template + class BucketHasherType = void> class MemoryStorage { public: + constexpr static bool isMemoryStorage = true; + constexpr static bool withOrdered = (attribute & Attribute::ORDERED) != 0; constexpr static bool withConcurrent = (attribute & Attribute::CONCURRENT) != 0; constexpr static bool withLRU = (attribute & Attribute::LRU) != 0; constexpr static bool withLogicalDeletion = (attribute & Attribute::LOGICAL_DELETION) != 0; -private: constexpr static unsigned BUCKETS_COUNT = 64; // Magic number 64 constexpr unsigned getBucketSize() { return withConcurrent ? BUCKETS_COUNT : 1; } - static_assert(!withConcurrent || !std::is_void_v); + static_assert(!withConcurrent || !std::is_void_v); constexpr static unsigned DEFAULT_CAPACITY = 32 * 1024 * 1024; // For mru using Mutex = tbb::spin_rw_mutex; @@ -80,61 +81,9 @@ class MemoryStorage Buckets m_buckets; [[no_unique_address]] std::conditional_t m_maxCapacity; - Bucket& getBucket(auto const& key) & noexcept - { - if constexpr (!withConcurrent) - { - return m_buckets[0]; - } - auto index = getBucketIndex(key); - - auto& bucket = m_buckets[index]; - return bucket; - } - - size_t getBucketIndex(auto const& key) const - { - if constexpr (!withConcurrent) - { - return 0; - } - else - { - auto hash = BucketHasher{}(key); - return hash % m_buckets.size(); - } - } - - void updateMRUAndCheck( - Bucket& bucket, typename Container::template nth_index<0>::type::iterator entryIt) - requires withLRU - { - auto& index = bucket.container.template get<1>(); - auto seqIt = index.iterator_to(*entryIt); - index.relocate(index.end(), seqIt); - - while (bucket.capacity > m_maxCapacity && !bucket.container.empty()) - { - auto const& item = index.front(); - bucket.capacity -= (getSize(item.key) + getSize(item.value)); - index.pop_front(); - } - } - - static int64_t getSize(auto const& object) - { - using ObjectType = std::remove_cvref_t; - if constexpr (HasMemberSize) - { - return object.size(); - } - // Treat any no-size() object as trivial, TODO: fix it - return sizeof(ObjectType); - } - -public: using Key = KeyType; using Value = ValueType; + using BucketHasher = BucketHasherType; explicit MemoryStorage(unsigned buckets = BUCKETS_COUNT) { @@ -152,175 +101,224 @@ class MemoryStorage MemoryStorage& operator=(const MemoryStorage&) = delete; MemoryStorage& operator=(MemoryStorage&&) noexcept = default; ~MemoryStorage() noexcept = default; +}; + +template +concept IsMemoryStorage = std::remove_cvref_t::isMemoryStorage; - void setMaxCapacity(int64_t capacity) - requires withLRU +template +void setMaxCapacity(MemoryStorage& storage, int64_t capacity) + requires MemoryStorage::withLRU +{ + storage.m_maxCapacity = capacity; +} + +template +size_t getBucketIndex(MemoryStorage const& storage, auto const& key) +{ + if constexpr (!MemoryStorage::withConcurrent) { - m_maxCapacity = capacity; + return 0; } + else + { + auto hash = typename MemoryStorage::BucketHasher{}(key); + return hash % storage.m_buckets.size(); + } +} - friend auto tag_invoke(bcos::storage2::tag_t /*unused*/, MemoryStorage& storage, - RANGES::input_range auto&& keys) - -> task::AwaitableValue>> +template +typename MemoryStorage::Bucket& getBucket(MemoryStorage& storage, auto const& key) noexcept +{ + if constexpr (!MemoryStorage::withConcurrent) { - task::AwaitableValue>> result; - if constexpr (RANGES::sized_range) - { - result.value().reserve(RANGES::size(keys)); - } + return storage.m_buckets[0]; + } + auto index = getBucketIndex(storage, key); - for (auto&& key : keys) - { - auto& bucket = storage.getBucket(key); - Lock lock(bucket.mutex, false); + auto& bucket = storage.m_buckets[index]; + return bucket; +} - auto const& index = bucket.container.template get<0>(); - auto it = index.find(key); - if (it != index.end()) - { - result.value().emplace_back(it->value); +inline int64_t getSize(auto const& object) +{ + using ObjectType = std::remove_cvref_t; + if constexpr (HasMemberSize) + { + return object.size(); + } + // Treat any no-size() object as trivial, TODO: fix it + return sizeof(ObjectType); +} + +template +void updateMRUAndCheck(MemoryStorage& storage, typename MemoryStorage::Bucket& bucket, + typename MemoryStorage::Container::template nth_index<0>::type::iterator entryIt) + requires MemoryStorage::withLRU +{ + auto& index = bucket.container.template get<1>(); + auto seqIt = index.iterator_to(*entryIt); + index.relocate(index.end(), seqIt); - if constexpr (std::decay_t::withLRU) - { - lock.upgrade_to_writer(); - storage.updateMRUAndCheck(bucket, it); - } - } - else - { - result.value().emplace_back(std::optional{}); - } - } - return result; + while (bucket.capacity > storage.m_maxCapacity && !bucket.container.empty()) + { + auto const& item = index.front(); + bucket.capacity -= (getSize(item.key) + getSize(item.value)); + index.pop_front(); + } +} + +template +auto tag_invoke(bcos::storage2::tag_t /*unused*/, MemoryStorage& storage, + RANGES::input_range auto&& keys) + -> task::AwaitableValue>> +{ + task::AwaitableValue>> result; + if constexpr (RANGES::sized_range) + { + result.value().reserve(RANGES::size(keys)); } - friend task::AwaitableValue> tag_invoke( - storage2::tag_t /*unused*/, MemoryStorage& storage, auto&& key, - auto&&... args) + for (auto&& key : keys) { - task::AwaitableValue> result; - auto& bucket = storage.getBucket(key); - Lock lock(bucket.mutex, false); + auto& bucket = getBucket(storage, key); + typename MemoryStorage::Lock lock(bucket.mutex, false); auto const& index = bucket.container.template get<0>(); auto it = index.find(key); if (it != index.end()) { + result.value().emplace_back(it->value); + if constexpr (std::decay_t::withLRU) { lock.upgrade_to_writer(); - storage.updateMRUAndCheck(bucket, it); + updateMRUAndCheck(storage, bucket, it); } - - result.value() = it->value; } - return result; + else + { + result.value().emplace_back(std::optional{}); + } } + return result; +} + +template +task::AwaitableValue> tag_invoke( + storage2::tag_t /*unused*/, MemoryStorage& storage, auto&& key, + auto&&... args) +{ + task::AwaitableValue> result; + auto& bucket = getBucket(storage, key); + typename MemoryStorage::Lock lock(bucket.mutex, false); - friend task::AwaitableValue tag_invoke(storage2::tag_t /*unused*/, - MemoryStorage& storage, RANGES::input_range auto&& keys, RANGES::input_range auto&& values) + auto const& index = bucket.container.template get<0>(); + auto it = index.find(key); + if (it != index.end()) { - for (auto&& [key, value] : RANGES::views::zip(keys, values)) + if constexpr (std::decay_t::withLRU) { - auto& bucket = storage.getBucket(key); - Lock lock(bucket.mutex, true); - auto const& index = bucket.container.template get<0>(); + lock.upgrade_to_writer(); + updateMRUAndCheck(storage, bucket, it); + } - std::conditional_t::withLRU, int64_t, Empty> - updatedCapacity; - if constexpr (std::decay_t::withLRU) - { - updatedCapacity = getSize(key) + getSize(value); - } + result.value() = it->value; + } + return result; +} - typename Container::iterator it; - if constexpr (std::decay_t::withOrdered) - { - it = index.lower_bound(key); - } - else - { - it = index.find(key); - } - if (it != index.end() && std::equal_to{}(it->key, key)) - { - if constexpr (std::decay_t::withLRU) - { - auto& existsValue = it->value; - updatedCapacity -= (getSize(key) + getSize(existsValue)); - } +template +task::AwaitableValue tag_invoke(storage2::tag_t /*unused*/, + MemoryStorage& storage, RANGES::input_range auto&& keys, RANGES::input_range auto&& values) +{ + for (auto&& [key, value] : RANGES::views::zip(keys, values)) + { + auto& bucket = getBucket(storage, key); + typename MemoryStorage::Lock lock(bucket.mutex, true); + auto const& index = bucket.container.template get<0>(); - bucket.container.modify( - it, [newValue = std::forward(value)](Data& data) mutable { - data.value = std::forward(newValue); - }); - } - else - { - it = bucket.container.emplace_hint( - it, Data{.key = KeyType(std::forward(key)), - .value = std::forward(value)}); - } + std::conditional_t::withLRU, int64_t, Empty> + updatedCapacity; + if constexpr (std::decay_t::withLRU) + { + updatedCapacity = getSize(key) + getSize(value); + } + typename MemoryStorage::Container::iterator it; + if constexpr (std::decay_t::withOrdered) + { + it = index.lower_bound(key); + } + else + { + it = index.find(key); + } + if (it != index.end() && std::equal_to{}(it->key, key)) + { if constexpr (std::decay_t::withLRU) { - bucket.capacity += updatedCapacity; - storage.updateMRUAndCheck(bucket, it); + auto& existsValue = it->value; + updatedCapacity -= (getSize(key) + getSize(existsValue)); } + + bucket.container.modify(it, [newValue = std::forward(value)]( + typename MemoryStorage::Data& data) mutable { + data.value = std::forward(newValue); + }); + } + else + { + it = bucket.container.emplace_hint( + it, typename MemoryStorage::Data{ + .key = typename MemoryStorage::Key(std::forward(key)), + .value = std::forward(value)}); } - return {}; + if constexpr (std::decay_t::withLRU) + { + bucket.capacity += updatedCapacity; + updateMRUAndCheck(storage, bucket, it); + } } - friend task::AwaitableValue tag_invoke(storage2::tag_t /*unused*/, - MemoryStorage& storage, RANGES::input_range auto&& keys) - { - return removeSome(storage, std::forward(keys), false); - } + return {}; +} - friend task::AwaitableValue tag_invoke(storage2::tag_t /*unused*/, - MemoryStorage& storage, RANGES::input_range auto&& keys, DIRECT_TYPE /*unused*/) +template +task::AwaitableValue removeSome( + MemoryStorage& storage, RANGES::input_range auto&& keys, bool direct) +{ + for (auto&& key : keys) { - return removeSome(storage, std::forward(keys), true); - } + auto& bucket = getBucket(storage, key); + typename MemoryStorage::Lock lock(bucket.mutex, true); + auto const& index = bucket.container.template get<0>(); - static task::AwaitableValue removeSome( - MemoryStorage& storage, RANGES::input_range auto&& keys, bool direct) - { - for (auto&& key : keys) + auto it = index.find(key); + if (it != index.end()) { - auto& bucket = storage.getBucket(key); - Lock lock(bucket.mutex, true); - auto const& index = bucket.container.template get<0>(); - - auto it = index.find(key); - if (it != index.end()) + auto& existsValue = it->value; + if constexpr (std::decay_t::withLogicalDeletion) { - auto& existsValue = it->value; - if constexpr (std::decay_t::withLogicalDeletion) + if (!existsValue) { - if (!existsValue) - { - // Already deleted - return {}; - } + // Already deleted + return {}; } + } - if constexpr (withLRU) - { - bucket.capacity -= (getSize(key) + getSize(existsValue)); - } + if constexpr (MemoryStorage::withLRU) + { + bucket.capacity -= (getSize(key) + getSize(existsValue)); + } - if constexpr (withLogicalDeletion) + if constexpr (MemoryStorage::withLogicalDeletion) + { + if (!direct) { - if (!direct) - { - bucket.container.modify(it, [](Data& data) mutable { data.value.reset(); }); - } - else - { - bucket.container.erase(it); - } + bucket.container.modify( + it, [](typename MemoryStorage::Data& data) mutable { data.value.reset(); }); } else { @@ -329,165 +327,192 @@ class MemoryStorage } else { - if constexpr (withLogicalDeletion) + bucket.container.erase(it); + } + } + else + { + if constexpr (MemoryStorage::withLogicalDeletion) + { + if constexpr (std::is_same_v, + typename MemoryStorage::Key>) { - if constexpr (std::is_same_v, KeyType>) - { - it = bucket.container.emplace_hint(it, Data{.key = key, .value = {}}); - } - else - { - it = bucket.container.emplace_hint(it, Data{.key = Key{key}, .value = {}}); - } + it = bucket.container.emplace_hint( + it, typename MemoryStorage::Data{.key = key, .value = {}}); + } + else + { + it = bucket.container.emplace_hint( + it, typename MemoryStorage::Data{ + .key = typename MemoryStorage::Key{key}, .value = {}}); } } } - - return {}; } - friend task::AwaitableValue tag_invoke( - storage2::tag_t /*unused*/, MemoryStorage& toStorage, MemoryStorage&& fromStorage) - requires(!std::is_const_v) + return {}; +} + +template +task::AwaitableValue tag_invoke(storage2::tag_t /*unused*/, + MemoryStorage& storage, RANGES::input_range auto&& keys) +{ + return removeSome(storage, std::forward(keys), false); +} + +template +task::AwaitableValue tag_invoke(storage2::tag_t /*unused*/, + MemoryStorage& storage, RANGES::input_range auto&& keys, DIRECT_TYPE /*unused*/) +{ + return removeSome(storage, std::forward(keys), true); +} + +template +task::AwaitableValue tag_invoke( + storage2::tag_t /*unused*/, MemoryStorage& toStorage, MemoryStorage&& fromStorage) + requires(!std::is_const_v) +{ + for (auto&& [bucket, fromBucket] : + RANGES::views::zip(toStorage.m_buckets, fromStorage.m_buckets)) { - for (auto&& [bucket, fromBucket] : - RANGES::views::zip(toStorage.m_buckets, fromStorage.m_buckets)) - { - Lock toLock(bucket.mutex, true); - Lock fromLock(fromBucket.mutex, true); + typename MemoryStorage::Lock toLock(bucket.mutex, true); + typename MemoryStorage::Lock fromLock(fromBucket.mutex, true); - auto& toIndex = bucket.container.template get<0>(); - auto& fromIndex = fromBucket.container.template get<0>(); + auto& toIndex = bucket.container.template get<0>(); + auto& fromIndex = fromBucket.container.template get<0>(); - if (toIndex.empty()) + if (toIndex.empty()) + { + toIndex.swap(fromIndex); + continue; + } + auto hintIt = toIndex.end(); + while (!fromIndex.empty()) + { + auto node = fromIndex.extract(fromIndex.begin()); + hintIt = toIndex.insert(hintIt, std::move(node)); + if (!node.empty()) { - toIndex.swap(fromIndex); - continue; - } - auto hintIt = toIndex.end(); - while (!fromIndex.empty()) - { - auto node = fromIndex.extract(fromIndex.begin()); - hintIt = toIndex.insert(hintIt, std::move(node)); - if (!node.empty()) - { - hintIt = toIndex.insert(toIndex.erase(hintIt), std::move(node)); - } + hintIt = toIndex.insert(toIndex.erase(hintIt), std::move(node)); } } - return {}; } + return {}; +} - friend task::Task tag_invoke( - storage2::tag_t /*unused*/, MemoryStorage& toStorage, auto&& fromStorage) +template +task::Task tag_invoke( + storage2::tag_t /*unused*/, MemoryStorage& toStorage, auto&& fromStorage) +{ + auto iterator = co_await storage2::range(fromStorage); + while (auto item = co_await iterator.next()) { - auto iterator = co_await storage2::range(fromStorage); - while (auto item = co_await iterator.next()) + auto&& [key, value] = *item; + if constexpr (std::is_pointer_v) { - auto&& [key, value] = *item; - if constexpr (std::is_pointer_v) + if (value) { - if (value) - { - co_await storage2::writeOne(toStorage, key, *value); - } - else - { - co_await storage2::removeOne(toStorage, key); - } + co_await storage2::writeOne(toStorage, key, *value); } else { - co_await storage2::writeOne(toStorage, key, value); + co_await storage2::removeOne(toStorage, key); } } + else + { + co_await storage2::writeOne(toStorage, key, value); + } } +} + +template +class Iterator +{ +private: + std::reference_wrapper m_buckets; + size_t m_bucketIndex = 0; + RANGES::iterator_t m_begin; + RANGES::iterator_t m_end; + + using IteratorValue = std::conditional_t; + +public: + Iterator(const typename MemoryStorage::Buckets& buckets) + : m_buckets(buckets), + m_begin((m_buckets.get()[m_bucketIndex]).container.begin()), + m_end((m_buckets.get()[m_bucketIndex]).container.end()) + {} - class Iterator + auto next() { - private: - std::reference_wrapper m_buckets; - size_t m_bucketIndex = 0; - RANGES::iterator_t m_begin; - RANGES::iterator_t m_end; - - using IteratorValue = - std::conditional_t; - - public: - Iterator(const Buckets& buckets) - : m_buckets(buckets), - m_begin((m_buckets.get()[m_bucketIndex]).container.begin()), - m_end((m_buckets.get()[m_bucketIndex]).container.end()) - {} - - auto next() + std::optional> result; + if (m_begin != m_end) { - std::optional> result; - if (m_begin != m_end) + auto const& data = *m_begin; + if constexpr (MemoryStorage::withLogicalDeletion) { - auto const& data = *m_begin; - if constexpr (withLogicalDeletion) - { - result.emplace(std::make_tuple( - std::cref(data.key), data.value ? std::addressof(*(data.value)) : nullptr)); - } - else - { - result.emplace(std::make_tuple(std::cref(data.key), std::cref(data.value))); - } - ++m_begin; - return task::AwaitableValue(std::move(result)); + result.emplace(std::make_tuple( + std::cref(data.key), data.value ? std::addressof(*(data.value)) : nullptr)); } - - if (m_bucketIndex + 1 < m_buckets.get().size()) + else { - ++m_bucketIndex; - m_begin = m_buckets.get()[m_bucketIndex].container.begin(); - m_end = m_buckets.get()[m_bucketIndex].container.end(); - return next(); + result.emplace(std::make_tuple(std::cref(data.key), std::cref(data.value))); } + ++m_begin; return task::AwaitableValue(std::move(result)); } - auto seek(auto&& key) - requires(!withConcurrent && withOrdered) + if (m_bucketIndex + 1 < m_buckets.get().size()) { - auto const& index = m_buckets.get()[m_bucketIndex].container.template get<0>(); - m_begin = index.lower_bound(std::forward(key)); + ++m_bucketIndex; + m_begin = m_buckets.get()[m_bucketIndex].container.begin(); + m_end = m_buckets.get()[m_bucketIndex].container.end(); + return next(); } - }; - - friend auto tag_invoke( - bcos::storage2::tag_t /*unused*/, MemoryStorage const& storage) - { - return task::AwaitableValue(Iterator(storage.m_buckets)); + return task::AwaitableValue(std::move(result)); } - friend auto tag_invoke(bcos::storage2::tag_t /*unused*/, - MemoryStorage const& storage, RANGE_SEEK_TYPE /*unused*/, auto&& key) - requires(!withConcurrent && withOrdered) + auto seek(auto&& key) + requires(!MemoryStorage::withConcurrent && MemoryStorage::withOrdered) { - auto iterator = Iterator(storage.m_buckets); - iterator.seek(std::forward(key)); - return task::AwaitableValue(std::move(iterator)); + auto const& index = m_buckets.get()[m_bucketIndex].container.template get<0>(); + m_begin = index.lower_bound(std::forward(key)); } +}; - bool empty() const +template +auto tag_invoke(bcos::storage2::tag_t /*unused*/, MemoryStorage const& storage) +{ + return task::AwaitableValue(Iterator(storage.m_buckets)); +} + +template +auto tag_invoke(bcos::storage2::tag_t /*unused*/, MemoryStorage const& storage, + RANGE_SEEK_TYPE /*unused*/, auto&& key) + requires(!MemoryStorage::withConcurrent && MemoryStorage::withOrdered) +{ + auto iterator = Iterator(storage.m_buckets); + iterator.seek(std::forward(key)); + return task::AwaitableValue(std::move(iterator)); +} + +template +bool empty(MemoryStorage const& storage) +{ + bool allEmpty = true; + for (auto& bucket : storage.m_buckets) { - bool allEmpty = true; - for (auto& bucket : m_buckets) + typename MemoryStorage::Lock lock(bucket.mutex, false); + if (!bucket.container.empty()) { - Lock lock(bucket.mutex, false); - if (!bucket.container.empty()) - { - allEmpty = false; - break; - } + allEmpty = false; + break; } - - return allEmpty; } -}; + + return allEmpty; +} } // namespace bcos::storage2::memory_storage diff --git a/bcos-framework/test/unittests/storage2/TestMemoryStorage.cpp b/bcos-framework/test/unittests/storage2/TestMemoryStorage.cpp index 0ee8af1bf0..620ba1367a 100644 --- a/bcos-framework/test/unittests/storage2/TestMemoryStorage.cpp +++ b/bcos-framework/test/unittests/storage2/TestMemoryStorage.cpp @@ -141,7 +141,7 @@ BOOST_AUTO_TEST_CASE(lru) { task::syncWait([]() -> task::Task { MemoryStorage storage(1); - storage.setMaxCapacity(1040); + setMaxCapacity(storage, 1040); // write 10 100byte value storage::Entry entry; diff --git a/bcos-front/CMakeLists.txt b/bcos-front/CMakeLists.txt index e37ff484ad..af0533ca7e 100644 --- a/bcos-front/CMakeLists.txt +++ b/bcos-front/CMakeLists.txt @@ -22,6 +22,7 @@ aux_source_directory(bcos-front SRCS) add_library(${FRONT_TARGET} ${SRCS}) target_link_libraries(${FRONT_TARGET} PUBLIC bcos-framework ${UTILITIES_TARGET}) +set_target_properties(${FRONT_TARGET} PROPERTIES UNITY_BUILD "ON") if (TESTS) enable_testing() diff --git a/bcos-gateway/CMakeLists.txt b/bcos-gateway/CMakeLists.txt index 456308d779..680cbb8cfa 100644 --- a/bcos-gateway/CMakeLists.txt +++ b/bcos-gateway/CMakeLists.txt @@ -29,6 +29,7 @@ find_package(tarscpp REQUIRED) add_library(${GATEWAY_TARGET} ${SRCS}) target_link_libraries(${GATEWAY_TARGET} PUBLIC jsoncpp_static Boost::filesystem bcos-boostssl ${FRONT_TARGET} ${TARS_PROTOCOL_TARGET} tarscpp::tarsservant tarscpp::tarsutil) +set_target_properties(${GATEWAY_TARGET} PROPERTIES UNITY_BUILD "ON") if (APPLE) # target_compile_options(${GATEWAY_TARGET} PRIVATE -faligned-allocation) diff --git a/bcos-ledger/CMakeLists.txt b/bcos-ledger/CMakeLists.txt index 24c49106a3..762d8ac5e3 100644 --- a/bcos-ledger/CMakeLists.txt +++ b/bcos-ledger/CMakeLists.txt @@ -25,6 +25,7 @@ find_package(Boost REQUIRED serialization) add_library(${LEDGER_TARGET} ${SRCS}) target_link_libraries(${LEDGER_TARGET} PUBLIC ${TOOL_TARGET} ${CODEC_TARGET} ${TABLE_TARGET} bcos-concepts Boost::serialization) +set_target_properties(${LEDGER_TARGET} PROPERTIES UNITY_BUILD "ON") # test related if (TESTS) diff --git a/bcos-pbft/CMakeLists.txt b/bcos-pbft/CMakeLists.txt index 28c76ba366..8b3b3933c7 100644 --- a/bcos-pbft/CMakeLists.txt +++ b/bcos-pbft/CMakeLists.txt @@ -51,6 +51,11 @@ find_package(jsoncpp CONFIG REQUIRED) file(GLOB_RECURSE SRCS bcos-pbft/*.cpp) add_library(${PBFT_TARGET} ${SRCS} ${MESSAGES_SRCS}) target_link_libraries(${PBFT_TARGET} PUBLIC ${TXPOOL_TARGET} ${UTILITIES_TARGET} ${TOOL_TARGET} bcos-framework jsoncpp_static) +set_source_files_properties( + "bcos-pbft/pbft/protocol/proto/PBFT.pb.cc" + "bcos-pbft/core/proto/Consensus.pb.cc" + PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON) +set_target_properties(${PBFT_TARGET} PROPERTIES UNITY_BUILD "ON") if (TESTS) # fetch bcos-test diff --git a/bcos-pbft/test/CMakeLists.txt b/bcos-pbft/test/CMakeLists.txt index 1552728465..d5edd00ef4 100644 --- a/bcos-pbft/test/CMakeLists.txt +++ b/bcos-pbft/test/CMakeLists.txt @@ -26,5 +26,5 @@ target_include_directories(${TEST_BINARY_NAME} PRIVATE . ${CMAKE_SOURCE_DIR}) find_package(Boost REQUIRED unit_test_framework) -target_link_libraries(${TEST_BINARY_NAME} ${PBFT_TARGET} ${RPBFT_TARGET} ${TOOL_TARGET} ${TABLE_TARGET} bcos-crypto ${TARS_PROTOCOL_TARGET} protobuf::libprotobuf Boost::unit_test_framework) +target_link_libraries(${TEST_BINARY_NAME} ${RPBFT_TARGET} ${PBFT_TARGET} ${TOOL_TARGET} ${TABLE_TARGET} bcos-crypto ${TARS_PROTOCOL_TARGET} protobuf::libprotobuf Boost::unit_test_framework) add_test(NAME test-pbft WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} COMMAND ${TEST_BINARY_NAME}) \ No newline at end of file diff --git a/bcos-rpbft/CMakeLists.txt b/bcos-rpbft/CMakeLists.txt index d13e829c8e..02f9e9511e 100644 --- a/bcos-rpbft/CMakeLists.txt +++ b/bcos-rpbft/CMakeLists.txt @@ -23,7 +23,9 @@ project(bcos-rpbft VERSION ${VERSION}) file(GLOB_RECURSE SRCS bcos-rpbft/*.cpp) add_library(${RPBFT_TARGET} ${SRCS}) include_directories(${CMAKE_BINARY_DIR}/bcos-pbft/) -target_link_libraries(${RPBFT_TARGET} PUBLIC ${PBFT_TARGET}) +target_link_libraries(${RPBFT_TARGET} PUBLIC bcos-framework) +set_target_properties(${RPBFT_TARGET} PROPERTIES UNITY_BUILD "ON") +add_dependencies(${RPBFT_TARGET} ${PBFT_TARGET}) if (TESTS) # fetch bcos-test diff --git a/bcos-rpbft/test/CMakeLists.txt b/bcos-rpbft/test/CMakeLists.txt index 7b73493a6e..509b0e592a 100644 --- a/bcos-rpbft/test/CMakeLists.txt +++ b/bcos-rpbft/test/CMakeLists.txt @@ -25,5 +25,5 @@ target_include_directories(${TEST_BINARY_NAME} PRIVATE . ${CMAKE_SOURCE_DIR}) find_package(Boost REQUIRED unit_test_framework) -target_link_libraries(${TEST_BINARY_NAME} ${PBFT_TARGET} ${RPBFT_TARGET} ${TABLE_TARGET} bcos-crypto ${TARS_PROTOCOL_TARGET} ${PBFT_TARGET} Boost::unit_test_framework) +target_link_libraries(${TEST_BINARY_NAME} ${RPBFT_TARGET} ${TABLE_TARGET} bcos-crypto ${TARS_PROTOCOL_TARGET} ${PBFT_TARGET} Boost::unit_test_framework) add_test(NAME test-rpbft WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} COMMAND ${TEST_BINARY_NAME}) \ No newline at end of file diff --git a/bcos-rpc/CMakeLists.txt b/bcos-rpc/CMakeLists.txt index 8c6bfc1002..5ea6038dec 100644 --- a/bcos-rpc/CMakeLists.txt +++ b/bcos-rpc/CMakeLists.txt @@ -30,6 +30,7 @@ find_package(tarscpp REQUIRED) add_library(${RPC_TARGET} ${SRCS} ${HEADERS}) target_link_libraries(${RPC_TARGET} PUBLIC bcos-boostssl ${LEDGER_TARGET} ${CRYPTO_TARGET} ${TARS_PROTOCOL_TARGET} jsoncpp_static tarscpp::tarsservant tarscpp::tarsutil) +set_target_properties(${RPC_TARGET} PROPERTIES UNITY_BUILD "ON") if (TESTS) enable_testing() diff --git a/bcos-scheduler/CMakeLists.txt b/bcos-scheduler/CMakeLists.txt index d8e84d3b1c..86432ceafa 100644 --- a/bcos-scheduler/CMakeLists.txt +++ b/bcos-scheduler/CMakeLists.txt @@ -7,6 +7,7 @@ aux_source_directory(src SRCS) add_library(${SCHEDULER_TARGET} ${SRCS}) target_link_libraries(${SCHEDULER_TARGET} PUBLIC ${TABLE_TARGET} ${TARS_PROTOCOL_TARGET}) +set_target_properties(${SCHEDULER_TARGET} PROPERTIES UNITY_BUILD "ON") if(TESTS) enable_testing() diff --git a/bcos-scheduler/src/BlockExecutive.cpp b/bcos-scheduler/src/BlockExecutive.cpp index 947de24795..d0a64c68a9 100644 --- a/bcos-scheduler/src/BlockExecutive.cpp +++ b/bcos-scheduler/src/BlockExecutive.cpp @@ -1010,14 +1010,13 @@ void BlockExecutive::onDmcExecuteFinish( auto dmcChecksum = m_dmcRecorder->dumpAndClearChecksum(); if (m_staticCall) { - DMC_LOG(TRACE) << LOG_BADGE("Stat") << "DMCExecute.6:" - << "\t " << LOG_BADGE("DMCRecorder") << " DMCExecute for call finished " - << LOG_KV("blockNumber", number()) << LOG_KV("checksum", dmcChecksum); + DMC_LOG(TRACE) << LOG_BADGE("Stat") << "DMCExecute.6:" << "\t " << LOG_BADGE("DMCRecorder") + << " DMCExecute for call finished " << LOG_KV("blockNumber", number()) + << LOG_KV("checksum", dmcChecksum); } else { - DMC_LOG(INFO) << LOG_BADGE("Stat") << "DMCExecute.6:" - << "\t " << LOG_BADGE("DMCRecorder") + DMC_LOG(INFO) << LOG_BADGE("Stat") << "DMCExecute.6:" << "\t " << LOG_BADGE("DMCRecorder") << " DMCExecute for transaction finished " << LOG_KV("blockNumber", number()) << LOG_KV("checksum", dmcChecksum); diff --git a/bcos-scheduler/src/BlockExecutive.h b/bcos-scheduler/src/BlockExecutive.h index 8580a997e0..a60046ef88 100644 --- a/bcos-scheduler/src/BlockExecutive.h +++ b/bcos-scheduler/src/BlockExecutive.h @@ -14,8 +14,6 @@ #include #include #include -#include -#include #include #include diff --git a/bcos-scheduler/src/ExecutorManager.h b/bcos-scheduler/src/ExecutorManager.h index 2bba57ad24..68d41f9d48 100644 --- a/bcos-scheduler/src/ExecutorManager.h +++ b/bcos-scheduler/src/ExecutorManager.h @@ -5,14 +5,9 @@ #include #include #include -#include -#include -#include #include -#include #include #include -#include #include #include @@ -179,6 +174,7 @@ class ExecutorManager { return m_name2Executors[name]; } + private: std::shared_ptr m_timer; @@ -208,8 +204,6 @@ class ExecutorManager m_executorPriorityQueue; - - bcos::executor::ParallelTransactionExecutorInterface::Ptr const& executorView( const decltype(m_name2Executors)::value_type& value) const { diff --git a/bcos-scheduler/src/GraphKeyLocks.cpp b/bcos-scheduler/src/GraphKeyLocks.cpp index 9384d315e0..353623556b 100644 --- a/bcos-scheduler/src/GraphKeyLocks.cpp +++ b/bcos-scheduler/src/GraphKeyLocks.cpp @@ -12,7 +12,6 @@ #include #include #include -#include using namespace bcos::scheduler; diff --git a/bcos-scheduler/src/GraphKeyLocks.h b/bcos-scheduler/src/GraphKeyLocks.h index a9d9e2aee1..71f5d7d4c2 100644 --- a/bcos-scheduler/src/GraphKeyLocks.h +++ b/bcos-scheduler/src/GraphKeyLocks.h @@ -2,16 +2,8 @@ #include "Common.h" #include -#include -#include -#include -#include -#include -#include -#include #include #include -#include #include #include diff --git a/bcos-scheduler/src/SchedulerFactory.h b/bcos-scheduler/src/SchedulerFactory.h index 7fd013ee5f..65fdf34b5d 100644 --- a/bcos-scheduler/src/SchedulerFactory.h +++ b/bcos-scheduler/src/SchedulerFactory.h @@ -1,9 +1,7 @@ #pragma once #include - #include "SchedulerImpl.h" - namespace bcos::scheduler { class SchedulerFactory diff --git a/bcos-scheduler/src/SchedulerImpl.cpp b/bcos-scheduler/src/SchedulerImpl.cpp index 687e86efc3..22fd06a08c 100644 --- a/bcos-scheduler/src/SchedulerImpl.cpp +++ b/bcos-scheduler/src/SchedulerImpl.cpp @@ -1,7 +1,6 @@ #include "SchedulerImpl.h" #include "BlockExecutive.h" #include "Common.h" -#include "bcos-framework/ledger/Features.h" #include "bcos-framework/ledger/Ledger.h" #include "bcos-ledger/src/libledger/LedgerMethods.h" #include "bcos-task/Wait.h" @@ -22,7 +21,6 @@ #include #include #include -#include using namespace bcos::scheduler; diff --git a/bcos-scheduler/src/SchedulerImpl.h b/bcos-scheduler/src/SchedulerImpl.h index c960b7be3e..8efd666104 100644 --- a/bcos-scheduler/src/SchedulerImpl.h +++ b/bcos-scheduler/src/SchedulerImpl.h @@ -3,7 +3,6 @@ #include "BlockExecutive.h" #include "BlockExecutiveFactory.h" #include "ExecutorManager.h" -#include "bcos-protocol/TransactionSubmitResultFactoryImpl.h" #include #include #include @@ -14,7 +13,6 @@ #include #include #include -#include #include namespace bcos::scheduler diff --git a/bcos-sdk/CMakeLists.txt b/bcos-sdk/CMakeLists.txt index f3f78b2e64..386013ffcf 100644 --- a/bcos-sdk/CMakeLists.txt +++ b/bcos-sdk/CMakeLists.txt @@ -19,6 +19,7 @@ target_include_directories(${BCOS_CPP_SDK_TARGET} PUBLIC $ $) target_link_libraries(${BCOS_CPP_SDK_TARGET} PUBLIC ${LINK_LIB_LIST}) +set_target_properties(${BCOS_CPP_SDK_TARGET} PROPERTIES UNITY_BUILD "ON") if (TESTS) enable_testing() diff --git a/bcos-sealer/CMakeLists.txt b/bcos-sealer/CMakeLists.txt index 4645f5db6f..510fcf74ec 100644 --- a/bcos-sealer/CMakeLists.txt +++ b/bcos-sealer/CMakeLists.txt @@ -27,6 +27,7 @@ add_library(${SEALER_TARGET} ${SRC_LIST}) find_package(tarscpp REQUIRED) target_link_libraries(${SEALER_TARGET} PUBLIC ${TOOL_TARGET} ${UTILITIES_TARGET} bcos-framework ${TXPOOL_TARGET} ${TARS_PROTOCOL_TARGET}) +set_target_properties(${SEALER_TARGET} PROPERTIES UNITY_BUILD "ON") if(TESTS) enable_testing() diff --git a/bcos-sealer/bcos-sealer/Sealer.cpp b/bcos-sealer/bcos-sealer/Sealer.cpp index ef2276f6a3..8c167867af 100644 --- a/bcos-sealer/bcos-sealer/Sealer.cpp +++ b/bcos-sealer/bcos-sealer/Sealer.cpp @@ -91,7 +91,7 @@ void Sealer::asyncNoteLatestBlockNumber(int64_t _blockNumber) void Sealer::asyncNoteLatestBlockHash(crypto::HashType _hash) { SEAL_LOG(INFO) << LOG_DESC("asyncNoteLatestBlockHash") << LOG_KV("_hash", _hash.abridged()); - m_sealingManager->resetLatestHash(std::move(_hash)); + m_sealingManager->resetLatestHash(_hash); } void Sealer::asyncNoteUnSealedTxsSize( @@ -162,8 +162,8 @@ void Sealer::submitProposal(bool _containSysTxs, bcos::protocol::Block::Ptr _blo _block->blockHeader()->setVersion(version); _block->blockHeader()->calculateHash(*m_hashImpl); - auto encodedData = std::make_shared(); - _block->encode(*encodedData); + bytes encodedData; + _block->encode(encodedData); SEAL_LOG(INFO) << LOG_DESC("++++++++++++++++ Generate proposal") << LOG_KV("index", _block->blockHeader()->number()) << LOG_KV("curNum", m_sealingManager->latestNumber()) @@ -171,7 +171,7 @@ void Sealer::submitProposal(bool _containSysTxs, bcos::protocol::Block::Ptr _blo << LOG_KV("sysTxs", _containSysTxs) << LOG_KV("txsSize", _block->transactionsHashSize()) << LOG_KV("version", version); - m_sealerConfig->consensus()->asyncSubmitProposal(_containSysTxs, ref(*encodedData), + m_sealerConfig->consensus()->asyncSubmitProposal(_containSysTxs, ref(encodedData), _block->blockHeader()->number(), _block->blockHeader()->hash(), [_block](auto&& _error) { if (_error == nullptr) { diff --git a/bcos-sealer/bcos-sealer/Sealer.h b/bcos-sealer/bcos-sealer/Sealer.h index 7c9d8a493c..ffeb7df062 100644 --- a/bcos-sealer/bcos-sealer/Sealer.h +++ b/bcos-sealer/bcos-sealer/Sealer.h @@ -22,7 +22,6 @@ #include "SealingManager.h" #include "bcos-framework/sealer/SealerInterface.h" #include - #include namespace bcos::sealer @@ -67,8 +66,8 @@ class Sealer : public Worker, public SealerInterface, public std::enable_shared_ uint16_t hookWhenSealBlock([[maybe_unused]] bcos::protocol::Block::Ptr _block) override; // only for test - SealerConfig::Ptr const sealerConfig() const { return m_sealerConfig; } - SealingManager::Ptr const sealingManager() const { return m_sealingManager; } + SealerConfig::Ptr sealerConfig() const { return m_sealerConfig; } + SealingManager::Ptr sealingManager() const { return m_sealingManager; } protected: void executeWorker() override; diff --git a/bcos-sealer/bcos-sealer/SealingManager.h b/bcos-sealer/bcos-sealer/SealingManager.h index e81a98cac3..9a41ed4c96 100644 --- a/bcos-sealer/bcos-sealer/SealingManager.h +++ b/bcos-sealer/bcos-sealer/SealingManager.h @@ -20,7 +20,6 @@ #pragma once #include "Common.h" #include "SealerConfig.h" -#include "bcos-framework/protocol/BlockFactory.h" #include "bcos-framework/protocol/TransactionMetaData.h" #include #include @@ -152,6 +151,6 @@ class SealingManager : public std::enable_shared_from_this std::atomic_bool m_fetchingTxs = {false}; std::atomic m_latestNumber = {0}; - bcos::crypto::HashType m_latestHash = {}; + bcos::crypto::HashType m_latestHash; }; } // namespace bcos::sealer diff --git a/bcos-sealer/bcos-sealer/VRFBasedSealer.h b/bcos-sealer/bcos-sealer/VRFBasedSealer.h index 5589fb3843..f2302750e5 100644 --- a/bcos-sealer/bcos-sealer/VRFBasedSealer.h +++ b/bcos-sealer/bcos-sealer/VRFBasedSealer.h @@ -22,7 +22,6 @@ #include "Sealer.h" #include "SealerConfig.h" #include "SealingManager.h" -#include "bcos-framework/sealer/SealerInterface.h" #include #include diff --git a/bcos-sealer/test/CMakeLists.txt b/bcos-sealer/test/CMakeLists.txt index db7d50cf71..0c79d8a31e 100644 --- a/bcos-sealer/test/CMakeLists.txt +++ b/bcos-sealer/test/CMakeLists.txt @@ -25,7 +25,7 @@ target_include_directories(${TEST_BINARY_NAME} PRIVATE . ../bcos-sealer) find_package(Boost REQUIRED unit_test_framework log) find_package(fmt REQUIRED) -target_link_libraries(${TEST_BINARY_NAME} PUBLIC ${SEALER_TARGET} ${PBFT_TARGET} ${TARS_PROTOCOL_TARGET} Boost::unit_test_framework Boost::log fmt::fmt-header-only) +target_link_libraries(${TEST_BINARY_NAME} PUBLIC ${SEALER_TARGET} ${PBFT_TARGET} ${RPBFT_TARGET} ${TARS_PROTOCOL_TARGET} Boost::unit_test_framework Boost::log fmt::fmt-header-only) include(SearchTestCases) config_test_cases("" "${SOURCES}" ${TEST_BINARY_NAME} "${EXCLUDE_SUITES}") diff --git a/bcos-security/CMakeLists.txt b/bcos-security/CMakeLists.txt index 4dd35598f5..ae31d9be7f 100644 --- a/bcos-security/CMakeLists.txt +++ b/bcos-security/CMakeLists.txt @@ -27,6 +27,7 @@ add_library(${SECURITY_TARGET} ${SRC_LIST}) find_package(jsoncpp REQUIRED) target_link_libraries(${SECURITY_TARGET} PUBLIC ${UTILITIES_TARGET} ${TOOL_TARGET} ${CRYPTO_TARGET} jsoncpp_static) +set_target_properties(${SECURITY_TARGET} PROPERTIES UNITY_BUILD "ON") if(TESTS) enable_testing() diff --git a/bcos-storage/CMakeLists.txt b/bcos-storage/CMakeLists.txt index fe5a83f5f1..579ec92963 100644 --- a/bcos-storage/CMakeLists.txt +++ b/bcos-storage/CMakeLists.txt @@ -25,6 +25,8 @@ target_include_directories(${STORAGE_TARGET} PUBLIC $ $) target_link_libraries(${STORAGE_TARGET} PUBLIC ${LIB_LIST}) +set_target_properties(${STORAGE_TARGET} PROPERTIES UNITY_BUILD "ON") + if (APPLE) target_link_libraries(${STORAGE_TARGET} PUBLIC "-framework SystemConfiguration") endif() diff --git a/bcos-sync/CMakeLists.txt b/bcos-sync/CMakeLists.txt index 541e2fe57d..621c8deb9e 100644 --- a/bcos-sync/CMakeLists.txt +++ b/bcos-sync/CMakeLists.txt @@ -51,6 +51,7 @@ include_directories(${PROTO_OUTPUT_PATH}) file(GLOB_RECURSE SRCS bcos-sync/*.cpp) add_library(${SYNC_TARGET} ${SRCS} ${SYNC_SRCS}) target_link_libraries(${SYNC_TARGET} PUBLIC ${STORAGE_TARGET} bcos-framework ${UTILITIES_TARGET} ${CODEC_TARGET} ${TOOL_TARGET} jsoncpp_static) +set_target_properties(${SYNC_TARGET} PROPERTIES UNITY_BUILD "ON") if (TESTS) enable_testing() diff --git a/bcos-table/CMakeLists.txt b/bcos-table/CMakeLists.txt index b28789c21a..a7c367d038 100644 --- a/bcos-table/CMakeLists.txt +++ b/bcos-table/CMakeLists.txt @@ -27,6 +27,7 @@ find_package(TBB CONFIG REQUIRED) add_library(${TABLE_TARGET} ${SRCS}) target_link_libraries(${TABLE_TARGET} PUBLIC ${UTILITIES_TARGET} bcos-framework Boost::serialization TBB::tbb) +set_target_properties(${TABLE_TARGET} PROPERTIES UNITY_BUILD "ON") if (TESTS) enable_testing() diff --git a/bcos-table/src/LegacyStorageWrapper.h b/bcos-table/src/LegacyStorageWrapper.h index 2784ae9045..1ba9c8f65a 100644 --- a/bcos-table/src/LegacyStorageWrapper.h +++ b/bcos-table/src/LegacyStorageWrapper.h @@ -133,7 +133,7 @@ class LegacyStorageWrapper : public virtual bcos::storage::StorageInterface } else { - co_await storage2::writeOne(self->m_storage, + co_await storage2::writeOne(self->m_storage.get(), transaction_executor::StateKey(table, key), std::move(entry)); } callback(nullptr); diff --git a/bcos-tars-protocol/CMakeLists.txt b/bcos-tars-protocol/CMakeLists.txt index 47e14bae17..e24bbd2f98 100644 --- a/bcos-tars-protocol/CMakeLists.txt +++ b/bcos-tars-protocol/CMakeLists.txt @@ -40,6 +40,7 @@ target_include_directories(${TARS_PROTOCOL_TARGET} PUBLIC $ $) target_link_libraries(${TARS_PROTOCOL_TARGET} PUBLIC bcos-concepts bcos-crypto tarscpp::tarsservant tarscpp::tarsutil TBB::tbb) +set_target_properties(${TARS_PROTOCOL_TARGET} PROPERTIES UNITY_BUILD "ON") if(TESTS) enable_testing() diff --git a/bcos-tool/CMakeLists.txt b/bcos-tool/CMakeLists.txt index 4d0a166d3b..5ce5299218 100644 --- a/bcos-tool/CMakeLists.txt +++ b/bcos-tool/CMakeLists.txt @@ -32,6 +32,7 @@ target_include_directories(${TOOL_TARGET} PUBLIC $ ) target_link_libraries(${TOOL_TARGET} PUBLIC ${TABLE_TARGET} ${UTILITIES_TARGET} bcos-framework jsoncpp_static tarscpp::tarsservant tarscpp::tarsutil TBB::tbb) +set_target_properties(${TOOL_TARGET} PROPERTIES UNITY_BUILD "ON") if(TESTS) enable_testing() diff --git a/bcos-tool/bcos-tool/BfsFileFactory.cpp b/bcos-tool/bcos-tool/BfsFileFactory.cpp index 57c570954f..f98b92faa6 100644 --- a/bcos-tool/bcos-tool/BfsFileFactory.cpp +++ b/bcos-tool/bcos-tool/BfsFileFactory.cpp @@ -19,6 +19,7 @@ */ #include "BfsFileFactory.h" +#include "bcos-executor/src/Common.h" #include #include #include @@ -107,23 +108,23 @@ bool BfsFileFactory::buildAuth(Table& _table, const std::string& _admin) { Entry adminEntry; adminEntry.importFields({_admin}); - _table.setRow(ADMIN_FIELD, std::move(adminEntry)); + _table.setRow(executor::ADMIN_FIELD, std::move(adminEntry)); Entry statusEntry; statusEntry.importFields({"normal"}); - _table.setRow(STATUS_FIELD, std::move(statusEntry)); + _table.setRow(executor::STATUS_FIELD, std::move(statusEntry)); Entry emptyType; emptyType.importFields({""}); - _table.setRow(METHOD_AUTH_TYPE, std::move(emptyType)); + _table.setRow(executor::METHOD_AUTH_TYPE, std::move(emptyType)); Entry emptyWhite; emptyWhite.importFields({""}); - _table.setRow(METHOD_AUTH_WHITE, std::move(emptyWhite)); + _table.setRow(executor::METHOD_AUTH_WHITE, std::move(emptyWhite)); Entry emptyBlack; emptyBlack.importFields({""}); - _table.setRow(METHOD_AUTH_BLACK, std::move(emptyBlack)); + _table.setRow(executor::METHOD_AUTH_BLACK, std::move(emptyBlack)); return true; } bool BfsFileFactory::buildContract(Table& _table) diff --git a/bcos-tool/bcos-tool/BfsFileFactory.h b/bcos-tool/bcos-tool/BfsFileFactory.h index b7a3daeb25..e0f1c28e32 100644 --- a/bcos-tool/bcos-tool/BfsFileFactory.h +++ b/bcos-tool/bcos-tool/BfsFileFactory.h @@ -67,14 +67,6 @@ constexpr static const std::string_view FS_TYPE_LINK{"link"}; constexpr static const std::string_view FS_LINK_ADDRESS{"link_address"}; constexpr static const std::string_view FS_LINK_ABI{"link_abi"}; -/// auth -constexpr static const std::string_view CONTRACT_SUFFIX{"_accessAuth"}; -constexpr static const std::string_view ADMIN_FIELD{"admin"}; -constexpr static const std::string_view STATUS_FIELD{"status"}; -constexpr static const std::string_view METHOD_AUTH_TYPE{"method_auth_type"}; -constexpr static const std::string_view METHOD_AUTH_WHITE{"method_auth_white"}; -constexpr static const std::string_view METHOD_AUTH_BLACK{"method_auth_black"}; - enum FileType : uint16_t { DIRECTOR = 0, diff --git a/bcos-txpool/bcos-txpool/CMakeLists.txt b/bcos-txpool/bcos-txpool/CMakeLists.txt index 6e929bc481..f4e6523b14 100644 --- a/bcos-txpool/bcos-txpool/CMakeLists.txt +++ b/bcos-txpool/bcos-txpool/CMakeLists.txt @@ -30,3 +30,4 @@ find_package(Protobuf CONFIG REQUIRED) target_include_directories(${TXPOOL_TARGET} PUBLIC .) target_include_directories(${TXPOOL_TARGET} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/bcos-txpool) target_link_libraries(${TXPOOL_TARGET} PUBLIC TBB::tbb protobuf::libprotobuf bcos-protocol ${UTILITIES_TARGET} ${TOOL_TARGET}) +set_target_properties(${TXPOOL_TARGET} PROPERTIES UNITY_BUILD "ON") \ No newline at end of file diff --git a/bcos-txpool/bcos-txpool/txpool/utilities/TransactionBucket.h b/bcos-txpool/bcos-txpool/txpool/utilities/TransactionBucket.h index be55b0ac44..673e3c6b96 100644 --- a/bcos-txpool/bcos-txpool/txpool/utilities/TransactionBucket.h +++ b/bcos-txpool/bcos-txpool/txpool/utilities/TransactionBucket.h @@ -1,15 +1,14 @@ #include "bcos-crypto/interfaces/crypto/CommonType.h" #include "bcos-framework/protocol/Transaction.h" +#include "bcos-framework/txpool/TxPoolTypeDef.h" #include "bcos-utilities/BucketMap.h" -#include "bcos-utilities/FixedBytes.h" #include "boost/multi_index/hashed_index.hpp" -#include "boost/multi_index/mem_fun.hpp" #include "boost/multi_index/member.hpp" #include "boost/multi_index/ordered_index.hpp" #include "boost/multi_index_container.hpp" -using namespace bcos; - +namespace bcos +{ class MultiIndexTxContainer { public: @@ -199,3 +198,4 @@ class TransactionBucket return m_values.forEach(handler, accessor); } }; +} // namespace bcos \ No newline at end of file diff --git a/bcos-utilities/CMakeLists.txt b/bcos-utilities/CMakeLists.txt index 3fce46dc37..eb71aa67f3 100644 --- a/bcos-utilities/CMakeLists.txt +++ b/bcos-utilities/CMakeLists.txt @@ -25,6 +25,7 @@ if (ONLY_CPP_SDK) else () target_link_libraries(bcos-utilities PUBLIC Boost::iostreams Boost::log Boost::filesystem Boost::chrono Boost::thread Boost::serialization redis++::redis++_static ZLIB::ZLIB zstd::libzstd_static ittapi) endif () +set_target_properties(bcos-utilities PROPERTIES UNITY_BUILD "ON") if(TESTS) enable_testing() diff --git a/benchmark/benchmarkMemoryStorage.cpp b/benchmark/benchmarkMemoryStorage.cpp index 1a1bdcd795..dd06089f89 100644 --- a/benchmark/benchmarkMemoryStorage.cpp +++ b/benchmark/benchmarkMemoryStorage.cpp @@ -50,7 +50,7 @@ void setCapacityForMRU(auto& storage) MemoryStorage>>) { - storage.setMaxCapacity(1000 * 1000 * 1000); + setMaxCapacity(storage, 1000 * 1000 * 1000); } } diff --git a/cmake/CompilerSettings.cmake b/cmake/CompilerSettings.cmake index 9a9c44d24d..ddddbab443 100644 --- a/cmake/CompilerSettings.cmake +++ b/cmake/CompilerSettings.cmake @@ -120,6 +120,9 @@ if(("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR("${CMAKE_CXX_COMPILER_ID}" MATC add_compile_options(-Wno-restrict) add_compile_options(-Wno-error=format-truncation) + # gcc bug, refer to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105595 + add_compile_options(-Wno-error=subobject-linkage) + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0) add_compile_options(-Wno-stringop-overread) add_compile_options(-Wno-maybe-uninitialized) @@ -128,7 +131,7 @@ if(("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR("${CMAKE_CXX_COMPILER_ID}" MATC endif() if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 14.0) - set(CMAKE_CXX_STANDARD 23) + # set(CMAKE_CXX_STANDARD 23) add_compile_options(-Wno-error=uninitialized) endif() # add_compile_options(-fconcepts-diagnostics-depth=10) @@ -140,6 +143,7 @@ if(("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR("${CMAKE_CXX_COMPILER_ID}" MATC add_compile_options(-fstack-protector) add_compile_options(-Winconsistent-missing-override) add_compile_options(-foptimize-sibling-calls) + add_compile_options(-Wno-error=unused-private-field) # Some Linux-specific Clang settings. We don't want these for OS X. if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") diff --git a/fisco-bcos-air/AirNodeInitializer.cpp b/fisco-bcos-air/AirNodeInitializer.cpp index 6db4c32f0f..583affd3fa 100644 --- a/fisco-bcos-air/AirNodeInitializer.cpp +++ b/fisco-bcos-air/AirNodeInitializer.cpp @@ -30,11 +30,9 @@ #include #include #include -#include #include #include #include -#include using namespace bcos::node; using namespace bcos::initializer; diff --git a/fisco-bcos-air/AirNodeInitializer.h b/fisco-bcos-air/AirNodeInitializer.h index 0207b6f2dd..bc0d3b18bc 100644 --- a/fisco-bcos-air/AirNodeInitializer.h +++ b/fisco-bcos-air/AirNodeInitializer.h @@ -25,7 +25,6 @@ #include #include #include - #include diff --git a/fisco-bcos-air/CMakeLists.txt b/fisco-bcos-air/CMakeLists.txt index c77adce749..a242aef5fb 100644 --- a/fisco-bcos-air/CMakeLists.txt +++ b/fisco-bcos-air/CMakeLists.txt @@ -2,4 +2,5 @@ aux_source_directory(. SRC_LIST) set(BINARY_NAME fisco-bcos) add_executable(${BINARY_NAME} ${SRC_LIST}) -target_link_libraries(${BINARY_NAME} PUBLIC ${INIT_LIB} ${PBFT_INIT_LIB} ${TOOL_TARGET} ${COMMAND_HELPER_LIB} ${RPC_TARGET} ${GATEWAY_TARGET}) +target_link_libraries(${BINARY_NAME} PUBLIC ${INIT_LIB} ${PBFT_INIT_LIB} ${COMMAND_HELPER_LIB} ${GATEWAY_TARGET}) +set_target_properties(${BINARY_NAME} PROPERTIES UNITY_BUILD "ON") \ No newline at end of file diff --git a/fisco-bcos-air/Common.h b/fisco-bcos-air/Common.h index 54d5d11ed1..688b650271 100644 --- a/fisco-bcos-air/Common.h +++ b/fisco-bcos-air/Common.h @@ -20,28 +20,24 @@ #pragma once #include "bcos-utilities/Common.h" -#include -#include #include #include -#include -namespace bcos -{ -namespace node + +namespace bcos::node { class ExitHandler { public: - void exit() { exitHandler(0); } + static void exit() { exitHandler(0); } static void exitHandler(int signal) { - std::cout << "[" << bcos::getCurrentDateTime() << "] " - << "exit because receive signal " << signal << std::endl; + std::cout << "[" << bcos::getCurrentDateTime() << "] " << "exit because receive signal " + << signal << std::endl; ExitHandler::c_shouldExit.store(true); ExitHandler::c_shouldExit.notify_all(); } - bool shouldExit() const { return ExitHandler::c_shouldExit.load(); } + static bool shouldExit() { return ExitHandler::c_shouldExit.load(); } static boost::atomic_bool c_shouldExit; }; @@ -50,11 +46,10 @@ boost::atomic_bool ExitHandler::c_shouldExit = {false}; void setDefaultOrCLocale() { #if __unix__ - if (!std::setlocale(LC_ALL, "")) + if (std::setlocale(LC_ALL, "") == nullptr) { setenv("LC_ALL", "C", 1); } #endif } -} // namespace node -} // namespace bcos +} // namespace bcos::node diff --git a/fisco-bcos-air/main.cpp b/fisco-bcos-air/main.cpp index 9cf958af6f..bdeda8ab31 100644 --- a/fisco-bcos-air/main.cpp +++ b/fisco-bcos-air/main.cpp @@ -26,8 +26,6 @@ #include "Common.h" #include "libinitializer/CommandHelper.h" #include -#include -#include using namespace bcos::node; using namespace bcos::initializer; diff --git a/fisco-bcos-tars-service/GatewayService/GatewayServiceServer.h b/fisco-bcos-tars-service/GatewayService/GatewayServiceServer.h index 0517842b22..cdbfa3a605 100644 --- a/fisco-bcos-tars-service/GatewayService/GatewayServiceServer.h +++ b/fisco-bcos-tars-service/GatewayService/GatewayServiceServer.h @@ -10,9 +10,6 @@ #include #include -using namespace bcos; -using namespace bcos::group; - namespace bcostars { struct GatewayServiceParam @@ -30,7 +27,7 @@ class GatewayServiceServer : public bcostars::GatewayService bcostars::Error asyncSendBroadcastMessage(tars::Int32 _type, const std::string& groupID, tars::Int32 moduleID, const vector& srcNodeID, - const vector& payload, tars::TarsCurrentPtr current) override + const std::vector& payload, tars::TarsCurrentPtr current) override { current->setResponse(false); auto bcosNodeID = m_gatewayInitializer->keyFactory()->createKey( diff --git a/fisco-bcos-tars-service/GatewayService/main/Application.cpp b/fisco-bcos-tars-service/GatewayService/main/Application.cpp index 3bc6992e72..4f0bddc917 100644 --- a/fisco-bcos-tars-service/GatewayService/main/Application.cpp +++ b/fisco-bcos-tars-service/GatewayService/main/Application.cpp @@ -12,8 +12,8 @@ using namespace bcostars; class GatewayServiceApp : public tars::Application { public: - GatewayServiceApp() {} - ~GatewayServiceApp() override{}; + GatewayServiceApp() = default; + ~GatewayServiceApp() override {}; void destroyApp() override { @@ -51,7 +51,7 @@ class GatewayServiceApp : public tars::Application boost::property_tree::ptree pt; boost::property_tree::read_ini(_configPath, pt); - tool::NodeConfig nodeConfig; + bcos::tool::NodeConfig nodeConfig; nodeConfig.loadWithoutTarsFrameworkConfig(pt); diff --git a/libinitializer/AuthInitializer.h b/libinitializer/AuthInitializer.h index bf778556bf..418c8aa562 100644 --- a/libinitializer/AuthInitializer.h +++ b/libinitializer/AuthInitializer.h @@ -28,9 +28,6 @@ #include #include -using namespace bcos; -using namespace bcos::tool; -using namespace bcos::initializer; namespace bcos::initializer { // clang-format off @@ -43,7 +40,7 @@ class AuthInitializer public: static void init(protocol::BlockNumber _number, const std::shared_ptr& _protocol, - const std::shared_ptr& _nodeConfig, const protocol::Block::Ptr& block) + const std::shared_ptr& _nodeConfig, const protocol::Block::Ptr& block) { // hex bin code to bytes bytes code; diff --git a/libinitializer/BaselineSchedulerInitializer.h b/libinitializer/BaselineSchedulerInitializer.h index e8692cc5b7..bb78dee178 100644 --- a/libinitializer/BaselineSchedulerInitializer.h +++ b/libinitializer/BaselineSchedulerInitializer.h @@ -10,7 +10,6 @@ namespace bcos::transaction_scheduler { - class BaselineSchedulerInitializer { public: diff --git a/libinitializer/CMakeLists.txt b/libinitializer/CMakeLists.txt index 40ba4ca4d4..292b9c4fb4 100644 --- a/libinitializer/CMakeLists.txt +++ b/libinitializer/CMakeLists.txt @@ -13,6 +13,7 @@ target_link_libraries(${FRONTSERVICE_INIT_LIB} PUBLIC ${PROTOCOL_INIT_LIB} ${TOO add_library(${PBFT_INIT_LIB} PBFTInitializer.cpp ProPBFTInitializer.cpp) target_link_libraries(${PBFT_INIT_LIB} PUBLIC ${PROTOCOL_INIT_LIB} ${LEDGER_TARGET} ${TOOL_TARGET} ${SEALER_TARGET} ${RPBFT_TARGET} ${PBFT_TARGET} ${SYNC_TARGET} ${STORAGE_TARGET}) +set_target_properties(${PBFT_INIT_LIB} PROPERTIES UNITY_BUILD "ON") if(WITH_TIKV) target_link_libraries(${PBFT_INIT_LIB} PUBLIC ${LEADER_ELECTION_TARGET}) endif() @@ -27,8 +28,11 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(tomlplusplus) -add_library(${INIT_LIB} Initializer.cpp LightNodeInitializer.h BaselineSchedulerInitializer.cpp) -list(APPEND INIT_LIB_DEPENDS ${PROTOCOL_INIT_LIB} ${FRONTSERVICE_INIT_LIB} ${TXPOOL_INIT_LIB} ${SCHEDULER_TARGET} ${STORAGE_TARGET} ${EXECUTOR_TARGET} ${RPC_TARGET} transaction-scheduler transaction-executor bcos-boostssl tomlplusplus::tomlplusplus) +add_library(baseline_init BaselineSchedulerInitializer.cpp) +target_link_libraries(baseline_init transaction-scheduler transaction-executor ${STORAGE_TARGET}) + +add_library(${INIT_LIB} Initializer.cpp) +list(APPEND INIT_LIB_DEPENDS ${PROTOCOL_INIT_LIB} baseline_init ${FRONTSERVICE_INIT_LIB} ${TXPOOL_INIT_LIB} ${SCHEDULER_TARGET} ${STORAGE_TARGET} ${EXECUTOR_TARGET} ${RPC_TARGET} bcos-boostssl tomlplusplus::tomlplusplus) if(WITH_TIKV) list(APPEND INIT_LIB_DEPENDS ${LEADER_ELECTION_TARGET}) endif() @@ -38,4 +42,5 @@ if(WITH_LIGHTNODE) list(APPEND INIT_LIB_DEPENDS lightnodeinit bcos-concepts) endif() target_link_libraries(${INIT_LIB} PUBLIC ${INIT_LIB_DEPENDS}) +set_target_properties(${INIT_LIB} PROPERTIES UNITY_BUILD "ON") add_dependencies(${INIT_LIB} BuildInfo.h) diff --git a/libinitializer/Initializer.cpp b/libinitializer/Initializer.cpp index ecec45833b..706f738b85 100644 --- a/libinitializer/Initializer.cpp +++ b/libinitializer/Initializer.cpp @@ -423,6 +423,7 @@ void Initializer::init(bcos::protocol::NodeArchitectureType _nodeArchType, m_archiveService = std::make_shared(m_storage, ledger, m_blockStorage, m_nodeConfig->archiveListenIP(), m_nodeConfig->archiveListenPort()); } + #ifdef WITH_LIGHTNODE bcos::storage::StorageImpl storageWrapper(m_storage); diff --git a/libinitializer/LightNodeInitializer.h b/libinitializer/LightNodeInitializer.h index f90393240f..a93ad0c68c 100644 --- a/libinitializer/LightNodeInitializer.h +++ b/libinitializer/LightNodeInitializer.h @@ -1,6 +1,5 @@ #pragma once -#include "bcos-concepts/Exception.h" #include "bcos-concepts/Serialize.h" #include #include diff --git a/libtask/bcos-task/Task.h b/libtask/bcos-task/Task.h index ea23cec4f7..72b9710744 100644 --- a/libtask/bcos-task/Task.h +++ b/libtask/bcos-task/Task.h @@ -17,9 +17,8 @@ struct NoReturnValue : public bcos::error::Exception template struct FinalAwaitable { - static constexpr bool await_ready() noexcept { return false; } - static constexpr std::coroutine_handle<> await_suspend( - std::coroutine_handle handle) noexcept + 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) @@ -43,8 +42,8 @@ struct Continuation template struct PromiseBase { - static constexpr std::suspend_always initial_suspend() noexcept { return {}; } - static constexpr auto final_suspend() noexcept { return FinalAwaitable{}; } + constexpr std::suspend_always initial_suspend() noexcept { return {}; } + constexpr auto final_suspend() noexcept { return FinalAwaitable{}; } Task get_return_object() { auto handle = @@ -69,7 +68,7 @@ struct PromiseBase template struct PromiseVoid : public PromiseBase> { - static constexpr void return_void() noexcept {} + constexpr void return_void() noexcept {} }; template @@ -101,7 +100,7 @@ class [[nodiscard]] Task struct Awaitable { explicit Awaitable(std::coroutine_handle handle) - : m_handle(std::move(handle)){}; + : m_handle(std::move(handle)) {}; Awaitable(const Awaitable&) = delete; Awaitable(Awaitable&&) noexcept = default; Awaitable& operator=(const Awaitable&) = delete; diff --git a/transaction-executor/CMakeLists.txt b/transaction-executor/CMakeLists.txt index 73633f6bc3..32d0ffbffa 100644 --- a/transaction-executor/CMakeLists.txt +++ b/transaction-executor/CMakeLists.txt @@ -10,15 +10,16 @@ find_package(jsoncpp REQUIRED) add_library(transaction-executor bcos-transaction-executor/vm/VMInstance.cpp bcos-transaction-executor/precompiled/PrecompiledManager.cpp - bcos-transaction-executor/precompiled/PrecompiledImpl.cpp - bcos-transaction-executor/vm/HostContext.cpp - bcos-transaction-executor/TransactionExecutorImpl.cpp + bcos-transaction-executor/precompiled/PrecompiledImpl.cpp + bcos-transaction-executor/vm/HostContext.cpp + bcos-transaction-executor/TransactionExecutorImpl.cpp ) target_include_directories(transaction-executor PUBLIC $ $) -target_link_libraries(transaction-executor PUBLIC ${EXECUTOR_TARGET} ${STORAGE_TARGET} jsoncpp_static ${CODEC_TARGET} ${CRYPTO_TARGET} ${TABLE_TARGET} bcos-protocol +target_link_libraries(transaction-executor PUBLIC ${EXECUTOR_TARGET} jsoncpp_static ${CODEC_TARGET} ${CRYPTO_TARGET} ${TABLE_TARGET} bcos-protocol evmone evmc::loader evmc::instructions fmt::fmt-header-only) +set_target_properties(transaction-executor PROPERTIES UNITY_BUILD "ON") if (TESTS) enable_testing() diff --git a/transaction-executor/bcos-transaction-executor/RollbackableStorage.h b/transaction-executor/bcos-transaction-executor/RollbackableStorage.h index 0fef1911bb..0364233013 100644 --- a/transaction-executor/bcos-transaction-executor/RollbackableStorage.h +++ b/transaction-executor/bcos-transaction-executor/RollbackableStorage.h @@ -22,7 +22,10 @@ concept HasReadSomeDirect = requires(Storage& storage) { template class Rollbackable { -private: +public: + constexpr static bool isRollbackable = true; + using BackendStorage = Storage; + struct Record { StateKey key; @@ -33,116 +36,125 @@ class Rollbackable std::vector m_records; std::reference_wrapper m_storage; -public: using Savepoint = int64_t; using Key = typename Storage::Key; using Value = typename Storage::Value; Rollbackable(Storage& storage) : m_storage(storage) {} +}; - Storage& storage() { return m_storage; } - Savepoint current() const { return static_cast(m_records.size()); } +template +concept IsRollbackable = std::remove_cvref_t::isRollbackable; - task::Task rollback(Savepoint savepoint) +template +typename Rollbackable::Savepoint current(Rollbackable const& storage) +{ + return static_cast(storage.m_records.size()); +} + +template +task::Task rollback(Rollbackable& storage, typename Rollbackable::Savepoint savepoint) +{ + if (storage.m_records.empty()) + { + co_return; + } + for (auto index = static_cast(storage.m_records.size()); index > savepoint; --index) { - if (m_records.empty()) + assert(index > 0); + auto& record = storage.m_records[index - 1]; + if (record.oldValue) { - co_return; + co_await storage2::writeOne( + storage.m_storage.get(), std::move(record.key), std::move(*record.oldValue)); } - for (auto index = static_cast(m_records.size()); index > savepoint; --index) + else { - assert(index > 0); - auto& record = m_records[index - 1]; - if (record.oldValue) - { - co_await storage2::writeOne( - m_storage.get(), std::move(record.key), std::move(*record.oldValue)); - } - else - { - co_await storage2::removeOne(m_storage.get(), record.key, storage2::DIRECT); - } - m_records.pop_back(); + co_await storage2::removeOne(storage.m_storage.get(), record.key, storage2::DIRECT); } - co_return; - } - - friend auto tag_invoke(storage2::tag_t /*unused*/, Rollbackable& storage, - RANGES::input_range auto&& keys) - -> task::Task>> - { - co_return co_await storage2::readSome( - storage.m_storage.get(), std::forward(keys)); - } - - friend auto tag_invoke(storage2::tag_t /*unused*/, Rollbackable& storage, - auto&& key) -> task::Task>> - { - co_return co_await storage2::readOne( - storage.m_storage.get(), std::forward(key)); + storage.m_records.pop_back(); } - - friend auto tag_invoke(storage2::tag_t /*unused*/, Rollbackable& storage, - RANGES::input_range auto&& keys, RANGES::input_range auto&& values) - -> task::Task>> - requires HasReadSomeDirect + co_return; +} + +template +auto tag_invoke(storage2::tag_t /*unused*/, Rollbackable& storage, + RANGES::input_range auto&& keys) + -> task::Task>> +{ + co_return co_await storage2::readSome( + storage.m_storage.get(), std::forward(keys)); +} + +template +auto tag_invoke(storage2::tag_t /*unused*/, Rollbackable& storage, + auto&& key) -> task::Task>> +{ + co_return co_await storage2::readOne(storage.m_storage.get(), std::forward(key)); +} + +template +auto tag_invoke(storage2::tag_t /*unused*/, Rollbackable& storage, + RANGES::input_range auto&& keys, RANGES::input_range auto&& values) + -> task::Task>> + requires HasReadSomeDirect +{ + auto oldValues = co_await storage2::readSome(storage.m_storage.get(), keys, storage2::DIRECT); + for (auto&& [key, oldValue] : RANGES::views::zip(keys, oldValues)) { - auto oldValues = - co_await storage2::readSome(storage.m_storage.get(), keys, storage2::DIRECT); - for (auto&& [key, oldValue] : RANGES::views::zip(keys, oldValues)) - { - storage.m_records.emplace_back(Record{.key = typename Storage::Key{key}, + storage.m_records.emplace_back( + typename Rollbackable::Record{.key = typename Rollbackable::BackendStorage::Key{key}, .oldValue = std::forward(oldValue)}); - } - - co_return co_await storage2::writeSome(storage.m_storage.get(), - std::forward(keys), std::forward(values)); } - friend auto tag_invoke(storage2::tag_t /*unused*/, Rollbackable& storage, - auto&& key, auto&& value) - -> task::Task>> - requires HasReadOneDirect - { - auto& record = storage.m_records.emplace_back(); - record.key = key; - record.oldValue = - co_await storage2::readOne(storage.m_storage.get(), key, storage2::DIRECT); - co_await storage2::writeOne( - storage.m_storage.get(), record.key, std::forward(value)); - } + co_return co_await storage2::writeSome(storage.m_storage.get(), + std::forward(keys), std::forward(values)); +} - friend auto tag_invoke(storage2::tag_t /*unused*/, Rollbackable& storage, - RANGES::input_range auto const& keys) - -> task::Task, decltype(keys)>>> +template +auto tag_invoke(storage2::tag_t /*unused*/, Rollbackable& storage, auto&& key, + auto&& value) -> task::Task>> + requires HasReadOneDirect +{ + auto& record = storage.m_records.emplace_back(); + record.key = key; + record.oldValue = co_await storage2::readOne(storage.m_storage.get(), key, storage2::DIRECT); + co_await storage2::writeOne( + storage.m_storage.get(), record.key, std::forward(value)); +} + +template +auto tag_invoke(storage2::tag_t /*unused*/, Rollbackable& storage, + RANGES::input_range auto const& keys) + -> task::Task, decltype(keys)>>> +{ + // Store values to history + auto oldValues = co_await storage2::readSome(storage.m_storage.get(), keys, storage2::DIRECT); + for (auto&& [key, value] : RANGES::views::zip(keys, oldValues)) { - // Store values to history - auto oldValues = - co_await storage2::readSome(storage.m_storage.get(), keys, storage2::DIRECT); - for (auto&& [key, value] : RANGES::views::zip(keys, oldValues)) + if (value) { - if (value) - { - auto& record = storage.m_records.emplace_back( - Record{.key = StateKey{key}, .oldValue = std::move(*value)}); - } + auto& record = storage.m_records.emplace_back( + typename Rollbackable::Record{.key = StateKey{key}, .oldValue = std::move(*value)}); } - - co_return co_await storage2::removeSome(storage.m_storage.get(), keys); } - friend auto tag_invoke(bcos::storage2::tag_t /*unused*/, Rollbackable& storage, - auto&&... args) -> task::Task, decltype(args)...>>> - { - co_return co_await storage2::range( - storage.m_storage.get(), std::forward(args)...); - } -}; + co_return co_await storage2::removeSome(storage.m_storage.get(), keys); +} + +template +auto tag_invoke( + bcos::storage2::tag_t /*unused*/, Rollbackable& storage, auto&&... args) + -> task::Task, decltype(args)...>>> +{ + co_return co_await storage2::range( + storage.m_storage.get(), std::forward(args)...); +} } // namespace bcos::transaction_executor \ No newline at end of file diff --git a/transaction-executor/bcos-transaction-executor/vm/HostContext.cpp b/transaction-executor/bcos-transaction-executor/vm/HostContext.cpp index 95e34a5cf8..23560d1b1e 100644 --- a/transaction-executor/bcos-transaction-executor/vm/HostContext.cpp +++ b/transaction-executor/bcos-transaction-executor/vm/HostContext.cpp @@ -68,7 +68,7 @@ bcos::transaction_executor::CacheExecutables& bcos::transaction_executor::getCac CacheExecutables() { constexpr static auto maxContracts = 100; - m_cachedExecutables.setMaxCapacity(sizeof(std::shared_ptr) * maxContracts); + setMaxCapacity(m_cachedExecutables, sizeof(std::shared_ptr) * maxContracts); } } static cachedExecutables; diff --git a/transaction-executor/bcos-transaction-executor/vm/HostContext.h b/transaction-executor/bcos-transaction-executor/vm/HostContext.h index cac96102b6..e932f34acf 100644 --- a/transaction-executor/bcos-transaction-executor/vm/HostContext.h +++ b/transaction-executor/bcos-transaction-executor/vm/HostContext.h @@ -365,8 +365,8 @@ class HostContext : public evmc_host_context << " recipient:" << address2HexString(ref.recipient) << " gas:" << ref.gas; } - auto savepoint = m_rollbackableStorage.get().current(); - auto transientSavepoint = m_rollbackableTransientStorage.get().current(); + auto savepoint = current(m_rollbackableStorage.get()); + auto transientSavepoint = current(m_rollbackableTransientStorage.get()); std::optional evmResult; if (m_ledgerConfig.get().authCheckStatus() != 0U) { @@ -437,8 +437,8 @@ class HostContext : public evmc_host_context // If the call to system contract failed, the gasUsed is cleared to zero if (evmResult->status_code != EVMC_SUCCESS) { - co_await m_rollbackableStorage.get().rollback(savepoint); - co_await m_rollbackableTransientStorage.get().rollback(transientSavepoint); + co_await rollback(m_rollbackableStorage.get(), savepoint); + co_await rollback(m_rollbackableTransientStorage.get(), transientSavepoint); if (auto hexAddress = address2FixedArray(ref.code_address); bcos::precompiled::c_systemTxsAddress.find(concepts::bytebuffer::toView( diff --git a/transaction-executor/tests/CMakeLists.txt b/transaction-executor/tests/CMakeLists.txt index 9bca2080b2..234f27ef1b 100644 --- a/transaction-executor/tests/CMakeLists.txt +++ b/transaction-executor/tests/CMakeLists.txt @@ -1,8 +1,9 @@ file(GLOB_RECURSE SOURCES "*.cpp") - add_executable(test-transaction-executor ${SOURCES}) find_package(Boost REQUIRED serialization unit_test_framework) target_link_libraries(test-transaction-executor transaction-executor ${LEDGER_TARGET} ${TARS_PROTOCOL_TARGET} bcos-framework evmone Boost::unit_test_framework) +set_source_files_properties("main.cpp" PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON) +set_target_properties(test-transaction-executor PROPERTIES UNITY_BUILD "ON") add_test(NAME test-transaction-executor WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} COMMAND test-transaction-executor) \ No newline at end of file diff --git a/transaction-executor/tests/TestHostContext.cpp b/transaction-executor/tests/TestHostContext.cpp index 792f38e326..18b057031c 100644 --- a/transaction-executor/tests/TestHostContext.cpp +++ b/transaction-executor/tests/TestHostContext.cpp @@ -152,8 +152,6 @@ class TestHostContextFixture } }; -bcos::crypto::Hash::Ptr bcos::executor::GlobalHashImpl::g_hashImpl; - BOOST_FIXTURE_TEST_SUITE(TestHostContext, TestHostContextFixture) BOOST_AUTO_TEST_CASE(bits) diff --git a/transaction-executor/tests/TestRollbackableStorage.cpp b/transaction-executor/tests/TestRollbackableStorage.cpp index eb9237d6c7..ab731d1bf7 100644 --- a/transaction-executor/tests/TestRollbackableStorage.cpp +++ b/transaction-executor/tests/TestRollbackableStorage.cpp @@ -32,7 +32,7 @@ BOOST_AUTO_TEST_CASE(addRollback) co_await storage2::readSome(memoryStorage, view, storage2::DIRECT); std::string_view tableID = "table1"; - auto point = rollbackableStorage.current(); + auto point = current(rollbackableStorage); storage::Entry entry; entry.set("OK!"); co_await storage2::writeOne(rollbackableStorage, StateKey{tableID, "Key1"sv}, entry); @@ -52,7 +52,7 @@ BOOST_AUTO_TEST_CASE(addRollback) ++count; } BOOST_CHECK_EQUAL(count, 2); - co_await rollbackableStorage.rollback(point); + co_await rollback(rollbackableStorage, point); // Query again std::vector keys2{StateKey{tableID, "Key1"sv}, StateKey{"table1"sv, "Key2"sv}}; @@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE(addRollback) co_await storage2::writeOne( rollbackableStorage, StateKey{tableID, "Key1"sv}, storage::Entry{"OK!"}); - auto savepoint2 = rollbackableStorage.current(); + auto savepoint2 = current(rollbackableStorage); co_await storage2::writeOne( rollbackableStorage, StateKey{tableID, "Key1"s}, storage::Entry{"OK3!"}); auto value3 = @@ -74,7 +74,7 @@ BOOST_AUTO_TEST_CASE(addRollback) BOOST_CHECK(value3); BOOST_CHECK_EQUAL(value3->get(), "OK3!"); - co_await rollbackableStorage.rollback(savepoint2); + co_await rollback(rollbackableStorage, savepoint2); auto value4 = co_await storage2::readOne(rollbackableStorage, StateKeyView{tableID, "Key1"sv}); BOOST_CHECK(value4); @@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE(removeRollback) Rollbackable rollbackableStorage(memoryStorage); std::string_view tableID = "table1"; - auto point = rollbackableStorage.current(); + auto point = current(rollbackableStorage); storage::Entry entry; entry.set("OK!"); co_await storage2::writeOne(rollbackableStorage, StateKey{tableID, "Key1"sv}, entry); @@ -111,7 +111,7 @@ BOOST_AUTO_TEST_CASE(removeRollback) BOOST_CHECK_EQUAL(key, StateKey(tableID, "Key" + std::to_string(count + 1))); ++count; } - co_await rollbackableStorage.rollback(point); + co_await rollback(rollbackableStorage, point); // Query again std::vector keys2{StateKey{tableID, "Key1"sv}, StateKey{"table1"sv, "Key2"sv}}; diff --git a/transaction-executor/tests/TestTransactionExecutor.cpp b/transaction-executor/tests/TestTransactionExecutor.cpp index b4f3593875..3f82b4d7e3 100644 --- a/transaction-executor/tests/TestTransactionExecutor.cpp +++ b/transaction-executor/tests/TestTransactionExecutor.cpp @@ -15,10 +15,6 @@ using namespace bcos::transaction_executor; class TestTransactionExecutorImplFixture { public: - TestTransactionExecutorImplFixture() - { - bcos::executor::GlobalHashImpl::g_hashImpl = std::make_shared(); - } ledger::LedgerConfig ledgerConfig; }; diff --git a/transaction-scheduler/CMakeLists.txt b/transaction-scheduler/CMakeLists.txt index e6eac776c0..e71ca32725 100644 --- a/transaction-scheduler/CMakeLists.txt +++ b/transaction-scheduler/CMakeLists.txt @@ -7,6 +7,7 @@ target_include_directories(transaction-scheduler PUBLIC $ $) target_link_libraries(transaction-scheduler PUBLIC bcos-framework fmt::fmt-header-only) +set_target_properties(transaction-scheduler PROPERTIES UNITY_BUILD "ON") if (TESTS) enable_testing() diff --git a/transaction-scheduler/bcos-transaction-scheduler/BaselineScheduler.h b/transaction-scheduler/bcos-transaction-scheduler/BaselineScheduler.h index 2dc0b69748..0114710f2d 100644 --- a/transaction-scheduler/bcos-transaction-scheduler/BaselineScheduler.h +++ b/transaction-scheduler/bcos-transaction-scheduler/BaselineScheduler.h @@ -310,8 +310,8 @@ class BaselineScheduler : public scheduler::SchedulerInterface } auto now = current(); - auto view = scheduler.m_multiLayerStorage.get().fork(); - view.newMutable(); + auto view = fork(scheduler.m_multiLayerStorage.get()); + newMutable(view); auto transactions = co_await getTransactions(scheduler.m_txpool.get(), *block); ledger::LedgerConfig::Ptr ledgerConfig; @@ -329,7 +329,7 @@ class BaselineScheduler : public scheduler::SchedulerInterface auto executedBlockHeader = scheduler.m_blockHeaderFactory.get().populateBlockHeader(blockHeader); bool sysBlock = false; - finishExecute(view.mutableStorage(), receipts, *executedBlockHeader, *block, + finishExecute(mutableStorage(view), receipts, *executedBlockHeader, *block, transactions, sysBlock, scheduler.m_hashImpl.get()); if (verify && (executedBlockHeader->hash() != blockHeader->hash())) @@ -359,7 +359,7 @@ class BaselineScheduler : public scheduler::SchedulerInterface nullptr, false); } - scheduler.m_multiLayerStorage.get().pushView(std::move(view)); + pushView(scheduler.m_multiLayerStorage.get(), std::move(view)); scheduler.m_lastExecutedBlockNumber = blockHeader->number(); std::unique_lock resultsLock(scheduler.m_resultsMutex); @@ -448,7 +448,7 @@ class BaselineScheduler : public scheduler::SchedulerInterface resultsLock.unlock(); result.m_block->setBlockHeader(header); - auto lastStorage = scheduler.m_multiLayerStorage.get().backStorage(); + auto lastStorage = backStorage(scheduler.m_multiLayerStorage.get()); if (result.m_block->blockHeaderConst()->number() != 0) { ittapi::Report report(ittapi::ITT_DOMAINS::instance().BASE_SCHEDULER, @@ -457,7 +457,7 @@ class BaselineScheduler : public scheduler::SchedulerInterface co_await ledger::prewriteBlock(scheduler.m_ledger.get(), result.m_transactions, result.m_block, false, *lastStorage); } - auto mergedStorage = co_await scheduler.m_multiLayerStorage.get().mergeBackStorage(); + auto mergedStorage = co_await mergeBackStorage(scheduler.m_multiLayerStorage.get()); co_await ledger::storeTransactionsAndReceipts( scheduler.m_ledger.get(), result.m_transactions, result.m_block); @@ -578,8 +578,8 @@ class BaselineScheduler : public scheduler::SchedulerInterface { task::wait([](decltype(this) self, protocol::Transaction::Ptr transaction, decltype(callback) callback) -> task::Task { - auto view = self->m_multiLayerStorage.get().fork(); - view.newMutable(); + auto view = fork(self->m_multiLayerStorage.get()); + newMutable(view); auto blockHeader = self->m_blockHeaderFactory.get().createBlockHeader(); ledger::LedgerConfig::Ptr ledgerConfig; { @@ -619,7 +619,7 @@ class BaselineScheduler : public scheduler::SchedulerInterface { task::wait([](decltype(this) self, std::string_view contract, decltype(callback) callback) -> task::Task { - auto view = self->m_multiLayerStorage.get().fork(); + auto view = fork(self->m_multiLayerStorage.get()); auto contractAddress = unhexAddress(contract); ledger::account::EVMAccount account(view, contractAddress); auto code = co_await ledger::account::code(account); @@ -639,7 +639,7 @@ class BaselineScheduler : public scheduler::SchedulerInterface { task::wait([](decltype(this) self, std::string_view contract, decltype(callback) callback) -> task::Task { - auto view = self->m_multiLayerStorage.get().fork(); + auto view = fork(self->m_multiLayerStorage.get()); auto contractAddress = unhexAddress(contract); ledger::account::EVMAccount account(view, contractAddress); auto abi = co_await ledger::account::abi(account); diff --git a/transaction-scheduler/bcos-transaction-scheduler/MultiLayerStorage.h b/transaction-scheduler/bcos-transaction-scheduler/MultiLayerStorage.h index f0a2b8d4cb..4446c0665d 100644 --- a/transaction-scheduler/bcos-transaction-scheduler/MultiLayerStorage.h +++ b/transaction-scheduler/bcos-transaction-scheduler/MultiLayerStorage.h @@ -22,15 +22,51 @@ struct NotExistsImmutableStorageError : public bcos::Error {}; struct UnsupportedMethod : public bcos::Error {}; // clang-format on -template +template +task::Task fillMissingValues( + auto& storage, RANGES::input_range auto&& keys, RANGES::input_range auto& values) +{ + using StoreKeyType = + std::conditional_t>, + std::reference_wrapper, KeyType>; + + std::vector>>> + missingKeyValues; + for (auto&& [key, value] : RANGES::views::zip(std::forward(keys), values)) + { + if (!value) + { + missingKeyValues.emplace_back(std::forward(key), std::ref(value)); + } + } + auto gotValues = co_await storage2::readSome(storage, missingKeyValues | RANGES::views::keys); + + size_t count = 0; + for (auto&& [from, to] : + RANGES::views::zip(gotValues, missingKeyValues | RANGES::views::values)) + { + if (from) + { + to.get() = std::move(from); + ++count; + } + } + + co_return count == RANGES::size(gotValues); +} + +template requires((std::is_void_v || (!std::is_void_v))) class View { public: + constexpr static bool isView = true; + constexpr static bool withCacheStorage = !std::is_void_v; - using KeyType = std::remove_cvref_t; - using ValueType = std::remove_cvref_t; + using Key = std::remove_cvref_t; + using Value = std::remove_cvref_t; using MutableStorage = MutableStorageType; + using BackendStorage = BackendStorageType; std::shared_ptr m_mutableStorage; std::deque> m_immutableStorages; @@ -51,349 +87,334 @@ class View : m_backendStorage(backendStorage), m_cacheStorage(cacheStorage) {} - static task::Task fillMissingValues( - auto& storage, RANGES::input_range auto&& keys, RANGES::input_range auto& values) - { - using StoreKeyType = - std::conditional_t>, - std::reference_wrapper, KeyType>; - - std::vector>>> - missingKeyValues; - for (auto&& [key, value] : RANGES::views::zip(std::forward(keys), values)) - { - if (!value) - { - missingKeyValues.emplace_back(std::forward(key), std::ref(value)); - } - } - auto gotValues = - co_await storage2::readSome(storage, missingKeyValues | RANGES::views::keys); + View(const View&) = delete; + View& operator=(const View&) = delete; + View(View&&) noexcept = default; + View& operator=(View&&) noexcept = default; + ~View() noexcept = default; +}; - size_t count = 0; - for (auto&& [from, to] : - RANGES::views::zip(gotValues, missingKeyValues | RANGES::views::values)) - { - if (from) - { - to.get() = std::move(from); - ++count; - } - } +template +concept IsView = std::remove_cvref_t::isView; - co_return count == RANGES::size(gotValues); +template +typename View::MutableStorage& mutableStorage(View& storage) +{ + if (!storage.m_mutableStorage) + { + BOOST_THROW_EXCEPTION(NotExistsMutableStorageError{}); + } + return *storage.m_mutableStorage; +} + +template +auto tag_invoke( + storage2::tag_t /*unused*/, View& view, RANGES::input_range auto&& keys) + -> task::Task>> + requires RANGES::sized_range && + RANGES::sized_range>> +{ + task::AwaitableReturnType values( + RANGES::size(keys)); + if (view.m_mutableStorage && + co_await fillMissingValues( + *view.m_mutableStorage, keys, values)) + { + co_return values; + } + else + { + values.resize(RANGES::size(keys)); } - friend auto tag_invoke( - storage2::tag_t /*unused*/, View& view, RANGES::input_range auto&& keys) - -> task::Task>> - requires RANGES::sized_range && - RANGES::sized_range>> + for (auto& immutableStorage : view.m_immutableStorages) { - task::AwaitableReturnType - values(RANGES::size(keys)); - if (view.m_mutableStorage && - co_await fillMissingValues(*view.m_mutableStorage, keys, values)) + if (co_await fillMissingValues( + *immutableStorage, keys, values)) { co_return values; } - else - { - values.resize(RANGES::size(keys)); - } - - for (auto& immutableStorage : view.m_immutableStorages) - { - if (co_await fillMissingValues(*immutableStorage, keys, values)) - { - co_return values; - } - } - - if constexpr (withCacheStorage) - { - if (co_await fillMissingValues(view.m_cacheStorage.get(), keys, values)) - { - co_return values; - } - } - - co_await fillMissingValues(view.m_backendStorage.get(), keys, values); - co_return values; } - friend auto tag_invoke(storage2::tag_t /*unused*/, View& view, - RANGES::input_range auto&& keys, storage2::DIRECT_TYPE /*unused*/) - -> task::Task>> + if constexpr (View::withCacheStorage) { - if (view.m_mutableStorage) + if (co_await fillMissingValues( + view.m_cacheStorage.get(), keys, values)) { - co_return co_await storage2::readSome( - *view.m_mutableStorage, std::forward(keys)); + co_return values; } + } - for (auto& immutableStorage : view.m_immutableStorages) - { - co_return co_await storage2::readSome( - *immutableStorage, std::forward(keys)); - } + co_await fillMissingValues( + view.m_backendStorage.get(), keys, values); + co_return values; +} - if constexpr (withCacheStorage) - { - co_return co_await storage2::readSome( - view.m_cacheStorage.get(), std::forward(keys)); - } +template +auto tag_invoke(storage2::tag_t /*unused*/, View& view, + RANGES::input_range auto&& keys, storage2::DIRECT_TYPE /*unused*/) + -> task::Task>> +{ + if (view.m_mutableStorage) + { + co_return co_await storage2::readSome( + *view.m_mutableStorage, std::forward(keys)); + } + for (auto& immutableStorage : view.m_immutableStorages) + { co_return co_await storage2::readSome( - view.m_backendStorage.get(), std::forward(keys)); + *immutableStorage, std::forward(keys)); } - friend auto tag_invoke(storage2::tag_t /*unused*/, View& view, auto&& key) - -> task::Task>> + if constexpr (View::withCacheStorage) { - if (view.m_mutableStorage) - { - if (auto value = co_await storage2::readOne(*view.m_mutableStorage, key)) - { - co_return value; - } - } + co_return co_await storage2::readSome( + view.m_cacheStorage.get(), std::forward(keys)); + } - for (auto& immutableStorage : view.m_immutableStorages) - { - if (auto value = co_await storage2::readOne(*immutableStorage, key)) - { - co_return value; - } - } + co_return co_await storage2::readSome( + view.m_backendStorage.get(), std::forward(keys)); +} - if constexpr (withCacheStorage) +template +auto tag_invoke(storage2::tag_t /*unused*/, View& view, auto&& key) + -> task::Task>> +{ + if (view.m_mutableStorage) + { + if (auto value = co_await storage2::readOne(*view.m_mutableStorage, key)) { - if (auto value = co_await storage2::readOne(view.m_cacheStorage.get(), key)) - { - co_return value; - } + co_return value; } - - co_return co_await storage2::readOne(view.m_backendStorage.get(), key); } - friend auto tag_invoke(storage2::tag_t /*unused*/, View& view, auto&& key, - storage2::DIRECT_TYPE /*unused*/) - -> task::Task>> + for (auto& immutableStorage : view.m_immutableStorages) { - if (view.m_mutableStorage) + if (auto value = co_await storage2::readOne(*immutableStorage, key)) { - co_return co_await storage2::readOne( - *view.m_mutableStorage, std::forward(key)); + co_return value; } + } - for (auto& immutableStorage : view.m_immutableStorages) + if constexpr (View::withCacheStorage) + { + if (auto value = co_await storage2::readOne(view.m_cacheStorage.get(), key)) { - co_return co_await storage2::readOne( - *immutableStorage, std::forward(key)); + co_return value; } + } - if constexpr (withCacheStorage) - { - co_return co_await storage2::readOne( - view.m_cacheStorage.get(), std::forward(key)); - } + co_return co_await storage2::readOne(view.m_backendStorage.get(), key); +} +template +auto tag_invoke(storage2::tag_t /*unused*/, View& view, auto&& key, + storage2::DIRECT_TYPE /*unused*/) + -> task::Task>> +{ + if (view.m_mutableStorage) + { co_return co_await storage2::readOne( - view.m_backendStorage.get(), std::forward(key)); + *view.m_mutableStorage, std::forward(key)); } - friend task::Task tag_invoke(storage2::tag_t /*unused*/, View& view, - RANGES::input_range auto&& keys, RANGES::input_range auto&& values) + for (auto& immutableStorage : view.m_immutableStorages) { - co_await storage2::writeSome(view.mutableStorage(), std::forward(keys), - std::forward(values)); + co_return co_await storage2::readOne(*immutableStorage, std::forward(key)); } - friend auto tag_invoke(storage2::tag_t /*unused*/, View& view, auto&& key, - auto&& value) -> task::Task + if constexpr (View::withCacheStorage) { - co_await storage2::writeOne(view.mutableStorage(), std::forward(key), - std::forward(value)); + co_return co_await storage2::readOne( + view.m_cacheStorage.get(), std::forward(key)); } - friend task::Task tag_invoke( - storage2::tag_t /*unused*/, View& toView, auto&& fromStorage) - { - co_await storage2::merge( - toView.mutableStorage(), std::forward(fromStorage)); - } + co_return co_await storage2::readOne( + view.m_backendStorage.get(), std::forward(key)); +} - friend task::Task tag_invoke(storage2::tag_t /*unused*/, View& view, - RANGES::input_range auto&& keys, auto&&... args) - { - co_await storage2::removeSome(view.mutableStorage(), std::forward(keys), - std::forward(args)...); - } +template +task::Task tag_invoke(storage2::tag_t /*unused*/, View& view, + RANGES::input_range auto&& keys, RANGES::input_range auto&& values) +{ + co_await storage2::writeSome(mutableStorage(view), std::forward(keys), + std::forward(values)); +} + +template +auto tag_invoke(storage2::tag_t /*unused*/, View& view, auto&& key, + auto&& value) -> task::Task +{ + co_await storage2::writeOne(mutableStorage(view), std::forward(key), + std::forward(value)); +} + +template +task::Task tag_invoke( + storage2::tag_t /*unused*/, View& toView, auto&& fromStorage) +{ + co_await storage2::merge( + mutableStorage(toView), std::forward(fromStorage)); +} + +template +task::Task tag_invoke(storage2::tag_t /*unused*/, View& view, + RANGES::input_range auto&& keys, auto&&... args) +{ + co_await storage2::removeSome(mutableStorage(view), std::forward(keys), + std::forward(args)...); +} - class Iterator +template +class Iterator +{ +private: + using StorageIterator = + std::variant>>, + task::AwaitableReturnType>>>; + using RangeValue = std::optional< + std::tuple>; + std::vector> m_iterators; + + task::Task forwardIterators(auto&& iterators) { - private: - using StorageIterator = - std::variant>>, - task::AwaitableReturnType>>>; - using RangeValue = - std::optional>; - std::vector> m_iterators; - - task::Task forwardIterators(auto&& iterators) + for (auto& it : iterators) { - for (auto& it : iterators) - { - auto& [variantIterator, item] = it; - item = co_await std::visit( - bcos::recursiveLambda( - [&](auto const& self, auto& input) -> task::Task { - RangeValue item; - auto rangeValue = co_await input.next(); - if (rangeValue) + auto& [variantIterator, item] = it; + item = co_await std::visit( + bcos::recursiveLambda([&](auto const& self, auto& input) -> task::Task { + RangeValue item; + auto rangeValue = co_await input.next(); + if (rangeValue) + { + auto&& [key, value] = *rangeValue; + if constexpr (std::is_pointer_v>) + { + if (!value) { - auto&& [key, value] = *rangeValue; - if constexpr (std::is_pointer_v>) - { - if (!value) - { - co_return co_await self(self, input); - } - item.emplace(key, *value); - } - else - { - item = std::move(rangeValue); - } + co_return co_await self(self, input); } - co_return item; - }), - variantIterator); - } + item.emplace(key, *value); + } + else + { + item = std::move(rangeValue); + } + } + co_return item; + }), + variantIterator); } + } - public: - task::Task init(View& view, auto&&... args) +public: + task::Task init(View& view, auto&&... args) + { + if (view.m_mutableStorage) { - if (view.m_mutableStorage) - { - m_iterators.emplace_back(co_await storage2::range(*view.m_mutableStorage, - std::forward(args)...), - RangeValue{}); - } - for (auto& storage : view.m_immutableStorages) - { - m_iterators.emplace_back( - co_await storage2::range(*storage, std::forward(args)...), - RangeValue{}); - } - m_iterators.emplace_back(co_await storage2::range(view.m_backendStorage.get(), + m_iterators.emplace_back(co_await storage2::range(*view.m_mutableStorage, std::forward(args)...), RangeValue{}); - co_await forwardIterators(m_iterators); } + for (auto& storage : view.m_immutableStorages) + { + m_iterators.emplace_back( + co_await storage2::range(*storage, std::forward(args)...), + RangeValue{}); + } + m_iterators.emplace_back(co_await storage2::range(view.m_backendStorage.get(), + std::forward(args)...), + RangeValue{}); + co_await forwardIterators(m_iterators); + } - task::Task next() + task::Task next() + { + // 基于合并排序,找到所有迭代器的最小值,推进迭代器并返回值 + // Based on merge sort, find the minimum value of all iterators, advance the + // iterator and return its value + auto iterators = m_iterators | RANGES::views::filter([](auto const& rangeValue) { + return std::get<1>(rangeValue).has_value(); + }); + if (RANGES::empty(iterators)) { - // 基于合并排序,找到所有迭代器的最小值,推进迭代器并返回值 - // Based on merge sort, find the minimum value of all iterators, advance the - // iterator and return its value - auto iterators = m_iterators | RANGES::views::filter([](auto const& rangeValue) { - return std::get<1>(rangeValue).has_value(); - }); - if (RANGES::empty(iterators)) + co_return std::nullopt; + } + + std::vector*> minIterators; + for (auto& it : iterators) + { + if (minIterators.empty()) { - co_return std::nullopt; + minIterators.emplace_back(std::addressof(it)); } - - std::vector*> minIterators; - for (auto& it : iterators) + else { - if (minIterators.empty()) + auto& [variantIterator, value] = it; + auto& key = std::get<0>(*value); + auto& existsKey = std::get<0>(*std::get<1>(*minIterators[0])); + + if (key < existsKey) { + minIterators.clear(); minIterators.emplace_back(std::addressof(it)); } - else + else if (key == existsKey) { - auto& [variantIterator, value] = it; - auto& key = std::get<0>(*value); - auto& existsKey = std::get<0>(*std::get<1>(*minIterators[0])); - - if (key < existsKey) - { - minIterators.clear(); - minIterators.emplace_back(std::addressof(it)); - } - else if (key == existsKey) - { - minIterators.emplace_back(std::addressof(it)); - } + minIterators.emplace_back(std::addressof(it)); } } + } - RangeValue result = std::get<1>(*minIterators[0]); - co_await forwardIterators( - minIterators | - RANGES::views::transform([](auto* iterator) -> auto& { return *iterator; })); - co_return result; - }; + RangeValue result = std::get<1>(*minIterators[0]); + co_await forwardIterators( + minIterators | + RANGES::views::transform([](auto* iterator) -> auto& { return *iterator; })); + co_return result; }; +}; - friend task::Task tag_invoke( - bcos::storage2::tag_t /*unused*/, View& view, auto&&... args) - { - Iterator iterator; - co_await iterator.init(view, std::forward(args)...); - co_return iterator; - } +template +task::Task> tag_invoke( + bcos::storage2::tag_t /*unused*/, View& view, auto&&... args) +{ + Iterator iterator; + co_await iterator.init(view, std::forward(args)...); + co_return iterator; +} - MutableStorageType& mutableStorage() +template +void newMutable(View& storage, Args&&... args) +{ + if (storage.m_mutableStorage) { - if (!m_mutableStorage) - { - BOOST_THROW_EXCEPTION(NotExistsMutableStorageError{}); - } - return *m_mutableStorage; + BOOST_THROW_EXCEPTION(DuplicateMutableStorageError{}); } - View(const View&) = delete; - View& operator=(const View&) = delete; - View(View&&) noexcept = default; - View& operator=(View&&) noexcept = default; - ~View() noexcept = default; - - using Key = KeyType; - using Value = ValueType; - - template - void newMutable(Args&&... args) - { - if (m_mutableStorage) - { - BOOST_THROW_EXCEPTION(DuplicateMutableStorageError{}); - } + storage.m_mutableStorage = + std::make_shared(std::forward(args)...); +} - m_mutableStorage = - std::make_shared(std::forward(args)...); - } - - BackendStorage& backendStorage() & { return m_backendStorage; } -}; +template +typename View::BackendStorage& backendStorage(View& storage) +{ + return storage.m_backendStorage; +} template requires((std::is_void_v || (!std::is_void_v))) class MultiLayerStorage { -private: +public: + constexpr static bool isMultiLayerStorage = true; constexpr static bool withCacheStorage = !std::is_void_v; using KeyType = std::remove_cvref_t; using ValueType = std::remove_cvref_t; @@ -408,7 +429,6 @@ class MultiLayerStorage std::reference_wrapper>, std::monostate> m_cacheStorage; -public: using MutableStorage = MutableStorageType; using Key = KeyType; @@ -439,87 +459,103 @@ class MultiLayerStorage MultiLayerStorage& operator=(const MultiLayerStorage&) = delete; MultiLayerStorage& operator=(MultiLayerStorage&&) noexcept = default; ~MultiLayerStorage() noexcept = default; +}; + +template +concept IsMultiLayerStorage = std::remove_cvref_t::isMultiLayerStorage; - ViewType fork() +template +typename MultiLayerStorage::ViewType fork(MultiLayerStorage& storage) +{ + std::unique_lock lock(storage.m_listMutex); + if constexpr (MultiLayerStorage::withCacheStorage) { - std::unique_lock lock(m_listMutex); - if constexpr (withCacheStorage) - { - ViewType view(m_backendStorage, m_cacheStorage); - view.m_immutableStorages = m_storages; - return view; - } - else - { - ViewType view(m_backendStorage); - view.m_immutableStorages = m_storages; - return view; - } + typename MultiLayerStorage::ViewType view(storage.m_backendStorage, storage.m_cacheStorage); + view.m_immutableStorages = storage.m_storages; + return view; + } + else + { + typename MultiLayerStorage::ViewType view(storage.m_backendStorage); + view.m_immutableStorages = storage.m_storages; + return view; } +} - void pushView(ViewType&& view) +template +void pushView(MultiLayerStorage& storage, typename MultiLayerStorage::ViewType&& view) +{ + if (!view.m_mutableStorage) { - if (!view.m_mutableStorage) - { - return; - } - std::unique_lock lock(m_listMutex); - m_storages.push_front(std::move(view.m_mutableStorage)); + return; } + std::unique_lock lock(storage.m_listMutex); + storage.m_storages.push_front(std::move(view.m_mutableStorage)); +} - task::Task> mergeBackStorage() +template +task::Task> mergeBackStorage( + MultiLayerStorage& storage) +{ + std::unique_lock mergeLock(storage.m_mergeMutex); + std::unique_lock listLock(storage.m_listMutex); + if (storage.m_storages.empty()) { - std::unique_lock mergeLock(m_mergeMutex); - std::unique_lock listLock(m_listMutex); - if (m_storages.empty()) - { - BOOST_THROW_EXCEPTION(NotExistsImmutableStorageError{}); - } - auto backStoragePtr = m_storages.back(); - auto const& backStorage = *backStoragePtr; - listLock.unlock(); + BOOST_THROW_EXCEPTION(NotExistsImmutableStorageError{}); + } + auto backStoragePtr = storage.m_storages.back(); + auto const& backStorage = *backStoragePtr; + listLock.unlock(); - if constexpr (withCacheStorage) - { - tbb::parallel_invoke( - [&]() { - task::tbb::syncWait(storage2::merge(m_backendStorage.get(), backStorage)); - }, - [&]() { task::tbb::syncWait(storage2::merge(m_cacheStorage.get(), backStorage)); }); - } - else - { - co_await storage2::merge(m_backendStorage.get(), backStorage); - } + if constexpr (MultiLayerStorage::withCacheStorage) + { + tbb::parallel_invoke( + [&]() { + task::tbb::syncWait(storage2::merge(storage.m_backendStorage.get(), backStorage)); + }, + [&]() { + task::tbb::syncWait(storage2::merge(storage.m_cacheStorage.get(), backStorage)); + }); + } + else + { + co_await storage2::merge(storage.m_backendStorage.get(), backStorage); + } - listLock.lock(); - m_storages.pop_back(); + listLock.lock(); + storage.m_storages.pop_back(); - co_return backStoragePtr; - } + co_return backStoragePtr; +} - std::shared_ptr frontStorage() +template +std::shared_ptr frontStorage(MultiLayerStorage& storage) +{ + std::unique_lock immutablesLock(storage.m_listMutex); + if (storage.m_storages.empty()) { - std::unique_lock immutablesLock(m_listMutex); - if (m_storages.empty()) - { - BOOST_THROW_EXCEPTION(NotExistsImmutableStorageError{}); - } - - return m_storages.front(); + BOOST_THROW_EXCEPTION(NotExistsImmutableStorageError{}); } - std::shared_ptr backStorage() - { - std::unique_lock immutablesLock(m_listMutex); - if (m_storages.empty()) - { - BOOST_THROW_EXCEPTION(NotExistsImmutableStorageError{}); - } - return m_storages.back(); + return storage.m_storages.front(); +} + +template +std::shared_ptr backStorage(MultiLayerStorage& storage) +{ + std::unique_lock immutablesLock(storage.m_listMutex); + if (storage.m_storages.empty()) + { + BOOST_THROW_EXCEPTION(NotExistsImmutableStorageError{}); } - BackendStorage& backendStorage() { return m_backendStorage; } -}; + return storage.m_storages.back(); +} + +template +typename MultiLayerStorage::BackendStorage& backendStorage(MultiLayerStorage& storage) +{ + return storage.m_backendStorage; +} } // namespace bcos::transaction_scheduler diff --git a/transaction-scheduler/bcos-transaction-scheduler/ReadWriteSetStorage.h b/transaction-scheduler/bcos-transaction-scheduler/ReadWriteSetStorage.h index d0b2c1825d..2552353bfd 100644 --- a/transaction-scheduler/bcos-transaction-scheduler/ReadWriteSetStorage.h +++ b/transaction-scheduler/bcos-transaction-scheduler/ReadWriteSetStorage.h @@ -9,7 +9,8 @@ namespace bcos::transaction_scheduler template class ReadWriteSetStorage { -private: +public: + constexpr static bool isReadWriteSetStorage = true; std::reference_wrapper> m_storage; struct ReadWriteFlag { @@ -18,142 +19,164 @@ class ReadWriteSetStorage }; std::unordered_map m_readWriteSet; - void putSet(bool write, auto const& key) - { - auto hash = std::hash{}(key); - putSet(write, hash); - } + using Key = KeyType; + using Value = typename task::AwaitableReturnType()))>::value_type; + using BackendStorage = Storage; - void putSet(bool write, size_t hash) - { - auto [it, inserted] = - m_readWriteSet.try_emplace(hash, ReadWriteFlag{.read = !write, .write = write}); - if (!inserted) - { - it->second.write |= write; - it->second.read |= (!write); - } - } + ReadWriteSetStorage(Storage& storage) : m_storage(std::ref(storage)) {} +}; -public: - friend auto tag_invoke(storage2::tag_t /*unused*/, - ReadWriteSetStorage& storage, RANGES::input_range auto&& keys) - -> task::Task>> - { - for (auto&& key : keys) - { - storage.putSet(false, std::forward(key)); - } - co_return co_await storage2::readSome( - storage.m_storage.get(), std::forward(keys)); - } +template +concept IsReadWriteSetStorage = std::remove_cvref_t::isReadWriteSetStorage; - friend auto tag_invoke(storage2::tag_t /*unused*/, - ReadWriteSetStorage& storage, RANGES::input_range auto&& keys, storage2::DIRECT_TYPE direct) - -> task::Task>> +template +void putSet(ReadWriteSetStorage& storage, bool write, size_t hash) +{ + auto [it, inserted] = storage.m_readWriteSet.try_emplace( + hash, typename ReadWriteSetStorage::ReadWriteFlag{.read = !write, .write = write}); + if (!inserted) { - co_return co_await storage2::readSome( - storage.m_storage.get(), std::forward(keys), direct); + it->second.write |= write; + it->second.read |= (!write); } +} - friend auto tag_invoke( - storage2::tag_t /*unused*/, ReadWriteSetStorage& storage, auto&& key) - -> task::Task>> +template +void putSet(ReadWriteSetStorage& storage, bool write, auto const& key) +{ + auto hash = std::hash{}(key); + putSet(storage, write, hash); +} + +template +auto tag_invoke(storage2::tag_t /*unused*/, ReadWriteSetStorage& storage, + RANGES::input_range auto&& keys) + -> task::Task>> +{ + for (auto&& key : keys) { - storage.putSet(false, key); - co_return co_await storage2::readOne( - storage.m_storage.get(), std::forward(key)); + putSet(storage, false, std::forward(key)); } - - friend auto tag_invoke(storage2::tag_t /*unused*/, - ReadWriteSetStorage& storage, auto&& key, storage2::DIRECT_TYPE direct) - -> task::Task>> + co_return co_await storage2::readSome( + storage.m_storage.get(), std::forward(keys)); +} + +template +auto tag_invoke(storage2::tag_t /*unused*/, ReadWriteSetStorage& storage, + RANGES::input_range auto&& keys, storage2::DIRECT_TYPE direct) + -> task::Task>> +{ + co_return co_await storage2::readSome( + storage.m_storage.get(), std::forward(keys), direct); +} + +template +auto tag_invoke(storage2::tag_t /*unused*/, ReadWriteSetStorage& storage, + auto&& key) -> task::Task>> +{ + putSet(storage, false, key); + co_return co_await storage2::readOne(storage.m_storage.get(), std::forward(key)); +} + +template +auto tag_invoke(storage2::tag_t /*unused*/, ReadWriteSetStorage& storage, + auto&& key, storage2::DIRECT_TYPE direct) + -> task::Task>> +{ + co_return co_await storage2::readOne( + storage.m_storage.get(), std::forward(key), direct); +} + +template +auto tag_invoke(storage2::tag_t /*unused*/, ReadWriteSetStorage& storage, + RANGES::input_range auto&& keys, RANGES::input_range auto&& values) + -> task::Task>> +{ + for (auto&& key : keys) { - co_return co_await storage2::readOne( - storage.m_storage.get(), std::forward(key), direct); + putSet(storage, true, key); } - - friend auto tag_invoke(storage2::tag_t /*unused*/, - ReadWriteSetStorage& storage, RANGES::input_range auto&& keys, - RANGES::input_range auto&& values) - -> task::Task>> + co_return co_await storage2::writeSome( + storage.m_storage.get(), keys, std::forward(values)); +} + +template +auto tag_invoke(storage2::tag_t /*unused*/, ReadWriteSetStorage& storage, + RANGES::input_range auto const& keys, auto&&... args) + -> task::Task, decltype(keys), + decltype(args)...>>> +{ + for (auto&& key : keys) { - for (auto&& key : keys) - { - storage.putSet(true, key); - } - co_return co_await storage2::writeSome( - storage.m_storage.get(), keys, std::forward(values)); + putSet(storage, true, key); } + co_return co_await storage2::removeSome( + storage.m_storage.get(), keys, std::forward(args)...); +} + +template +auto tag_invoke(bcos::storage2::tag_t /*unused*/, ReadWriteSetStorage& storage, + auto&&... args) -> task::Task, + decltype(args)...>>> +{ + co_return co_await storage2::range( + storage.m_storage.get(), std::forward(args)...); +} + +template +auto& readWriteSet(ReadWriteSetStorage& storage) +{ + return storage.m_readWriteSet; +} - friend auto tag_invoke(storage2::tag_t /*unused*/, - ReadWriteSetStorage& storage, RANGES::input_range auto const& keys, auto&&... args) - -> task::Task, decltype(keys), decltype(args)...>>> +template +auto const& readWriteSet(ReadWriteSetStorage const& storage) +{ + return storage.m_readWriteSet; +} + +template +void mergeWriteSet(ReadWriteSetStorage& storage, auto& inputWriteSet) +{ + auto& writeMap = readWriteSet(inputWriteSet); + for (auto& [key, flag] : writeMap) { - for (auto&& key : keys) + if (flag.write) { - storage.putSet(true, key); + putSet(storage, true, key); } - co_return co_await storage2::removeSome( - storage.m_storage.get(), keys, std::forward(args)...); } +} - friend auto tag_invoke(bcos::storage2::tag_t /*unused*/, - ReadWriteSetStorage& storage, - auto&&... args) -> task::Task, decltype(args)...>>> - { - co_return co_await storage2::range( - storage.m_storage.get(), std::forward(args)...); - } - - using Key = KeyType; - using Value = typename task::AwaitableReturnType()))>::value_type; - - ReadWriteSetStorage(Storage& storage) : m_storage(std::ref(storage)) {} +// RAW: read after write +template +bool hasRAWIntersection(ReadWriteSetStorage const& lhs, const auto& rhs) +{ + auto const& lhsSet = readWriteSet(lhs); + auto const& rhsSet = readWriteSet(rhs); - auto& readWriteSet() { return m_readWriteSet; } - auto const& readWriteSet() const { return m_readWriteSet; } - void mergeWriteSet(auto& inputWriteSet) + if (RANGES::empty(lhsSet) || RANGES::empty(rhsSet)) { - auto& writeMap = inputWriteSet.readWriteSet(); - for (auto& [key, flag] : writeMap) - { - if (flag.write) - { - putSet(true, key); - } - } + return false; } - // RAW: read after write - bool hasRAWIntersection(const auto& rhs) const + for (auto const& [key, flag] : rhsSet) { - auto const& lhsSet = m_readWriteSet; - auto const& rhsSet = rhs.readWriteSet(); - - if (RANGES::empty(lhsSet) || RANGES::empty(rhsSet)) + if (flag.read && lhsSet.contains(key)) { - return false; + return true; } - - for (auto const& [key, flag] : rhsSet) - { - if (flag.read && lhsSet.contains(key)) - { - return true; - } - } - - return false; } -}; + + return false; +} } // namespace bcos::transaction_scheduler \ No newline at end of file diff --git a/transaction-scheduler/bcos-transaction-scheduler/SchedulerParallelImpl.h b/transaction-scheduler/bcos-transaction-scheduler/SchedulerParallelImpl.h index 4d84243676..a0db91e5d3 100644 --- a/transaction-scheduler/bcos-transaction-scheduler/SchedulerParallelImpl.h +++ b/transaction-scheduler/bcos-transaction-scheduler/SchedulerParallelImpl.h @@ -75,7 +75,7 @@ class ChunkStatus m_storageView(storage), m_readWriteSetStorage(m_storageView) { - m_storageView.newMutable(); + newMutable(m_storageView); } int64_t chunkIndex() const { return m_chunkIndex; } @@ -140,206 +140,207 @@ class ChunkStatus } }; -template +template class SchedulerParallelImpl { -private: +public: + constexpr static bool isSchedulerParallelImpl = true; + using MutableStorage = MutableStorageType; + constexpr static auto DEFAULT_TRANSACTION_GRAIN_SIZE = 16L; GC m_gc; size_t m_grainSize = DEFAULT_TRANSACTION_GRAIN_SIZE; +}; - friend task::Task mergeLastStorage( - SchedulerParallelImpl& scheduler, auto& storage, auto&& lastStorage) - { - ittapi::Report mergeReport(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, - ittapi::ITT_DOMAINS::instance().MERGE_LAST_CHUNK); - PARALLEL_SCHEDULER_LOG(DEBUG) << "Final merge lastStorage"; - co_await storage2::merge(storage, std::forward(lastStorage)); - } +template +concept IsSchedulerParallelImpl = Scheduler::isSchedulerParallelImpl; - friend size_t executeSinglePass(SchedulerParallelImpl& scheduler, auto& storage, auto& executor, - protocol::BlockHeader const& blockHeader, ledger::LedgerConfig const& ledgerConfig, - RANGES::random_access_range auto& contexts, size_t chunkSize) - { - ittapi::Report report(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, - ittapi::ITT_DOMAINS::instance().SINGLE_PASS); - - const auto count = RANGES::size(contexts); - ReadWriteSetStorage writeSet(storage); - - using Chunk = ChunkStatus, - std::decay_t, - decltype(RANGES::subrange>(contexts))>; - - boost::atomic_flag hasRAW; - MutableStorage lastStorage; - auto contextChunks = RANGES::views::chunk(contexts, chunkSize); - - std::atomic_size_t offset = 0; - std::atomic_size_t chunkIndex = 0; - - tbb::task_group_context context; - // 五级流水线:分片准备、并行执行、检测RAW冲突&合并读写集、生成回执、合并storage - // Five-stage pipeline: shard preparation, parallel execution, detection of RAW - // conflicts & merging read/write sets, generating receipts, and merging storage - tbb::parallel_pipeline(tbb::this_task_arena::max_concurrency(), - tbb::make_filter>(tbb::filter_mode::serial_in_order, - [&](tbb::flow_control& control) -> std::unique_ptr { - if (chunkIndex >= RANGES::size(contextChunks) || hasRAW.test()) +template +task::Task mergeLastStorage( + SchedulerParallelImpl& scheduler, auto& storage, auto&& lastStorage) +{ + ittapi::Report mergeReport(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, + ittapi::ITT_DOMAINS::instance().MERGE_LAST_CHUNK); + PARALLEL_SCHEDULER_LOG(DEBUG) << "Final merge lastStorage"; + co_await storage2::merge(storage, std::forward(lastStorage)); +} + +template +size_t executeSinglePass(SchedulerParallelImpl& scheduler, auto& storage, auto& executor, + protocol::BlockHeader const& blockHeader, ledger::LedgerConfig const& ledgerConfig, + RANGES::random_access_range auto& contexts, size_t chunkSize) +{ + ittapi::Report report(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, + ittapi::ITT_DOMAINS::instance().SINGLE_PASS); + + const auto count = RANGES::size(contexts); + ReadWriteSetStorage writeSet(storage); + + using Chunk = ChunkStatus, std::decay_t, + decltype(RANGES::subrange>(contexts))>; + + boost::atomic_flag hasRAW; + typename SchedulerParallelImpl::MutableStorage lastStorage; + auto contextChunks = RANGES::views::chunk(contexts, chunkSize); + + std::atomic_size_t offset = 0; + std::atomic_size_t chunkIndex = 0; + + tbb::task_group_context context; + // 五级流水线:分片准备、并行执行、检测RAW冲突&合并读写集、生成回执、合并storage + // Five-stage pipeline: shard preparation, parallel execution, detection of RAW + // conflicts & merging read/write sets, generating receipts, and merging storage + tbb::parallel_pipeline(tbb::this_task_arena::max_concurrency(), + tbb::make_filter>(tbb::filter_mode::serial_in_order, + [&](tbb::flow_control& control) -> std::unique_ptr { + if (chunkIndex >= RANGES::size(contextChunks) || hasRAW.test()) + { + control.stop(); + return {}; + } + + ittapi::Report report(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, + ittapi::ITT_DOMAINS::instance().STAGE_1); + PARALLEL_SCHEDULER_LOG(DEBUG) << "Chunk: " << chunkIndex; + auto chunk = std::make_unique( + chunkIndex, hasRAW, contextChunks[chunkIndex], executor, storage); + ++chunkIndex; + return chunk; + }) & + tbb::make_filter, std::unique_ptr>( + tbb::filter_mode::parallel, + [&](std::unique_ptr chunk) -> std::unique_ptr { + ittapi::Report report(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, + ittapi::ITT_DOMAINS::instance().STAGE_2); + if (chunk && !hasRAW.test()) { - control.stop(); - return {}; + chunk->executeStep1(blockHeader, ledgerConfig); + chunk->executeStep2(); } - ittapi::Report report(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, - ittapi::ITT_DOMAINS::instance().STAGE_1); - PARALLEL_SCHEDULER_LOG(DEBUG) << "Chunk: " << chunkIndex; - auto chunk = std::make_unique( - chunkIndex, hasRAW, contextChunks[chunkIndex], executor, storage); - ++chunkIndex; return chunk; }) & - tbb::make_filter, std::unique_ptr>( - tbb::filter_mode::parallel, - [&](std::unique_ptr chunk) -> std::unique_ptr { - ittapi::Report report(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, - ittapi::ITT_DOMAINS::instance().STAGE_2); - if (chunk && !hasRAW.test()) - { - chunk->executeStep1(blockHeader, ledgerConfig); - chunk->executeStep2(); - } + tbb::make_filter, std::unique_ptr>( + tbb::filter_mode::serial_in_order, + [&](std::unique_ptr chunk) -> std::unique_ptr { + ittapi::Report report1(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, + ittapi::ITT_DOMAINS::instance().STAGE_3); + if (hasRAW.test()) + { + scheduler.m_gc.collect(std::move(chunk)); + return {}; + } - return chunk; - }) & - tbb::make_filter, std::unique_ptr>( - tbb::filter_mode::serial_in_order, - [&](std::unique_ptr chunk) -> std::unique_ptr { - ittapi::Report report1(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, - ittapi::ITT_DOMAINS::instance().STAGE_3); - if (hasRAW.test()) + auto index = chunk->chunkIndex(); + if (index > 0) + { + ittapi::Report report2(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, + ittapi::ITT_DOMAINS::instance().DETECT_RAW); + if (hasRAWIntersection(writeSet, chunk->readWriteSetStorage())) { + hasRAW.test_and_set(); + PARALLEL_SCHEDULER_LOG(DEBUG) << "Detected RAW Intersection:" << index; scheduler.m_gc.collect(std::move(chunk)); return {}; } + } - auto index = chunk->chunkIndex(); - if (index > 0) - { - ittapi::Report report2( - ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, - ittapi::ITT_DOMAINS::instance().DETECT_RAW); - if (writeSet.hasRAWIntersection(chunk->readWriteSetStorage())) - { - hasRAW.test_and_set(); - PARALLEL_SCHEDULER_LOG(DEBUG) - << "Detected RAW Intersection:" << index; - scheduler.m_gc.collect(std::move(chunk)); - return {}; - } - } + PARALLEL_SCHEDULER_LOG(DEBUG) + << "Merging rwset... " << index << " | " << chunk->count(); + ittapi::Report report3(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, + ittapi::ITT_DOMAINS::instance().MERGE_RWSET); + mergeWriteSet(writeSet, chunk->readWriteSetStorage()); + return chunk; + }) & + tbb::make_filter, std::unique_ptr>( + tbb::filter_mode::parallel, + [&](std::unique_ptr chunk) -> std::unique_ptr { + ittapi::Report report(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, + ittapi::ITT_DOMAINS::instance().STAGE_4); + if (chunk) + { + chunk->executeStep3(); + } + return chunk; + }) & + tbb::make_filter, void>(tbb::filter_mode::serial_in_order, + [&](std::unique_ptr chunk) { + if (chunk) + { + ittapi::Report report1(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, + ittapi::ITT_DOMAINS::instance().STAGE_5); + offset += (size_t)chunk->count(); + ittapi::Report report2(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, + ittapi::ITT_DOMAINS::instance().MERGE_CHUNK); PARALLEL_SCHEDULER_LOG(DEBUG) - << "Merging rwset... " << index << " | " << chunk->count(); - ittapi::Report report3(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, - ittapi::ITT_DOMAINS::instance().MERGE_RWSET); - writeSet.mergeWriteSet(chunk->readWriteSetStorage()); - return chunk; - }) & - tbb::make_filter, std::unique_ptr>( - tbb::filter_mode::parallel, - [&](std::unique_ptr chunk) -> std::unique_ptr { - ittapi::Report report(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, - ittapi::ITT_DOMAINS::instance().STAGE_4); - if (chunk) - { - chunk->executeStep3(); - } - - return chunk; - }) & - tbb::make_filter, void>(tbb::filter_mode::serial_in_order, - [&](std::unique_ptr chunk) { - if (chunk) - { - ittapi::Report report1( - ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, - ittapi::ITT_DOMAINS::instance().STAGE_5); - offset += (size_t)chunk->count(); - ittapi::Report report2( - ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, - ittapi::ITT_DOMAINS::instance().MERGE_CHUNK); - PARALLEL_SCHEDULER_LOG(DEBUG) - << "Merging storage... " << chunk->chunkIndex() << " | " - << chunk->count(); - task::tbb::syncWait(storage2::merge( - lastStorage, std::move(chunk->storageView().mutableStorage()))); - scheduler.m_gc.collect(std::move(chunk)); - } - else - { - context.cancel_group_execution(); - } - }), - context); - - task::tbb::syncWait(mergeLastStorage(scheduler, storage, std::move(lastStorage))); - scheduler.m_gc.collect(std::move(writeSet)); - if (offset < count) - { - PARALLEL_SCHEDULER_LOG(DEBUG) - << "Start new chunk executing... " << offset << " | " << RANGES::size(contexts); - auto nextView = RANGES::views::drop(contexts, offset); - return 1 + executeSinglePass(scheduler, storage, executor, blockHeader, ledgerConfig, - nextView, chunkSize); - } + << "Merging storage... " << chunk->chunkIndex() << " | " + << chunk->count(); + task::tbb::syncWait(storage2::merge( + lastStorage, std::move(mutableStorage(chunk->storageView())))); + scheduler.m_gc.collect(std::move(chunk)); + } + else + { + context.cancel_group_execution(); + } + }), + context); - return 0; + task::tbb::syncWait(mergeLastStorage(scheduler, storage, std::move(lastStorage))); + scheduler.m_gc.collect(std::move(writeSet)); + if (offset < count) + { + PARALLEL_SCHEDULER_LOG(DEBUG) + << "Start new chunk executing... " << offset << " | " << RANGES::size(contexts); + auto nextView = RANGES::views::drop(contexts, offset); + return 1 + executeSinglePass(scheduler, storage, executor, blockHeader, ledgerConfig, + nextView, chunkSize); } - friend task::Task> tag_invoke( - tag_t /*unused*/, SchedulerParallelImpl& scheduler, auto& storage, - auto& executor, protocol::BlockHeader const& blockHeader, - RANGES::random_access_range auto const& transactions, - ledger::LedgerConfig const& ledgerConfig) - { - auto count = RANGES::size(transactions); + return 0; +} - ittapi::Report report(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, - ittapi::ITT_DOMAINS::instance().PARALLEL_EXECUTE); - std::vector receipts(count); - - using Storage = std::decay_t; - using CoroType = - std::invoke_result_t::LocalReadWriteSetStorage>, - protocol::BlockHeader const&, protocol::Transaction const&, int, - ledger::LedgerConfig const&, task::tbb::SyncWait>; - std::vector, - tbb::cache_aligned_allocator>> - contexts; - contexts.reserve(RANGES::size(transactions)); - for (auto index : RANGES::views::iota(0, (int)RANGES::size(transactions))) - { - contexts.emplace_back( - ExecutionContext{index, transactions[index], receipts[index], {}, {}}); - } +template +task::Task> tag_invoke( + tag_t /*unused*/, SchedulerParallelImpl& scheduler, auto& storage, auto& executor, + protocol::BlockHeader const& blockHeader, RANGES::random_access_range auto const& transactions, + ledger::LedgerConfig const& ledgerConfig) +{ + auto count = RANGES::size(transactions); + + ittapi::Report report(ittapi::ITT_DOMAINS::instance().PARALLEL_SCHEDULER, + ittapi::ITT_DOMAINS::instance().PARALLEL_EXECUTE); + std::vector receipts(count); + + using Storage = std::decay_t; + using CoroType = std::invoke_result_t::LocalReadWriteSetStorage>, + protocol::BlockHeader const&, protocol::Transaction const&, int, + ledger::LedgerConfig const&, task::tbb::SyncWait>; + std::vector, + tbb::cache_aligned_allocator>> + contexts; + contexts.reserve(RANGES::size(transactions)); + for (auto index : RANGES::views::iota(0, (int)RANGES::size(transactions))) + { + contexts.emplace_back( + ExecutionContext{index, transactions[index], receipts[index], {}, {}}); + } - constexpr static auto DEFAULT_PARALLEL_ARENA = 8; - static tbb::task_arena arena(DEFAULT_PARALLEL_ARENA); - arena.execute([&]() { - auto retryCount = executeSinglePass(scheduler, storage, executor, blockHeader, - ledgerConfig, contexts, scheduler.m_grainSize); + constexpr static auto DEFAULT_PARALLEL_ARENA = 8; + static tbb::task_arena arena(DEFAULT_PARALLEL_ARENA); + arena.execute([&]() { + auto retryCount = executeSinglePass(scheduler, storage, executor, blockHeader, ledgerConfig, + contexts, scheduler.m_grainSize); - PARALLEL_SCHEDULER_LOG(INFO) << "Parallel execute block retry count: " << retryCount; - scheduler.m_gc.collect(std::move(contexts)); - }); + PARALLEL_SCHEDULER_LOG(INFO) << "Parallel execute block retry count: " << retryCount; + scheduler.m_gc.collect(std::move(contexts)); + }); - co_return receipts; - } + co_return receipts; +} -public: - void setGrainSize(size_t grainSize) { m_grainSize = grainSize; } -}; } // namespace bcos::transaction_scheduler \ No newline at end of file diff --git a/transaction-scheduler/bcos-transaction-scheduler/SchedulerSerialImpl.h b/transaction-scheduler/bcos-transaction-scheduler/SchedulerSerialImpl.h index 4a1947833d..4483f9a78f 100644 --- a/transaction-scheduler/bcos-transaction-scheduler/SchedulerSerialImpl.h +++ b/transaction-scheduler/bcos-transaction-scheduler/SchedulerSerialImpl.h @@ -20,104 +20,102 @@ namespace bcos::transaction_scheduler class SchedulerSerialImpl { -private: +public: constexpr static auto MIN_TRANSACTION_GRAIN_SIZE = 16; GC m_gc; +}; + +task::Task> tag_invoke( + tag_t /*unused*/, SchedulerSerialImpl& scheduler, auto& storage, auto& executor, + protocol::BlockHeader const& blockHeader, RANGES::input_range auto const& transactions, + ledger::LedgerConfig const& ledgerConfig) +{ + ittapi::Report report(ittapi::ITT_DOMAINS::instance().SERIAL_SCHEDULER, + ittapi::ITT_DOMAINS::instance().SERIAL_EXECUTE); - friend task::Task> tag_invoke( - tag_t /*unused*/, SchedulerSerialImpl& scheduler, auto& storage, - auto& executor, protocol::BlockHeader const& blockHeader, - RANGES::input_range auto const& transactions, ledger::LedgerConfig const& ledgerConfig) + using CoroType = std::invoke_result_t; + struct ExecutionContext { - ittapi::Report report(ittapi::ITT_DOMAINS::instance().SERIAL_SCHEDULER, - ittapi::ITT_DOMAINS::instance().SERIAL_EXECUTE); + std::optional coro; + std::optionalbegin())> iterator; + protocol::TransactionReceipt::Ptr receipt; + }; - using CoroType = std::invoke_result_t; - struct ExecutionContext - { - std::optional coro; - std::optionalbegin())> iterator; - protocol::TransactionReceipt::Ptr receipt; - }; + auto count = static_cast(RANGES::size(transactions)); + std::vector> contexts(count); - auto count = static_cast(RANGES::size(transactions)); - std::vector> contexts( - count); + auto chunks = RANGES::views::iota( + RANGES::range_size_t(0), RANGES::size(transactions)) | + RANGES::views::chunk( + std::max((size_t)(count / tbb::this_task_arena::max_concurrency()), + (size_t)SchedulerSerialImpl::MIN_TRANSACTION_GRAIN_SIZE)); + using ChunkRange = RANGES::range_value_t; + RANGES::range_size_t chunkIndex = 0; - auto chunks = RANGES::views::iota(RANGES::range_size_t(0), - RANGES::size(transactions)) | - RANGES::views::chunk(std::max( - (size_t)(count / tbb::this_task_arena::max_concurrency()), - (size_t)MIN_TRANSACTION_GRAIN_SIZE)); - using ChunkRange = RANGES::range_value_t; - RANGES::range_size_t chunkIndex = 0; + // 三级流水线,2个线程 + // Three-stage pipeline, with 2 threads + static tbb::task_arena arena(2); + arena.execute([&]() { + tbb::parallel_pipeline(tbb::this_task_arena::max_concurrency(), + tbb::make_filter(tbb::filter_mode::serial_in_order, + [&](tbb::flow_control& control) -> ChunkRange { + if (chunkIndex >= RANGES::size(chunks)) + { + control.stop(); + return {}; + } + ittapi::Report report(ittapi::ITT_DOMAINS::instance().SERIAL_SCHEDULER, + ittapi::ITT_DOMAINS::instance().STAGE_1); - // 三级流水线,2个线程 - // Three-stage pipeline, with 2 threads - static tbb::task_arena arena(2); - arena.execute([&]() { - tbb::parallel_pipeline(tbb::this_task_arena::max_concurrency(), - tbb::make_filter(tbb::filter_mode::serial_in_order, - [&](tbb::flow_control& control) -> ChunkRange { - if (chunkIndex >= RANGES::size(chunks)) - { - control.stop(); - return {}; - } + auto range = chunks[chunkIndex++]; + for (auto i : range) + { + auto& [coro, iterator, receipt] = contexts[i]; + coro.emplace(transaction_executor::execute3Step(executor, storage, + blockHeader, transactions[i], i, ledgerConfig, task::tbb::syncWait)); + iterator.emplace(coro->begin()); + receipt = *(*iterator); + } + return range; + }) & + tbb::make_filter(tbb::filter_mode::serial_in_order, + [&](ChunkRange range) { ittapi::Report report(ittapi::ITT_DOMAINS::instance().SERIAL_SCHEDULER, - ittapi::ITT_DOMAINS::instance().STAGE_1); - - auto range = chunks[chunkIndex++]; + ittapi::ITT_DOMAINS::instance().STAGE_2); for (auto i : range) { auto& [coro, iterator, receipt] = contexts[i]; - coro.emplace( - transaction_executor::execute3Step(executor, storage, blockHeader, - transactions[i], i, ledgerConfig, task::tbb::syncWait)); - iterator.emplace(coro->begin()); - receipt = *(*iterator); + if (!receipt) + { + receipt = *(++(*iterator)); + } } return range; }) & - tbb::make_filter(tbb::filter_mode::serial_in_order, - [&](ChunkRange range) { - ittapi::Report report(ittapi::ITT_DOMAINS::instance().SERIAL_SCHEDULER, - ittapi::ITT_DOMAINS::instance().STAGE_2); - for (auto i : range) - { - auto& [coro, iterator, receipt] = contexts[i]; - if (!receipt) - { - receipt = *(++(*iterator)); - } - } - return range; - }) & - tbb::make_filter( - tbb::filter_mode::serial_in_order, [&](ChunkRange range) { - ittapi::Report report(ittapi::ITT_DOMAINS::instance().SERIAL_SCHEDULER, - ittapi::ITT_DOMAINS::instance().STAGE_3); - for (auto i : range) + tbb::make_filter( + tbb::filter_mode::serial_in_order, [&](ChunkRange range) { + ittapi::Report report(ittapi::ITT_DOMAINS::instance().SERIAL_SCHEDULER, + ittapi::ITT_DOMAINS::instance().STAGE_3); + for (auto i : range) + { + auto& [coro, iterator, receipt] = contexts[i]; + if (!receipt) { - auto& [coro, iterator, receipt] = contexts[i]; - if (!receipt) - { - receipt = *(++(*iterator)); - } - coro.reset(); + receipt = *(++(*iterator)); } - })); - }); + coro.reset(); + } + })); + }); - std::vector receipts; - receipts.reserve(count); - RANGES::move(RANGES::views::transform(contexts, - [](ExecutionContext& context) -> auto& { return context.receipt; }), - RANGES::back_inserter(receipts)); - scheduler.m_gc.collect(std::move(contexts)); - co_return receipts; - } -}; + std::vector receipts; + receipts.reserve(count); + RANGES::move(RANGES::views::transform( + contexts, [](ExecutionContext& context) -> auto& { return context.receipt; }), + RANGES::back_inserter(receipts)); + scheduler.m_gc.collect(std::move(contexts)); + co_return receipts; +} } // namespace bcos::transaction_scheduler \ No newline at end of file diff --git a/transaction-scheduler/benchmark/benchmarkMultiLayerStorage.cpp b/transaction-scheduler/benchmark/benchmarkMultiLayerStorage.cpp index 32355d3470..f752a00cae 100644 --- a/transaction-scheduler/benchmark/benchmarkMultiLayerStorage.cpp +++ b/transaction-scheduler/benchmark/benchmarkMultiLayerStorage.cpp @@ -20,8 +20,8 @@ struct Fixture { // Write count data task::syncWait([this](int64_t count) -> task::Task { - auto view = multiLayerStorage.fork(); - view.newMutable(); + auto view = fork(multiLayerStorage); + newMutable(view); allKeys = RANGES::views::iota(0, count) | RANGES::views::transform([](int num) { auto key = fmt::format("key: {}", num); return transaction_executor::StateKey{"test_table"sv, std::string_view(key)}; @@ -35,14 +35,14 @@ struct Fixture }); co_await storage2::writeSome(view, allKeys, allValues); - multiLayerStorage.pushView(std::move(view)); + pushView(multiLayerStorage, std::move(view)); }(count)); for (auto i = 0; i < layer; ++i) { - auto view = multiLayerStorage.fork(); - view.newMutable(); - multiLayerStorage.pushView(std::move(view)); + auto view = fork(multiLayerStorage); + newMutable(view); + pushView(multiLayerStorage, std::move(view)); } } @@ -65,7 +65,7 @@ static void read1(benchmark::State& state) int i = 0; task::syncWait([&](benchmark::State& state) -> task::Task { - auto view = fixture.multiLayerStorage.fork(); + auto view = fork(fixture.multiLayerStorage); for (auto const& it : state) { [[maybe_unused]] auto data = @@ -85,7 +85,7 @@ static void read10(benchmark::State& state) int i = 0; task::syncWait([&](benchmark::State& state) -> task::Task { - auto view = fixture.multiLayerStorage.fork(); + auto view = fork(fixture.multiLayerStorage); for (auto const& it : state) { [[maybe_unused]] auto data = @@ -103,8 +103,8 @@ static void write1(benchmark::State& state) int i = 0; task::syncWait([&](benchmark::State& state) -> task::Task { - auto view = fixture.multiLayerStorage.fork(); - view.newMutable(); + auto view = fork(fixture.multiLayerStorage); + newMutable(view); for (auto const& it : state) { storage::Entry entry; diff --git a/transaction-scheduler/benchmark/benchmarkScheduler.cpp b/transaction-scheduler/benchmark/benchmarkScheduler.cpp index 1223a1db56..8582abe85d 100644 --- a/transaction-scheduler/benchmark/benchmarkScheduler.cpp +++ b/transaction-scheduler/benchmark/benchmarkScheduler.cpp @@ -91,8 +91,8 @@ struct Fixture RANGES::single_view(std::addressof(createTransaction)) | RANGES::views::transform([](auto* ptr) -> auto const& { return *ptr; }); - auto view = m_multiLayerStorage.fork(); - view.newMutable(); + auto view = fork(m_multiLayerStorage); + newMutable(view); ledger::LedgerConfig ledgerConfig; auto receipts = co_await transaction_scheduler::executeBlock(scheduler, view, @@ -103,8 +103,8 @@ struct Fixture receipts[0]->status(), receipts[0]->message()); co_return; } - m_multiLayerStorage.pushView(std::move(view)); - co_await m_multiLayerStorage.mergeBackStorage(); + pushView(m_multiLayerStorage, std::move(view)); + co_await mergeBackStorage(m_multiLayerStorage); m_contractAddress = receipts[0]->contractAddress(); }()); @@ -233,8 +233,8 @@ struct Fixture RANGES::to< std::vector>>(); - auto view = m_multiLayerStorage.fork(); - view.newMutable(); + auto view = fork(m_multiLayerStorage); + newMutable(view); ledger::LedgerConfig ledgerConfig; auto receipts = co_await transaction_scheduler::executeBlock(scheduler, view, m_executor, blockHeader, @@ -304,8 +304,8 @@ static void issue(benchmark::State& state) else { task::syncWait([&](benchmark::State& state) -> task::Task { - auto view = fixture.m_multiLayerStorage.fork(); - view.newMutable(); + auto view = fork(fixture.m_multiLayerStorage); + newMutable(view); for (auto const& it : state) { bcostars::protocol::BlockHeaderImpl blockHeader( @@ -327,7 +327,7 @@ static void issue(benchmark::State& state) ledgerConfig); } - fixture.m_multiLayerStorage.pushView(std::move(view)); + pushView(fixture.m_multiLayerStorage, std::move(view)); auto balances = co_await fixture.balances(); for (auto& balance : balances) { @@ -338,7 +338,7 @@ static void issue(benchmark::State& state) balance.template convert_to()))); } } - co_await fixture.m_multiLayerStorage.mergeBackStorage(); + co_await mergeBackStorage(fixture.m_multiLayerStorage); }(state)); } }, @@ -373,8 +373,8 @@ static void transfer(benchmark::State& state) blockHeader.setNumber(0); blockHeader.setVersion((uint32_t)bcos::protocol::BlockVersion::V3_1_VERSION); - auto view = fixture.m_multiLayerStorage.fork(); - view.newMutable(); + auto view = fork(fixture.m_multiLayerStorage); + newMutable(view); ledger::LedgerConfig ledgerConfig; [[maybe_unused]] auto receipts = co_await transaction_scheduler::executeBlock( scheduler, view, fixture.m_executor, blockHeader, @@ -410,7 +410,7 @@ static void transfer(benchmark::State& state) } // Check - fixture.m_multiLayerStorage.pushView(std::move(view)); + pushView(fixture.m_multiLayerStorage, std::move(view)); auto balances = co_await fixture.balances(); for (auto&& range : balances | RANGES::views::chunk(2)) { @@ -431,7 +431,7 @@ static void transfer(benchmark::State& state) to.template convert_to()))); } } - co_await fixture.m_multiLayerStorage.mergeBackStorage(); + co_await mergeBackStorage(fixture.m_multiLayerStorage); }(state)); } }, @@ -457,8 +457,8 @@ static void conflictTransfer(benchmark::State& state) else { int i = 0; - auto view = fixture.m_multiLayerStorage.fork(); - view.newMutable(); + auto view = fork(fixture.m_multiLayerStorage); + newMutable(view); task::syncWait([&](benchmark::State& state) -> task::Task { // First issue @@ -503,7 +503,7 @@ static void conflictTransfer(benchmark::State& state) } // Check - fixture.m_multiLayerStorage.pushView(std::move(view)); + pushView(fixture.m_multiLayerStorage, std::move(view)); auto balances = co_await fixture.balances(); for (auto&& [balance, index] : RANGES::views::zip(balances, RANGES::views::iota(0LU))) @@ -536,7 +536,7 @@ static void conflictTransfer(benchmark::State& state) } } } - co_await fixture.m_multiLayerStorage.mergeBackStorage(); + co_await mergeBackStorage(fixture.m_multiLayerStorage); }(state)); } }, diff --git a/transaction-scheduler/tests/CMakeLists.txt b/transaction-scheduler/tests/CMakeLists.txt index 170a97af69..e5ab2461bb 100644 --- a/transaction-scheduler/tests/CMakeLists.txt +++ b/transaction-scheduler/tests/CMakeLists.txt @@ -1,8 +1,9 @@ file(GLOB_RECURSE SOURCES "*.cpp") add_executable(test-transaction-scheduler ${SOURCES}) - find_package(Boost REQUIRED serialization unit_test_framework) target_link_libraries(test-transaction-scheduler transaction-scheduler ${EXECUTOR_TARGET} ${TARS_PROTOCOL_TARGET} ${TABLE_TARGET} bcos-framework Boost::unit_test_framework) +set_source_files_properties("main.cpp" PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON) +set_target_properties(test-transaction-scheduler PROPERTIES UNITY_BUILD "ON") add_test(NAME test-transaction-scheduler WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} COMMAND test-transaction-scheduler) diff --git a/transaction-scheduler/tests/testBaselineScheduler.cpp b/transaction-scheduler/tests/testBaselineScheduler.cpp index 2a333feb5f..fa082077fa 100644 --- a/transaction-scheduler/tests/testBaselineScheduler.cpp +++ b/transaction-scheduler/tests/testBaselineScheduler.cpp @@ -22,12 +22,12 @@ using namespace bcos::storage2; using namespace bcos::transaction_executor; using namespace bcos::transaction_scheduler; -struct MockExecutor +struct MockExecutorBaseline { friend task::Task tag_invoke( bcos::transaction_executor::tag_t< bcos::transaction_executor::executeTransaction> /*unused*/, - MockExecutor& executor, auto& storage, protocol::BlockHeader const& blockHeader, + MockExecutorBaseline& executor, auto& storage, protocol::BlockHeader const& blockHeader, protocol::Transaction const& transaction, int contextID, ledger::LedgerConfig const&, auto&& waitOperator) { @@ -173,8 +173,8 @@ class TestBaselineSchedulerFixture MockLedger mockLedger; MockTxPool mockTxPool; MultiLayerStorage multiLayerStorage; - MockExecutor mockExecutor; - BaselineScheduler + MockExecutorBaseline mockExecutor; + BaselineScheduler baselineScheduler; }; diff --git a/transaction-scheduler/tests/testMultiLayerStorage.cpp b/transaction-scheduler/tests/testMultiLayerStorage.cpp index 30ed4a58bf..10dff228d7 100644 --- a/transaction-scheduler/tests/testMultiLayerStorage.cpp +++ b/transaction-scheduler/tests/testMultiLayerStorage.cpp @@ -35,7 +35,7 @@ BOOST_FIXTURE_TEST_SUITE(TestMultiLayerStorage, TestMultiLayerStorageFixture) BOOST_AUTO_TEST_CASE(noMutable) { task::syncWait([this]() -> task::Task { - auto view = multiLayerStorage.fork(); + auto view = fork(multiLayerStorage); storage::Entry entry; BOOST_CHECK_THROW(co_await storage2::writeOne( view, StateKey{"test_table"sv, "test_key"sv}, std::move(entry)), @@ -48,8 +48,8 @@ BOOST_AUTO_TEST_CASE(noMutable) BOOST_AUTO_TEST_CASE(readWriteMutable) { task::syncWait([this]() -> task::Task { - auto view = std::make_optional(multiLayerStorage.fork()); - view->newMutable(); + auto view = std::make_optional(fork(multiLayerStorage)); + newMutable(*view); StateKey key{"test_table"sv, "test_key"sv}; storage::Entry entry; @@ -60,9 +60,9 @@ BOOST_AUTO_TEST_CASE(readWriteMutable) auto values = co_await storage2::readSome(*view, keyViews); BOOST_CHECK_EQUAL(values[0]->get(), entry.get()); - BOOST_CHECK_NO_THROW(multiLayerStorage.pushView(std::move(*view))); + BOOST_CHECK_NO_THROW(pushView(multiLayerStorage, std::move(*view))); - auto view2 = multiLayerStorage.fork(); + auto view2 = fork(multiLayerStorage); BOOST_CHECK_THROW( co_await storage2::writeOne(view2, key, entry), NotExistsMutableStorageError); @@ -73,8 +73,8 @@ BOOST_AUTO_TEST_CASE(readWriteMutable) BOOST_AUTO_TEST_CASE(merge) { task::syncWait([this]() -> task::Task { - auto view = std::make_optional(multiLayerStorage.fork()); - view->newMutable(); + auto view = std::make_optional(fork(multiLayerStorage)); + newMutable(*view); auto toKey = RANGES::views::transform( [](int num) { return StateKey{"test_table"sv, fmt::format("key: {}", num)}; }); auto toValue = RANGES::views::transform([](int num) { @@ -88,12 +88,12 @@ BOOST_AUTO_TEST_CASE(merge) RANGES::iota_view(0, 100) | toValue); BOOST_CHECK_THROW( - co_await multiLayerStorage.mergeBackStorage(), NotExistsImmutableStorageError); + co_await mergeBackStorage(multiLayerStorage), NotExistsImmutableStorageError); - multiLayerStorage.pushView(std::move(*view)); - co_await multiLayerStorage.mergeBackStorage(); + pushView(multiLayerStorage, std::move(*view)); + co_await mergeBackStorage(multiLayerStorage); - auto view2 = multiLayerStorage.fork(); + auto view2 = fork(multiLayerStorage); auto keys = RANGES::iota_view(0, 100) | toKey; auto values = co_await storage2::readSome(view2, keys); @@ -103,11 +103,11 @@ BOOST_AUTO_TEST_CASE(merge) } BOOST_CHECK_EQUAL(RANGES::size(values), 100); - auto view3 = multiLayerStorage.fork(); - view3.newMutable(); + auto view3 = fork(multiLayerStorage); + newMutable(view3); co_await storage2::removeSome(view3, RANGES::iota_view(20, 30) | toKey); - multiLayerStorage.pushView(std::move(view3)); - co_await multiLayerStorage.mergeBackStorage(); + pushView(multiLayerStorage, std::move(view3)); + co_await mergeBackStorage(multiLayerStorage); auto values2 = co_await storage2::readSome(view3, keys); for (auto&& [index, value] : RANGES::views::enumerate(values2)) @@ -140,14 +140,14 @@ BOOST_AUTO_TEST_CASE(rangeMulti) MultiLayerStorage myMultiLayerStorage(backendStorage); - auto view1 = myMultiLayerStorage.fork(); - view1.newMutable(); + auto view1 = fork(myMultiLayerStorage); + newMutable(view1); co_await storage2::writeSome(view1, RANGES::views::iota(2, 6), RANGES::views::repeat(1)); co_await storage2::removeOne(view1, 2); - myMultiLayerStorage.pushView(std::move(view1)); + pushView(myMultiLayerStorage, std::move(view1)); - auto view2 = myMultiLayerStorage.fork(); - view2.newMutable(); + auto view2 = fork(myMultiLayerStorage); + newMutable(view2); co_await storage2::writeSome(view2, RANGES::views::iota(4, 8), RANGES::views::repeat(2)); auto resultList = co_await storage2::readSome(view2, RANGES::views::iota(0, 8)); diff --git a/transaction-scheduler/tests/testReadWriteSetStorage.cpp b/transaction-scheduler/tests/testReadWriteSetStorage.cpp index 56a5f7dc34..78018921fd 100644 --- a/transaction-scheduler/tests/testReadWriteSetStorage.cpp +++ b/transaction-scheduler/tests/testReadWriteSetStorage.cpp @@ -38,10 +38,10 @@ BOOST_AUTO_TEST_CASE(readWriteSet) co_await storage2::readOne(secondStorage, 500); co_await storage2::readOne(secondStorage, 600); - BOOST_CHECK(!firstStorage.hasRAWIntersection(secondStorage)); + BOOST_CHECK(!hasRAWIntersection(firstStorage, secondStorage)); co_await storage2::readOne(secondStorage, 200); - BOOST_CHECK(firstStorage.hasRAWIntersection(secondStorage)); + BOOST_CHECK(hasRAWIntersection(firstStorage, secondStorage)); co_return; }()); diff --git a/transaction-scheduler/tests/testSchedulerParallel.cpp b/transaction-scheduler/tests/testSchedulerParallel.cpp index 56899ac40d..700284a70b 100644 --- a/transaction-scheduler/tests/testSchedulerParallel.cpp +++ b/transaction-scheduler/tests/testSchedulerParallel.cpp @@ -19,12 +19,13 @@ using namespace bcos::transaction_executor; using namespace bcos::transaction_scheduler; using namespace std::string_view_literals; -struct MockExecutor +struct MockExecutorParallel { friend task::Generator tag_invoke( - transaction_executor::tag_t /*unused*/, MockExecutor& executor, auto& storage, - protocol::BlockHeader const& blockHeader, protocol::Transaction const& transaction, - int contextID, ledger::LedgerConfig const& ledgerConfig, auto&& waitOperator) + transaction_executor::tag_t /*unused*/, MockExecutorParallel& executor, + auto& storage, protocol::BlockHeader const& blockHeader, + protocol::Transaction const& transaction, int contextID, + ledger::LedgerConfig const& ledgerConfig, auto&& waitOperator) { BCOS_LOG(INFO) << "Step1"; co_yield std::shared_ptr(); @@ -37,7 +38,7 @@ struct MockExecutor friend task::Task tag_invoke( bcos::transaction_executor::tag_t< bcos::transaction_executor::executeTransaction> /*unused*/, - MockExecutor& executor, auto& storage, protocol::BlockHeader const& blockHeader, + MockExecutorParallel& executor, auto& storage, protocol::BlockHeader const& blockHeader, protocol::Transaction const& transaction, int contextID, ledger::LedgerConfig const&, auto&& waitOperator) { @@ -73,7 +74,7 @@ BOOST_FIXTURE_TEST_SUITE(TestSchedulerParallel, TestSchedulerParallelFixture) BOOST_AUTO_TEST_CASE(simple) { task::syncWait([&, this]() -> task::Task { - MockExecutor executor; + MockExecutorParallel executor; SchedulerParallelImpl scheduler; bcostars::protocol::BlockHeaderImpl blockHeader( @@ -85,8 +86,8 @@ BOOST_AUTO_TEST_CASE(simple) }) | RANGES::to>>(); - auto view = multiLayerStorage.fork(); - view.newMutable(); + auto view = fork(multiLayerStorage); + newMutable(view); ledger::LedgerConfig ledgerConfig; auto receipts = co_await bcos::transaction_scheduler::executeBlock(scheduler, view, executor, blockHeader, @@ -141,9 +142,9 @@ BOOST_AUTO_TEST_CASE(conflict) MockConflictExecutor executor; SchedulerParallelImpl scheduler; - auto view1 = multiLayerStorage.fork(); - view1.newMutable(); - multiLayerStorage.pushView(std::move(view1)); + auto view1 = fork(multiLayerStorage); + newMutable(view1); + pushView(multiLayerStorage, std::move(view1)); constexpr static int INITIAL_VALUE = 100000; for (auto i : RANGES::views::iota(0LU, MOCK_USER_COUNT)) @@ -151,7 +152,7 @@ BOOST_AUTO_TEST_CASE(conflict) StateKey key{"t_test"sv, boost::lexical_cast(i)}; storage::Entry entry; entry.set(boost::lexical_cast(INITIAL_VALUE)); - co_await storage2::writeOne(*multiLayerStorage.frontStorage(), key, std::move(entry)); + co_await storage2::writeOne(*frontStorage(multiLayerStorage), key, std::move(entry)); } bcostars::protocol::BlockHeaderImpl blockHeader( @@ -170,17 +171,17 @@ BOOST_AUTO_TEST_CASE(conflict) auto transactionRefs = transactions | RANGES::views::transform([](auto& ptr) -> auto& { return *ptr; }); - auto view = multiLayerStorage.fork(); - view.newMutable(); + auto view = fork(multiLayerStorage); + newMutable(view); ledger::LedgerConfig ledgerConfig; auto receipts = co_await bcos::transaction_scheduler::executeBlock( scheduler, view, executor, blockHeader, transactionRefs, ledgerConfig); - multiLayerStorage.pushView(std::move(view)); + pushView(multiLayerStorage, std::move(view)); for (auto i : RANGES::views::iota(0LU, MOCK_USER_COUNT)) { StateKey key{"t_test"sv, boost::lexical_cast(i)}; - auto entry = co_await storage2::readOne(*multiLayerStorage.frontStorage(), key); + auto entry = co_await storage2::readOne(*frontStorage(multiLayerStorage), key); BOOST_CHECK_EQUAL(boost::lexical_cast(entry->get()), INITIAL_VALUE); } for (auto const& receipt : receipts) diff --git a/transaction-scheduler/tests/testSchedulerSerial.cpp b/transaction-scheduler/tests/testSchedulerSerial.cpp index 0c4eb4c915..c36f5d283f 100644 --- a/transaction-scheduler/tests/testSchedulerSerial.cpp +++ b/transaction-scheduler/tests/testSchedulerSerial.cpp @@ -17,12 +17,13 @@ using namespace bcos::storage2; using namespace bcos::transaction_executor; using namespace bcos::transaction_scheduler; -struct MockExecutor +struct MockExecutorSerial { friend task::Generator tag_invoke( - transaction_executor::tag_t /*unused*/, MockExecutor& executor, auto& storage, - protocol::BlockHeader const& blockHeader, protocol::Transaction const& transaction, - int contextID, ledger::LedgerConfig const& ledgerConfig, auto&& waitOperator) + transaction_executor::tag_t /*unused*/, MockExecutorSerial& executor, + auto& storage, protocol::BlockHeader const& blockHeader, + protocol::Transaction const& transaction, int contextID, + ledger::LedgerConfig const& ledgerConfig, auto&& waitOperator) { co_yield std::shared_ptr(); co_yield std::shared_ptr(); @@ -31,7 +32,7 @@ struct MockExecutor friend task::Task tag_invoke( transaction_executor::tag_t /*unused*/, - MockExecutor& executor, auto& storage, protocol::BlockHeader const& blockHeader, + MockExecutorSerial& executor, auto& storage, protocol::BlockHeader const& blockHeader, protocol::Transaction const& transaction, int contextID, ledger::LedgerConfig const&, auto&& waitOperator) { @@ -78,9 +79,9 @@ BOOST_AUTO_TEST_CASE(executeBlock) }) | RANGES::to>>(); - MockExecutor executor; - auto view = multiLayerStorage.fork(); - view.newMutable(); + MockExecutorSerial executor; + auto view = fork(multiLayerStorage); + newMutable(view); ledger::LedgerConfig ledgerConfig; auto receipts = co_await bcos::transaction_scheduler::executeBlock(scheduler, view, executor, blockHeader,