Skip to content
Permalink
Browse files

Allow fractional fee per byte for nicer resulting fee amounts

  • Loading branch information
zpalmtree committed Dec 17, 2019
1 parent 7445c25 commit 2248068744392be0959b8f4fc6c36f8d4d778e87
@@ -484,8 +484,9 @@ namespace WalletTypes
/* Fee will be specified as fee per byte, for example, 1 atomic TRTL per byte. */
bool isFeePerByte = false;

/* Fee for each byte, in atomic units */
uint64_t feePerByte = 0;
/* Fee for each byte, in atomic units. Allowed to be a double, since
* we will truncate it to an int upon performing the chunking. */
double feePerByte = 0;

/* Fee will be specified as a fixed fee */
bool isFixedFee = false;
@@ -503,7 +504,7 @@ namespace WalletTypes
return fee;
}

static FeeType FeePerByte(const uint64_t feePerByte)
static FeeType FeePerByte(const double feePerByte)
{
FeeType fee;
fee.isFeePerByte = true;
@@ -89,20 +89,18 @@ namespace CryptoNote
/* TODO: Remove? */
const uint64_t MINIMUM_FEE = UINT64_C(10);

/* Fee to charge per byte of transaction. Will be applied in chunks, see
* below. */
const uint64_t MINIMUM_FEE_PER_BYTE_V1 = 2;

/* Fee per byte is rounded up in chunks. This helps makes estimates
* more accurate. It's suggested to make this a power of two, to relate
* to the underlying storage cost / page sizes for storing a transaction. */
const uint64_t FEE_PER_BYTE_CHUNK_SIZE = 256;

/* 512 atomic units of fee, per 256 bytes of transaction - i.e., 2
* atomic units per byte. We do it in chunks of 256 bytes, as we have
* varint fields and so on. */
const uint64_t MINIMUM_FEE_PER_CHUNK = FEE_PER_BYTE_CHUNK_SIZE * MINIMUM_FEE_PER_BYTE_V1;

/* Fee to charge per byte of transaction. Will be applied in chunks, see
* above. This value comes out to 1.953125. We use this value instead of
* something like 2 because it makes for pretty resulting fees
* - 5 TRTL vs 5.12 TRTL. You can read this as.. the fee per chunk
* is 500 atomic units. The fee per byte is 500 / chunk size. */
const double MINIMUM_FEE_PER_BYTE_V1 = 500.00 / FEE_PER_BYTE_CHUNK_SIZE;

/* Height for our first fee to byte change to take effect. */
const uint64_t MINIMUM_FEE_PER_BYTE_V1_HEIGHT = 2200000;

@@ -219,15 +219,15 @@ namespace Utilities
uint64_t getTransactionFee(
const size_t transactionSize,
const uint64_t height,
const uint64_t feePerByte)
const double feePerByte)
{
const double numChunks = std::ceil(
const uint64_t numChunks = static_cast<uint64_t>(std::ceil(
transactionSize / static_cast<double>(CryptoNote::parameters::FEE_PER_BYTE_CHUNK_SIZE)
);

const uint64_t multiplier = feePerByte * CryptoNote::parameters::FEE_PER_BYTE_CHUNK_SIZE;
));

return static_cast<uint64_t>(numChunks) * multiplier;
return static_cast<uint64_t>(
numChunks * feePerByte * CryptoNote::parameters::FEE_PER_BYTE_CHUNK_SIZE
);
}

uint64_t getMinimumTransactionFee(
@@ -39,7 +39,7 @@ namespace Utilities
uint64_t getTransactionFee(
const size_t transactionSize,
const uint64_t height,
const uint64_t feePerByte);
const double feePerByte);

uint64_t getMinimumTransactionFee(
const size_t transactionSize,
@@ -1767,7 +1767,7 @@ namespace CryptoNote

if (!fee.isFixedFee)
{
const uint64_t feePerByte = fee.isFeePerByte
const double feePerByte = fee.isFeePerByte
? fee.feePerByte
: CryptoNote::parameters::MINIMUM_FEE_PER_BYTE_V1;

@@ -781,7 +781,7 @@ std::tuple<Error, uint16_t> ApiDispatcher::makeAdvancedTransaction(
}
else if (body.find("feePerByte") != body.end())
{
fee = WalletTypes::FeeType::FeePerByte(getJsonValue<uint64_t>(body, "feePerByte"));
fee = WalletTypes::FeeType::FeePerByte(getJsonValue<float>(body, "feePerByte"));
}

std::vector<std::string> subWalletsToTakeFrom = {};
@@ -354,7 +354,7 @@ namespace SendTransaction
extraData.size()
);

const uint64_t feePerByte = fee.isFeePerByte
const double feePerByte = fee.isFeePerByte
? fee.feePerByte
: CryptoNote::parameters::MINIMUM_FEE_PER_BYTE_V1;

@@ -576,7 +576,7 @@ namespace SendTransaction
const uint64_t sumOfInputs,
uint64_t amountPreFee,
uint64_t amountIncludingFee,
const uint64_t feePerByte,
const double feePerByte,
std::vector<std::pair<std::string, uint64_t>> addressesAndAmounts,
const std::string changeAddress,
const uint64_t mixin,
@@ -1462,13 +1462,13 @@ namespace SendTransaction
}
else
{
const uint64_t feePerByte = expectedFee.isFeePerByte
const double feePerByte = expectedFee.isFeePerByte
? expectedFee.feePerByte
: CryptoNote::parameters::MINIMUM_FEE_PER_BYTE_V1;

const size_t txSize = toBinaryArray(tx).size();

const size_t calculatedFee = feePerByte * txSize;
const size_t calculatedFee = static_cast<uint64_t>(feePerByte * txSize);

/* Ensure fee is greater or equal to the fee per byte specified,
* and no more than two times the fee per byte specified. */
@@ -116,7 +116,7 @@ namespace SendTransaction
const uint64_t sumOfInputs,
uint64_t totalAmount,
uint64_t estimatedAmount,
const uint64_t feePerByte,
const double feePerByte,
std::vector<std::pair<std::string, uint64_t>> addressesAndAmounts,
const std::string changeAddress,
const uint64_t mixin,
@@ -296,7 +296,7 @@ namespace PaymentService
serializer(changeAddress, "changeAddress");

uint64_t fixedFee;
uint64_t feePerByte;
double feePerByte;

if (serializer(fixedFee, "fee"))
{
@@ -341,7 +341,7 @@ namespace PaymentService
serializer(changeAddress, "changeAddress");

uint64_t fixedFee;
uint64_t feePerByte;
double feePerByte;

if (!serializer(fixedFee, "fee"))
{

0 comments on commit 2248068

Please sign in to comment.
You can’t perform that action at this time.