Skip to content

Commit

Permalink
Update fee calc to use CLSAG + other minor changes
Browse files Browse the repository at this point in the history
  • Loading branch information
j-berman committed Feb 28, 2022
1 parent a53e57f commit 9032a05
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 30 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ Useful for displaying an estimated fee – To obtain exact fees, see "Creating a
* `n_outputs: UInt32String`
* `extra_size: UInt32String`
* `bulletproof: BoolString`
* `clsag: BooLString`

* Returns: `retVal: UInt32String`

Expand Down
27 changes: 15 additions & 12 deletions src/monero_fee_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ uint64_t monero_fee_utils::estimated_tx_network_fee(
) {
uint64_t fee_multiplier = get_fee_multiplier(priority, default_priority(), get_fee_algorithm(use_fork_rules_fn), use_fork_rules_fn);
std::vector<uint8_t> extra; // blank extra
size_t est_tx_size = estimate_rct_tx_size(2, fixed_mixinsize(), 2, extra.size(), true/*bulletproof*/); // typically ~14kb post-rct, pre-bulletproofs
size_t est_tx_size = estimate_rct_tx_size(2, fixed_mixinsize(), 2, extra.size(), true/*bulletproof*/, true/*clsag*/); // typically ~14kb post-rct, pre-bulletproofs
uint64_t estimated_fee = calculate_fee_from_size(base_fee, est_tx_size, fee_multiplier);
//
return estimated_fee;
Expand Down Expand Up @@ -137,7 +137,7 @@ int monero_fee_utils::get_fee_algorithm(use_fork_rules_fn_type use_fork_rules_fn
return 1;
return 0;
}
size_t monero_fee_utils::estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof)
size_t monero_fee_utils::estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag)
{
size_t size = 0;

Expand Down Expand Up @@ -171,16 +171,19 @@ size_t monero_fee_utils::estimate_rct_tx_size(int n_inputs, int mixin, int n_out
else
size += (2*64*32+32+64*32) * n_outputs;

// MGs
size += n_inputs * (64 * (mixin+1) + 32);
// MGs/CLSAGs
if (clsag)
size += n_inputs * (32 * (mixin+1) + 64);
else
size += n_inputs * (64 * (mixin+1) + 32);

// mixRing - not serialized, can be reconstructed
/* size += 2 * 32 * (mixin+1) * n_inputs; */

// pseudoOuts
size += 32 * n_inputs;
// ecdhInfo
size += 2 * 32 * n_outputs;
size += 8 * n_outputs;
// outPk - only commitment is saved
size += 32 * n_outputs;
// txnFee
Expand All @@ -189,16 +192,16 @@ size_t monero_fee_utils::estimate_rct_tx_size(int n_inputs, int mixin, int n_out
LOG_PRINT_L2("estimated " << (bulletproof ? "bulletproof" : "borromean") << " rct tx size for " << n_inputs << " inputs with ring size " << (mixin+1) << " and " << n_outputs << " outputs: " << size << " (" << ((32 * n_inputs/*+1*/) + 2 * 32 * (mixin+1) * n_inputs + 32 * n_outputs) << " saved)");
return size;
}
size_t monero_fee_utils::estimate_tx_size(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof)
size_t monero_fee_utils::estimate_tx_size(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag)
{
if (use_rct)
return estimate_rct_tx_size(n_inputs, mixin, n_outputs, extra_size, bulletproof);
return estimate_rct_tx_size(n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag);
else
return n_inputs * (mixin+1) * APPROXIMATE_INPUT_BYTES + extra_size;
}
uint64_t monero_fee_utils::estimate_tx_weight(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof)
uint64_t monero_fee_utils::estimate_tx_weight(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag)
{
size_t size = estimate_tx_size(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof);
size_t size = estimate_tx_size(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag);
if (use_rct && bulletproof && n_outputs > 2)
{
const uint64_t bp_base = 368;
Expand All @@ -213,16 +216,16 @@ uint64_t monero_fee_utils::estimate_tx_weight(bool use_rct, int n_inputs, int mi
}
return size;
}
uint64_t monero_fee_utils::estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, uint64_t base_fee, uint64_t fee_multiplier, uint64_t fee_quantization_mask)
uint64_t monero_fee_utils::estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, uint64_t base_fee, uint64_t fee_multiplier, uint64_t fee_quantization_mask)
{
if (use_per_byte_fee)
{
const size_t estimated_tx_weight = estimate_tx_weight(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof);
const size_t estimated_tx_weight = estimate_tx_weight(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag);
return calculate_fee_from_weight(base_fee, estimated_tx_weight, fee_multiplier, fee_quantization_mask);
}
else
{
const size_t estimated_tx_size = estimate_tx_size(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof);
const size_t estimated_tx_size = estimate_tx_size(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag);
return calculate_fee_from_size(base_fee, estimated_tx_size, fee_multiplier);
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/monero_fee_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,16 @@ namespace monero_fee_utils
int get_fee_algorithm(use_fork_rules_fn_type use_fork_rules_fn);
uint64_t get_base_fee(uint64_t fee_per_b);
//
uint64_t estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, uint64_t base_fee, uint64_t fee_multiplier, uint64_t fee_quantization_mask);
uint64_t estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, uint64_t base_fee, uint64_t fee_multiplier, uint64_t fee_quantization_mask);
//
uint64_t calculate_fee_from_weight(uint64_t base_fee, uint64_t weight, uint64_t fee_multiplier, uint64_t fee_quantization_mask);
uint64_t calculate_fee(bool use_per_byte_fee, const cryptonote::transaction &tx, size_t blob_size, uint64_t base_fee, uint64_t fee_multiplier, uint64_t fee_quantization_mask);
//
/*Added*/ uint64_t calculate_fee_from_size(uint64_t fee_per_b, size_t bytes, uint64_t fee_multiplier);
//
size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof);
uint64_t estimate_tx_weight(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof);
size_t estimate_tx_size(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof);
size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag);
uint64_t estimate_tx_weight(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag);
size_t estimate_tx_size(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag);
uint64_t estimated_tx_network_fee( // convenience function for size + calc
uint64_t fee_per_b,
uint32_t priority, // when priority=0, falls back to monero_fee_utils::default_priority()
Expand Down
13 changes: 7 additions & 6 deletions src/monero_transfer_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ void monero_transfer_utils::send_step1__prepare_params_for_get_decoys(
//
bool use_rct = true;
bool bulletproof = true;
bool clsag = true;
//
std::vector<uint8_t> extra;
CreateTransactionErrorCode tx_extra__code = _add_pid_to_tx_extra(payment_id_string, extra);
Expand All @@ -274,9 +275,9 @@ void monero_transfer_utils::send_step1__prepare_params_for_get_decoys(
//
uint64_t attempt_at_min_fee;
if (passedIn_attemptAt_fee == none) {
attempt_at_min_fee = estimate_fee(true/*use_per_byte_fee*/, true/*use_rct*/, 2/*est num inputs*/, fake_outs_count, 2, extra.size(), bulletproof, base_fee, fee_multiplier, fee_quantization_mask);
// opted to do this instead of `const uint64_t min_fee = (fee_multiplier * base_fee * estimate_tx_size(use_rct, 1, fake_outs_count, 2, extra.size(), bulletproof));`
// TODO: estimate with 1 input or 2?
attempt_at_min_fee = estimate_fee(true/*use_per_byte_fee*/, true/*use_rct*/, 1/*est num inputs*/, fake_outs_count, 2, extra.size(), bulletproof, clsag, base_fee, fee_multiplier, fee_quantization_mask);
// use a minimum viabale estimate_fee() with 1 input. It would be better to under-shoot this estimate, and then need to use a higher fee from calculate_fee() because the estimate is too low,
// versus the worse alternative of over-estimating here and getting stuck using too high of a fee that leads to fingerprinting
} else {
attempt_at_min_fee = *passedIn_attemptAt_fee;
}
Expand Down Expand Up @@ -324,10 +325,10 @@ void monero_transfer_utils::send_step1__prepare_params_for_get_decoys(
uint64_t needed_fee = estimate_fee(
true/*use_per_byte_fee*/, use_rct,
retVals.using_outs.size(), fake_outs_count, /*tx.dsts.size()*/1+1, extra.size(),
bulletproof, base_fee, fee_multiplier, fee_quantization_mask
bulletproof, clsag, base_fee, fee_multiplier, fee_quantization_mask
);
// if newNeededFee < neededFee, use neededFee instead (should only happen on the 2nd or later times through (due to estimated fee being too low))
if (needed_fee < attempt_at_min_fee) {
if (passedIn_attemptAt_fee != none && needed_fee < attempt_at_min_fee) {
needed_fee = attempt_at_min_fee;
}
//
Expand Down Expand Up @@ -362,7 +363,7 @@ void monero_transfer_utils::send_step1__prepare_params_for_get_decoys(
needed_fee = estimate_fee(
true/*use_per_byte_fee*/, use_rct,
retVals.using_outs.size(), fake_outs_count, /*tx.dsts.size()*/1+1, extra.size(),
bulletproof, base_fee, fee_multiplier, fee_quantization_mask
bulletproof, clsag, base_fee, fee_multiplier, fee_quantization_mask
);
total_incl_fees = sending_amount + needed_fee; // because fee changed
}
Expand Down
9 changes: 6 additions & 3 deletions src/serial_bridge_index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,14 +343,15 @@ string serial_bridge::estimate_fee(const string &args_string)
int n_outputs = stoul(json_root.get<string>("n_outputs"));
size_t extra_size = stoul(json_root.get<string>("extra_size"));
bool bulletproof = json_root.get<bool>("bulletproof");
bool clsag = json_root.get<bool>("clsag");
uint64_t base_fee = stoull(json_root.get<string>("base_fee"));
uint64_t fee_quantization_mask = stoull(json_root.get<string>("fee_quantization_mask"));
uint32_t priority = stoul(json_root.get<string>("priority"));
uint8_t fork_version = stoul(json_root.get<string>("fork_version"));
use_fork_rules_fn_type use_fork_rules_fn = monero_fork_rules::make_use_fork_rules_fn(fork_version);
uint64_t fee_multiplier = monero_fee_utils::get_fee_multiplier(priority, monero_fee_utils::default_priority(), monero_fee_utils::get_fee_algorithm(use_fork_rules_fn), use_fork_rules_fn);
//
uint64_t fee = monero_fee_utils::estimate_fee(use_per_byte_fee, use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, base_fee, fee_multiplier, fee_quantization_mask);
uint64_t fee = monero_fee_utils::estimate_fee(use_per_byte_fee, use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, base_fee, fee_multiplier, fee_quantization_mask);
//
std::ostringstream o;
o << fee;
Expand All @@ -372,8 +373,9 @@ string serial_bridge::estimate_tx_weight(const string &args_string)
int n_outputs = stoul(json_root.get<string>("n_outputs"));
size_t extra_size = stoul(json_root.get<string>("extra_size"));
bool bulletproof = json_root.get<bool>("bulletproof");
bool clsag = json_root.get<bool>("clsag");
//
uint64_t weight = monero_fee_utils::estimate_tx_weight(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof);
uint64_t weight = monero_fee_utils::estimate_tx_weight(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag);
//
std::ostringstream o;
o << weight;
Expand All @@ -394,7 +396,8 @@ string serial_bridge::estimate_rct_tx_size(const string &args_string)
stoul(json_root.get<string>("mixin")),
stoul(json_root.get<string>("n_outputs")),
stoul(json_root.get<string>("extra_size")),
json_root.get<bool>("bulletproof")
json_root.get<bool>("bulletproof"),
json_root.get<bool>("clsag")
);
std::ostringstream o;
o << size;
Expand Down
13 changes: 8 additions & 5 deletions test/test_all.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ BOOST_AUTO_TEST_CASE(bridge__transfers__send__amountWOnlyDusty)
boost::property_tree::read_json(ret_stream, ret_tree);
optional<uint32_t> err_code = ret_tree.get_optional<uint32_t>(ret_json_key__any__err_code());
BOOST_REQUIRE_MESSAGE(err_code == none, "Expected no error");
BOOST_REQUIRE_MESSAGE(ret_tree.get<string>("using_fee") == string("66290000"), "Expected using_fee of 66290000");
BOOST_REQUIRE_MESSAGE(ret_tree.get<string>("using_fee") == string("35190000"), "Expected using_fee of 35190000");
BOOST_REQUIRE_MESSAGE(ret_tree.get<string>("final_total_wo_fee") == string("1000000"), "Expected final_total_wo_fee of 1000000");
}
string DG_postsweep__unspent_outs_json = "{\"unspent_outs\":[{\"amount\":\"3000000000\",\"public_key\":\"41be1978f58cabf69a9bed5b6cb3c8d588621ef9b67602328da42a213ee42271\",\"index\":1,\"global_index\":7611174,\"rct\":\"86a2c9f1f8e66848cd99bfda7a14d4ac6c3525d06947e21e4e55fe42a368507eb5b234ccdd70beca8b1fc8de4f2ceb1374e0f1fd8810849e7f11316c2cc063060008ffa5ac9827b776993468df21af8c963d12148622354f950cbe1369a92a0c\",\"tx_id\":5334971,\"tx_hash\":\"9d37c7fdeab91abfd1e7e120f5c49eac17b7ac04a97a0c93b51c172115df21ea\",\"tx_pub_key\":\"bd703d7f37995cc7071fb4d2929594b5e2a4c27d2b7c68a9064500ca7bc638b8\"}]}";
Expand Down Expand Up @@ -895,7 +895,7 @@ BOOST_AUTO_TEST_CASE(bridged__estimated_tx_network_fee)
BOOST_REQUIRE(fee_string != none);
BOOST_REQUIRE((*fee_string).size() > 0);
uint64_t fee = stoull(*fee_string);
BOOST_REQUIRE(fee == 330047330);
BOOST_REQUIRE(fee == 237333250);
cout << "bridged__estimated_tx_network_fee: " << fee << endl;
}
BOOST_AUTO_TEST_CASE(bridged__estimate_fee)
Expand All @@ -910,6 +910,7 @@ BOOST_AUTO_TEST_CASE(bridged__estimate_fee)
root.put("n_outputs", "2");
root.put("extra_size", "0");
root.put("bulletproof", "true");
root.put("clsag", "true");
root.put("base_fee", "24658");
root.put("fee_quantization_mask", "10000");
root.put("priority", "2");
Expand All @@ -928,7 +929,7 @@ BOOST_AUTO_TEST_CASE(bridged__estimate_fee)
BOOST_REQUIRE(fee_string != none);
BOOST_REQUIRE((*fee_string).size() > 0);
uint64_t fee = stoull(*fee_string);
BOOST_REQUIRE(fee == 330050000);
BOOST_REQUIRE(fee == 237340000);
cout << "bridged__estimate_fee: " << fee << endl;
}
BOOST_AUTO_TEST_CASE(bridged__estimate_tx_weight)
Expand All @@ -942,6 +943,7 @@ BOOST_AUTO_TEST_CASE(bridged__estimate_tx_weight)
root.put("n_outputs", "2");
root.put("extra_size", "0");
root.put("bulletproof", "true");
root.put("clsag", "true");
//
auto ret_string = serial_bridge::estimate_tx_weight(args_string_from_root(root));
stringstream ret_stream;
Expand All @@ -956,7 +958,7 @@ BOOST_AUTO_TEST_CASE(bridged__estimate_tx_weight)
BOOST_REQUIRE(weight_string != none);
BOOST_REQUIRE((*weight_string).size() > 0);
uint64_t weight = stoull(*weight_string);
BOOST_REQUIRE(weight == 2677);
BOOST_REQUIRE(weight == 1925);
cout << "bridged__estimate_tx_weight: " << weight << endl;
}
BOOST_AUTO_TEST_CASE(bridged__estimate_rct_tx_size)
Expand All @@ -969,6 +971,7 @@ BOOST_AUTO_TEST_CASE(bridged__estimate_rct_tx_size)
root.put("n_outputs", "2");
root.put("extra_size", "0");
root.put("bulletproof", "true");
root.put("clsag", "true");
//
auto ret_string = serial_bridge::estimate_rct_tx_size(args_string_from_root(root));
stringstream ret_stream;
Expand All @@ -983,7 +986,7 @@ BOOST_AUTO_TEST_CASE(bridged__estimate_rct_tx_size)
BOOST_REQUIRE(size_string != none);
BOOST_REQUIRE((*size_string).size() > 0);
size_t size = stoul(*size_string);
BOOST_REQUIRE(size == 1848);
BOOST_REQUIRE(size == 1416);
cout << "bridged__estimate_rct_tx_size: " << size << endl;
}
BOOST_AUTO_TEST_CASE(bridged__generate_key_image)
Expand Down

0 comments on commit 9032a05

Please sign in to comment.