get_dynamic_per_kb_fee_estimate added and default mixing changed to 4

pull/4/head
moneroexamples 7 years ago
parent 943e65c385
commit 4e10b44a80

@ -1622,8 +1622,11 @@ var cnUtil = (function(initConfig) {
var in_contexts = [];
var inputs_money = JSBigInt.ZERO;
var i, j;
console.log('Sources: ');
for (i = 0; i < sources.length; i++) {
for (i = 0; i < sources.length; i++)
{
console.log(i + ': ' + this.formatMoneyFull(sources[i].amount));
if (sources[i].real_out >= sources[i].outputs.length) {
throw "real index >= outputs.length";
@ -1721,7 +1724,6 @@ var cnUtil = (function(initConfig) {
console.log(tx);
return tx;
};
this.create_transaction = function(pub_keys, sec_keys, dsts, outputs, mix_outs, fake_outputs_count, fee_amount, payment_id, pid_encrypt, realDestViewKey, unlock_time, rct) {
unlock_time = unlock_time || 0;
mix_outs = mix_outs || [];
@ -1759,9 +1761,7 @@ var cnUtil = (function(initConfig) {
}
var found_money = JSBigInt.ZERO;
var sources = [];
//console.log('Selected transfers: ', outputs);
console.log('Selected transfers: ', outputs);
for (i = 0; i < outputs.length; ++i) {
found_money = found_money.add(outputs[i].amount);
if (found_money.compare(UINT64_MAX) !== -1) {
@ -1787,9 +1787,6 @@ var cnUtil = (function(initConfig) {
var oe = {};
oe.index = out.global_index.toString();
oe.key = out.public_key;
//console.log('outputs[',i,']: ', outputs[i]);
if (rct){
if (out.rct){
oe.commit = out.rct.slice(0,64); //add commitment from rct mix outs
@ -1835,7 +1832,7 @@ var cnUtil = (function(initConfig) {
}
sources.push(src);
}
//console.log('sources: ', sources);
console.log('sources: ', sources);
var change = {
amount: JSBigInt.ZERO
};
@ -1935,19 +1932,19 @@ var cnUtil = (function(initConfig) {
this.decompose_amount_into_digits = function(amount) {
/*if (dust_threshold === undefined) {
dust_threshold = config.dustThreshold;
}*/
dust_threshold = config.dustThreshold;
}*/
amount = amount.toString();
var ret = [];
while (amount.length > 0) {
//split all the way down since v2 fork
/*var remaining = new JSBigInt(amount);
if (remaining.compare(config.dustThreshold) <= 0) {
if (remaining.compare(0) > 0) {
ret.push(remaining);
}
break;
}*/
if (remaining.compare(config.dustThreshold) <= 0) {
if (remaining.compare(0) > 0) {
ret.push(remaining);
}
break;
}*/
//check so we don't create 0s
if (amount[0] !== "0"){
var digit = amount[0];
@ -1987,12 +1984,11 @@ var cnUtil = (function(initConfig) {
return a["amount"] - b["amount"];
});
};
this.is_tx_unlocked = function(unlock_time, blockchain_height) {
if (!config.maxBlockNumber) {
throw "Max block number is not set in config!";
}
//console.log(blockchain_height, unlock_time);
if (unlock_time < config.maxBlockNumber) {
// unlock time is block height
return blockchain_height >= unlock_time;
@ -2031,4 +2027,4 @@ var cnUtil = (function(initConfig) {
}
return this;
})(config);
})(config);

@ -15,7 +15,7 @@ var config = {
feePerKB: new JSBigInt('2000000000'),//10^10
dustThreshold: new JSBigInt('1000000000'),//10^10 used for choosing outputs/change - we decompose all the way down if the receiver wants now regardless of threshold
txChargeRatio: 0.5,
defaultMixin: 3,
defaultMixin: 4,
txChargeAddress: '',
idleTimeout: 30,
idleWarningDuration: 20,

@ -186,8 +186,12 @@ thinwalletCtrls.controller('SendCoinsCtrl', function($scope, $http, $q, AccountS
}
})(deferred, target);
}
// Transaction will need at least 1KB fee (13KB for RingCT)
var neededFee = rct ? config.feePerKB.multiply(13) : config.feePerKB;
var feePerKB = new JSBigInt(config.feePerKB);
var neededFee = rct ? feePerKB.multiply(13) : feePerKB;
var totalAmountWithoutFee;
var unspentOuts;
var pid_encrypt = false; //don't encrypt payment ID unless we find an integrated one
@ -247,6 +251,10 @@ thinwalletCtrls.controller('SendCoinsCtrl', function($scope, $http, $q, AccountS
unused_outs = unspentOuts.slice(0);
using_outs = [];
using_outs_amount = new JSBigInt(0);
if (data.per_kb_fee)
{
feePerKB = new JSBigInt(data.per_kb_fee);
}
transfer().then(transferSuccess, transferFailure);
})
.error(function(data) {
@ -297,7 +305,7 @@ thinwalletCtrls.controller('SendCoinsCtrl', function($scope, $http, $q, AccountS
numKB++;
}
console.log(txBlobBytes + " bytes <= " + numKB + " KB (current fee: " + cnUtil.formatMoneyFull(prevFee) + ")");
neededFee = config.feePerKB.multiply(numKB);
neededFee = feePerKB.multiply(numKB);
// if we need a higher fee
if (neededFee.compare(prevFee) > 0) {
console.log("Previous fee: " + cnUtil.formatMoneyFull(prevFee) + " New fee: " + cnUtil.formatMoneyFull(neededFee));
@ -387,28 +395,37 @@ thinwalletCtrls.controller('SendCoinsCtrl', function($scope, $http, $q, AccountS
select_outputs(totalAmount);
//compute fee as closely as possible before hand
if (using_outs.length > 1 && rct) {
var newNeededFee = JSBigInt(Math.ceil(cnUtil.estimateRctSize(using_outs.length, mixin, 2) / 1024)).multiply(config.feePerKB);
if (using_outs.length > 1 && rct)
{
var newNeededFee = JSBigInt(Math.ceil(cnUtil.estimateRctSize(using_outs.length, mixin, 2) / 1024)).multiply(feePerKB);
totalAmount = totalAmountWithoutFee.add(newNeededFee);
//add outputs 1 at a time till we either have them all or can meet the fee
while (using_outs_amount.compare(totalAmount) < 0 && unused_outs.length > 0) {
while (using_outs_amount.compare(totalAmount) < 0 && unused_outs.length > 0)
{
var out = pop_random_value(unused_outs);
using_outs.push(out);
using_outs_amount = using_outs_amount.add(out.amount);
console.log("Using output: " + cnUtil.formatMoney(out.amount) + " - " + JSON.stringify(out));
newNeededFee = JSBigInt(Math.ceil(cnUtil.estimateRctSize(using_outs.length, mixin, 2) / 1024)).multiply(config.feePerKB);
newNeededFee = JSBigInt(Math.ceil(cnUtil.estimateRctSize(using_outs.length, mixin, 2) / 1024)).multiply(feePerKB);
totalAmount = totalAmountWithoutFee.add(newNeededFee);
}
console.log("New fee: " + cnUtil.formatMoneySymbol(newNeededFee) + " for " + using_outs.length + " inputs");
neededFee = newNeededFee;
}
if (using_outs_amount.compare(totalAmount) < 0) {
deferred.reject("Not enough spendable outputs / balance too low (have: " + cnUtil.formatMoneyFull(using_outs_amount) + " need: " + cnUtil.formatMoneyFull(totalAmount) + ")");
if (using_outs_amount.compare(totalAmount) < 0)
{
deferred.reject("Not enough spendable outputs / balance too low (have: "
+ cnUtil.formatMoneyFull(using_outs_amount) + " need: "
+ cnUtil.formatMoneyFull(totalAmount) + ")");
return;
} else if (using_outs_amount.compare(totalAmount) > 0) {
}
else if (using_outs_amount.compare(totalAmount) > 0)
{
var changeAmount = using_outs_amount.subtract(totalAmount);
if (!rct) { //for rct we don't presently care about dustiness
if (!rct)
{ //for rct we don't presently care about dustiness
//do not give ourselves change < dust threshold
var changeAmountDivRem = changeAmount.divRem(config.dustThreshold);
if (changeAmountDivRem[1].toString() !== "0") {
@ -424,15 +441,20 @@ thinwalletCtrls.controller('SendCoinsCtrl', function($scope, $http, $q, AccountS
amount: usableChange
});
}
} else {
}
else
{
//add entire change for rct
console.log("Sending change of " + cnUtil.formatMoneySymbol(changeAmount) + " to " + AccountService.getAddress());
console.log("Sending change of " + cnUtil.formatMoneySymbol(changeAmount)
+ " to " + AccountService.getAddress());
dsts.push({
address: AccountService.getAddress(),
amount: changeAmount
});
}
} else if (using_outs_amount.compare(totalAmount) === 0 && rct) {
}
else if (using_outs_amount.compare(totalAmount) === 0 && rct)
{
//create random destination to keep 2 outputs always in case of 0 change
var fakeAddress = cnUtil.create_address(cnUtil.random_scalar()).public_addr;
console.log("Sending 0 XMR to a fake address to keep tx uniform (no change exists): " + fakeAddress);
@ -442,9 +464,11 @@ thinwalletCtrls.controller('SendCoinsCtrl', function($scope, $http, $q, AccountS
});
}
if (mixin > 0) {
if (mixin > 0)
{
var amounts = [];
for (var l = 0; l < using_outs.length; l++) {
for (var l = 0; l < using_outs.length; l++)
{
amounts.push(using_outs[l].rct ? "0" : using_outs[l].amount.toString());
}
var request = {
@ -470,18 +494,24 @@ thinwalletCtrls.controller('SendCoinsCtrl', function($scope, $http, $q, AccountS
}
// Create & serialize transaction
function createTx(mix_outs) {
function createTx(mix_outs)
{
var signed;
try {
console.log('Destinations: ');
cnUtil.printDsts(dsts);
//need to get viewkey for encrypting here, because of splitting and sorting
if (pid_encrypt) {
if (pid_encrypt)
{
var realDestViewKey = cnUtil.decode_address(dsts[0].address).view;
}
var splittedDsts = cnUtil.decompose_tx_destinations(dsts, rct);
console.log('Decomposed destinations:');
cnUtil.printDsts(splittedDsts);
signed = cnUtil.create_transaction(
AccountService.getPublicKeys(),
AccountService.getSecretKeys(),

@ -57,7 +57,7 @@
<label class="send-label" for="field4">Privacy Level (Mixin)</label>
<select class="w-select" id="field4" name="Select-a-number" data-name="Select a number"
required="required" ng-model="mixins">
<option value="3">Low (mix with 3 others)</option>
<option value="4">Low (mix with 4 others)</option>
<option value="6">Medium (mix with 6 others)</option>
<option value="10">High (mix with 10 others)</option>
<option value="20">Paranoid (mix with 20 others)</option>

@ -274,9 +274,10 @@ CurrentBlockchainStatus::get_amount_specific_indices(const crypto::hash& tx_hash
}
bool
CurrentBlockchainStatus::get_random_outputs(const vector<uint64_t>& amounts,
const uint64_t& outs_count,
vector<COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount>& found_outputs)
CurrentBlockchainStatus::get_random_outputs(
const vector<uint64_t>& amounts,
const uint64_t& outs_count,
vector<COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount>& found_outputs)
{
rpccalls rpc {deamon_url};
@ -291,6 +292,24 @@ CurrentBlockchainStatus::get_random_outputs(const vector<uint64_t>& amounts,
return true;
}
bool
CurrentBlockchainStatus::get_dynamic_per_kb_fee_estimate(uint64_t& fee_estimated)
{
rpccalls rpc {deamon_url};
string error_msg;
if (!rpc.get_dynamic_per_kb_fee_estimate(
FEE_ESTIMATE_GRACE_BLOCKS,
fee_estimated, error_msg))
{
cerr << "rpc.get_dynamic_per_kb_fee_estimate failed" << endl;
return false;
}
return true;
}
bool
CurrentBlockchainStatus::commit_tx(const string& tx_blob)

@ -122,6 +122,9 @@ struct CurrentBlockchainStatus
const uint64_t& outs_count,
vector<COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount>& found_outputs);
static bool
get_dynamic_per_kb_fee_estimate(uint64_t& fee_estimated);
static bool
commit_tx(const string& tx_blob);

@ -512,6 +512,20 @@ YourMoneroRequests::get_unspent_outs(const shared_ptr< Session > session, const
j_response["amount"] = total_outputs_amount;
// need proper per_kb_fee estimate for testnet as
// it is already using dynanamic fees. frontend
// uses old fixed fees.
if (CurrentBlockchainStatus::testnet)
{
uint64_t fee_estimated {DYNAMIC_FEE_PER_KB_BASE_FEE};
if (CurrentBlockchainStatus::get_dynamic_per_kb_fee_estimate(fee_estimated))
{
j_response["per_kb_fee"] = fee_estimated;
}
}
} // if (xmr_accounts->select(xmr_address, acc))
string response_body = j_response.dump();

@ -14,6 +14,7 @@
#define KEY_IMAGE_EXPORT_FILE_MAGIC "Monero key image export\002"
#define OUTPUT_EXPORT_FILE_MAGIC "Monero output export\002"
#define FEE_ESTIMATE_GRACE_BLOCKS 10
#include "net/http_client.h"
#include "storages/http_abstract_invoke.h"

@ -282,6 +282,50 @@ namespace xmreg
return true;
}
bool
get_dynamic_per_kb_fee_estimate(uint64_t grace_blocks,
uint64_t& fee,
string& error_msg)
{
epee::json_rpc::request<COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE::request>
req_t = AUTO_VAL_INIT(req_t);
epee::json_rpc::response<COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE::response, std::string>
resp_t = AUTO_VAL_INIT(resp_t);
req_t.jsonrpc = "2.0";
req_t.id = epee::serialization::storage_entry(0);
req_t.method = "get_fee_estimate";
req_t.params.grace_blocks = grace_blocks;
std::lock_guard<std::mutex> guard(m_daemon_rpc_mutex);
if (!connect_to_monero_deamon())
{
cerr << "get_current_height: not connected to deamon" << endl;
return false;
}
bool r = epee::net_utils::invoke_http_json("/json_rpc",
req_t, resp_t,
m_http_client);
if (!r || resp_t.result.status == "Failed")
{
error_msg = resp_t.error;
cerr << "Error get_dynamic_per_kb_fee_estimate: " << error_msg << endl;
return false;
}
fee = resp_t.result.fee;
return true;
}
bool
commit_tx(tools::wallet2::pending_tx& ptx, string& error_msg)

Loading…
Cancel
Save