Electroneum
transaction_history.cpp
Go to the documentation of this file.
1 // Copyrights(c) 2017-2021, The Electroneum Project
2 // Copyrights(c) 2014-2019, The Monero Project
3 //
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without modification, are
7 // permitted provided that the following conditions are met:
8 //
9 // 1. Redistributions of source code must retain the above copyright notice, this list of
10 // conditions and the following disclaimer.
11 //
12 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
13 // of conditions and the following disclaimer in the documentation and/or other
14 // materials provided with the distribution.
15 //
16 // 3. Neither the name of the copyright holder nor the names of its contributors may be
17 // used to endorse or promote products derived from this software without specific
18 // prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
31 
32 
33 #include "transaction_history.h"
34 #include "transaction_info.h"
35 #include "wallet.h"
36 
37 #include "crypto/hash.h"
38 #include "wallet/wallet2.h"
39 
40 
41 #include <string>
42 #include <list>
43 
44 using namespace epee;
45 
46 namespace Electroneum {
47 
48 TransactionHistory::~TransactionHistory() {}
49 
50 
51 TransactionHistoryImpl::TransactionHistoryImpl(WalletImpl *wallet)
52  : m_wallet(wallet)
53 {
54 
55 }
56 
58 {
59  for (auto t : m_history)
60  delete t;
61 }
62 
64 {
65  boost::shared_lock<boost::shared_mutex> lock(m_historyMutex);
66  int result = m_history.size();
67  return result;
68 }
69 
71 {
72  boost::shared_lock<boost::shared_mutex> lock(m_historyMutex);
73  // sanity check
74  if (index < 0)
75  return nullptr;
76  unsigned index_ = static_cast<unsigned>(index);
77  return index_ < m_history.size() ? m_history[index_] : nullptr;
78 }
79 
81 {
82  boost::shared_lock<boost::shared_mutex> lock(m_historyMutex);
83  auto itr = std::find_if(m_history.begin(), m_history.end(),
84  [&](const TransactionInfo * ti) {
85  return ti->hash() == id;
86  });
87  return itr != m_history.end() ? *itr : nullptr;
88 }
89 
90 std::vector<TransactionInfo *> TransactionHistoryImpl::getAll() const
91 {
92  boost::shared_lock<boost::shared_mutex> lock(m_historyMutex);
93  return m_history;
94 }
95 
97 {
98  // multithreaded access:
99  // boost::lock_guard<boost::mutex> guarg(m_historyMutex);
100  // for "write" access, locking exclusively
101  boost::unique_lock<boost::shared_mutex> lock(m_historyMutex);
102 
103  // TODO: configurable values;
104  uint64_t min_height = 0;
105  uint64_t max_height = (uint64_t)-1;
106  uint64_t wallet_height = m_wallet->blockChainHeight();
107 
108  // delete old transactions;
109  for (auto t : m_history)
110  delete t;
111  m_history.clear();
112 
113  // transactions are stored in wallet2:
114  // - confirmed_transfer_details - out transfers
115  // - unconfirmed_transfer_details - pending out transfers
116  // - payment_details - input transfers
117 
118  // payments are "input transactions";
119  // one input transaction contains only one transfer. e.g. <transaction_id> - <100ETN>
120 
121  std::list<std::pair<crypto::hash, tools::wallet2::payment_details>> in_payments;
122  m_wallet->m_wallet->get_payments(in_payments, min_height, max_height);
123  for (std::list<std::pair<crypto::hash, tools::wallet2::payment_details>>::const_iterator i = in_payments.begin(); i != in_payments.end(); ++i) {
124  const tools::wallet2::payment_details &pd = i->second;
125  std::string payment_id = string_tools::pod_to_hex(i->first);
126  if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
127  payment_id = payment_id.substr(0,16);
129  ti->m_paymentid = payment_id;
130  ti->m_amount = pd.m_amount;
131  ti->m_direction = TransactionInfo::Direction_In;
132  ti->m_hash = string_tools::pod_to_hex(pd.m_tx_hash);
133  ti->m_blockheight = pd.m_block_height;
134  ti->m_subaddrIndex = { pd.m_subaddr_index.minor };
135  ti->m_subaddrAccount = pd.m_subaddr_index.major;
136  ti->m_label = m_wallet->m_wallet->get_subaddress_label(pd.m_subaddr_index);
137  ti->m_timestamp = pd.m_timestamp;
138  ti->m_confirmations = (wallet_height > pd.m_block_height) ? wallet_height - pd.m_block_height : 0;
139  ti->m_unlock_time = pd.m_unlock_time;
140  m_history.push_back(ti);
141 
142  }
143 
144  // confirmed output transactions
145  // one output transaction may contain more than one etn transfer, e.g.
146  // <transaction_id>:
147  // transfer1: 100ETN to <address_1>
148  // transfer2: 50ETN to <address_2>
149  // fee: fee charged per transaction
150  //
151 
152  std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> out_payments;
153  m_wallet->m_wallet->get_payments_out(out_payments, min_height, max_height);
154 
155  for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::const_iterator i = out_payments.begin();
156  i != out_payments.end(); ++i) {
157 
158  const crypto::hash &hash = i->first;
159  const tools::wallet2::confirmed_transfer_details &pd = i->second;
160 
161  uint64_t change = pd.m_change == (uint64_t)-1 ? 0 : pd.m_change; // change may not be known
162  uint64_t fee = pd.m_amount_in - pd.m_amount_out;
163 
164 
165  std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id);
166  if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
167  payment_id = payment_id.substr(0,16);
168 
169 
171  ti->m_paymentid = payment_id;
172  ti->m_amount = pd.m_amount_in - change - fee;
173  ti->m_fee = fee;
174  ti->m_direction = TransactionInfo::Direction_Out;
175  ti->m_hash = string_tools::pod_to_hex(hash);
176  ti->m_blockheight = pd.m_block_height;
177  ti->m_subaddrIndex = pd.m_subaddr_indices;
178  ti->m_subaddrAccount = pd.m_subaddr_account;
179  ti->m_label = pd.m_subaddr_indices.size() == 1 ? m_wallet->m_wallet->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "";
180  ti->m_timestamp = pd.m_timestamp;
181  ti->m_confirmations = (wallet_height > pd.m_block_height) ? wallet_height - pd.m_block_height : 0;
182 
183  // single output transaction might contain multiple transfers
184  for (const auto &d: pd.m_dests) {
185  ti->m_transfers.push_back({d.amount, get_account_address_as_str(m_wallet->m_wallet->nettype(), d.is_subaddress, d.addr)});
186  }
187  m_history.push_back(ti);
188  }
189 
190  // unconfirmed output transactions
191  std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>> upayments_out;
192  m_wallet->m_wallet->get_unconfirmed_payments_out(upayments_out);
193  for (std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>>::const_iterator i = upayments_out.begin(); i != upayments_out.end(); ++i) {
194  const tools::wallet2::unconfirmed_transfer_details &pd = i->second;
195  const crypto::hash &hash = i->first;
196  uint64_t amount = pd.m_amount_in;
197  uint64_t fee = amount - pd.m_amount_out;
198  std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id);
199  if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
200  payment_id = payment_id.substr(0,16);
202 
204  ti->m_paymentid = payment_id;
205  ti->m_amount = amount - pd.m_change - fee;
206  ti->m_fee = fee;
207  ti->m_direction = TransactionInfo::Direction_Out;
208  ti->m_failed = is_failed;
209  ti->m_pending = true;
210  ti->m_hash = string_tools::pod_to_hex(hash);
211  ti->m_subaddrIndex = pd.m_subaddr_indices;
212  ti->m_subaddrAccount = pd.m_subaddr_account;
213  ti->m_label = pd.m_subaddr_indices.size() == 1 ? m_wallet->m_wallet->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "";
214  ti->m_timestamp = pd.m_timestamp;
215  ti->m_confirmations = 0;
216  m_history.push_back(ti);
217  }
218 
219 
220  // unconfirmed payments (tx pool)
221  std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>> upayments;
222  m_wallet->m_wallet->get_unconfirmed_payments(upayments);
223  for (std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>>::const_iterator i = upayments.begin(); i != upayments.end(); ++i) {
224  const tools::wallet2::payment_details &pd = i->second.m_pd;
225  std::string payment_id = string_tools::pod_to_hex(i->first);
226  if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
227  payment_id = payment_id.substr(0,16);
229  ti->m_paymentid = payment_id;
230  ti->m_amount = pd.m_amount;
231  ti->m_direction = TransactionInfo::Direction_In;
232  ti->m_hash = string_tools::pod_to_hex(pd.m_tx_hash);
233  ti->m_blockheight = pd.m_block_height;
234  ti->m_pending = true;
235  ti->m_subaddrIndex = { pd.m_subaddr_index.minor };
236  ti->m_subaddrAccount = pd.m_subaddr_index.major;
237  ti->m_label = m_wallet->m_wallet->get_subaddress_label(pd.m_subaddr_index);
238  ti->m_timestamp = pd.m_timestamp;
239  ti->m_confirmations = 0;
240  m_history.push_back(ti);
241 
242  LOG_PRINT_L1(__FUNCTION__ << ": Unconfirmed payment found " << pd.m_amount);
243  }
244 
245 }
246 
247 } // namespace
248 
249 namespace Bitelectroneum = Electroneum;
std::string get_account_address_as_str(network_type nettype, bool subaddress, account_public_address const &adr)
cryptonote::subaddress_index m_subaddr_index
Definition: wallet2.h:362
#define LOG_PRINT_L1(x)
Definition: misc_log_ex.h:100
enum tools::wallet2::unconfirmed_transfer_details::@63 m_state
::std::string string
Definition: gtest-port.h:1097
std::vector< cryptonote::tx_destination_entry > m_dests
Definition: wallet2.h:400
for(i=1;i< 1;++i) fe_sq(t0
std::string pod_to_hex(const t_pod_type &s)
Definition: string_tools.h:317
unsigned __int64 uint64_t
Definition: stdint.h:136
uint64_t blockChainHeight() const override
blockChainHeight - returns current blockchain height
Definition: wallet.cpp:1006
std::set< uint32_t > m_subaddr_indices
Definition: wallet2.h:405
POD_CLASS hash
Definition: hash.h:50
virtual std::vector< TransactionInfo * > getAll() const
virtual TransactionInfo * transaction(int index) const
The TransactionInfo - interface for displaying transaction information.
Definition: wallet2_api.h:168