github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/fs/blockchain/blockchain_api.cpp (about) 1 // Copyright (C) 2018 go-nebulas authors 2 // 3 // This file is part of the go-nebulas library. 4 // 5 // the go-nebulas library is free software: you can redistribute it and/or 6 // modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation, either version 3 of the License, or 9 // (at your option) any later version. 10 // 11 // the go-nebulas library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with the go-nebulas library. If not, see 18 // <http://www.gnu.org/licenses/>. 19 // 20 21 #include "fs/blockchain/blockchain_api.h" 22 #include "common/nebulas_currency.h" 23 #include "fs/blockchain/trie/trie.h" 24 #include "fs/util.h" 25 #include <boost/property_tree/json_parser.hpp> 26 #include <boost/property_tree/ptree.hpp> 27 28 namespace neb { 29 namespace fs { 30 31 blockchain_api_base::~blockchain_api_base() {} 32 33 blockchain_api::blockchain_api() {} 34 35 blockchain_api::~blockchain_api() {} 36 37 std::unique_ptr<std::vector<transaction_info_t>> 38 blockchain_api::get_block_transactions_api(block_height_t height) { 39 40 auto ret = std::make_unique<std::vector<transaction_info_t>>(); 41 // special for block height 1 42 if (height <= 1) { 43 return ret; 44 } 45 46 auto block = blockchain::load_block_with_height(height); 47 int64_t timestamp = block->header().timestamp(); 48 49 std::string events_root_str = block->header().events_root(); 50 neb::bytes events_root_bytes = neb::string_to_byte(events_root_str); 51 52 for (auto &tx : block->transactions()) { 53 transaction_info_t info; 54 55 info.m_height = height; 56 info.m_timestamp = timestamp; 57 58 info.m_from = to_address(tx.from()); 59 info.m_to = to_address(tx.to()); 60 info.m_tx_value = storage_to_wei(neb::string_to_byte(tx.value())); 61 info.m_gas_price = storage_to_wei(neb::string_to_byte(tx.gas_price())); 62 info.m_tx_type = tx.data().type(); 63 64 // get topic chain.transactionResult 65 std::string tx_hash_str = tx.hash(); 66 neb::bytes tx_hash_bytes = neb::string_to_byte(tx_hash_str); 67 auto txs_result_ptr = 68 get_transaction_result_api(events_root_bytes, tx_hash_bytes); 69 70 info.m_status = txs_result_ptr->m_status; 71 info.m_gas_used = txs_result_ptr->m_gas_used; 72 73 // ignore failed transactions 74 if (info.m_status == tx_status_succ) { 75 ret->push_back(info); 76 } 77 } 78 return ret; 79 } 80 81 std::unique_ptr<event_info_t> 82 blockchain_api::get_transaction_result_api(const neb::bytes &events_root, 83 const neb::bytes &tx_hash) { 84 trie t; 85 neb::bytes txs_result; 86 87 for (int64_t id = 1;; id++) { 88 neb::bytes id_bytes = neb::number_to_byte<neb::bytes>(id); 89 neb::bytes events_tx_hash = tx_hash; 90 events_tx_hash.append_bytes(id_bytes.value(), id_bytes.size()); 91 92 neb::bytes trie_node_bytes; 93 bool ret = t.get_trie_node(events_root, events_tx_hash, trie_node_bytes); 94 if (!ret) { 95 break; 96 } 97 txs_result = trie_node_bytes; 98 } 99 assert(!txs_result.empty()); 100 101 std::string json_str = neb::byte_to_string(txs_result); 102 103 return json_parse_event(json_str); 104 } 105 106 std::unique_ptr<event_info_t> 107 blockchain_api::json_parse_event(const std::string &json) { 108 boost::property_tree::ptree pt; 109 std::stringstream ss(json); 110 boost::property_tree::read_json(ss, pt); 111 112 std::string topic = pt.get<std::string>("Topic"); 113 assert(topic.compare("chain.transactionResult") == 0); 114 115 std::string data_json = pt.get<std::string>("Data"); 116 ss = std::stringstream(data_json); 117 boost::property_tree::read_json(ss, pt); 118 119 int32_t status = pt.get<int32_t>("status"); 120 wei_t gas_used = boost::lexical_cast<wei_t>(pt.get<std::string>("gas_used")); 121 122 auto ret = std::make_unique<event_info_t>(event_info_t{status, gas_used}); 123 return ret; 124 } 125 126 std::unique_ptr<corepb::Account> 127 blockchain_api::get_account_api(const address_t &addr, block_height_t height) { 128 129 auto block = blockchain::load_block_with_height(height); 130 131 // get block header account state 132 std::string state_root_str = block->header().state_root(); 133 neb::bytes state_root_bytes = neb::string_to_byte(state_root_str); 134 135 // get trie node 136 trie t; 137 neb::bytes trie_node_bytes; 138 bool is_found = t.get_trie_node(state_root_bytes, addr, trie_node_bytes); 139 auto corepb_account_ptr = std::make_unique<corepb::Account>(); 140 if (!is_found) { 141 corepb_account_ptr->set_address(std::to_string(addr)); 142 corepb_account_ptr->set_balance(std::to_string(neb::wei_to_storage(0))); 143 return corepb_account_ptr; 144 } 145 146 bool ret = corepb_account_ptr->ParseFromArray(trie_node_bytes.value(), 147 trie_node_bytes.size()); 148 if (!ret) { 149 throw std::runtime_error("parse corepb Account failed"); 150 } 151 return corepb_account_ptr; 152 } 153 154 std::unique_ptr<corepb::Transaction> 155 blockchain_api::get_transaction_api(const std::string &tx_hash, 156 block_height_t height) { 157 auto corepb_txs_ptr = std::make_unique<corepb::Transaction>(); 158 159 // suppose height is the latest block height 160 auto block = blockchain::load_block_with_height(height); 161 162 // get block header transaction root 163 std::string txs_root_str = block->header().txs_root(); 164 neb::bytes txs_root_bytes = neb::string_to_byte(txs_root_str); 165 166 // get trie node 167 trie t; 168 neb::bytes tx_hash_bytes = neb::string_to_byte(tx_hash); 169 neb::bytes trie_node_bytes; 170 bool ret = t.get_trie_node(txs_root_bytes, tx_hash_bytes, trie_node_bytes); 171 if (!ret) { 172 return corepb_txs_ptr; 173 } 174 175 ret = corepb_txs_ptr->ParseFromArray(trie_node_bytes.value(), 176 trie_node_bytes.size()); 177 if (!ret) { 178 throw std::runtime_error("parse corepb Transaction failed"); 179 } 180 return corepb_txs_ptr; 181 } 182 183 } // namespace fs 184 } // namespace neb