Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[History] Feature/mas 1759 get transfers #146

Draft
wants to merge 23 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d449c8d
Add get_transfers endpoint
adsorptionenthalpy May 26, 2020
241db07
remove unused digest_type
adsorptionenthalpy May 26, 2020
a56f45b
make get_transfers return specific transfer information
adsorptionenthalpy May 28, 2020
59b9621
Add transfer_information members to FC REFLECT
adsorptionenthalpy May 28, 2020
eaa17ef
Add get_transfers support for xferdomain/xferaddress
adsorptionenthalpy May 28, 2020
1887a6d
Skip over emplacing unprocessed transcation information
adsorptionenthalpy May 28, 2020
50b41a2
parse json response for fee_amount
adsorptionenthalpy May 28, 2020
196d607
work on fee extraction
githubStinks May 29, 2020
54d0566
alter transaction record names to use payee/payer, use public key for…
githubStinks May 29, 2020
dd4a24c
Merge branch 'develop' into feature/MAS-1759-get_transfers
adsorptionenthalpy Jun 9, 2020
87af0e6
Except subtransfers after trnsfiopbky (dup trx id handling)
adsorptionenthalpy Jun 9, 2020
a588b99
Rewrite logic, bugfix
adsorptionenthalpy Jun 9, 2020
c19259d
Enable lookup time limit, limit by 100000 us * 3, increase max sequen…
adsorptionenthalpy Jun 16, 2020
b818038
move the 3
adsorptionenthalpy Jun 16, 2020
b2b95b1
rename ti.block_height to block_num, add account_action_seq and globa…
adsorptionenthalpy Jun 17, 2020
2219c7f
Allow result for trnfiopbky hashed down payee pub key in get_transfers
adsorptionenthalpy Jun 18, 2020
f7b64b7
additional filter in logic (get_transfers
adsorptionenthalpy Jun 19, 2020
c6e62f4
handle subtransfer
adsorptionenthalpy Jun 22, 2020
36aafaf
revert previous work, move previoustrx condition to trnsfiopbky filter
adsorptionenthalpy Jun 24, 2020
66a7e19
Add transferdata to/from fields to transfer filtering
adsorptionenthalpy Jun 25, 2020
d9bfd6e
Make transfer_amount field optional for fee transfers to fio.treasury
adsorptionenthalpy Jun 25, 2020
3e4b33c
fix parenthesis placement
adsorptionenthalpy Jun 25, 2020
c17927f
set amounts to 0 instead of omitting the fields
adsorptionenthalpy Jun 29, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions libraries/chain/include/eosio/chain/contract_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <eosio/chain/chain_config.hpp>
#include <eosio/chain/config.hpp>
#include <eosio/chain/types.hpp>
#include <eosio/chain/asset.hpp>

namespace eosio {
namespace chain {
Expand All @@ -25,6 +26,21 @@ namespace eosio {
}
};

struct transfer {
name from;
name to;
eosio::chain::asset quantity;
string memo;

static account_name get_account() {
return N(fio.token);
}

static action_name get_name() {
return N(transfer);
}
};

struct trnsfiopubky {
string payee_public_key;
int64_t amount;
Expand Down Expand Up @@ -257,3 +273,4 @@ FC_REFLECT(eosio::chain::regaddress, (fio_address)(owner_fio_public_key)(max_fee
FC_REFLECT(eosio::chain::regdomain, (fio_domain)(owner_fio_public_key)(max_fee)(actor)(tpid))
FC_REFLECT(eosio::chain::xferdomain, (fio_domain)(new_owner_fio_public_key)(max_fee)(actor)(tpid))
FC_REFLECT(eosio::chain::xferaddress, (fio_address)(new_owner_fio_public_key)(max_fee)(actor)(tpid))
FC_REFLECT(eosio::chain::transfer, (from)(to)(quantity)(memo))
3 changes: 2 additions & 1 deletion plugins/history_api_plugin/history_api_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ namespace eosio {
CHAIN_RO_CALL(get_transaction),
CHAIN_RO_CALL(get_block_txids),
CHAIN_RO_CALL(get_key_accounts),
CHAIN_RO_CALL(get_controlled_accounts)
CHAIN_RO_CALL(get_controlled_accounts),
CHAIN_RO_CALL(get_transfers)
});
}

Expand Down
163 changes: 162 additions & 1 deletion plugins/history_plugin/history_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ namespace eosio {
}
}

//Used to retrieve the fee paid from action_trace.receipt->response
static const uint64_t extract_fee (const action_trace &t) {
const string &extract = t.receipt->response.substr(t.receipt->response.find("d\":") + 3,
std::numeric_limits<unsigned long long>::max());
const string &fee = extract.substr(0, extract.find("}"));
return boost::lexical_cast<uint64_t>(fee);
}

struct filter_entry {
name receiver;
name action;
Expand Down Expand Up @@ -549,9 +557,162 @@ namespace eosio {
}
}
return result;
}
} //get actions

read_only::get_transfers_result read_only::get_transfers(const read_only::get_transfers_params &params) const {
// edump((params));
auto &chain = history->chain_plug->chain();
const auto& hdb = chain.hdb();
const auto& hidb = chain.hidb();
const auto abi_serializer_max_time = history->chain_plug->get_abi_serializer_max_time();

const auto& idx = hidb.get_index<account_history_index, by_account_action_seq>();
account_name account_name = fioio::key_to_account(params.fio_public_key);
int64_t start = 0;
int64_t pos = params.pos ? *params.pos : -1;
int64_t end = 0;
int64_t offset = params.offset ? *params.offset : -20;
auto n = account_name;
// idump((pos));
if (pos == -1) {
auto itr = idx.lower_bound(boost::make_tuple(name(n.value + 1), 0));
if (itr == idx.begin()) {
if (itr->account == n)
pos = itr->account_sequence_num + 1;
} else if (itr != idx.begin()) --itr;

if (itr->account == n)
pos = itr->account_sequence_num + 1;
}

if (pos == -1) pos = 0xfffffffffffffff;

if (offset > 0) {
start = pos;
end = start + offset;
} else {
start = pos + offset;
if (start > pos) start = 0;
end = pos;
}
EOS_ASSERT(end >= start, chain::plugin_exception, "end position is earlier than start position");

// idump((start)(end));

// Find latest stored action (will have lowest available ACCOUNT seq number)
const auto max_itr = idx.lower_bound( boost::make_tuple( n, 0 ) );
const auto min_seq_number = max_itr->account_sequence_num;
if (min_seq_number > 0) { // Reject outside of retention policy boundary.
const auto max_seq_number = min_seq_number + history->history_per_account * 3;
EOS_ASSERT( start >= min_seq_number, chain::plugin_range_not_satisfiable, "start position is earlier than account retention policy (${p}). Latest available: ${l}. Requested start: ${r}", ("p",history->history_per_account)("l",min_seq_number)("r",start) );
// Below should actually never occur..?
EOS_ASSERT( end >= min_seq_number, chain::plugin_range_not_satisfiable, "end position is earlier than account retention policy (${p}). Latest available: ${l}. Requested end: ${r}", ("p",history->history_per_account)("l",min_seq_number)("r",end) );
}

auto start_itr = idx.lower_bound(boost::make_tuple(n, start));
auto end_itr = idx.upper_bound(boost::make_tuple(n, end));

auto start_time = fc::time_point::now();
auto end_time = start_time;

get_actions_result action_result;
get_transfers_result result;
result.last_irreversible_block = chain.last_irreversible_block_num();
action_result.last_irreversible_block = chain.last_irreversible_block_num();
fc::sha256 previoustrxid;
while (start_itr != end_itr) {
uint64_t action_sequence_num;
int64_t account_sequence_num;
if (params.pos < 0) {
--end_itr;
action_sequence_num = end_itr->action_sequence_num;
account_sequence_num = end_itr->account_sequence_num;
} else {
action_sequence_num = start_itr->action_sequence_num;
account_sequence_num = start_itr->account_sequence_num;
++start_itr;
}

const auto& a = hdb.get<action_history_object, by_action_sequence_num>( action_sequence_num );
fc::datastream<const char *> ds(a.packed_action_trace.data(), a.packed_action_trace.size());
action_trace t;
fc::raw::unpack(ds, t);

transfer_information ti;
ti.transaction_id = t.trx_id;
ti.block_num = t.block_num;
ti.block_time = t.block_time;
ti.global_action_seq = action_sequence_num;
ti.account_action_seq = account_sequence_num;
if (t.act.name == N(trnsfiopubky)) {
const auto transferdata = t.act.data_as<eosio::trnsfiopubky>();
const auto paccount = fioio::key_to_account(transferdata.payee_public_key);
if ( previoustrxid != t.trx_id && (account_name == paccount ||
t.receipt->receiver == N(account_name) ||
t.receipt->receiver == transferdata.actor ||
t.receipt->receiver == N(paccount) ||
paccount == "fio.treasury" ||
transferdata.actor.to_string() == paccount ||
transferdata.actor.to_string() == account_name)) {
ti.action = "trnsfiopubky";
ti.tpid = transferdata.tpid;
ti.note = "FIO Transfer";
ti.payer = transferdata.actor.to_string();
ti.payee = paccount;
ti.payee_public_key = transferdata.payee_public_key;
ti.fee_amount = extract_fee(t);
std::cout<<"*****TRANSFERPUB*******";
ti.transaction_total = ti.fee_amount + transferdata.amount;
ti.transfer_amount = transferdata.amount;
if (params.pos < 0) {
result.transfers.emplace(result.transfers.begin(), ti );
} else {
result.transfers.emplace_back( ti );
}
}
}
else if (t.act.name == N(transfer)) {
const auto transferdata = t.act.data_as<eosio::transfer>();
if (t.receipt->receiver == account_name ||
transferdata.to.to_string() == account_name ||
transferdata.from.to_string() == account_name) {
ti.action = "transfer";
ti.tpid = "";
ti.note = transferdata.memo;
ti.payer = transferdata.from.to_string();
ti.payee = transferdata.to.to_string();
ti.payee_public_key = "";
if (ti.payee == "fio.treasury") {
ti.fee_amount = transferdata.quantity.get_amount();
ti.transfer_amount = 0;
} else {
ti.fee_amount = 0;
ti.transfer_amount = transferdata.quantity.get_amount(); //transfer amount is optional result and only set in cases where transfer is not fee to fio.treasury
}
ti.transaction_total = transferdata.quantity.get_amount();

if (params.pos < 0) {
result.transfers.emplace(result.transfers.begin(), ti );
} else {
result.transfers.emplace_back( ti );
}
}
}
previoustrxid = t.trx_id;

end_time = fc::time_point::now();
if (end_time - start_time > (fc::microseconds(100000 * 3))) {
action_result.time_limit_exceeded_error = true;
break;
}


} // while

return result;
}

//get actions
read_only::get_transaction_result read_only::get_transaction(const read_only::get_transaction_params &p) const {
auto &chain = history->chain_plug->chain();
const auto abi_serializer_max_time = history->chain_plug->get_abi_serializer_max_time();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,38 @@ namespace eosio {
uint32_t last_irreversible_block;
optional<bool> time_limit_exceeded_error;
};
get_actions_result get_actions(const get_actions_params &) const;

struct get_transfers_params {
string fio_public_key;
optional<int64_t> pos; /// a absolute sequence positon -1 is the end/last action
optional<int64_t> offset; ///< the number of actions relative to pos, negative numbers return [pos-offset,pos), positive numbers return [pos,pos+offset)
};

get_actions_result get_actions(const get_actions_params &) const;
struct transfer_information {
uint64_t global_action_seq;
uint64_t account_action_seq;
uint32_t block_num;
chain::block_timestamp_type block_time;
string payer;
string payee;
string payee_public_key;
uint64_t transfer_amount;
uint64_t fee_amount;
uint64_t transaction_total;
string note;
string action;
string tpid;
string transaction_id;
};

struct get_transfers_result {
vector<transfer_information> transfers;
uint32_t last_irreversible_block;
optional<bool> time_limit_exceeded_error;
};

get_transfers_result get_transfers(const get_transfers_params &) const;


struct get_transaction_params {
Expand Down Expand Up @@ -152,6 +181,12 @@ namespace eosio {
FC_REFLECT(eosio::history_apis::read_only::get_actions_params, (account_name)(pos)(offset))
FC_REFLECT(eosio::history_apis::read_only::get_actions_result,
(actions)(last_irreversible_block)(time_limit_exceeded_error))
FC_REFLECT(eosio::history_apis::read_only::get_transfers_params, (fio_public_key)(pos)(offset))
FC_REFLECT(eosio::history_apis::read_only::get_transfers_result,
(transfers)(last_irreversible_block)(time_limit_exceeded_error))
FC_REFLECT(eosio::history_apis::read_only::transfer_information, (global_action_seq)(account_action_seq)(block_num)
(block_time)(payer)(payee)(payee_public_key)(transfer_amount)(fee_amount)
(transaction_total)(note)(action)(tpid)(transaction_id) )
FC_REFLECT(eosio::history_apis::read_only::ordered_action_result,
(global_action_seq)(account_action_seq)(block_num)(block_time)(action_trace))

Expand Down