-
Notifications
You must be signed in to change notification settings - Fork 16
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
Use evaluateTransactionFee in calculate-min-fee #534
Conversation
hey @GeorgeFlerovsky i compiled this version to test it. looks like the calculated-fee is correct. question: can you make the "old" parameters for "mainnet/testnet" and the "tx-in-count/tx-out-count" optional so that it does not directly break existing code? |
Sure, I suppose I can reintroduce them with a deprecation notice. (They won't do anything) |
@GeorgeFlerovsky can you answer me a short question. looking at the length of the witnessed txBody in cbor format = txSize. the amount is 1 byte off when it comes to the txFee calculation. like a txWitnessedBody
has a cbor with a size of 337 bytes. using this as the txSize to calculate the |
@gitmachtl I think that this question gets fairly deep into the way that cbor gets decoded into Cardano Ledger types. In principle, I could probably track down the answer, but it would be fairly long and tedious across multiple libraries. If I had to guess, I would say that it's caused by the |
@gitmachtl Done. |
i have recompiled it, looks good to me. not breaking anything anymore. |
cc @Jimbo4350 |
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.
Thank you for this. It's been on our TODO list for some time.
cardano-cli/test/cardano-cli-golden/Test/Golden/Babbage/Transaction/CalculateMinFee.hs
Outdated
Show resolved
Hide resolved
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 just had a chat with @lehins. This command was created in the early Shelley era days so it does not take into consideration other things that can influence the tx fee. The best solution would be to use setMinFeeTx and modify the calculate-min-fee
command to take a witnessed transaction instead of a tx body. Perhaps also including an option to output the fee or the fee updated tx.
Edit: Apologies. calculate-min-fee
eventually calls evaluateTransactionFee.
Edit: Settled on implementing item 1 here. 2 and 3 can be done at a later date.
hmm... that would require all current cli tools to "fake" future witnesses. what would be other things that would influence tx fee? |
Anything that affects the size of the transaction:
So, the only way to accurately compute the fee is to construct a full transaction and call |
The fee amount is most likely always a 5byte cbor representation, that would cover all fees between 65536 and 4294967296 lovelaces. Thats why people should at least use an avg. fee value of f.e. 200000 lovelaces for the dummyTxBody generation imo. Script witnesses, are you talking about minting/burning scripts - which are already provided in the build-raw process. Or other ones? Maybe i am confused right now, but when the tx was built with all details via build-raw f.e. and the only thing that is left to do is to assemble witnesses, what can you do to the tx to modify its size at that stage other than providing the witnesses? |
So this needs some more thought. I propose the following scenarios:
Overall I think we only want to submit valid transactions or valid transaction fees otherwise we are creating more work for the user. |
What do you mean with fee updated tx? To have the balance correct the sum of the input utxos and all the outputs including the fee must be zero. (if there is no other deposit or so). I don't understand how this would work with a "fee updated tx"? Or are you talking "build" command and not "build-raw" ? These solutions to use witnessed or signed transactions sounds impractical to me in "real life". We have offline transactions, and we have transactions that are signed by multiple entities spread across different locations for example. Like pool owners providing a witness for a ready made txBody with there hardware wallets, etc. |
We're using So when I say "fee updated tx" I'm referring to a tx updated with a valid fee. |
from what i have seen so far the method to generate transactions with the existing 3rd party tools (which are using cardano-cli) are:
so i would say that your proposal to keep
is the right one for the current workflow imo. |
Yes, this scenario is covered in item 1 of my proposal. However, all three items should be implemented. I think it is acceptable to only implement 1 in place of this PR as this covers the prior functionality but 2 and 3 would be useful. |
@Jimbo4350 I got a bit confused by your direct edits of my comment lol. George (msg 1): Cardano Ledger already constructs dummy Shelley witnesses when you invoke Ledger.evaluateTransactionFee via Cardano.Api.evaluateTransactionFee: Unfortunately, it doesn't make dummy Byron witnesses, but IMO estimating Byron witness fees without dummy Byron witnesses (as I did in this PR) is reasonable given how rare they are these days. Jimbo (msg 2):
I agree however I'd prefer this is done via the way I outlined in item 1.. We want to avoid the size calculation function and instead rely on ledger functionality. Can you move the golden test changes to the final commit and squash them? |
Also, note that (assuming there are no Byron witnesses) we only need a TxBody to give to Cardano.Api.evaluateTransactionFee, not a full signed Tx. (When you have a full Tx, you can extract the body) |
How can AuxData be modified after witnesses are already provided for the tx hash? The Hash of the AuxData is part of the txBody. Alternating AuxData would make the whole witnessing before useless. I am confused. Or do you mean that only a hash of the AuxData is present in time of the fee calculation an not also the data for the AuxData itself too? Most unlikely to have this scenario talking cardano-cli imo. If people are messing around with self generated transactions via own tooling thats another thing. But cardano-cli shouldn't be responsible to get it right then imo. Most common scenario for tx building on the cli is like i pointed out here: #534 (comment) |
@Jimbo4350 Would it be OK to implement support for scenarios 2 and 3 in a subsequent PR? Unfortunately, I have to move on to other tasks this week. I can deal with bugfixes and minor adjustments in the PR, but adding new features might be a bit much for now. |
I agree, transactions witnessed with byron keys on the cli via cardano-cli are rare these days. I would go with the "worst case" scenario for byron witnesses and do a bit of an overestimation. |
That's what I did in the PR. 👍 |
Are you doing that because the transaction builder hasn't been handling fee calculation to begin with, or because you want to split it into two steps? |
@GeorgeFlerovsky I'm not sure, but there might be some edge cases where the fee isn't calculated properly. Possibly if an output utxo has inline datums or a datum hash. Haven't tested this in quite awhile though. This is the main reason a lot of us do the dummy transaction thing. It's the only way to REALLY know if the fees are correct. I do know that the current situation is un-tennable. Just this morning I tried building a transaction and the fee it calculated came in too low. I had to manually rebuild the tx and hard-code the fee.
Unfortunately, I didn't think to keep these files and when I re-built the hardcoded-fee tx, I overwrote them. |
It was too low with my new code in this PR, or the main branch of cardano-cli? |
We are sometimes building "difficult" transactions, and the decision on who is paying for what is sometimes mixed. So utxo-1 is paying for the fee of this transaction, so the tx-out is reduced about that amount for this address. utxo-2 is paying for the key deposit fee, utxo-3 is paying for half of the pool-registration deposit, etc. So, not just a simple transaction. And for that we always used (it was the only option back in the days) the build-raw command to have full control over the outcome. Thats all good, so if the fee calculation gets some updates and we still can do it by providing a pre-composed txBody to get the correct fee out of it we would be happy. |
I had a "fee too low" issue with your latest version of cardano-cli in combination with hw-wallet signing, because of CIP-0021 "violation" to use Tag258 everywhere or nowhere. I opened up an issue #567 Its not an issue with the fee calculation - which was on point at the time of the tx was generated, but the tx itself missed a Tag258. |
@gitmachtl |
Main branch code, not this one. I was lamenting not keeping the tx so you could test it to make sure it calculated properly. It's probably easy enough to re-create in a test setting though. It was a tx with a single utxo in with 500 ada + a big bucket of a single native asset. Then it was sent out to 56 different stake addresses with change returned. |
OK, please share the reproducible example when you find it. |
@GeorgeFlerovsky I was not able to reproduce it. I re-ran the transaction building script I had and it came out to 444373 this time. No idea what caused it to fail before. |
What is left that is holding up this PR given the current calculation is broken? |
Cardano.Api.estimateTransactionFee is deprecated and tends to over-estimate transaction fees. There is a deprecation note currently attached to Cardano.Api.estimateTransactionFee, saying that Cardano.Api.evaluateTransactionFee should be used instead. https://github.com/IntersectMBO/cardano-api/blob/1c10a287093ea1396c4c0ef0c92460f60bab690f/cardano-api/internal/Cardano/Api/Fees.hs#L190 Therefore, cardano-cli should be updated to use Cardano.Api.evaluateTransactionFee in the handler for calculate-min-fee. The existing golden test for calculate-min-fee was adjusted and another golden test with a babbage transaction was added.
@Jimbo4350 @gitmachtl @carbolymer cc @AndrewWestberg Can you please finish your review of this PR and merge it if it is ready? If it's not ready, can you please fork the branch and continue working on it yourselves in a different PR? I unfortunately don't have much more bandwidth to continue monitoring this PR if it's just stalled. |
@disassembler What is the status of this PR? The status quo is not really acceptable given that fees are sometimes calculated wrongly. |
|
this is not yet exposed via cardano-cli, right? |
I actually confused Turns out That being said, current implementation of So, I'd suggest merging this PR and then do some follow up work to figure out how |
@lehins hmm... now i am confused too. because for the current fee calculation on the cli we already create a dummyTx with the input utxo(s), the outputs, added certificates, etc. we pass this dummyTx than to the so utxos and outputs in the dummyTx are actually not used to calculate the fee currently? |
That is one of the main points of why ledger provides fee calculation functionality, so that you don't need to do this in cardano-node. Moreover, dummy tx approach taken here is incomplete and incorrect:
I understand that access to UTxO is not always possible, so we can do the best we can at guessing how big the witnesses will be, which is why So, taking one more look at the current PR, I'd suggest removing With respect to ref scripts (the point 2 above), that change will be present in the next ledger release. |
@GeorgeFlerovsky We have limited bandwidth at the moment because we are focused on Conway related testing. However I will pick this up within the next 2 weeks. |
No worries. If you need to make any administrative commits to the PR, please don't hesitate to do so. Let me know if I need to grant you any permissions to my fork. |
@GeorgeFlerovsky I haven't forgotten about this. I have assigned the task to my team as I will be off for essentially the rest of this month. |
@Jimbo4350 Thanks. Enjoy your time off. 🙏 |
Superceded by #642. |
Cardano.Api.estimateTransactionFee (currently used by Cardano CLI calculate-min-fee) tends to overestimate transaction fees. Furthermore, inspecting the code, estimateTransactionFee appears to only apply the old
a * x + b
fee formula to the transaction size (augmented to take into account the user-provided shelley and byron witness counts). This is not how fees should be calculated for later eras.A deprecation note is currently attached to Cardano.Api.estimateTransactionFee, saying that Cardano.Api.evaluateTransactionFee should be used instead. Inspecting the code, evaluateTransactionFee calls the Cardano Ledger's era-aware fee calculation function Cardano.Ledger.Shelley.API.Wallet.evaluateTransactionFee, which in turn calls the EraTx class function getMinFeeTx that is instantiated for every Cardano Ledger era.
https://github.com/IntersectMBO/cardano-api/blob/1c10a287093ea1396c4c0ef0c92460f60bab690f/cardano-api/internal/Cardano/Api/Fees.hs#L190
Therefore, cardano-cli should be updated to use Cardano.Api.evaluateTransactionFee in the handler for calculate-min-fee.
Changelog
Context
https://twitter.com/amw7/status/1740008349905928326
How to trust this PR
I added a golden test to calculate the min fee of a Babbage transaction body with Babbage protocol parameters, comparing against the known minimum fee (below which the transaction gets rejected when submitted to node).
https://github.com/IntersectMBO/cardano-cli/pull/534/files#diff-8d95bc46c5ef4bbab74b92c6b29635f1c3792d1e084d8c7668b0ce75bf9d2b52
Checklist