input-output-hk / plutus-apps

The Plutus application platform

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`Wallet.Emulator.Folds.walletFees` incorrectly computes fees for transactions that failed with missing UTxO error in Phase 2

MaximilianAlgehed opened this issue · comments

Summary

The emulator fold Wallet.Emulator.Folds.walletFees incorrectly computes the fees from a faulty assumption that all transactions that fail in phase 2 will result in fees being charged. This is not the case for all transactions as seen below.

Steps to reproduce the behavior

Produce two transactions that race for the same UTxO. Using QuickCheck we found the following trace that results in walletFees telling us 20 lovelace was used in fees when the actual number is only 10 lovelace:

Prelude Test.QuickCheck Spec.Escrow Main> quickCheck . withMaxSuccess 100 $ prop_Escrow
/nix/store/hy3lz2vfv9qq2v5jz9nzlx6mmiaq79rj-binutils-2.35.1/bin/ld: warning: type and size of dynamic symbol `plutuszmledgerzm0zi1zi0zi0zminplace_LedgerziIndex_minAdaTxOut_closure' are not defined
*** Failed! Assertion failed (after 24 tests and 5 shrinks):
Actions
 [AnyRefund (Wallet d3eddd0d37989746b029a0e050386bc425363901) (Wallet 7ce812d7a4770bbf58004067665c3a48f28ddd58),
  Pay (Wallet d3eddd0d37989746b029a0e050386bc425363901) 29]
Expected funds of Wd3eddd0 to change by
  Value (Map [(,Map [("",-29000000)])])
but they changed by
  Value (Map [(,Map [("",-28999990)])])
Test failed.
Emulator log:
[INFO] Slot 0: TxnValidate ee3a44b98e0325e19bc6be1e6f25cdb269301666a3473758296e96cd7ea9a851
[INFO] Slot 1: 00000000-0000-4000-8000-000000000000 {Wallet W872c}:
                 Contract instance started
[INFO] Slot 1: 00000000-0000-4000-8000-000000000001 {Wallet W7ce8}:
                 Contract instance started
[INFO] Slot 1: 00000000-0000-4000-8000-000000000002 {Wallet Wc30e}:
                 Contract instance started
[INFO] Slot 1: 00000000-0000-4000-8000-000000000003 {Wallet W5f5a}:
                 Contract instance started
[INFO] Slot 1: 00000000-0000-4000-8000-000000000004 {Wallet Wd3ed}:
                 Contract instance started
[INFO] Slot 1: 00000000-0000-4000-8000-000000000004 {Wallet Wd3ed}:
                 Receive endpoint call on 'anyrefund-escrow' for Object (fromList [("contents",Array [Object (fromList [("getEndpointDescription",String "anyrefund-escrow")]),Object (fromList [("unEndpointValue",Object (fromList [("unPaymentPubKeyHash",Object (fromList [("getPubKeyHash",String "80a4f45b56b88d1139da23bc4c3c75ec6d32943c087f250b86193ca7")]))]))])]),("tag",String "ExposeEndpointResp")])
[INFO] Slot 1: Wd3eddd0: Balancing an unbalanced transaction:
                           Tx:
                             Tx 10011e49ebb9f8435aba2a6d53a82adce83afb896e6d9eabbcb353eda04f31e7:
                               {inputs:
                               collateral inputs:
                               outputs:
                               mint: Value (Map [])
                               fee: Value (Map [])
                               mps:
                               signatures:
                               validity range: Interval {ivFrom = LowerBound NegInf True, ivTo = UpperBound PosInf True}
                               data:}
                           Requires signatures:
                           Utxo index:
                           Validity range:
                             [ POSIXTime 1596059092998 , +∞)
[INFO] Slot 1: Wd3eddd0: Finished balancing:
                           Tx f8b175e639e27f517052c8a1c2915174e26ee27145504fdb31451f2d2887857a:
                             {inputs:
                                - ee3a44b98e0325e19bc6be1e6f25cdb269301666a3473758296e96cd7ea9a851!7
                             collateral inputs:
                               - ee3a44b98e0325e19bc6be1e6f25cdb269301666a3473758296e96cd7ea9a851!7
                             outputs:
                               - Value (Map [(,Map [("",99999999999999990)])]) addressed to
                                 PubKeyCredential: bf342ddd3b1a6191d4ce936c92d29834d6879edf2849eaea84c827f8 (no staking credential)
                             mint: Value (Map [])
                             fee: Value (Map [(,Map [("",10)])])
                             mps:
                             signatures:
                               993684ab55aa4f999edb02c9cd1e730e91d785eccc0922db5d2aa805fde40f68
                             validity range: Interval {ivFrom = LowerBound (Finite (Slot {getSlot = 1})) False, ivTo = UpperBound PosInf True}
                             data:}
[INFO] Slot 1: Wd3eddd0: Submitting tx: f8b175e639e27f517052c8a1c2915174e26ee27145504fdb31451f2d2887857a
[INFO] Slot 1: Wd3eddd0: TxSubmit: f8b175e639e27f517052c8a1c2915174e26ee27145504fdb31451f2d2887857a
[INFO] Slot 2: 00000000-0000-4000-8000-000000000004 {Wallet Wd3ed}:
                 Receive endpoint call on 'pay-escrow' for Object (fromList [("contents",Array [Object (fromList [("getEndpointDescription",String "pay-escrow")]),Object (fromList [("unEndpointValue",Object (fromList [("getValue",Array [Array [Object (fromList [("unCurrencySymbol",String "")]),Array [Array [Object (fromList [("unTokenName",String "")]),Number 2.9e7]]]])]))])]),("tag",String "ExposeEndpointResp")])
[INFO] Slot 2: Wd3eddd0: Balancing an unbalanced transaction:
                           Tx:
                             Tx dab9bed6bface777ee4be812de7ec292e82241ae58f0fbc583994a806676e111:
                               {inputs:
                               collateral inputs:
                               outputs:
                                 - Value (Map [(,Map [("",29000000)])]) addressed to
                                   ScriptCredential: 5f0ea0cb1f3efccb057c221aac4e5670d965cb8cee44b678e5fee8be (no staking credential)
                               mint: Value (Map [])
                               fee: Value (Map [])
                               mps:
                               signatures:
                               validity range: Interval {ivFrom = LowerBound NegInf True, ivTo = UpperBound PosInf True}
                               data:
                                 "\191\&4-\221;\SUBa\145\212\206\147l\146\210\152\&4\214\135\158\223(I\234\234\132\200'\248"}
                           Requires signatures:
                           Utxo index:
                           Validity range:
                             [ POSIXTime 1 , POSIXTime 1596059131000 ]
[INFO] Slot 2: Wd3eddd0: Finished balancing:
                           Tx d5d5c4862fc57ad9b91f8ae4962d5d64c2aabd7f1f44a66213595691b4dcb9bb:
                             {inputs:
                                - ee3a44b98e0325e19bc6be1e6f25cdb269301666a3473758296e96cd7ea9a851!7
                             collateral inputs:
                               - ee3a44b98e0325e19bc6be1e6f25cdb269301666a3473758296e96cd7ea9a851!7
                             outputs:
                               - Value (Map [(,Map [("",99999999970999990)])]) addressed to
                                 PubKeyCredential: bf342ddd3b1a6191d4ce936c92d29834d6879edf2849eaea84c827f8 (no staking credential)
                               - Value (Map [(,Map [("",29000000)])]) addressed to
                                 ScriptCredential: 5f0ea0cb1f3efccb057c221aac4e5670d965cb8cee44b678e5fee8be (no staking credential)
                             mint: Value (Map [])
                             fee: Value (Map [(,Map [("",10)])])
                             mps:
                             signatures:
                               993684ab55aa4f999edb02c9cd1e730e91d785eccc0922db5d2aa805fde40f68
                             validity range: Interval {ivFrom = LowerBound (Finite (Slot {getSlot = -1596059091})) False, ivTo = UpperBound (Finite (Slot {getSlot = 40})) False}
                             data:
                               "\191\&4-\221;\SUBa\145\212\206\147l\146\210\152\&4\214\135\158\223(I\234\234\132\200'\248"}
[INFO] Slot 2: Wd3eddd0: Submitting tx: d5d5c4862fc57ad9b91f8ae4962d5d64c2aabd7f1f44a66213595691b4dcb9bb
[INFO] Slot 2: Wd3eddd0: TxSubmit: d5d5c4862fc57ad9b91f8ae4962d5d64c2aabd7f1f44a66213595691b4dcb9bb
[INFO] Slot 2: TxnValidate d5d5c4862fc57ad9b91f8ae4962d5d64c2aabd7f1f44a66213595691b4dcb9bb
[WARNING] Slot 2: TxnValidationFail Phase2 f8b175e639e27f517052c8a1c2915174e26ee27145504fdb31451f2d2887857a: TxOutRefNotFound (TxOutRef {txOutRefId = ee3a44b98e0325e19bc6be1e6f25cdb269301666a3473758296e96cd7ea9a851, txOutRefIdx = 7})
[INFO] Slot 3: 00000000-0000-4000-8000-000000000005 {supercalifragilisticexpialidocious}:
                 Contract instance started
[INFO] Slot 3: 00000000-0000-4000-8000-000000000005 {supercalifragilisticexpialidocious}:
                 Receive endpoint call on 'register-token-env' for Object (fromList [("contents",Array [Object (fromList [("getEndpointDescription",String "register-token-env")]),Object (fromList [("unEndpointValue",Object (fromList [("0",Object (fromList [])),("1",Object (fromList []))]))])]),("tag",String "ExposeEndpointResp")])
[INFO] Slot 3: 00000000-0000-4000-8000-000000000005 {supercalifragilisticexpialidocious}:
                 Contract instance stopped (no errors)

Actual Result

We get 20 lovelace spent on fees.

Expected Result

10 lovelace spent on fees.

Describe the approach you would take to fix this

I think it's a case of adjusting walletFees, which currently computes its fees by summing up the fees of all good txs and all txs that fail in phase 2, to only pick "the right" transactions to accumulate fees from. I would do it myself but I don't know the exact rules the ledger uses to determine what Phase 2 failed transactions compute fees.

System info

Plutus: main at the time of writing - this code hasn't been touched in a while anyway so I suspect it's not sensitive to specific commits.

Closing as quickCheck . withMaxSuccess 100 $ prop_Escrow doesn't produce an error anymore. There were some changes in that function in commit 2bfeae0

ezoic increase your site revenue