Skip to content

Commit

Permalink
fix many balance bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
JimmyShi22 committed Jan 28, 2024
1 parent 7e11450 commit 52e6fab
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ CallParameters::UniquePtr BillingTransactionExecutive::start(CallParameters::Uni
{
int64_t originGas = input->gas;
uint64_t currentSeq = input->seq;
std::string currentSenderAddr = input->senderAddress;
std::string currentSenderAddr = input->origin;
bool staticCall = input->staticCall;
u256 gasPrice = input->gasPrice;
auto message = TransactionExecutive::execute(std::move(input));
Expand Down
38 changes: 36 additions & 2 deletions bcos-executor/src/executive/TransactionExecutive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ bool TransactionExecutive::transferBalance(std::string_view origin, std::string_
// sender = sender - value
auto codec = CodecWrapper(m_blockContext.hashHandler(), m_blockContext.isWasm());
auto params = codec.encodeWithSig("subAccountBalance(uint256)", value);
auto formTableName = bcos::getContractTableName(executor::USER_APPS_PREFIX, sender);
auto formTableName = getContractTableName(sender, m_blockContext.isWasm());
std::vector<std::string> fromTableNameVector = {formTableName};
auto inputParams = codec.encode(fromTableNameVector, params);
auto subParams = codec.encode(std::string(ACCOUNT_ADDRESS), inputParams);
Expand All @@ -368,7 +368,7 @@ bool TransactionExecutive::transferBalance(std::string_view origin, std::string_
// to add balance
// receiver = receiver + value
auto params1 = codec.encodeWithSig("addAccountBalance(uint256)", value);
auto toTableName = bcos::getContractTableName(executor::USER_APPS_PREFIX, receiver);
auto toTableName = getContractTableName(receiver, m_blockContext.isWasm());
std::vector<std::string> toTableNameVector = {toTableName};
auto inputParams1 = codec.encode(toTableNameVector, params1);
auto addParams = codec.encode(std::string(ACCOUNT_ADDRESS), inputParams1);
Expand Down Expand Up @@ -1694,3 +1694,37 @@ uint8_t TransactionExecutive::checkAccountAvailable(const CallParameters::Unique
return precompiled::AccountPrecompiled::getAccountStatus(
callParameters->origin, shared_from_this());
}

std::string TransactionExecutive::getContractTableName(
const std::string_view& _address, bool isWasm, bool isCreate)
{
auto version = m_blockContext.blockVersion();

if (m_blockContext.isAuthCheck() ||
protocol::versionCompareTo(version, protocol::BlockVersion::V3_3_VERSION) >= 0)
{
if (_address.starts_with(precompiled::SYS_ADDRESS_PREFIX))
{
return std::string(USER_SYS_PREFIX).append(_address);
}
}

std::string_view formatAddress = _address;
if (isWasm)
{
// NOTE: if version < 3.2, then it will allow deploying contracts under /tables. It's a
// bug, but it should maintain data compatibility.
// NOTE2: if it's internalCreate it should allow creating table under /tables
if (protocol::versionCompareTo(version, protocol::BlockVersion::V3_2_VERSION) < 0 ||
!isCreate)
{
if (_address.starts_with(USER_TABLE_PREFIX))
{
return std::string(formatAddress);
}
}
formatAddress = formatAddress.starts_with('/') ? formatAddress.substr(1) : formatAddress;
}

return std::string(USER_APPS_PREFIX).append(formatAddress);
}
41 changes: 5 additions & 36 deletions bcos-executor/src/executive/TransactionExecutive.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,13 @@ class TransactionExecutive : public std::enable_shared_from_this<TransactionExec
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);

std::string getContractTableName(
const std::string_view& _address, bool isWasm = false, bool isCreate = false);

protected:
std::tuple<std::unique_ptr<HostContext>, CallParameters::UniquePtr> call(
CallParameters::UniquePtr callParameters);
CallParameters::UniquePtr callPrecompiled(CallParameters::UniquePtr callParameters);
Expand Down Expand Up @@ -194,41 +198,6 @@ class TransactionExecutive : public std::enable_shared_from_this<TransactionExec
_callParameters.data = std::move(codecOutput);
}

inline std::string getContractTableName(
const std::string_view& _address, bool isWasm = false, bool isCreate = false)
{
auto version = m_blockContext.blockVersion();

if (m_blockContext.isAuthCheck() ||
protocol::versionCompareTo(version, protocol::BlockVersion::V3_3_VERSION) >= 0)
{
if (_address.starts_with(precompiled::SYS_ADDRESS_PREFIX))
{
return std::string(USER_SYS_PREFIX).append(_address);
}
}

std::string_view formatAddress = _address;
if (isWasm)
{
// NOTE: if version < 3.2, then it will allow deploying contracts under /tables. It's a
// bug, but it should maintain data compatibility.
// NOTE2: if it's internalCreate it should allow creating table under /tables
if (protocol::versionCompareTo(version, protocol::BlockVersion::V3_2_VERSION) < 0 ||
!isCreate)
{
if (_address.starts_with(USER_TABLE_PREFIX))
{
return std::string(formatAddress);
}
}
formatAddress =
formatAddress.starts_with('/') ? formatAddress.substr(1) : formatAddress;
}

return std::string(USER_APPS_PREFIX).append(formatAddress);
}

bool checkExecAuth(const CallParameters::UniquePtr& callParameters);
int32_t checkContractAvailable(const CallParameters::UniquePtr& callParameters);
uint8_t checkAccountAvailable(const CallParameters::UniquePtr& callParameters);
Expand Down
24 changes: 16 additions & 8 deletions bcos-executor/src/precompiled/extension/BalancePrecompiled.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ std::shared_ptr<PrecompiledExecResult> BalancePrecompiled::call(
return _callParameters;
}


std::string BalancePrecompiled::getContractTableName(
const std::shared_ptr<executor::TransactionExecutive>& _executive,
const std::string_view& _address)
{
return _executive->getContractTableName(_address, _executive->isWasm(), false);
}

void BalancePrecompiled::createAccount(
const std::shared_ptr<executor::TransactionExecutive>& _executive,
const PrecompiledExecResult::Ptr& _callParameters, const bcos::CodecWrapper& codec,
Expand Down Expand Up @@ -141,7 +149,7 @@ void BalancePrecompiled::getBalance(

// get balance from account table
auto params = codec.encodeWithSig("getAccountBalance()");
auto tableName = getContractTableName(executor::USER_APPS_PREFIX, accountStr);
auto tableName = getContractTableName(_executive, accountStr);
std::vector<std::string> tableNameVector = {tableName};
auto params2 = codec.encode(tableNameVector, params);
auto input = codec.encode(std::string(ACCOUNT_ADDRESS), params2);
Expand Down Expand Up @@ -198,7 +206,7 @@ void BalancePrecompiled::addBalance(
<< LOG_KV("callerEntry", entry->get());

// check the account whether exist, if not exist, create the account
auto accountTableName = getContractTableName(executor::USER_APPS_PREFIX, accountStr);
auto accountTableName = getContractTableName(_executive, accountStr);
auto table1 = _executive->storage().openTable(accountTableName);
if (!table1)
{
Expand Down Expand Up @@ -259,7 +267,7 @@ void BalancePrecompiled::subBalance(
}

// check the account whether exist, if not exist, create the account
auto accountTableName = getContractTableName(executor::USER_APPS_PREFIX, accountStr);
auto accountTableName = getContractTableName(_executive, accountStr);
auto table1 = _executive->storage().openTable(accountTableName);
if (!table1)
{
Expand All @@ -275,7 +283,7 @@ void BalancePrecompiled::subBalance(

// AccountPrecompiledAddress + subAccountBalance(value), internal call
auto balanceParams = codec.encodeWithSig("subAccountBalance(uint256)", value);
auto tableName = getContractTableName(executor::USER_APPS_PREFIX, accountStr);
auto tableName = getContractTableName(_executive, accountStr);
std::vector<std::string> tableNameVector = {tableName};
auto inputParams = codec.encode(tableNameVector, balanceParams);

Expand Down Expand Up @@ -329,12 +337,12 @@ void BalancePrecompiled::transfer(const std::shared_ptr<executor::TransactionExe
// first subAccountBalance, then addAccountBalance

auto params = codec.encodeWithSig("subAccountBalance(uint256)", value);
auto formTableName = getContractTableName(executor::USER_APPS_PREFIX, fromStr);
auto formTableName = getContractTableName(_executive, fromStr);
std::vector<std::string> fromTableNameVector = {formTableName};
auto inputParams = codec.encode(fromTableNameVector, params);

// check the from account whether exist, if not exist, create the account
auto fromAccountTableName = getContractTableName(executor::USER_APPS_PREFIX, fromStr);
auto fromAccountTableName = getContractTableName(_executive, fromStr);
auto fromTable = _executive->storage().openTable(fromAccountTableName);
if (!fromTable)
{
Expand All @@ -356,13 +364,13 @@ void BalancePrecompiled::transfer(const std::shared_ptr<executor::TransactionExe
if (subBalanceResult->status == int32_t(CODE_SUCCESS))
{
auto params1 = codec.encodeWithSig("addAccountBalance(uint256)", value);
auto toTableName = getContractTableName(executor::USER_APPS_PREFIX, toStr);
auto toTableName = getContractTableName(_executive, toStr);
std::vector<std::string> toTableNameVector = {toTableName};
auto inputParams1 = codec.encode(toTableNameVector, params1);
auto addParams = codec.encode(std::string(ACCOUNT_ADDRESS), inputParams1);

// check the to account whether exist, if not exist, create the account
auto toAccountTableName = getContractTableName(executor::USER_APPS_PREFIX, toStr);
auto toAccountTableName = getContractTableName(_executive, toStr);
auto toTable = _executive->storage().openTable(toAccountTableName);
if (!toTable)
{
Expand Down
4 changes: 4 additions & 0 deletions bcos-executor/src/precompiled/extension/BalancePrecompiled.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ class BalancePrecompiled : public bcos::precompiled::Precompiled
PrecompiledExecResult::Ptr const& _callParameters, const CodecWrapper& codec,
std::string_view accountHex);

inline std::string getContractTableName(
const std::shared_ptr<executor::TransactionExecutive>& _executive,
const std::string_view& _address);

private:
mutable std::map<std::string, u256> m_fakeBalancePrecompiled;
};
Expand Down
9 changes: 3 additions & 6 deletions bcos-executor/src/vm/EVMHostInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,7 @@ evmc_bytes32 getBalance(evmc_host_context* _context, const evmc_address* _addr)
const auto& codec = bcos::CodecWrapper(blockContext.hashHandler(), blockContext.isWasm());
// get balance from account table
auto params = codec.encodeWithSig("getAccountBalance()");
auto tableName =
getContractTableName(executor::USER_APPS_PREFIX, address2HexString(_msg.recipient));
auto tableName = hostContext.getContractTableName(address2HexString(_msg.recipient));
std::vector<std::string> tableNameVector = {tableName};
auto input = codec.encode(tableNameVector, params);
bytes_view getBalance = bytes_view(input.data(), input.size());
Expand Down Expand Up @@ -200,8 +199,7 @@ bool selfdestruct(evmc_host_context* _context, const evmc_address* _addr,
// get _addr balance
const auto& codec = bcos::CodecWrapper(blockContext.hashHandler(), blockContext.isWasm());
bytes params = codec.encodeWithSig("getAccountBalance()");
auto tableName =
getContractTableName(executor::USER_APPS_PREFIX, address2HexString(_msg.recipient));
auto tableName = hostContext.getContractTableName(address2HexString(_msg.recipient));
std::vector<std::string> tableNameVector = {tableName};
auto getBalanceIn = codec.encode(tableNameVector, params);

Expand Down Expand Up @@ -239,8 +237,7 @@ bool selfdestruct(evmc_host_context* _context, const evmc_address* _addr,
// _beneficiary += balance
_msg.recipient = *_beneficiary;
bytes addParams = codec.encodeWithSig("addAccountBalance(uint256)", balance);
auto addTableName =
getContractTableName(executor::USER_APPS_PREFIX, address2HexString(_msg.recipient));
auto addTableName = hostContext.getContractTableName(address2HexString(_msg.recipient));
std::vector<std::string> addTableNameVector = {addTableName};
auto addBalanceIn = codec.encode(addTableNameVector, addParams);
bytes_view addBalance = bytes_view(addBalanceIn.data(), addBalanceIn.size());
Expand Down
25 changes: 24 additions & 1 deletion bcos-executor/src/vm/HostContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,15 @@ evmc_result HostContext::externalRequest(const evmc_message* _msg)
request->delegateCall = true;
request->codeAddress = evmAddress2String(_msg->code_address);
request->delegateCallSender = evmAddress2String(_msg->sender);
request->receiveAddress = codeAddress();

if (features().get(ledger::Features::Flag::bugfix_call_noaddr_return))
{
request->receiveAddress = myAddress();
}
else
{
request->receiveAddress = codeAddress();
}
request->data.assign(_msg->input_data, _msg->input_data + _msg->input_size);
break;
}
Expand Down Expand Up @@ -328,6 +336,21 @@ evmc_result HostContext::callBuiltInPrecompiled(
m_callParameters->logEntries = std::move(_request->logEntries);
}

if (features().get(ledger::Features::Flag::feature_balance) && _request->value > 0) [[unlikely]]
{
// must transfer balance
if (!m_executive->transferBalance(_request->origin, _request->senderAddress,
_request->receiveAddress, static_cast<u256>(_request->value), _request->gas))
{
callResults->type = CallParameters::REVERT;
callResults->status = (int32_t)TransactionStatus::NotEnoughCash;
preResult.status_code = EVMC_INSUFFICIENT_BALANCE;
preResult.gas_left = _request->gas;
m_responseStore.emplace_back(std::move(callResults));
return preResult;
}
}

if (resultCode != (int32_t)TransactionStatus::None)
{
callResults->type = CallParameters::REVERT;
Expand Down
5 changes: 5 additions & 0 deletions bcos-executor/src/vm/HostContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@ class HostContext : public evmc_host_context
return m_executive->blockContext().features();
}

std::string getContractTableName(const std::string_view& _address)
{
return m_executive->getContractTableName(_address, isWasm(), isCreate());
}

protected:
const CallParameters::UniquePtr& getCallParameters() const { return m_callParameters; }
virtual bcos::bytes externalCodeRequest(const std::string_view& address);
Expand Down
4 changes: 2 additions & 2 deletions bcos-scheduler/src/SchedulerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,11 +510,11 @@ void SchedulerImpl::commitBlock(bcos::protocol::BlockHeader::Ptr header,
std::shared_ptr<std::unique_lock<std::mutex>> commitLock =
std::make_shared<std::unique_lock<std::mutex>>(m_commitMutex, std::try_to_lock);

if (!commitLock->owns_lock())
if (!commitLock->try_lock_for(std::chrono::seconds(1)))
{
std::string message =
(boost::format("commitBlock: Another block is committing! Block to commit "
"number: %ld, hash: %s") %
"number: %ld, hash: %s, waiting for it") %
requestBlockNumber % header->hash().abridged())
.str();

Expand Down

0 comments on commit 52e6fab

Please sign in to comment.