Skip to content

Commit

Permalink
Merge #3226
Browse files Browse the repository at this point in the history
3226: Minting edge cases and additional testing r=paweljakubas a=paweljakubas

<!--
Detail in a few bullet points the work accomplished in this PR.

Before you submit, don't forget to:

* Make sure the GitHub PR fields are correct:
   ✓ Set a good Title for your PR.
   ✓ Assign yourself to the PR.
   ✓ Assign one or more reviewer(s).
   ✓ Link to a Jira issue, and/or other GitHub issues or PRs.
   ✓ In the PR description delete any empty sections
     and all text commented in <!--, so that this text does not appear
     in merge commit messages.

* Don't waste reviewers' time:
   ✓ If it's a draft, select the Create Draft PR option.
   ✓ Self-review your changes to make sure nothing unexpected slipped through.

* Try to make your intent clear:
   ✓ Write a good Description that explains what this PR is meant to do.
   ✓ Jira will detect and link to this PR once created, but you can also
     link this PR in the description of the corresponding Jira ticket.
   ✓ Highlight what Testing you have done.
   ✓ Acknowledge any changes required to the Documentation.
-->

Edge cases addressed:

- [x] We now reject asset names that are too long.
- [x] We now reject asset quantities that are out of bounds.
- [x] We now accept empty asset names.
- [x] We now handle minting to foreign addresses.

### Comments

<!-- Additional comments, links, or screenshots to attach, if any. -->

### Issue Number
ADP-1542
<!-- Reference the Jira/GitHub issue that this PR relates to, and which requirements it tackles.
  Note: Jira issues of the form ADP- will be auto-linked. -->


Co-authored-by: Pawel Jakubas <jakubas.pawel@gmail.com>
Co-authored-by: Jonathan Knowles <jonathan.knowles@iohk.io>
  • Loading branch information
3 people authored Apr 15, 2022
2 parents fec6ec6 + 646d2cb commit 72d6eb7
Show file tree
Hide file tree
Showing 12 changed files with 5,922 additions and 7,475 deletions.
15 changes: 15 additions & 0 deletions lib/core-integration/src/Test/Integration/Framework/TestData.hs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ module Test.Integration.Framework.TestData
, errMsg403MultidelegationTransaction
, errMsg403MultiaccountTransaction
, errMsg403CreatedWrongPolicyScriptTemplate
, errMsg403AssetNameTooLong
, errMsg403MintOrBurnAssetQuantityOutOfBounds
) where

import Prelude
Expand Down Expand Up @@ -677,6 +679,19 @@ errMsg403CreatedWrongPolicyScriptTemplate = mconcat
, "than one cosigner, or has a cosigner that is different from cosigner#0."
]

errMsg403AssetNameTooLong :: String
errMsg403AssetNameTooLong = mconcat
[ "Attempted to create a transaction with an asset name that is "
, "too long. The maximum length is 32 bytes."
]

errMsg403MintOrBurnAssetQuantityOutOfBounds :: String
errMsg403MintOrBurnAssetQuantityOutOfBounds = mconcat
[ "Attempted to mint or burn an asset quantity that is out of "
, "bounds. The asset quantity must be greater than zero and must "
, "not exceed 9223372036854775807 (2^63 - 1)."
]

--------------------------------------------------------------------------------
-- Transaction metadata
--------------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,14 @@ import Test.Integration.Framework.DSL
, (.>)
)
import Test.Integration.Framework.TestData
( errMsg403Collateral
( errMsg403AssetNameTooLong
, errMsg403Collateral
, errMsg403CreatedWrongPolicyScriptTemplate
, errMsg403Fee
, errMsg403ForeignTransaction
, errMsg403InvalidConstructTx
, errMsg403MinUTxOValue
, errMsg403MintOrBurnAssetQuantityOutOfBounds
, errMsg403MissingWitsInTransaction
, errMsg403MultiaccountTransaction
, errMsg403MultidelegationTransaction
Expand Down Expand Up @@ -3101,12 +3103,6 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do

it "TRANS_NEW_CREATE_10l - Minting when assetName too long" $
\ctx -> runResourceT $ do
liftIO $ pendingWith "Returns 500 - Something went wrong"
-- L ERROR: toCardanoValue: unable to deserialise TokenName
-- CallStack (from HasCallStack):
-- error, called at src/Cardano/Wallet/Util.hs:78:21 in cardano-wallet-core-2022.1.18-JtZoOG9AeSJ1z9Aw4Sok3f:Cardano.Wallet.Util
-- internalError, called at src/Cardano/Wallet/Util.hs:86:23 in cardano-wallet-core-2022.1.18-JtZoOG9AeSJ1z9Aw4Sok3f:Cardano.Wallet.Util
-- tina, called at src/Cardano/Wallet/Shelley/Compatibility.hs:1919:14 in cardano-wallet-2022.1.18-8A5EC3ZC9uxJp2wMrOQ62o:Cardano.Wallet.Shelley.Compatibilit

wa <- fixtureWallet ctx
addrs <- listAddresses @n ctx wa
Expand All @@ -3132,22 +3128,14 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do
(Link.createUnsignedTransaction @'Shelley wa) Default payload
verify rTx
[ expectResponseCode HTTP.status403
, expectErrorMessage errMsg403AssetNameTooLong
]

it "TRANS_NEW_CREATE_10m1 - Minting amount too big" $
\ctx -> runResourceT $ do
liftIO $ pendingWith "Should fail with 403"
-- Node accepts range for minging/burning:
-- min value: -9223372036854775808 max value: 9223372036854775807
-- Any amount outside will result in error on decoding:
-- "Error in $.transaction: Deserialisation failure while decoding Shelley Tx.
-- CBOR failed with error: DeserialiseFailure 167 'overflow when decoding mint field.
-- min value: -9223372036854775808 max value: 9223372036854775807 got: 9223372036854775808'"
wa <- fixtureWallet ctx
addrs <- listAddresses @n ctx wa
let destination = (addrs !! 1) ^. #id
-- Node accepts:
-- min value: -9223372036854775808 max value: 9223372036854775807
let payload = Json [json|{
"mint_burn": [{
"policy_script_template": "cosigner#0",
Expand All @@ -3168,13 +3156,12 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do
(Link.createUnsignedTransaction @'Shelley wa) Default payload
verify rTx
[ expectResponseCode HTTP.status403
, expectErrorMessage
errMsg403MintOrBurnAssetQuantityOutOfBounds
]

it "TRANS_NEW_CREATE_10m2 - Minting amount = 0" $
\ctx -> runResourceT $ do
liftIO $ pendingWith "Should fail with 403"
-- Probably it should not be allowed to have 0 as amount for mint/burn
-- It results in invalid transaction via cardano-cli
wa <- fixtureWallet ctx
addrs <- listAddresses @n ctx wa
let destination = (addrs !! 1) ^. #id
Expand All @@ -3198,6 +3185,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do
(Link.createUnsignedTransaction @'Shelley wa) Default payload
verify rTx
[ expectResponseCode HTTP.status403
, expectErrorMessage errMsg403MintOrBurnAssetQuantityOutOfBounds
]

it "TRANS_NEW_CREATE_10d - Minting assets without timelock" $
Expand Down Expand Up @@ -3327,6 +3315,138 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do

burnAssetsCheck ctx wa tokenName' payloadBurn scriptUsed

it "TRANS_NEW_CREATE_10g - Burning assets without timelock and token name" $
\ctx -> runResourceT $ do

wa <- fixtureWallet ctx
addrs <- listAddresses @n ctx wa
let destination = (addrs !! 1) ^. #id

let (Right tokenName') = mkTokenName ""
let payloadMint = Json [json|{
"mint_burn": [
{ "policy_script_template":
{ "all":
[ "cosigner#0"
]
}
, "operation":
{ "mint":
{ "receiving_address": #{destination}
, "amount":
{ "quantity": 50000
, "unit": "assets"
}
}
}
}
]
}|]

let scriptUsed policyKeyHash = RequireAllOf
[ RequireSignatureOf policyKeyHash
]

mintAssetsCheck ctx wa tokenName' payloadMint scriptUsed

let payloadBurn = Json [json|{
"mint_burn": [{
"policy_script_template":
{ "all":
[ "cosigner#0"
]
},
"operation":
{ "burn" :
{ "quantity": 50000
, "unit": "assets"
}
}
}]
}|]

burnAssetsCheck ctx wa tokenName' payloadBurn scriptUsed

it "TRANS_NEW_CREATE_10h - \
\Minting assets without timelock to foreign address" $
\ctx -> runResourceT $ do
wa <- fixtureWallet ctx
wForeign <- emptyWallet ctx
addrs <- listAddresses @n ctx wForeign
let destination = (addrs !! 1) ^. #id

let (Right tokenName') = mkTokenName "ab12"

let payload = Json [json|{
"mint_burn": [
{ "policy_script_template":
{ "all":
[ "cosigner#0"
]
}
, "asset_name": #{toText tokenName'}
, "operation":
{ "mint":
{ "receiving_address": #{destination}
, "amount":
{ "quantity": 50000
, "unit": "assets"
}
}
}
}
]
}|]

let scriptUsed policyKeyHash = RequireAllOf
[ RequireSignatureOf policyKeyHash
]

(initialBalance, expectedFee, tokens') <-
mintAssetsCheckWithoutBalanceCheck
ctx wa tokenName' payload scriptUsed

let minutxo = (minUTxOValue (_mainEra ctx) :: Natural)
-- we are sending to external address and it must be more than minimum
-- UTxO plus additional adjusting of assets in output. Here, we are
-- having 80-byte (10-word) asset's additional burden
let lovelacePerUtxoWord = 34482
let minUtxoWithAsset = minutxo + 10*lovelacePerUtxoWord

eventually
"Wallet balance is decreased by fee and adjusted minimum UTxO and \
\does not hold minted assets" $ do
rWa <- request @ApiWallet ctx
(Link.getWallet @'Shelley wa) Default Empty
verify rWa
[ expectSuccess
, expectField
(#balance . #available . #getQuantity)
(`shouldBe` initialBalance
- fromIntegral expectedFee
- minUtxoWithAsset
)
, expectField (#assets . #available . #getApiT)
(`shouldBe` TokenMap.empty)
, expectField (#assets . #total . #getApiT)
(`shouldBe` TokenMap.empty)
]

eventually
"Foreign Wallet balance is adjusted minimum UTxO and \
\holds minted assets" $ do
rForeign <- request @ApiWallet ctx
(Link.getWallet @'Shelley wForeign) Default Empty
verify rForeign
[ expectSuccess
, expectField
(#balance . #available . #getQuantity)
(`shouldBe` minUtxoWithAsset)
, expectField (#assets . #available . #getApiT)
(`shouldBe` tokens')
, expectField (#assets . #total . #getApiT)
(`shouldBe` tokens')
]
where

-- | Just one million Ada, in Lovelace.
Expand Down Expand Up @@ -3679,15 +3799,16 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do

in toCborHexTx txBody

mintAssetsCheck
mintAssetsCheckWithoutBalanceCheck
:: MonadUnliftIO m
=> Context
-> ApiWallet
-> TokenName
-> Payload
-> (KeyHash -> Script KeyHash)
-> m ()
mintAssetsCheck ctx wa tokenName' payload scriptUsedF = do
-> m (Natural, Natural, TokenMap.TokenMap)
mintAssetsCheckWithoutBalanceCheck
ctx wa tokenName' payload scriptUsedF = do

rTx <- request @(ApiConstructTransaction n) ctx
(Link.createUnsignedTransaction @'Shelley wa) Default payload
Expand Down Expand Up @@ -3776,6 +3897,23 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do

let initialBalance = wa ^. #balance . #available . #getQuantity
let expectedFee = getFromResponse (#fee . #getQuantity) rTx

pure (initialBalance, expectedFee, tokens')

mintAssetsCheck
:: MonadUnliftIO m
=> Context
-> ApiWallet
-> TokenName
-> Payload
-> (KeyHash -> Script KeyHash)
-> m ()
mintAssetsCheck ctx wa tokenName' payload scriptUsedF = do

(initialBalance, expectedFee, tokens') <-
mintAssetsCheckWithoutBalanceCheck
ctx wa tokenName' payload scriptUsedF

eventually
"Wallet balance is decreased by fee and holds minted assets" $ do
rWa <- request @ApiWallet ctx
Expand Down
2 changes: 2 additions & 0 deletions lib/core/src/Cardano/Wallet.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3494,6 +3494,8 @@ data ErrConstructTx
| ErrConstructTxMultidelegationNotSupported
| ErrConstructTxMultiaccountNotSupported
| ErrConstructTxWrongMintingBurningTemplate
| ErrConstructTxAssetNameTooLong
| ErrConstructTxMintOrBurnAssetQuantityOutOfBounds
| ErrConstructTxNotImplemented String
-- ^ Temporary error constructor.
deriving (Show, Eq)
Expand Down
Loading

0 comments on commit 72d6eb7

Please sign in to comment.