-
Notifications
You must be signed in to change notification settings - Fork 197
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
On Transaction API, add "initially paid fee" and "is refund" #4108
Conversation
Codecov Report
@@ Coverage Diff @@
## feat/rosetta #4108 +/- ##
===============================================
Coverage ? 75.30%
===============================================
Files ? 621
Lines ? 82490
Branches ? 0
===============================================
Hits ? 62119
Misses ? 15671
Partials ? 4700 Continue to review full report at Codecov.
|
go.sum
Outdated
@@ -33,6 +33,10 @@ github.com/ElrondNetwork/elrond-go-core v1.1.15 h1:CMGtJMsK+fBHsSrh5b3N/okYMywbf | |||
github.com/ElrondNetwork/elrond-go-core v1.1.15/go.mod h1:Yz8JK5sGBctw7+gU8j2mZHbzQ09Ek4XHJ4Uinq1N6nM= | |||
github.com/ElrondNetwork/elrond-go-core v1.1.16-0.20220520142226-1f321f3d1726 h1:f8UmoIKktGHrYvjXBquoJiejuzxJtJBQJBtEDe/yftk= | |||
github.com/ElrondNetwork/elrond-go-core v1.1.16-0.20220520142226-1f321f3d1726/go.mod h1:Yz8JK5sGBctw7+gU8j2mZHbzQ09Ek4XHJ4Uinq1N6nM= | |||
github.com/ElrondNetwork/elrond-go-core v1.1.16-0.20220523135140-7d93ca7217ce h1:KtcRP5g71Br1rOCvIuKyzjw+6jwqBWSB0ZaA3WuUMlM= |
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.
go mod tidy
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.
} | ||
|
||
// Also see: https://github.com/ElrondNetwork/elastic-indexer-go/blob/master/process/transactions/scrsDataToTransactions.go | ||
func (detector *refundDetector) isRefund(result refundDetectorInput) bool { |
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.
maybe can rename the result
variable in something more specific like input
or scrInput
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.
Renamed to input
.
return nil, err | ||
} | ||
|
||
computer.economicsInstances[epoch] = newInstance |
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.
can we get OOMs because of using maps that do not get cleared?
Why not using a cacher instead of the map?
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.
Using a cache is indeed desirable. Currently, our LRU / time-based caches are non-generic. Though we can work around their functionality and use them in this context (e.g. using a string representation of the epoch as a key), do you think it's OK to postpone until upgrading the go version & support generics (added a TODO)?
However, also added a test for analyzing the memory footprint of the fee computer: ~12 MB for 10 000 epochs
.
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.
Ok, will keep the TODO for now
checkComputedFee(t, "50000000000000", computer, 0, 80000, 1000000000, "", nil) | ||
checkComputedFee(t, "57500000000000", computer, 0, 80000, 1000000000, "hello", nil) | ||
checkComputedFee(t, "57500000000000", computer, 0, 1000000, 1000000000, "hello", contract) | ||
// (for review) >>> the following scenarios pass, as well. Is this all right? |
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.
The penalize too much gas feature is just to protect against malicious actors that try to "keep for themselves" the whole blockchain by issuing transactions with large values for the gas limit field. These types of transactions will have the fees computed in the same way as any other transactions except that, if a provided fee exceeds 10x the gas consumed when executing, the blockchain will not refund the extra gas provided. The fee is computed the same because of this scenario:
suppose that shard 0 sends a SC call towards shard 1 with a gas limit of 600 million. The fee is completely subtracted from the shard 0 account as that shard does not know what is the actual cost of the call. The tx ends up executing on shard 1 but consumes only 10 million. The resulting SCR towards the shard 0 will have a refund value of 0 because the penalize too much gas feature is on.
initiallyPaidFee, err := atp.feeComputer.ComputeTransactionFee(tx.Tx, int(tx.Epoch)) | ||
if err != nil { | ||
log.Warn("populateInitiallyPaidFee(): unexpected condition, cannot compute fee", "tx", tx.Hash) | ||
return |
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.
so in this case the tx.InitiallyPaidFee is empty as "no fee"?
The return is no different as of the return on L133. How can we know something went wrong other than looking in the logs?
The error is propagated from this call:
feeComputer.createEconomicsInstance(epoch int) which was kind of tested in the constructor already in order to not hit "late construction errors due to programming errors"
Wondering if we can get rid of the error parameter and ease the handling results as seen in this component
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.
outdated log message? should have been populateComputedFieldInitiallyPaidFee()
instead of populateInitiallyPaidFee()
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.
Good catch & simplification.
Fixed to not return an error in ComputeTransactionFee
, indeed.
Also fixed the outdated log message.
|
||
isZero := initiallyPaidFee.Cmp(big.NewInt(0)) == 0 | ||
if isZero { | ||
return |
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.
why not setting tx.InitiallyPaidFee to "0" and then return? Will be more consistent when consuming the request.
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.
Previously, I wanted to not have the field in the response if that's zero ("0" will not be omitted by the serializer). However, on a second thought, changed to:
func (atp *apiTransactionProcessor) populateComputedFieldInitiallyPaidFee(tx *transaction.ApiTransactionResult) {
// Only user-initiated transactions will present an initially paid fee.
if tx.Type == string(transaction.TxTypeNormal) || tx.Type == string(transaction.TxTypeInvalid) {
fee := atp.feeComputer.ComputeTransactionFee(tx.Tx, int(tx.Epoch))
tx.InitiallyPaidFee = fee.String()
}
}
@iulianpascalau, @bogdan-rosianu, @miiu96, is this all right?
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.
actually, for 0 it will still return "" because it's a big.Int
🤦♂️
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.
Will handle this in next PR 🙏
return &refundDetector{} | ||
} | ||
|
||
// Also see: https://github.com/ElrondNetwork/elastic-indexer-go/blob/master/process/transactions/scrsDataToTransactions.go |
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.
wondering how we can remove all these code duplicates
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.
One option would be to create a new repository (and go package), such as transaction-decoder
or transaction-classifier
, independent of any other package. Then, we would reference this package in elrond-go
and elastic-indexer-go
.
The newly created repository / package would be quite stable in practice.
E.g. @tanghel created this repository for the JS ecosystem. Similarly, we can create extra, small and stable packages (and with no dependencies) for go.
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.
yup
I think we can easily place this in elrond-go-core since it is a business core-logic function
initiallyPaidFee, err := atp.feeComputer.ComputeTransactionFee(tx.Tx, int(tx.Epoch)) | ||
if err != nil { | ||
log.Warn("populateInitiallyPaidFee(): unexpected condition, cannot compute fee", "tx", tx.Hash) | ||
return |
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.
outdated log message? should have been populateComputedFieldInitiallyPaidFee()
instead of populateInitiallyPaidFee()
On Transaction API, add:
InitiallyPaidFee
(computed wrt. the epoch of the transaction)IsRefund