Skip to content

Commit

Permalink
fix getCode compatibility bug
Browse files Browse the repository at this point in the history
  • Loading branch information
JimmyShi22 committed Jan 16, 2024
1 parent 9913615 commit 3786fa7
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 95 deletions.
171 changes: 90 additions & 81 deletions bcos-executor/src/executive/TransactionExecutive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,60 +122,36 @@ CallParameters::UniquePtr TransactionExecutive::externalCall(CallParameters::Uni
assert(!m_blockContext.isWasm());
auto tableName = getContractTableName(input->codeAddress, false);

// get codeHash in contract table
auto codeHashEntry = storage().getRow(tableName, ACCOUNT_CODE_HASH);
do
bool needTryFromContractTable =
m_blockContext.features().get(ledger::Features::Flag::bugfix_call_noaddr_return);
auto codeEntry = getCodeByContractTableName(tableName, needTryFromContractTable);
if (codeEntry && codeEntry.has_value() && !codeEntry->get().empty())
{
if (!codeHashEntry || codeHashEntry->get().empty())
{
auto& output = input;
EXECUTIVE_LOG(DEBUG) << "Could not getCodeHash during externalCall"
<< LOG_KV("codeAddress", input->codeAddress);

if (m_blockContext.features().get(
ledger::Features::Flag::bugfix_call_noaddr_return))
{
auto entry = storage().getRow(tableName, ACCOUNT_CODE);
if (entry && !entry->get().empty())
{
input->delegateCallCode = toBytes(entry->get());
break;
}
}
input->delegateCallCode = toBytes(codeEntry->get());
}
else
{
EXECUTIVE_LOG(DEBUG) << "Could not getCode during externalCall"
<< LOG_KV("codeAddress", input->codeAddress)
<< LOG_KV("needTryFromContractTable", needTryFromContractTable);
input->delegateCallCode = bytes();

output->data = bytes();
if (m_blockContext.features().get(
ledger::Features::Flag::bugfix_call_noaddr_return))
{
// This is eth's bug, but we still need to compat with it :)
// https://docs.soliditylang.org/en/v0.8.17/control-structures.html#error-handling-assert-require-revert-and-exceptions
output->status = (int32_t)TransactionStatus::None;
output->evmStatus = EVMC_SUCCESS;
}
else
{
output->status = (int32_t)TransactionStatus::RevertInstruction;
output->evmStatus = EVMC_REVERT;
}
return std::move(output);
auto& output = input;
output->data = bytes();
if (m_blockContext.features().get(ledger::Features::Flag::bugfix_call_noaddr_return))
{
// This is eth's bug, but we still need to compat with it :)
// https://docs.soliditylang.org/en/v0.8.17/control-structures.html#error-handling-assert-require-revert-and-exceptions
output->status = (int32_t)TransactionStatus::None;
output->evmStatus = EVMC_SUCCESS;
}

auto codeHash = codeHashEntry->getField(0);

// get code in code binary table
auto entry = storage().getRow(bcos::ledger::SYS_CODE_BINARY, codeHash);
if (!entry || entry->get().empty())
else
{
auto& output = input;
EXECUTIVE_LOG(DEBUG) << "Could not getCode during externalCall"
<< LOG_KV("codeAddress", input->codeAddress);
output->data = bytes();
output->status = (int32_t)TransactionStatus::RevertInstruction;
output->evmStatus = EVMC_REVERT;
return std::move(output);
}
input->delegateCallCode = toBytes(entry->get());
} while (0);
return std::move(output);
}
}

if (input->data == bcos::protocol::GET_CODE_INPUT_BYTES)
Expand All @@ -184,44 +160,26 @@ CallParameters::UniquePtr TransactionExecutive::externalCall(CallParameters::Uni
<< LOG_KV("codeAddress", input->codeAddress);

auto tableName = getContractTableName(input->codeAddress, false);

auto& output = input;
// get codeHash in contract table
auto codeHashEntry = storage().getRow(tableName, ACCOUNT_CODE_HASH);
if (!codeHashEntry || codeHashEntry->get().empty())
{
if (m_blockContext.features().get(ledger::Features::Flag::bugfix_call_noaddr_return))
{
auto entry = storage().getRow(tableName, ACCOUNT_CODE);
if (entry && !entry->get().empty())
{
output->data = toBytes(entry->get());
return std::move(output);
}
}

EXECUTIVE_LOG(DEBUG) << "Could not get external code hash from local storage"
<< LOG_KV("codeAddress", input->codeAddress);
output->data = bytes();
bool needTryFromContractTable =
m_blockContext.features().get(ledger::Features::Flag::bugfix_call_noaddr_return);
auto codeEntry = getCodeByContractTableName(tableName, needTryFromContractTable);
if (codeEntry && codeEntry.has_value() && !codeEntry->get().empty())
{
output->data = toBytes(codeEntry->get());
return std::move(output);
}

auto codeHash = codeHashEntry->getField(0);

// get code in code binary table
auto entry = storage().getRow(bcos::ledger::SYS_CODE_BINARY, codeHash);
if (!entry || entry->get().empty())
else
{
EXECUTIVE_LOG(DEBUG) << "Could not get external code from local storage"
<< LOG_KV("codeAddress", input->codeAddress);
<< LOG_KV("codeAddress", input->codeAddress)
<< LOG_KV("needTryFromContractTable", needTryFromContractTable);
output->data = bytes();
return std::move(output);
}
output->data = toBytes(entry->get());
return std::move(output);
}


auto executive =
buildChildExecutive(input->codeAddress, m_contextID, newSeq, ExecutiveType::common);

Expand Down Expand Up @@ -286,7 +244,7 @@ CallParameters::UniquePtr TransactionExecutive::execute(CallParameters::UniquePt
callResults = std::move(callParameters);
callResults->type = CallParameters::FINISHED;
callResults->status = (int32_t)TransactionStatus::None;
return callResults;
return callResults;
}
}

Expand Down Expand Up @@ -317,22 +275,72 @@ CallParameters::UniquePtr TransactionExecutive::execute(CallParameters::UniquePt
}


crypto::HashType TransactionExecutive::getCodeHash(const std::string_view& contractTableName)
{
auto entry = storage().getRow(contractTableName, ACCOUNT_CODE_HASH);
if (entry)
{
auto code = entry->getField(0);
return crypto::HashType(code, crypto::HashType::StringDataType::FromBinary);
}

return {};
}

std::optional<storage::Entry> TransactionExecutive::getCodeEntryFromContractTable(
const std::string_view contractTableName)
{
return storage().getRow(contractTableName, ACCOUNT_CODE);
}

std::optional<storage::Entry> TransactionExecutive::getCodeByHash(const std::string_view& codeHash)
{
auto entry = storage().getRow(bcos::ledger::SYS_CODE_BINARY, codeHash);
if (entry && !entry->get().empty())
{
return entry;
}
else
{
return {};
}
}

std::optional<storage::Entry> TransactionExecutive::getCodeByContractTableName(
const std::string_view& contractTableName, bool tryFromContractTable)
{
auto hash = getCodeHash(contractTableName);
auto entry = getCodeByHash(std::string_view((char*)hash.data(), hash.size()));
if (entry && entry.has_value() && !entry->get().empty())
{
return entry;
}

if (tryFromContractTable)
{
return getCodeEntryFromContractTable(contractTableName);
}
else
{
return {};
}
}

bool TransactionExecutive::transferBalance(std::string_view origin, std::string_view sender,
std::string_view receiver, const u256& value, int64_t gas)
{
// origin 是发送方
// sender 是合约地址
// receiver 是转账接收方
EXECUTIVE_LOG(TRACE) << LOG_BADGE("Execute") << "now to transferBalance"
<< LOG_KV("origin", origin)
<< LOG_KV("subAccount", sender)
<< LOG_KV("origin", origin) << LOG_KV("subAccount", sender)
<< LOG_KV("addAccount", receiver)
<< LOG_KV("receiveAddress", ACCOUNT_ADDRESS)
<< LOG_KV("value", value)
<< LOG_KV("receiveAddress", ACCOUNT_ADDRESS) << LOG_KV("value", value)
<< LOG_KV("gas", gas);
if (isPrecompiled(std::string(receiver)))
{
EXECUTIVE_LOG(DEBUG) << LOG_BADGE("Execute") << "transferBalance, receiverAddress is precompiled address";
EXECUTIVE_LOG(DEBUG) << LOG_BADGE("Execute")
<< "transferBalance, receiverAddress is precompiled address";
return false;
}
// first subAccountBalance, then addAccountBalance
Expand Down Expand Up @@ -374,7 +382,8 @@ bool TransactionExecutive::transferBalance(std::string_view origin, std::string_
{
EXECUTIVE_LOG(DEBUG) << LOG_BADGE("Execute")
<< LOG_DESC("transferBalance add failed, need to restore")
<< LOG_KV("tableName", formTableName) << LOG_KV("will add balance", value);
<< LOG_KV("tableName", formTableName)
<< LOG_KV("will add balance", value);

// if receiver add failed, sender need to restore
// sender = sender + value
Expand Down
7 changes: 7 additions & 0 deletions bcos-executor/src/executive/TransactionExecutive.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,13 @@ class TransactionExecutive : public std::enable_shared_from_this<TransactionExec
void creatAuthTable(std::string_view _tableName, std::string_view _origin,
std::string_view _sender, uint32_t _version);

crypto::HashType getCodeHash(const std::string_view& contractTableName);
std::optional<storage::Entry> getCodeEntryFromContractTable(
const std::string_view contractTableName);
std::optional<storage::Entry> getCodeByHash(const std::string_view& codeHash);
std::optional<storage::Entry> getCodeByContractTableName(
const std::string_view& contractTableName, bool needTryFromContractTable = true);

protected:
bool transferBalance(std::string_view origin, std::string_view sender,
std::string_view receiver, const u256& value, int64_t gas);
Expand Down
19 changes: 5 additions & 14 deletions bcos-executor/src/vm/HostContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,29 +611,20 @@ std::optional<storage::Entry> HostContext::code()
{
if (blockVersion() >= uint32_t(bcos::protocol::BlockVersion::V3_1_VERSION))
{
auto codehash = codeHash();

auto key = std::string_view((char*)codehash.data(), codehash.size());
auto entry = m_executive->storage().getRow(bcos::ledger::SYS_CODE_BINARY, key);
if (entry && !entry->get().empty())
auto hash = codeHash();
auto entry = m_executive->getCodeByHash(std::string_view((char*)hash.data(), hash.size()));
if (entry && entry.has_value() && !entry->get().empty())
{
return entry;
}
}

return m_executive->storage().getRow(m_tableName, ACCOUNT_CODE);
return m_executive->getCodeEntryFromContractTable(m_tableName);
}

crypto::HashType HostContext::codeHash()
{
auto entry = m_executive->storage().getRow(m_tableName, ACCOUNT_CODE_HASH);
if (entry)
{
auto code = entry->getField(0);
return crypto::HashType(code, crypto::HashType::StringDataType::FromBinary);
}

return {};
return m_executive->getCodeHash(m_tableName);
}

bool HostContext::isWasm()
Expand Down

0 comments on commit 3786fa7

Please sign in to comment.