diff --git a/bcos-crypto/bcos-crypto/ChecksumAddress.h b/bcos-crypto/bcos-crypto/ChecksumAddress.h index 1369787744..dcf3cff11f 100644 --- a/bcos-crypto/bcos-crypto/ChecksumAddress.h +++ b/bcos-crypto/bcos-crypto/ChecksumAddress.h @@ -100,12 +100,13 @@ inline std::string newEVMAddress( inline std::string newEVMAddress(bcos::crypto::Hash::Ptr _hashImpl, const std::string_view& _sender, bytesConstRef _init, u256 const& _salt) { - auto hash = - _hashImpl->hash(bytes{0xff} + _sender + toBigEndian(_salt) + _hashImpl->hash(_init)); + auto hash = _hashImpl->hash( + bytes{0xff} + (_sender.starts_with("0x") ? fromHexWithPrefix(_sender) : fromHex(_sender)) + + toBigEndian(_salt) + _hashImpl->hash(_init)); std::string hexAddress; hexAddress.reserve(40); - boost::algorithm::hex(hash.data(), hash.data() + 20, std::back_inserter(hexAddress)); + boost::algorithm::hex(hash.data() + 12, hash.data() + 32, std::back_inserter(hexAddress)); toAddress(hexAddress, _hashImpl); diff --git a/bcos-executor/src/executor/TransactionExecutor.cpp b/bcos-executor/src/executor/TransactionExecutor.cpp index b4b12ff217..dc6325e326 100644 --- a/bcos-executor/src/executor/TransactionExecutor.cpp +++ b/bcos-executor/src/executor/TransactionExecutor.cpp @@ -972,14 +972,6 @@ void TransactionExecutor::executeTransactionsInternal(std::string contractAddres } }); - if (isStaticCall) - { - EXECUTOR_NAME_LOG(FATAL) - << "executeTransactionsInternal() only handle non static transactions but " - "receive static call"; - assert(false); - } - auto prepareT = utcTime() - startT; startT = utcTime(); diff --git a/bcos-executor/src/vm/DelegateHostContext.cpp b/bcos-executor/src/vm/DelegateHostContext.cpp index cbe0f52a3f..949d3ce009 100644 --- a/bcos-executor/src/vm/DelegateHostContext.cpp +++ b/bcos-executor/src/vm/DelegateHostContext.cpp @@ -14,6 +14,7 @@ DelegateHostContext::DelegateHostContext(CallParameters::UniquePtr callParameter } setCode(getCallParameters()->delegateCallCode); m_delegateCallSender = getCallParameters()->delegateCallSender; + m_thisAddress = getCallParameters()->receiveAddress; } std::optional DelegateHostContext::code() @@ -35,6 +36,16 @@ h256 DelegateHostContext::codeHash() return m_codeHash; } +std::string_view DelegateHostContext::myAddress() const +{ + if (this->features().get(ledger::Features::Flag::bugfix_evm_create2_delegatecall_staticcall_codecopy)) + { + return m_thisAddress; + } + + return HostContext::myAddress(); +} + std::string_view DelegateHostContext::caller() const { return m_delegateCallSender; diff --git a/bcos-executor/src/vm/DelegateHostContext.h b/bcos-executor/src/vm/DelegateHostContext.h index c9c700e786..ea0bbabc52 100644 --- a/bcos-executor/src/vm/DelegateHostContext.h +++ b/bcos-executor/src/vm/DelegateHostContext.h @@ -37,11 +37,13 @@ class DelegateHostContext : public HostContext bool setCode(bytes code) override; h256 codeHash() override; + std::string_view myAddress() const override; std::string_view caller() const override; private: storage::Entry m_code; h256 m_codeHash; + std::string m_thisAddress; std::string m_delegateCallSender; }; diff --git a/bcos-executor/src/vm/EVMHostInterface.cpp b/bcos-executor/src/vm/EVMHostInterface.cpp index 685fd485c2..522fe35d8a 100644 --- a/bcos-executor/src/vm/EVMHostInterface.cpp +++ b/bcos-executor/src/vm/EVMHostInterface.cpp @@ -114,10 +114,24 @@ evmc_bytes32 getCodeHash(evmc_host_context* _context, const evmc_address* _addr) * @param _bufferSize : code size to copy * @return size_t : return copied code size(in byte) */ -size_t copyCode(evmc_host_context* _context, const evmc_address*, size_t, uint8_t* _bufferData, - size_t _bufferSize) +size_t copyCode(evmc_host_context* _context, const evmc_address* _addr, size_t _codeOffset, + uint8_t* _bufferData, size_t _bufferSize) { auto& hostContext = static_cast(*_context); + if (hostContext.features().get(ledger::Features::Flag::bugfix_evm_create2_delegatecall_staticcall_codecopy)) + { + auto addr = fromEvmC(*_addr); + bytes const& code = hostContext.codeAt(addr); + + // Handle "big offset" edge case. + if (_codeOffset >= code.size()) + return 0; + + size_t maxToCopy = code.size() - _codeOffset; + size_t numToCopy = std::min(maxToCopy, _bufferSize); + std::copy_n(&code[_codeOffset], numToCopy, _bufferData); + return numToCopy; + } hostContext.setCode(bytes((bcos::byte*)_bufferData, (bcos::byte*)_bufferData + _bufferSize)); return _bufferSize; diff --git a/bcos-executor/src/vm/HostContext.cpp b/bcos-executor/src/vm/HostContext.cpp index 527768ab5d..b526a1a0fa 100644 --- a/bcos-executor/src/vm/HostContext.cpp +++ b/bcos-executor/src/vm/HostContext.cpp @@ -133,6 +133,11 @@ evmc_result HostContext::externalRequest(const evmc_message* _msg) { case EVMC_CREATE2: request->createSalt = fromEvmC(_msg->create2_salt); + if (features().get(ledger::Features::Flag::bugfix_evm_create2_delegatecall_staticcall_codecopy)) + { + request->data.assign(_msg->input_data, _msg->input_data + _msg->input_size); + request->create = true; + } break; case EVMC_CALL: if (blockContext.isWasm()) @@ -209,6 +214,15 @@ evmc_result HostContext::externalRequest(const evmc_message* _msg) request->staticCall = m_callParameters->staticCall; + if (features().get(ledger::Features::Flag::bugfix_evm_create2_delegatecall_staticcall_codecopy)) + { + // EVM STATICCALL opcode support + if (_msg->flags & EVMC_STATIC) + { + request->staticCall = true; + } + } + auto response = m_executive->externalCall(std::move(request)); // Convert CallParameters to evmc_resultx diff --git a/bcos-executor/src/vm/HostContext.h b/bcos-executor/src/vm/HostContext.h index e4fde37387..6f9a95d225 100644 --- a/bcos-executor/src/vm/HostContext.h +++ b/bcos-executor/src/vm/HostContext.h @@ -115,7 +115,7 @@ class HostContext : public evmc_host_context void log(h256s&& _topics, bytesConstRef _data); /// ------ get interfaces related to HostContext------ - std::string_view myAddress() const; + virtual std::string_view myAddress() const; virtual std::string_view caller() const { return m_callParameters->senderAddress; } std::string_view origin() const { return m_callParameters->origin; } std::string_view codeAddress() const { return m_callParameters->codeAddress; } @@ -160,6 +160,12 @@ class HostContext : public evmc_host_context bool isWasm(); + bcos::bytes codeAt(const std::string_view& address) { return externalCodeRequest(address); } + const bcos::ledger::Features& features() const + { + return m_executive->blockContext().lock()->features(); + } + protected: const CallParameters::UniquePtr& getCallParameters() const { return m_callParameters; } virtual bcos::bytes externalCodeRequest(const std::string_view& address); diff --git a/bcos-framework/bcos-framework/ledger/Features.h b/bcos-framework/bcos-framework/ledger/Features.h index a3cd5afb0d..f27c0ce951 100644 --- a/bcos-framework/bcos-framework/ledger/Features.h +++ b/bcos-framework/bcos-framework/ledger/Features.h @@ -32,6 +32,7 @@ class Features { bugfix_revert, // https://github.com/FISCO-BCOS/FISCO-BCOS/issues/3629 bugfix_statestorage_hash, + bugfix_evm_create2_delegatecall_staticcall_codecopy, feature_dmc2serial, feature_sharding, feature_rpbft, @@ -119,6 +120,7 @@ class Features if (version >= protocol::BlockVersion::V3_2_4_VERSION) { set(Flag::bugfix_statestorage_hash); + set(Flag::bugfix_evm_create2_delegatecall_staticcall_codecopy); } setToShardingDefault(version); } diff --git a/bcos-framework/test/unittests/interfaces/FeaturesTest.cpp b/bcos-framework/test/unittests/interfaces/FeaturesTest.cpp index 4020594f9e..50850fd902 100644 --- a/bcos-framework/test/unittests/interfaces/FeaturesTest.cpp +++ b/bcos-framework/test/unittests/interfaces/FeaturesTest.cpp @@ -126,16 +126,18 @@ BOOST_AUTO_TEST_CASE(feature) BOOST_CHECK_EQUAL(features7.get("feature_balance_policy1"), true); auto keys = Features::featureKeys(); - BOOST_CHECK_EQUAL(keys.size(), 9); + + BOOST_CHECK_EQUAL(keys.size(), 10); BOOST_CHECK_EQUAL(keys[0], "bugfix_revert"); BOOST_CHECK_EQUAL(keys[1], "bugfix_statestorage_hash"); - BOOST_CHECK_EQUAL(keys[2], "feature_dmc2serial"); - BOOST_CHECK_EQUAL(keys[3], "feature_sharding"); - BOOST_CHECK_EQUAL(keys[4], "feature_rpbft"); - BOOST_CHECK_EQUAL(keys[5], "feature_paillier"); - BOOST_CHECK_EQUAL(keys[6], "feature_balance"); - BOOST_CHECK_EQUAL(keys[7], "feature_balance_precompiled"); - BOOST_CHECK_EQUAL(keys[8], "feature_balance_policy1"); + BOOST_CHECK_EQUAL(keys[2], "bugfix_evm_create2_delegatecall_staticcall_codecopy"); + BOOST_CHECK_EQUAL(keys[3], "feature_dmc2serial"); + BOOST_CHECK_EQUAL(keys[4], "feature_sharding"); + BOOST_CHECK_EQUAL(keys[5], "feature_rpbft"); + BOOST_CHECK_EQUAL(keys[6], "feature_paillier"); + BOOST_CHECK_EQUAL(keys[7], "feature_balance"); + BOOST_CHECK_EQUAL(keys[8], "feature_balance_precompiled"); + BOOST_CHECK_EQUAL(keys[9], "feature_balance_policy1"); } BOOST_AUTO_TEST_SUITE_END() diff --git a/bcos-scheduler/src/BlockExecutive.cpp b/bcos-scheduler/src/BlockExecutive.cpp index 2f2eb21b13..0edddcf31e 100644 --- a/bcos-scheduler/src/BlockExecutive.cpp +++ b/bcos-scheduler/src/BlockExecutive.cpp @@ -1514,7 +1514,7 @@ DmcExecutor::Ptr BlockExecutive::buildDmcExecutor(const std::string& name, bcos::executor::ParallelTransactionExecutorInterface::Ptr executor) { auto dmcExecutor = std::make_shared(name, contractAddress, m_block, executor, - m_keyLocks, m_scheduler->m_hashImpl, m_dmcRecorder); + m_keyLocks, m_scheduler->m_hashImpl, m_dmcRecorder, isCall()); return dmcExecutor; } diff --git a/bcos-scheduler/src/DmcExecutor.cpp b/bcos-scheduler/src/DmcExecutor.cpp index 5e6ff06b5e..0b41142c16 100644 --- a/bcos-scheduler/src/DmcExecutor.cpp +++ b/bcos-scheduler/src/DmcExecutor.cpp @@ -223,7 +223,7 @@ void DmcExecutor::go(std::function callbac // record all send message for debug m_dmcRecorder->recordSends(m_contractAddress, *messages); - if (messages->size() == 1 && (*messages)[0]->staticCall()) + if (isCall()) { DMC_LOG(TRACE) << "send call request, address:" << m_contractAddress << LOG_KV("executor", m_name) << LOG_KV("to", (*messages)[0]->to()) diff --git a/bcos-scheduler/src/DmcExecutor.h b/bcos-scheduler/src/DmcExecutor.h index 895bcfba74..b9f49f69db 100644 --- a/bcos-scheduler/src/DmcExecutor.h +++ b/bcos-scheduler/src/DmcExecutor.h @@ -53,14 +53,15 @@ class DmcExecutor : public std::enable_shared_from_this DmcExecutor(std::string name, std::string contractAddress, bcos::protocol::Block::Ptr block, bcos::executor::ParallelTransactionExecutorInterface::Ptr executor, GraphKeyLocks::Ptr keyLocks, bcos::crypto::Hash::Ptr hashImpl, - DmcStepRecorder::Ptr dmcRecorder) + DmcStepRecorder::Ptr dmcRecorder, bool isCall) : m_name(name), m_contractAddress(contractAddress), m_block(block), m_executor(executor), m_keyLocks(keyLocks), m_hashImpl(hashImpl), - m_dmcRecorder(dmcRecorder) + m_dmcRecorder(dmcRecorder), + m_isCall(isCall) {} virtual ~DmcExecutor() = default; @@ -142,6 +143,7 @@ class DmcExecutor : public std::enable_shared_from_this callback); void handleCreateMessage(protocol::ExecutionMessage::UniquePtr& message, int64_t currentSeq); + void setIsCall(bool isCall) { m_isCall = isCall; } protected: MessageHint handleExecutiveMessage(ExecutiveState::Ptr executive); @@ -153,6 +155,7 @@ class DmcExecutor : public std::enable_shared_from_this std::string newEVMAddress(int64_t blockNumber, int64_t contextID, int64_t seq); std::string newEVMAddress( const std::string_view& _sender, bytesConstRef _init, u256 const& _salt); + bool isCall() { return m_isCall; } protected: std::string m_name; @@ -164,6 +167,7 @@ class DmcExecutor : public std::enable_shared_from_this DmcStepRecorder::Ptr m_dmcRecorder; ExecutivePool m_executivePool; bool m_hasContractTableChanged = false; + bool m_isCall; mutable SharedMutex x_concurrentLock; diff --git a/bcos-scheduler/test/testDmcExecutor.cpp b/bcos-scheduler/test/testDmcExecutor.cpp index fd77a52209..6ba348e10d 100644 --- a/bcos-scheduler/test/testDmcExecutor.cpp +++ b/bcos-scheduler/test/testDmcExecutor.cpp @@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(stateSwitchTest) block->setBlockHeader(blockHeader); // block = fakeBlock(cryptoSuite, blockFactory, 1, 1, 1); auto dmcExecutor = std::make_shared( - "DmcExecutor1", "0xaabbccdd", block, executor1, keyLocks, hashImpl, dmcRecorder); + "DmcExecutor1", "0xaabbccdd", block, executor1, keyLocks, hashImpl, dmcRecorder, false); dmcExecutor->setSchedulerOutHandler( [this, &dmcFlagStruct](bcos::scheduler::ExecutiveState::Ptr executiveState) { @@ -103,7 +103,7 @@ BOOST_AUTO_TEST_CASE(stateSwitchTest) blockHeader->calculateHash(*hashImpl); block->setBlockHeader(blockHeader); auto dmcExecutor2 = std::make_shared( - "DmcExecutor2", to, block, executor1, keyLocks, hashImpl, dmcRecorder); + "DmcExecutor2", to, block, executor1, keyLocks, hashImpl, dmcRecorder, false); dmcExecutor2->scheduleIn(executiveState); }); @@ -226,6 +226,7 @@ BOOST_AUTO_TEST_CASE(stateSwitchTest) // call + dmcExecutor->setIsCall(true); auto callMessage = createMessage(4, 0, 1, "0xaabbccdd", true); dmcExecutor->submit(std::move(callMessage), false); dmcExecutor->prepare(); @@ -253,7 +254,7 @@ BOOST_AUTO_TEST_CASE(keyLocksTest) block->setBlockHeader(blockHeader); // block = fakeBlock(cryptoSuite, blockFactory, 1, 1, 1); auto dmcExecutor = std::make_shared( - "DmcExecutor1", "0xaabbccdd", block, executor1, keyLocks, hashImpl, dmcRecorder); + "DmcExecutor1", "0xaabbccdd", block, executor1, keyLocks, hashImpl, dmcRecorder, false); dmcExecutor->setSchedulerOutHandler( [this, &dmcFlagStruct](bcos::scheduler::ExecutiveState::Ptr executiveState) { @@ -266,7 +267,7 @@ BOOST_AUTO_TEST_CASE(keyLocksTest) blockHeader->calculateHash(*blockFactory->cryptoSuite()->hashImpl()); block->setBlockHeader(blockHeader); auto dmcExecutor2 = std::make_shared( - "DmcExecutor2", to, block, executor1, keyLocks, hashImpl, dmcRecorder); + "DmcExecutor2", to, block, executor1, keyLocks, hashImpl, dmcRecorder, false); dmcExecutor2->scheduleIn(executiveState); });