24 std::shared_ptr<broker::interface> broker,
25 std::shared_ptr<logging::log> log,
28 m_srv(std::move(srv)) {
29 m_srv->register_handler_callback(
30 [&](
const std::string& method,
31 const Json::Value& params,
33 return request_handler(method, params, callback);
38 m_log->trace(
"Agent server shutting down...");
40 m_log->trace(
"Shut down agent server");
47 auto http_server::request_handler(
48 const std::string& method,
49 const Json::Value& params,
50 const server_type::result_callback_type& callback) ->
bool {
51 m_log->trace(
"http_server::request_handler() received request",
54 auto maybe_handled = handle_supported(method, params, callback);
55 if(maybe_handled.has_value()) {
56 return maybe_handled.value();
59 maybe_handled = handle_static(method, params, callback);
60 if(maybe_handled.has_value()) {
61 return maybe_handled.value();
64 return handle_unsupported(method, params, callback);
67 auto http_server::handle_supported(
68 const std::string& method,
69 const Json::Value& params,
70 const server_type::result_callback_type& callback)
71 -> std::optional<bool> {
72 if(method ==
"eth_sendRawTransaction") {
73 return handle_send_raw_transaction(params, callback);
76 if(method ==
"eth_sendTransaction") {
77 return handle_send_transaction(params, callback);
80 if(method ==
"eth_getTransactionCount") {
81 return handle_get_transaction_count(params, callback);
84 if(method ==
"eth_call") {
85 return handle_call(params, callback);
88 if(method ==
"eth_gasPrice") {
89 return handle_gas_price(params, callback);
92 if(method ==
"eth_getCode") {
93 return handle_get_code(params, callback);
96 if(method ==
"eth_getBalance") {
97 return handle_get_balance(params, callback);
100 if(method ==
"eth_accounts") {
101 return handle_accounts(params, callback);
104 if(method ==
"eth_getTransactionByHash") {
105 return handle_get_transaction_by_hash(params, callback);
108 if(method ==
"eth_getTransactionReceipt") {
109 return handle_get_transaction_receipt(params, callback);
112 if(method ==
"eth_getBlockByNumber"
113 || method ==
"eth_getBlockByHash") {
114 return handle_get_block(params, callback);
117 if(method ==
"eth_getBlockTransactionCountByHash"
118 || method ==
"eth_getBlockTransactionCountByNumber") {
119 return handle_get_block_txcount(params, callback);
122 if(method ==
"eth_getTransactionByBlockHashAndIndex"
123 || method ==
"eth_getTransactionByBlockNumberAndIndex") {
124 return handle_get_block_tx(params, callback);
127 if(method ==
"eth_blockNumber") {
128 return handle_block_number(params, callback);
131 if(method ==
"eth_feeHistory") {
132 return handle_fee_history(params, callback);
135 if(method ==
"eth_getLogs") {
136 return handle_get_logs(params, callback);
139 if(method ==
"eth_getStorageAt") {
140 return handle_get_storage_at(params, callback);
146 auto http_server::handle_static(
147 const std::string& method,
148 const Json::Value& params,
149 const server_type::result_callback_type& callback)
150 -> std::optional<bool> {
151 if(method ==
"eth_chainId" || method ==
"net_version") {
152 return handle_chain_id(params, callback);
155 if(method ==
"web3_clientVersion") {
156 return handle_client_version(params, callback);
159 if(method ==
"eth_decodeRawTransaction") {
160 return handle_decode_raw_transaction(params, callback);
163 if(method ==
"web3_sha3") {
164 return handle_sha3(params, callback);
167 if(method ==
"eth_estimateGas") {
168 return handle_estimate_gas(params, callback);
174 auto http_server::handle_unsupported(
175 const std::string& method,
176 const Json::Value& params,
177 const server_type::result_callback_type& callback) ->
bool {
178 if(method ==
"eth_signTransaction" || method ==
"eth_sign") {
182 error_code::wallet_not_supported,
183 "Wallet support not enabled - sign transactions "
184 "locally before submitting");
187 if(method ==
"eth_uninstallFilter"
188 || method ==
"eth_newPendingTransactionFilter"
189 || method ==
"eth_newFilter" || method ==
"eth_newBlockFilter"
190 || method ==
"eth_getFilterLogs"
191 || method ==
"eth_getFilterChanges") {
192 return handle_error(params,
194 error_code::wallet_not_supported,
195 "OpenCBDC does not support filters");
198 if(method ==
"eth_getWork" || method ==
"eth_submitWork"
199 || method ==
"eth_submitHashrate") {
200 return handle_error(params,
202 error_code::mining_not_supported,
203 "OpenCBDC does not use mining");
206 if(method ==
"evm_increaseTime") {
207 return handle_error(params,
209 error_code::time_travel_not_supported,
210 "OpenCBDC does not support time travel");
213 if(method ==
"eth_getCompilers" || method ==
"eth_compileSolidity"
214 || method ==
"eth_compileLLL" || method ==
"eth_compileSerpent") {
215 return handle_error(params,
217 error_code::compiler_not_supported,
218 "OpenCBDC does not provide compiler support - "
219 "compile contracts locally before submitting");
222 if(method ==
"eth_coinbase") {
223 return handle_error(params,
225 error_code::coinbase_not_supported,
226 "Coinbase payouts are not used in OpenCBDC");
229 if(method ==
"eth_getUncleByBlockHashAndIndex"
230 || method ==
"eth_getUncleByBlockNumberAndIndex") {
232 return handle_error(params,
234 error_code::uncles_not_supported,
235 "Uncle block not found");
238 if(method ==
"eth_getUncleCountByBlockHash"
239 || method ==
"eth_getUncleCountByBlockNumber"
240 || method ==
"eth_hashrate") {
242 return handle_number(params, callback, 0);
245 if(method ==
"eth_mining") {
246 return handle_boolean(params, callback,
false);
249 if(method ==
"eth_syncing") {
250 return handle_boolean(params, callback,
false);
253 if(method ==
"net_listening") {
254 return handle_boolean(params, callback,
false);
257 if(method ==
"net_peerCount") {
258 return handle_number(params, callback, 1);
261 m_log->warn(
"Unknown method", method);
262 return handle_error(params,
264 error_code::unknown_method,
265 "Unknown method: " + method);
268 auto http_server::handle_decode_raw_transaction(
270 const server_type::result_callback_type& callback) ->
bool {
272 if(!maybe_tx.has_value()) {
273 m_log->warn(
"Unable to deserialize transaction");
276 auto& tx = maybe_tx.value();
277 auto ret = Json::Value();
283 auto http_server::handle_send_raw_transaction(
285 const server_type::result_callback_type& callback) ->
bool {
286 auto res_cb = std::function<void(interface::exec_return_type)>();
289 if(!maybe_tx.has_value()) {
290 m_log->warn(
"Unable to deserialize transaction");
293 auto& tx = maybe_tx.value();
296 return exec_tx(callback,
302 auto ret = Json::Value();
303 ret[
"result"] =
"0x" + txid.to_hex();
308 auto http_server::handle_fee_history(
310 const server_type::result_callback_type& callback) ->
bool {
311 auto ret = Json::Value();
313 if(!params.isArray() || params.size() < 3 || !params[0].isString()
314 || !params[1].isString() || !params[2].isArray()) {
315 m_log->warn(
"Invalid parameters to feeHistory");
319 auto blocks_str = params[0].asString();
321 auto end_block_str = params[1].asString();
322 uint64_t end_block = 0;
323 if(end_block_str ==
"latest" || end_block_str ==
"pending") {
324 end_block = m_broker->highest_ticket();
328 ret[
"error"] = Json::Value();
329 ret[
"error"][
"code"] = error_code::invalid_block_identifier;
330 ret[
"error"][
"message"] =
"Invalid block identifier";
334 end_block =
to_uint64(maybe_block.value());
336 blocks = std::stoull(blocks_str);
337 if(blocks > end_block) {
340 ret[
"result"] = Json::Value();
341 ret[
"result"][
"oldestBlock"]
343 ret[
"result"][
"reward"] = Json::Value(Json::arrayValue);
344 ret[
"result"][
"baseFeePerGas"] = Json::Value(Json::arrayValue);
345 ret[
"result"][
"gasUsedRatio"] = Json::Value(Json::arrayValue);
346 for(uint64_t i = 0; i < blocks; i++) {
347 auto rwd = Json::Value(Json::arrayValue);
348 for(Json::ArrayIndex j = 0; j < params[2].size(); j++) {
351 ret[
"result"][
"reward"].append(rwd);
352 ret[
"result"][
"baseFeePerGas"].append(
"0x0");
353 ret[
"result"][
"gasUsedRatio"].append(0.0);
355 ret[
"result"][
"baseFeePerGas"].append(
"0x0");
360 auto http_server::handle_get_transaction_count(
362 const server_type::result_callback_type& callback) ->
bool {
363 if(!params.isArray() || params.empty() || !params[0].isString()) {
364 m_log->warn(
"Invalid parameters to getTransactionCount");
368 auto params_str = params[0].asString();
369 auto maybe_runner_params
371 if(!maybe_runner_params.has_value()) {
372 m_log->warn(
"Unable to decode params", params_str);
375 auto runner_params = std::move(maybe_runner_params.value());
382 auto ret = Json::Value();
384 auto& updates = std::get<return_type>(res);
385 auto it = updates.find(runner_params);
387 if(it == updates.end() || it->second.size() == 0) {
396 if(!maybe_acc.has_value()) {
397 ret[
"error"] = Json::Value();
398 ret[
"error"][
"code"] = error_code::internal_error;
399 ret[
"error"][
"message"] =
"Internal error";
404 auto& acc = maybe_acc.value();
406 auto tx_count = acc.m_nonce + evmc::uint256be(1);
412 auto http_server::handle_get_balance(
414 const server_type::result_callback_type& callback) ->
bool {
415 if(!params.isArray() || params.empty() || !params[0].isString()) {
416 m_log->warn(
"Invalid parameters to getBalance");
420 auto params_str = params[0].asString();
421 auto maybe_runner_params
423 if(!maybe_runner_params.has_value()) {
424 m_log->warn(
"Unable to decode params", params_str);
427 auto runner_params = std::move(maybe_runner_params.value());
434 auto ret = Json::Value();
435 auto& updates = std::get<return_type>(res);
436 auto it = updates.find(runner_params);
437 if(it == updates.end() || it->second.size() == 0) {
439 ret[
"result"] =
"0x0";
446 if(!maybe_acc.has_value()) {
447 ret[
"error"] = Json::Value();
448 ret[
"error"][
"code"] = error_code::internal_error;
449 ret[
"error"][
"message"] =
"Internal error";
454 auto& acc = maybe_acc.value();
460 auto http_server::handle_get_storage_at(
462 const server_type::result_callback_type& callback) ->
bool {
463 if(!params.isArray() || params.empty() || !params[0].isString()
464 || !params[1].isString()) {
465 m_log->warn(
"Invalid parameters to getBalance");
470 if(!maybe_addr.has_value()) {
471 m_log->warn(
"Unable to decode params");
474 auto key_str = params[1].asString();
476 if(!maybe_key.has_value()) {
477 m_log->warn(
"Unable to decode params", key_str);
482 storage_key{maybe_addr.value(), maybe_key.value()});
489 auto ret = Json::Value();
490 auto& updates = std::get<return_type>(res);
491 auto it = updates.find(runner_params);
492 if(it == updates.end() || it->second.size() == 0) {
494 ret[
"result"] =
"0x";
499 ret[
"result"] =
"0x" + it->second.to_hex();
504 auto http_server::handle_get_transaction_by_hash(
506 const server_type::result_callback_type& callback) ->
bool {
507 if(!params.isArray() || params.empty() || !params[0].isString()) {
508 m_log->warn(
"Invalid parameters to getTransactionByHash");
511 auto params_str = params[0].asString();
512 auto maybe_runner_params
514 if(!maybe_runner_params.has_value()) {
515 m_log->warn(
"Unable to decode params", params_str);
518 auto runner_params = std::move(maybe_runner_params.value());
525 auto ret = Json::Value();
526 auto& updates = std::get<return_type>(res);
527 auto it = updates.find(runner_params);
528 if(it == updates.end() || it->second.size() == 0) {
529 ret[
"error"] = Json::Value();
530 ret[
"error"][
"code"] = error_code::not_found;
531 ret[
"error"][
"message"] =
"Transaction not found";
538 if(!maybe_tx.has_value()) {
539 ret[
"error"] = Json::Value();
540 ret[
"error"][
"code"] = error_code::internal_error;
541 ret[
"error"][
"message"] =
"Internal error";
546 auto& tx_rcpt = maybe_tx.value();
547 auto json_tx =
tx_to_json(tx_rcpt.m_tx, m_secp);
550 auto block_num = evmc::uint256be(tx_rcpt.m_ticket_number);
551 json_tx[
"blockHash"] =
"0x" +
to_hex(block_num);
553 json_tx[
"transactionIndex"] =
"0x0";
555 ret[
"result"] = json_tx;
560 auto http_server::extract_evm_log_query_addresses(
562 const server_type::result_callback_type& callback,
564 auto parseError =
false;
565 if(params[0][
"address"].isString()) {
568 qry.m_addresses.push_back(maybe_addr.value());
572 }
else if(params[0][
"address"].isArray()) {
573 for(
auto& val : params[0][
"address"]) {
576 qry.m_addresses.push_back(maybe_addr.value());
583 if(qry.m_addresses.empty() || parseError) {
584 auto ret = Json::Value();
585 ret[
"error"] = Json::Value();
586 ret[
"error"][
"code"] = error_code::invalid_address;
587 ret[
"error"][
"message"]
588 =
"Address(es) in your query are either absent or invalid";
596 auto http_server::extract_evm_log_query_topics(
598 const server_type::result_callback_type& callback,
600 auto parseError =
false;
601 if(params[0][
"topics"].isArray()) {
602 for(
auto& val : params[0][
"topics"]) {
605 qry.m_topics.push_back(maybe_topic.value());
612 if(qry.m_topics.empty() || parseError) {
613 auto ret = Json::Value();
614 ret[
"error"] = Json::Value();
615 ret[
"error"][
"code"] = error_code::invalid_topic;
616 ret[
"error"][
"message"]
617 =
"Topic(s) in your query are either absent or invalid";
625 auto http_server::extract_evm_log_query_block(
627 const server_type::result_callback_type& callback,
629 auto ret = Json::Value();
631 if(params[0][
"blockhash"].isString()) {
634 if(!maybe_block_num) {
635 m_log->warn(
"Invalid blockNumber / hash parameter");
637 ret[
"error"] = Json::Value();
638 ret[
"error"][
"code"] = error_code::invalid_block_parameter;
639 ret[
"error"][
"message"]
640 =
"Invalid blockNumber / hash parameter";
644 qry.m_from_block =
to_uint64(maybe_block_num.value());
645 qry.m_to_block = qry.m_from_block;
646 }
else if(params[0][
"fromBlock"].isString()
647 && params[0][
"toBlock"].isString()) {
648 auto highest_ticket_number = m_broker->highest_ticket();
649 if(params[0][
"fromBlock"].asString() ==
"latest") {
650 qry.m_from_block = highest_ticket_number;
654 if(!maybe_block_num) {
655 m_log->warn(
"Invalid fromBlock parameter");
656 ret[
"error"] = Json::Value();
657 ret[
"error"][
"code"] = error_code::invalid_block_parameter;
658 ret[
"error"][
"message"] =
"Invalid fromBlock parameter";
662 qry.m_from_block =
to_uint64(maybe_block_num.value());
665 if(params[0][
"toBlock"].asString() ==
"latest") {
666 qry.m_to_block = highest_ticket_number;
670 if(!maybe_block_num) {
671 m_log->warn(
"Invalid toBlock parameter");
672 ret[
"error"] = Json::Value();
673 ret[
"error"][
"code"] = error_code::invalid_block_parameter;
674 ret[
"error"][
"message"] =
"Invalid toBlock parameter";
678 qry.m_to_block =
to_uint64(maybe_block_num.value());
681 ret[
"error"] = Json::Value();
682 ret[
"error"][
"code"] = error_code::invalid_block_parameter;
683 ret[
"error"][
"message"]
684 =
"from/toBlock or blockHash parameter missing";
689 auto block_count =
static_cast<int64_t
>(qry.m_to_block)
690 -
static_cast<int64_t
>(qry.m_from_block);
692 if(block_count < 0) {
693 ret[
"error"] = Json::Value();
694 ret[
"error"][
"code"] = error_code::from_block_after_to;
695 ret[
"error"][
"message"] =
"From block cannot be after to block";
700 auto uint_block_count =
static_cast<uint64_t
>(block_count);
702 constexpr auto max_block_count = 100;
703 if(uint_block_count * qry.m_addresses.size() > max_block_count) {
704 ret[
"error"] = Json::Value();
705 ret[
"error"][
"code"] = error_code::block_range_too_large;
706 ret[
"error"][
"message"] =
"The product of address count and block "
707 "range in your query cannot exceed 100";
715 auto http_server::parse_evm_log_query(
716 const Json::Value& params,
717 const server_type::result_callback_type& callback)
718 -> std::optional<parsec::agent::runner::evm_log_query> {
721 auto success = extract_evm_log_query_addresses(params, callback, qry);
726 success = extract_evm_log_query_topics(params, callback, qry);
731 success = extract_evm_log_query_block(params, callback, qry);
739 void http_server::handle_get_logs_result(
740 const server_type::result_callback_type& callback,
744 auto ret = Json::Value();
745 auto& updates = std::get<return_type>(res);
746 auto it = updates.find(runner_params);
747 if(it == updates.end() || it->second.size() == 0) {
748 ret[
"error"] = Json::Value();
749 ret[
"error"][
"code"] = error_code::not_found;
750 ret[
"error"][
"message"] =
"Logs not found";
757 if(!maybe_logs.has_value()) {
758 ret[
"error"] = Json::Value();
759 ret[
"error"][
"code"] = error_code::internal_error;
760 ret[
"error"][
"message"] =
"Internal error";
765 auto& logs = maybe_logs.value();
766 ret[
"result"] = Json::Value(Json::arrayValue);
767 for(
auto& log_idx : logs) {
768 for(
auto& log : log_idx.m_logs) {
770 for(
auto& have_topic : log.m_topics) {
771 for(
const auto& want_topic : qry.
m_topics) {
772 if(have_topic == want_topic) {
782 ret[
"result"].append(
784 log_idx.m_ticket_number,
792 auto http_server::handle_get_logs(
794 const server_type::result_callback_type& callback) ->
bool {
795 if(!params.isArray() || params.empty() || !params[0].isObject()) {
796 m_log->warn(
"Invalid parameters to getLogs");
797 auto ret = Json::Value();
798 ret[
"error"] = Json::Value();
800 ret[
"error"][
"code"] = error_code::invalid_block_parameter;
801 ret[
"error"][
"message"] =
"Invalid parameters to getLogs";
806 auto maybe_qry = parse_evm_log_query(params, callback);
812 auto qry = maybe_qry.value();
820 handle_get_logs_result(callback,
827 auto http_server::handle_get_transaction_receipt(
829 const server_type::result_callback_type& callback) ->
bool {
830 if(!params.isArray() || params.empty() || !params[0].isString()) {
831 m_log->warn(
"Invalid parameters to getTransactionReceipt");
832 auto ret = Json::Value();
833 ret[
"error"] = Json::Value();
834 ret[
"error"][
"code"] = error_code::invalid_block_parameter;
835 ret[
"error"][
"message"]
836 =
"Invalid parameters to getTransactionReceipt";
840 auto params_str = params[0].asString();
841 auto maybe_runner_params
843 if(!maybe_runner_params.has_value()) {
844 m_log->warn(
"Unable to decode params", params_str);
847 auto runner_params = std::move(maybe_runner_params.value());
854 auto ret = Json::Value();
855 auto& updates = std::get<return_type>(res);
856 auto it = updates.find(runner_params);
857 if(it == updates.end() || it->second.size() == 0) {
858 ret[
"error"] = Json::Value();
859 ret[
"error"][
"code"] = error_code::not_found;
860 ret[
"error"][
"message"] =
"Transaction not found";
867 if(!maybe_rcpt.has_value()) {
868 ret[
"error"] = Json::Value();
869 ret[
"error"][
"code"] = error_code::internal_error;
870 ret[
"error"][
"message"] =
"Internal error";
875 auto& rcpt = maybe_rcpt.value();
882 auto http_server::handle_get_code(
884 const server_type::result_callback_type& callback) ->
bool {
885 if(!params.isArray() || params.empty() || !params[0].isString()) {
886 m_log->warn(
"Invalid parameters to getCode");
887 auto ret = Json::Value();
888 ret[
"error"] = Json::Value();
889 ret[
"error"][
"code"] = error_code::invalid_block_parameter;
890 ret[
"error"][
"message"] =
"Invalid parameters to getCode";
895 auto params_str = params[0].asString();
896 auto maybe_runner_params
898 if(!maybe_runner_params.has_value()) {
899 m_log->warn(
"Unable to decode params", params_str);
900 auto ret = Json::Value();
901 ret[
"error"] = Json::Value();
902 ret[
"error"][
"code"] = error_code::execution_error;
903 ret[
"error"][
"message"]
904 =
"Unable to decode getCode parameters: " + params_str;
908 auto runner_params = std::move(maybe_runner_params.value());
915 auto ret = Json::Value();
916 auto& updates = std::get<return_type>(res);
917 auto it = updates.find(runner_params);
918 if(it == updates.end() || it->second.size() == 0) {
920 ret[
"result"] =
"0x";
924 ret[
"result"] =
"0x" + it->second.to_hex();
929 auto http_server::handle_chain_id(
931 const server_type::result_callback_type& callback) ->
bool {
932 auto ret = Json::Value();
933 ret[
"result"] =
to_hex_trimmed(evmc::uint256be(opencbdc_chain_id));
938 auto http_server::handle_block_number(
940 const server_type::result_callback_type& callback) ->
bool {
941 auto highest_ticket_number = m_broker->highest_ticket();
942 auto ret = Json::Value();
943 ret[
"result"] =
to_hex_trimmed(evmc::uint256be(highest_ticket_number));
948 auto http_server::fetch_block(
950 const server_type::result_callback_type& callback,
953 if(!params.isArray() || params.empty() || !params[0].isString()
954 || (params.size() > 1 && !params[1].isBool())) {
955 m_log->warn(
"Invalid parameters to getBlock", params.size());
956 auto ret = Json::Value();
957 ret[
"error"] = Json::Value();
958 ret[
"error"][
"code"] = error_code::invalid_block_parameter;
959 ret[
"error"][
"message"] =
"Invalid parameters to getBlock (size: "
960 + std::to_string(params.size()) +
")";
966 if(params[0].asString() ==
"latest") {
968 evmc::uint256be(m_broker->highest_ticket()));
971 if(!maybe_block_num) {
972 m_log->warn(
"Invalid blockNumber / hash parameter");
973 auto ret = Json::Value();
974 ret[
"error"] = Json::Value();
975 ret[
"error"][
"code"] = error_code::invalid_block_parameter;
976 ret[
"error"][
"message"]
977 =
"Invalid blockNumber / hash parameter";
990 res_cb(std::move(res), runner_params);
994 auto http_server::handle_get_block(
996 const server_type::result_callback_type& callback) ->
bool {
997 auto include_tx_details = params[1].asBool();
1001 [
this, callback, include_tx_details](
1004 auto& updates = std::get<return_type>(res);
1005 auto it = updates.find(runner_params);
1006 auto ret = Json::Value();
1007 if(it == updates.end() || it->second.size() == 0) {
1008 ret[
"error"] = Json::Value();
1009 ret[
"error"][
"code"] = error_code::not_found;
1010 ret[
"error"][
"message"] =
"Data was not found";
1015 auto maybe_pretend_block
1017 if(!maybe_pretend_block) {
1018 ret[
"error"] = Json::Value();
1019 ret[
"error"][
"code"] = error_code::internal_error;
1020 ret[
"error"][
"message"] =
"Internal error";
1024 ret[
"result"] = Json::Value();
1025 auto blk = maybe_pretend_block.value();
1026 auto tn256 = evmc::uint256be(blk.m_ticket_number);
1028 ret[
"result"][
"hash"] =
"0x" +
to_hex(tn256);
1029 ret[
"result"][
"parentHash"]
1030 =
"0x" +
to_hex(evmc::uint256be(blk.m_ticket_number - 1));
1031 ret[
"result"][
"gasLimit"] =
"0xffffffff";
1032 ret[
"result"][
"gasUsed"] =
"0x0";
1033 ret[
"result"][
"baseFeePerGas"] =
"0x0";
1034 ret[
"result"][
"miner"]
1035 =
"0x0000000000000000000000000000000000000000";
1036 ret[
"result"][
"transactions"] = Json::Value(Json::arrayValue);
1037 ret[
"result"][
"nonce"] =
"0x0000000000000000";
1040 constexpr auto bits_in_32_bytes = 256;
1041 bloom.extend(bits_in_32_bytes);
1042 uint64_t timestamp = 0;
1043 for(
auto& tx_rcpt : blk.m_transactions) {
1044 if(tx_rcpt.m_timestamp > timestamp) {
1045 timestamp = tx_rcpt.m_timestamp;
1047 for(
auto& l : tx_rcpt.m_logs) {
1049 for(
auto& t : l.m_topics) {
1053 if(include_tx_details) {
1054 auto json_tx =
tx_to_json(tx_rcpt.m_tx, m_secp);
1055 json_tx[
"blockHash"] =
"0x" +
to_hex(tn256);
1057 json_tx[
"transactionIndex"] =
"0x0";
1058 ret[
"result"][
"transactions"].append(json_tx);
1060 ret[
"result"][
"transactions"].append(
1064 ret[
"result"][
"timestamp"]
1066 ret[
"result"][
"extraData"] =
"0x" +
to_hex(evmc::uint256be(0));
1067 ret[
"result"][
"logsBloom"] = bloom.to_hex_prefixed();
1069 ret[
"result"][
"uncles"] = Json::Value(Json::arrayValue);
1074 auto http_server::handle_get_block_txcount(
1076 const server_type::result_callback_type& callback) ->
bool {
1082 auto& updates = std::get<return_type>(res);
1083 auto it = updates.find(runner_params);
1084 auto ret = Json::Value();
1085 if(it == updates.end() || it->second.size() == 0) {
1086 ret[
"error"] = Json::Value();
1087 ret[
"error"][
"code"] = error_code::not_found;
1088 ret[
"error"][
"message"] =
"Data was not found";
1093 auto maybe_pretend_block
1095 if(!maybe_pretend_block) {
1096 ret[
"error"] = Json::Value();
1097 ret[
"error"][
"code"] = error_code::internal_error;
1098 ret[
"error"][
"message"] =
"Internal error";
1102 auto blk = maybe_pretend_block.value();
1104 evmc::uint256be(blk.m_transactions.size()));
1110 http_server::handle_sha3(Json::Value params,
1111 const server_type::result_callback_type& callback)
1113 if(!params.isArray() || params.empty() || !params[0].isString()) {
1114 m_log->warn(
"Invalid parameters to sha3");
1120 m_log->warn(
"Could not parse argument as buffer");
1124 auto input = maybe_buf.value();
1125 auto sha3 =
keccak_data(input.data(), input.size());
1127 auto ret = Json::Value();
1133 auto http_server::handle_error(
1134 const Json::Value& ,
1135 const server_type::result_callback_type& callback,
1137 const std::string& message) ->
bool {
1138 auto ret = Json::Value();
1139 ret[
"error"] = Json::Value();
1140 ret[
"error"][
"code"] = code;
1141 ret[
"error"][
"message"] = message;
1146 auto http_server::handle_number(
1147 const Json::Value& ,
1148 const server_type::result_callback_type& callback,
1149 uint64_t number) ->
bool {
1150 auto ret = Json::Value();
1156 auto http_server::handle_boolean(
1157 const Json::Value& ,
1158 const server_type::result_callback_type& callback,
1159 bool result) ->
bool {
1160 auto ret = Json::Value();
1161 ret[
"result"] = result;
1166 auto http_server::handle_get_block_tx(
1168 const server_type::result_callback_type& callback) ->
bool {
1169 if(!params.isArray() || params.size() < 2 || !params[0].isString()
1170 || !params[1].isString()) {
1171 m_log->warn(
"Invalid parameters to "
1172 "getTransacionByBlock{Hash/Number}AndIndex");
1173 auto ret = Json::Value();
1174 ret[
"error"] = Json::Value();
1175 ret[
"error"][
"code"] = error_code::invalid_block_parameter;
1176 ret[
"error"][
"message"]
1177 =
"Invalid parameters to "
1178 "getTransacionByBlock{Hash/Number}AndIndex";
1183 auto shadow_params = Json::Value(Json::arrayValue);
1184 shadow_params.append(params[0]);
1191 auto& updates = std::get<return_type>(res);
1192 auto it = updates.find(runner_params);
1193 auto ret = Json::Value();
1194 if(it == updates.end() || it->second.size() == 0) {
1195 ret[
"error"] = Json::Value();
1196 ret[
"error"][
"code"] = error_code::not_found;
1197 ret[
"error"][
"message"] =
"Data was not found";
1202 auto maybe_pretend_block
1204 if(!maybe_pretend_block) {
1205 ret[
"error"] = Json::Value();
1206 ret[
"error"][
"code"] = error_code::internal_error;
1207 ret[
"error"][
"message"] =
"Internal error";
1214 ret[
"error"] = Json::Value();
1215 ret[
"error"][
"code"]
1216 = error_code::invalid_transaction_index;
1217 ret[
"error"][
"message"]
1218 =
"Transaction index was invalid - expect hex format";
1222 auto idx =
to_uint64(maybe_idx256.value());
1223 auto blk = maybe_pretend_block.value();
1224 if(blk.m_transactions.size() < idx) {
1225 ret[
"error"] = Json::Value();
1226 ret[
"error"][
"code"] = error_code::not_found;
1227 ret[
"error"][
"message"] =
"Data was not found";
1233 =
tx_to_json(blk.m_transactions[idx].m_tx, m_secp);
1234 auto tn256 = evmc::uint256be(blk.m_ticket_number);
1235 json_tx[
"blockHash"] =
"0x" +
to_hex(tn256);
1237 json_tx[
"transactionIndex"] =
"0x0";
1238 ret[
"result"] = json_tx;
1243 auto http_server::handle_accounts(
1244 const Json::Value& ,
1245 const server_type::result_callback_type& callback) ->
bool {
1246 auto ret = Json::Value();
1247 ret[
"result"] = Json::Value(Json::arrayValue);
1252 auto http_server::handle_estimate_gas(
1253 const Json::Value& ,
1254 const server_type::result_callback_type& callback) ->
bool {
1255 auto ret = Json::Value();
1258 ret[
"result"] =
"0xffffffffff";
1263 auto http_server::handle_client_version(
1264 const Json::Value& ,
1265 const server_type::result_callback_type& callback) ->
bool {
1266 auto ret = Json::Value();
1267 ret[
"result"] =
"opencbdc/v0.0";
1272 auto http_server::handle_gas_price(
1273 const Json::Value& ,
1274 const server_type::result_callback_type& callback) ->
bool {
1275 auto ret = Json::Value();
1276 ret[
"result"] =
"0x0";
1282 http_server::handle_call(Json::Value params,
1283 const server_type::result_callback_type& callback)
1285 if(!params.isArray() || params.empty() || !params[0].isObject()) {
1286 m_log->warn(
"Parameter to call is invalid");
1287 auto ret = Json::Value();
1288 ret[
"error"] = Json::Value();
1289 ret[
"error"][
"code"] = error_code::invalid_block_parameter;
1290 ret[
"error"][
"message"] =
"Parameter to call is invalid";
1297 m_log->warn(
"Parameter is not a valid transaction");
1298 auto ret = Json::Value();
1299 ret[
"error"] = Json::Value();
1300 ret[
"error"][
"code"] = error_code::invalid_transaction_index;
1301 ret[
"error"][
"message"]
1302 =
"Parameter to call is not a valid transaction";
1307 auto& tx = maybe_tx.value();
1310 return exec_tx(callback,
1315 auto ret = Json::Value();
1318 auto& updates = std::get<return_type>(res);
1319 auto it = updates.find(txid);
1320 if(it == updates.end()) {
1321 ret[
"error"] = Json::Value();
1322 ret[
"error"][
"code"] = error_code::not_found;
1323 ret[
"error"][
"message"] =
"Data was not found";
1330 if(!maybe_receipt) {
1331 ret[
"error"] = Json::Value();
1332 ret[
"error"][
"code"]
1333 = error_code::internal_error;
1334 ret[
"error"][
"message"] =
"Internal error";
1340 buf.extend(maybe_receipt->m_output_data.size());
1341 std::memcpy(buf.data(),
1342 maybe_receipt->m_output_data.data(),
1343 maybe_receipt->m_output_data.size());
1344 ret[
"result"] =
"0x" + buf.to_hex();
1349 auto http_server::handle_send_transaction(
1351 const server_type::result_callback_type& callback) ->
bool {
1352 if(!params.isArray() || params.empty() || !params[0].isObject()) {
1353 m_log->warn(
"Invalid parameters to sendTransaction");
1354 auto ret = Json::Value();
1355 ret[
"error"] = Json::Value();
1356 ret[
"error"][
"code"] = error_code::invalid_block_parameter;
1357 ret[
"error"][
"message"] =
"Invalid parameters to sendTransaction";
1364 m_log->warn(
"Parameter is not a valid transaction");
1365 auto ret = Json::Value();
1366 ret[
"error"] = Json::Value();
1367 ret[
"error"][
"code"] = error_code::invalid_transaction_index;
1368 ret[
"error"][
"message"]
1369 =
"Parameter to sendTransaction is not a valid transaction";
1374 auto& tx = maybe_tx.value();
1376 return exec_tx(callback,
1382 auto ret = Json::Value();
1383 ret[
"result"] =
"0x" + txid.to_hex();
1388 auto http_server::exec_tx(
1389 const server_type::result_callback_type& json_ret_callback,
1392 bool is_readonly_run,
1396 function.append(&f_type,
sizeof(f_type));
1397 auto id = m_next_id++;
1399 const auto res_cb_for_agent =
1400 [
this, id, res_success_cb, json_ret_callback](
1402 const auto success = std::holds_alternative<return_type>(res);
1404 res_success_cb(res);
1405 m_cleanup_queue.push(
id);
1408 const auto ec = std::get<interface::error_code>(res);
1411 m_retry_queue.push(
id);
1413 auto ret = Json::Value();
1414 ret[
"error"] = Json::Value();
1415 ret[
"error"][
"code"] = error_code::execution_error
1416 -
static_cast<int>(ec);
1417 ret[
"error"][
"message"] =
"Execution error";
1418 json_ret_callback(ret);
1424 auto agent = std::make_shared<impl>(
1437 std::unique_lock l(m_agents_mut);
1438 m_agents.emplace(
id, agent);
Buffer to store and retrieve byte data.
static auto from_hex(const std::string &hex) -> std::optional< cbdc::buffer >
Creates a new buffer from the provided hex string.
std::variant< return_type, error_code > exec_return_type
Return type from function execution.
@ retry
Transient error, execution should be retried.
~http_server() override
Stops listening for incoming connections, waits for existing connections to drain.
auto init() -> bool override
Starts listening for incoming connections and processing requests.
Server interface for an agent.
static constexpr auto initial_lock_type
Initial lock type for the agent to request when retrieving the function key.
Runner factory for agents to intiantiate new runners of a particular type while only worrying about t...
std::function< void(std::optional< Json::Value >)> result_callback_type
Type alias for the callback function for returning response values to the server.
auto tx_to_json(cbdc::parsec::agent::runner::evm_tx &tx, const std::shared_ptr< secp256k1_context > &ctx) -> Json::Value
Encodes the given transaction into a eth-RPC compatible representation in JSON - as Json::Value.
auto raw_tx_from_json(const Json::Value ¶m) -> std::optional< std::shared_ptr< cbdc::parsec::agent::runner::evm_tx > >
Converts a given Json::Value to an evm_tx.
auto to_hex_trimmed(const evmc::bytes32 &b, const std::string &prefix) -> std::string
auto address_from_json(const Json::Value &addr) -> std::optional< evmc::address >
Converts a given Json::Value to an evmc::address.
evm_runner_function
Commands accepted by the EVM contract runner.
@ get_transaction_receipt
Return the receipt for a transaction.
@ read_account_code
Read the contract code of an account.
@ get_logs
Query the logs for a particular address, block range and topic filter.
@ get_block
Return a pretend block that is based on the ticket number, and the transaction (potentially) correspo...
@ execute_transaction
Execute a normal transaction.
@ read_account_storage
Read a specific key of an account's storage.
@ read_account
Read the metadata of an account.
@ dryrun_transaction
Execute a transaction without applying any changes.
auto tx_log_to_json(cbdc::parsec::agent::runner::evm_log &log, interface::ticket_number_type tn, cbdc::hash_t txid) -> Json::Value
Encodes the given transaction log into a eth-RPC compatible representation in JSON - as Json::Value.
auto tx_receipt_to_json(cbdc::parsec::agent::runner::evm_tx_receipt &rcpt, const std::shared_ptr< secp256k1_context > &ctx) -> Json::Value
Encodes the given transaction receipt into a eth-RPC compatible representation in JSON - as Json::Val...
auto to_hex(const evmc::address &addr) -> std::string
auto buffer_from_json(const Json::Value &val) -> std::optional< cbdc::buffer >
Converts a given Json::Value to a cbdc::buffer.
auto dryrun_tx_from_json(const Json::Value &json, uint64_t chain_id) -> std::optional< std::shared_ptr< cbdc::parsec::agent::runner::evm_dryrun_tx > >
Converts a given Json::Value to an evm_dryrun_tx.
auto uint256be_from_hex(const std::string &hex) -> std::optional< evmc::uint256be >
Generates a uint256be from a hex string.
auto tx_from_json(const Json::Value &json, uint64_t) -> std::optional< std::shared_ptr< cbdc::parsec::agent::runner::evm_tx > >
Converts a given Json::Value to an evm_tx.
auto uint256be_from_json(const Json::Value &val) -> std::optional< evmc::uint256be >
Converts a given Json::Value to an evmc::uint256be.
auto from_hex(const std::string &hex) -> typename std::enable_if_t< std::is_same< T, evmc::bytes32 >::value||std::is_same< T, evmc::address >::value, std::optional< T > >
Parses hexadecimal representation in string format to T.
void add_to_bloom(cbdc::buffer &bloom, const cbdc::buffer &entry)
Adds an entry to a bloom value.
auto to_uint64(const evmc::uint256be &v) -> uint64_t
Converts an uint256be to a uint64_t, ignoring higher order bits.
auto tx_id(const cbdc::parsec::agent::runner::evm_tx &tx, uint64_t chain_id) -> cbdc::hash_t
Calculate ethereum-compatible txid.
auto from_buffer(nuraft::buffer &buf) -> std::optional< T >
Deserialize object of given type from a nuraft::buffer.
@ buffer
A singular RLP value (byte array)
auto keccak_data(const void *data, size_t len) -> hash_t
Calculates the Keccak256 hash of the specified data.
auto to_string(const hash_t &val) -> std::string
Converts a hash to a hexadecimal string.
auto make_buffer(const T &obj) -> std::enable_if_t< std::is_same_v< B, nuraft::ptr< nuraft::buffer > >, nuraft::ptr< nuraft::buffer > >
Serialize object into nuraft::buffer using a cbdc::nuraft_serializer.
Describes the parameters of a query on EVM logs - used to transfer these parameters from the getLogs ...
std::vector< evmc::bytes32 > m_topics
The topics for which logs are queried.
Type for account storage keys.
Configuration parameters for a phase two system.