executor/contract/manager/contract_manager.cpp (107 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "executor/contract/manager/contract_manager.h" #include "eEVM/processor.h" #include "executor/contract/manager/address_manager.h" #include "glog/logging.h" namespace resdb { namespace contract { void AppendArgToInput(std::vector<uint8_t>& code, const uint256_t& arg) { const auto pre_size = code.size(); code.resize(pre_size + 32u); eevm::to_big_endian(arg, code.data() + pre_size); } void AppendArgToInput(std::vector<uint8_t>& code, const std::string& arg) { AppendArgToInput(code, eevm::to_uint256(arg)); } ContractManager::ContractManager(Storage* storage) { gs_ = std::make_unique<GlobalState>(storage); } std::string ContractManager::GetFuncAddress(const Address& contract_address, const std::string& func_name) { return func_address_[contract_address][func_name]; } void ContractManager::SetFuncAddress(const Address& contract_address, const FuncInfo& func) { func_address_[contract_address][func.func_name()] = func.hash(); } Address ContractManager::DeployContract(const Address& owner_address, const DeployInfo& deploy_info) { const auto contract_address = AddressManager::CreateContractAddress(owner_address); auto contract_constructor = eevm::to_bytes(deploy_info.contract_bin()); for (const std::string& param : deploy_info.init_param()) { AppendArgToInput(contract_constructor, param); } try { auto contract = gs_->create(contract_address, 0u, contract_constructor); auto result = Execute(owner_address, contract_address, {}); if (result.ok()) { // set the initialized class context code. contract.acc.set_code(std::move(*result)); for (const auto& info : deploy_info.func_info()) { SetFuncAddress(contract_address, info); } return contract.acc.get_address(); } else { gs_->remove(contract_address); return 0; } } catch (...) { LOG(ERROR) << "Deploy throw expection"; return 0; } } absl::StatusOr<eevm::AccountState> ContractManager::GetContract( const Address& address) { if (!gs_->Exists(address)) { return absl::InvalidArgumentError("Contract not exist."); } return gs_->get(address); } absl::StatusOr<std::string> ContractManager::ExecContract( const Address& caller_address, const Address& contract_address, const Params& func_param) { std::string func_addr = GetFuncAddress(contract_address, func_param.func_name()); if (func_addr.empty()) { LOG(ERROR) << "no fouction:" << func_param.func_name(); return absl::InvalidArgumentError("Func not exist."); } std::vector<uint8_t> inputs = eevm::to_bytes(func_addr); for (const std::string& param : func_param.param()) { AppendArgToInput(inputs, param); } auto result = Execute(caller_address, contract_address, inputs); if (result.ok()) { return eevm::to_hex_string(*result); } return result.status(); } absl::StatusOr<std::vector<uint8_t>> ContractManager::Execute( const Address& caller_address, const Address& contract_address, const std::vector<uint8_t>& input) { // Ignore any logs produced by this transaction eevm::NullLogHandler ignore; eevm::Transaction tx(caller_address, ignore); // Record a trace to aid debugging eevm::Trace tr; eevm::Processor p(*gs_); // Run the transaction try { const auto exec_result = p.run(tx, caller_address, gs_->get(contract_address), input, 0u, &tr); if (exec_result.er != eevm::ExitReason::returned) { // Print the trace if nothing was returned if (exec_result.er == eevm::ExitReason::threw) { return absl::InternalError( fmt::format("Execution error: {}", exec_result.exmsg)); } return absl::InternalError("Deployment did not return"); } return exec_result.output; } catch (...) { return absl::InternalError(fmt::format("Execution error:")); } } std::string ContractManager::GetBalance(const Address& account) { return gs_->GetBalance(account); } int ContractManager::SetBalance(const Address& account, const uint256_t& balance) { return gs_->SetBalance(account, balance); } } // namespace contract } // namespace resdb