-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Address elevated transaction fees. #4022
Changes from all commits
d6fdd4c
ef635e7
fc6015b
010f0cf
aa20afa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -96,13 +96,13 @@ class TxQ | |
FeeLevel64 minimumEscalationMultiplier = baseLevel * 500; | ||
/// Minimum number of transactions to allow into the ledger | ||
/// before escalation, regardless of the prior ledger's size. | ||
std::uint32_t minimumTxnInLedger = 5; | ||
std::uint32_t minimumTxnInLedger = 32; | ||
/// Like @ref minimumTxnInLedger for standalone mode. | ||
/// Primarily so that tests don't need to worry about queuing. | ||
std::uint32_t minimumTxnInLedgerSA = 1000; | ||
/// Number of transactions per ledger that fee escalation "works | ||
/// towards". | ||
std::uint32_t targetTxnInLedger = 50; | ||
std::uint32_t targetTxnInLedger = 256; | ||
/** Optional maximum allowed value of transactions per ledger before | ||
fee escalation kicks in. By default, the maximum is an emergent | ||
property of network, validator, and consensus performance. This | ||
|
@@ -613,17 +613,30 @@ class TxQ | |
} | ||
}; | ||
|
||
/// Used for sorting @ref MaybeTx by `feeLevel` | ||
class GreaterFee | ||
/// Used for sorting @ref MaybeTx | ||
class OrderCandidates | ||
{ | ||
public: | ||
/// Default constructor | ||
explicit GreaterFee() = default; | ||
|
||
/// Is the fee level of `lhs` greater than the fee level of `rhs`? | ||
explicit OrderCandidates() = default; | ||
|
||
/** Sort @ref MaybeTx by `feeLevel` descending, then by | ||
* transaction ID ascending | ||
* | ||
* The transaction queue is ordered such that transactions | ||
* paying a higher fee are in front of transactions paying | ||
* a lower fee, giving them an opportunity to be processed into | ||
* the open ledger first. Within transactions paying the same | ||
* fee, order by the arbitrary but consistent transaction ID. | ||
* This allows validators to build similar queues in the same | ||
* order, and thus have more similar initial proposals. | ||
* | ||
*/ | ||
bool | ||
operator()(const MaybeTx& lhs, const MaybeTx& rhs) const | ||
{ | ||
if (lhs.feeLevel == rhs.feeLevel) | ||
return lhs.txID < rhs.txID; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LIke @mDuo13 said in the comments, this is mineable, but if the variation of fees is random enough, shouldn't matter. If you wanted to be fancy, you could use the ledger sequence, or even better, the previous ledger hash, as a salt for a non-cryptographic hash of the transaction id, and order by that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, please consider using a similar method to transaction processing ordering also for queue sorting. It might not be an issue now, but it seems like it could be used to gain an unfair advantage. Even worse - the unfair advantage might be used to cause increasing load on the network, since I don't see much downside to push every incrementally "better" transaction immediately out instead of waiting for a "winner" and just let the remaining ones become invalid (e.g. through using the same sequence number?). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe could reuse some of the logic and thinking from CanonicalTxSet, in a reusable class? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Regarding mining for a low My recollection of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While we were discussing this fix, @thejohnfreeman suggested using the parent ledger's hash, just as you did @donovanhide. I think it makes sense and it's solution I would prefer too. But I'm of two minds here: one the one hand, I agree that adding this sort of "anti-mining" support makes sense and it's fairly easy; on the other hand, given that we're all moving fast to try and get this fix done on an expedited basis, I'd rather minimize the number of changes. So I'm fine with leaving this as a "TODO" but if others feels it's important to have it added now and @ximinez feels he can add it with minimal risk, I'm supportive. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. First, @mDuo13 , @MarkusTeufelberger , and @donovanhide , thank you very much for the feedback! I've already got anti-mining on the radar, and as @scottschurr mentioned, we've got some ideas for it. However, to emphasize what @nbougalis said, the priority for this PR is to keep the changes as small, simple, and easy to reason about as possible. I also think that the risk right now even just using the unmodified TX id is small for a few reasons.
So yes, there's a risk, and I'd like to address it in another minor release soon, but it seems like it's a very small risk. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that this issue should not be addressed in this PR. However, just wanted to highlight the nuances of one particular fictional example motive for mining: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @donovanhide Yeah, I can see how that might be a viable attack. It's still an open question whether it would still be cheaper to just have those noop transactions pay 13 drops vs. pre-mining. |
||
return lhs.feeLevel > rhs.feeLevel; | ||
} | ||
}; | ||
|
@@ -722,7 +735,7 @@ class TxQ | |
&MaybeTx::byFeeListHook>; | ||
|
||
using FeeMultiSet = boost::intrusive:: | ||
multiset<MaybeTx, FeeHook, boost::intrusive::compare<GreaterFee>>; | ||
multiset<MaybeTx, FeeHook, boost::intrusive::compare<OrderCandidates>>; | ||
|
||
using AccountMap = std::map<AccountID, TxQAccount>; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was initially surprised to see the comparison operator direction swapped between
txID
andfeeLevel
. Feels like it might be worth a comment that we sort with the smallesttxID
at the front, and the largestfeeLevel
at the front.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left such a comment at the top of the class. I can move it to the function, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done