mirror of
https://github.com/oxen-io/oxen-core.git
synced 2023-12-14 02:22:56 +01:00
0b17bb9adb
still need to make tests build and fix up some behavior correctness around RPC (and maybe other areas)
127 lines
3.9 KiB
C++
127 lines
3.9 KiB
C++
#include "transaction_constructor.hpp"
|
|
#include "pending_transaction.hpp"
|
|
#include "oxen_economy.h"
|
|
|
|
namespace wallet
|
|
{
|
|
PendingTransaction::PendingTransaction(const std::vector<cryptonote::tx_destination_entry>& new_recipients)
|
|
: recipients(new_recipients)
|
|
{
|
|
tx = cryptonote::transaction{};
|
|
int64_t sum_recipient_amounts = 0;
|
|
for (const auto& recipient : new_recipients)
|
|
{
|
|
if (sum_recipient_amounts < 0)
|
|
throw std::runtime_error("Transaction amounts must be positive");
|
|
sum_recipient_amounts += recipient.amount;
|
|
}
|
|
if (new_recipients.empty() || sum_recipient_amounts < 0)
|
|
throw std::runtime_error("Transaction amounts must be positive");
|
|
}
|
|
|
|
void
|
|
PendingTransaction::update_change()
|
|
{
|
|
change.amount = sum_inputs() - sum_outputs() - get_fee();
|
|
}
|
|
|
|
int64_t
|
|
PendingTransaction::sum_inputs() const
|
|
{
|
|
return std::accumulate(
|
|
chosen_outputs.begin(),
|
|
chosen_outputs.end(),
|
|
int64_t{0},
|
|
[](int64_t accumulator, const Output& output) { return accumulator + output.amount; });
|
|
}
|
|
|
|
int64_t
|
|
PendingTransaction::sum_outputs() const
|
|
{
|
|
return std::accumulate(
|
|
recipients.begin(),
|
|
recipients.end(),
|
|
int64_t{0},
|
|
[](int64_t accumulator, const cryptonote::tx_destination_entry& recipient) {
|
|
return accumulator + recipient.amount;
|
|
});
|
|
}
|
|
|
|
int64_t
|
|
PendingTransaction::get_fee() const
|
|
{
|
|
return get_fee(chosen_outputs.size());
|
|
}
|
|
int64_t
|
|
PendingTransaction::get_fee(int64_t n_inputs) const
|
|
{
|
|
// TODO sean add this
|
|
int64_t fixed_fee = 0;
|
|
// TODO sean add this
|
|
int64_t burn_pct = 0;
|
|
int64_t fee_percent = oxen::BLINK_BURN_TX_FEE_PERCENT_V18; // 100%
|
|
if (blink)
|
|
fee_percent = oxen::BLINK_MINER_TX_FEE_PERCENT + oxen::BLINK_BURN_TX_FEE_PERCENT_V18 + burn_pct; // Blink ends up being 300%
|
|
|
|
int64_t fee = (get_tx_weight(n_inputs) * fee_per_byte + (recipients.size() + 1) * fee_per_output) * fee_percent / 100;
|
|
// Add fixed amount to the fee for items such as burning. This is defined in the pending transactions
|
|
fee += fixed_fee;
|
|
return fee;
|
|
}
|
|
|
|
size_t
|
|
PendingTransaction::get_tx_weight(int64_t n_inputs) const
|
|
{
|
|
size_t size = 0;
|
|
// If there is no inputs then we estimate using one input
|
|
if (n_inputs == 0)
|
|
n_inputs = 1;
|
|
|
|
size_t n_outputs = recipients.size() + 1; // Recipients plus change
|
|
if (n_outputs == 0)
|
|
throw std::runtime_error{"Get Transaction Weight called on a transaction with no recipients"};
|
|
|
|
size += 1 + 6; // tx prefix, first few bytes
|
|
size += n_inputs * (1+6+(mixin_count+1)*2+32); // vin
|
|
size += n_outputs * (6+32); // vout
|
|
size += extra_size(); // extra
|
|
// rct signatures
|
|
size += 1; // type
|
|
size_t log_padded_outputs = 0;
|
|
while ((uint64_t(1)<<log_padded_outputs) < n_outputs)
|
|
++log_padded_outputs;
|
|
size += (2 * (6 + static_cast<int64_t>(log_padded_outputs)) + 4 + 5) * 32 + 3; // rangeSigs
|
|
|
|
size += n_inputs * (32 * (mixin_count+1) + 64); // CLSAGs
|
|
size += 32 * n_inputs; // pseudoOuts
|
|
size += 8 * n_outputs; // ecdhInfo
|
|
size += 32 * n_outputs; // outPk - only commitment is saved
|
|
size += 4; // txnFee
|
|
|
|
if (n_outputs > 2)
|
|
{
|
|
const uint64_t bp_base = 368;
|
|
size_t log_padded_outputs = 2;
|
|
while ((uint64_t(1)<<log_padded_outputs) < n_outputs)
|
|
++log_padded_outputs;
|
|
uint64_t nlr = 2 * (6 + log_padded_outputs);
|
|
const uint64_t bp_size = 32 * (9 + nlr);
|
|
const uint64_t bp_clawback = (bp_base * (1<<log_padded_outputs) - bp_size) * 4 / 5;
|
|
size += bp_clawback;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
bool
|
|
PendingTransaction::finalise()
|
|
{
|
|
if ((sum_inputs() - sum_outputs() - fee - change.amount) != 0)
|
|
return false;
|
|
for (size_t i=0; i < recipients.size(); i++)
|
|
tx.output_unlock_times.push_back(unlock_time);
|
|
tx.output_unlock_times.push_back(change_unlock_time);
|
|
|
|
return true;
|
|
}
|
|
|
|
} // namespace wallet
|