Loading...
Searching...
No Matches
contract_manager.cpp
Go to the documentation of this file.
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
21
22#include "eEVM/processor.h"
24#include "glog/logging.h"
25
26namespace resdb {
27namespace contract {
28
29void AppendArgToInput(std::vector<uint8_t>& code, const uint256_t& arg) {
30 const auto pre_size = code.size();
31 code.resize(pre_size + 32u);
32 eevm::to_big_endian(arg, code.data() + pre_size);
33}
34
35void AppendArgToInput(std::vector<uint8_t>& code, const std::string& arg) {
36 AppendArgToInput(code, eevm::to_uint256(arg));
37}
38
40 gs_ = std::make_unique<eevm::SimpleGlobalState>();
41}
42
43std::string ContractManager::GetFuncAddress(const Address& contract_address,
44 const std::string& func_name) {
45 return func_address_[contract_address][func_name];
46}
47
48void ContractManager::SetFuncAddress(const Address& contract_address,
49 const FuncInfo& func) {
50 func_address_[contract_address][func.func_name()] = func.hash();
51}
52
54 const DeployInfo& deploy_info) {
55 const auto contract_address =
57
58 auto contract_constructor = eevm::to_bytes(deploy_info.contract_bin());
59 for (const std::string& param : deploy_info.init_param()) {
60 AppendArgToInput(contract_constructor, param);
61 }
62
63 try {
64 auto contract = gs_->create(contract_address, 0u, contract_constructor);
65
66 auto result = Execute(owner_address, contract_address, {});
67 if (result.ok()) {
68 // set the initialized class context code.
69 contract.acc.set_code(std::move(*result));
70
71 for (const auto& info : deploy_info.func_info()) {
72 SetFuncAddress(contract_address, info);
73 }
74 return contract.acc.get_address();
75 } else {
76 gs_->remove(contract_address);
77 return 0;
78 }
79 } catch (...) {
80 LOG(ERROR) << "Deploy throw expection";
81 return 0;
82 }
83}
84
85absl::StatusOr<eevm::AccountState> ContractManager::GetContract(
86 const Address& address) {
87 if (!gs_->exists(address)) {
88 return absl::InvalidArgumentError("Contract not exist.");
89 }
90
91 return gs_->get(address);
92}
93
94absl::StatusOr<std::string> ContractManager::ExecContract(
95 const Address& caller_address, const Address& contract_address,
96 const Params& func_param) {
97 std::string func_addr =
98 GetFuncAddress(contract_address, func_param.func_name());
99 if (func_addr.empty()) {
100 LOG(ERROR) << "no fouction:" << func_param.func_name();
101 return absl::InvalidArgumentError("Func not exist.");
102 }
103
104 std::vector<uint8_t> inputs = eevm::to_bytes(func_addr);
105 for (const std::string& param : func_param.param()) {
106 AppendArgToInput(inputs, param);
107 }
108
109 auto result = Execute(caller_address, contract_address, inputs);
110
111 if (result.ok()) {
112 return eevm::to_hex_string(*result);
113 }
114 return result.status();
115}
116
117absl::StatusOr<std::vector<uint8_t>> ContractManager::Execute(
118 const Address& caller_address, const Address& contract_address,
119 const std::vector<uint8_t>& input) {
120 // Ignore any logs produced by this transaction
121 eevm::NullLogHandler ignore;
122 eevm::Transaction tx(caller_address, ignore);
123
124 // Record a trace to aid debugging
125 eevm::Trace tr;
126 eevm::Processor p(*gs_);
127
128 // Run the transaction
129 try {
130 const auto exec_result =
131 p.run(tx, caller_address, gs_->get(contract_address), input, 0u, &tr);
132
133 if (exec_result.er != eevm::ExitReason::returned) {
134 // Print the trace if nothing was returned
135 if (exec_result.er == eevm::ExitReason::threw) {
136 return absl::InternalError(
137 fmt::format("Execution error: {}", exec_result.exmsg));
138 }
139 return absl::InternalError("Deployment did not return");
140 }
141 return exec_result.output;
142 } catch (...) {
143 return absl::InternalError(fmt::format("Execution error:"));
144 }
145}
146
147} // namespace contract
148} // namespace resdb
static Address CreateContractAddress(const Address &owner)
Address DeployContract(const Address &owner_address, const DeployInfo &deploy_info)
absl::StatusOr< eevm::AccountState > GetContract(const Address &address)
absl::StatusOr< std::string > ExecContract(const Address &caller_address, const Address &contract_address, const Params &func_param)
eevm::Address Address
Definition utils.h:27
void AppendArgToInput(std::vector< uint8_t > &code, const uint256_t &arg)