Skip to content

Commit

Permalink
Merge #2405
Browse files Browse the repository at this point in the history
2405: Additional checks for input existence in transactions r=piotr-iohk a=piotr-iohk

# Issue Number

It turns out there are no checks for that.
A bit related to #2327.

# Overview

- 2605a9f
  Additional checks for inputs in incoming and outgoing transactions in integration tests
  
- 1247f9a
  Additional checks for inputs in join/quit pool transactions
  
- bd2916b
  remove redundant cases & fix fixture wallet sharing common funding UTxOs
      It's a bit fucked up. Since the scenario is using fixtureWallet, the
    UtxO from the wallet comes from one of the fixture transaction made
    when initializing the cluster. There are many pre-funded fixture
    wallets with 10 UTxO, but in order not to spend 10 days funding them
    all, the cluster generate pretty large transaction with ~100
    outputs. So a single fixture transaction funds about 10 fixture
    wallets.

    Now it means that, a particular fixture wallet will know the value
    of all inputs of its funding fixture transaction and therefore, when
    picking two fixtureWallet one after the other, it may likely happen
    that both wallets are able to resolve inputs of any UTxO coming from
    their original fixture transaction.

    I fixed it by simply using fixtureWalletWith [...] which generates
    completly new and uncorrelated UTxOs.

- cdf556a
  Add input check for multi-address pending tx



# Comments

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

<!--
Don't forget to:

 ✓ Self-review your changes to make sure nothing unexpected slipped through
 ✓ Assign yourself to the PR
 ✓ Assign one or several reviewer(s)
 ✓ Jira will detect and link to this PR once created, but you can also link this PR in the description of the corresponding ticket
 ✓ Acknowledge any changes required to the Wiki
 ✓ Finally, in the PR description delete any empty sections and all text commented in <!--, so that this text does not appear in merge commit messages.
-->


Co-authored-by: Piotr Stachyra <[email protected]>
Co-authored-by: KtorZ <[email protected]>
  • Loading branch information
3 people authored Jan 5, 2021
2 parents 6194a93 + cdf556a commit 37ff0b2
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import Cardano.Wallet.Api.Types
, ApiStakePoolFlag (..)
, ApiT (..)
, ApiTransaction
, ApiTxId (..)
, ApiTxInput (..)
, ApiWallet
, ApiWalletDelegationStatus (..)
, DecodeAddress
Expand Down Expand Up @@ -221,6 +223,8 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do
, expectField (#status . #getApiT) (`shouldBe` Pending)
, expectField (#direction . #getApiT) (`shouldBe` Outgoing)
, expectField #deposit (`shouldBe` Quantity 1000000)
, expectField #inputs $ \inputs' -> do
inputs' `shouldSatisfy` all (isJust . source)
]
eventually "Wallet has joined pool and deposit info persists" $ do
rJoin' <- request @(ApiTransaction n) ctx
Expand All @@ -234,6 +238,19 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do
, expectField #deposit (`shouldBe` Quantity 1000000)
]

let txId = getFromResponse #id rJoin
let link = Link.getTransaction @'Shelley src (ApiTxId txId)
eventually "delegation transaction is in ledger" $ do
rSrc <- request @(ApiTransaction n) ctx link Default Empty
verify rSrc
[ expectResponseCode HTTP.status200
, expectField (#direction . #getApiT) (`shouldBe` Outgoing)
, expectField (#status . #getApiT) (`shouldBe` InLedger)
, expectField (#metadata . #getApiTxMetadata) (`shouldBe` Nothing)
, expectField #inputs $ \inputs' -> do
inputs' `shouldSatisfy` all (isJust . source)
]

-- Earn rewards
waitForNextEpoch ctx
waitForNextEpoch ctx
Expand Down Expand Up @@ -507,11 +524,11 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do
eventually "Certificates are inserted" $ do
let ep = Link.listTransactions @'Shelley w
request @[ApiTransaction n] ctx ep Default Empty >>= flip verify
[ expectListField 0
(#direction . #getApiT) (`shouldBe` Outgoing)
, expectListField 0
(#status . #getApiT) (`shouldBe` InLedger)
]
[ expectListField 0
(#direction . #getApiT) (`shouldBe` Outgoing)
, expectListField 0
(#status . #getApiT) (`shouldBe` InLedger)
]

request @ApiWallet ctx (Link.getWallet @'Shelley w) Default Empty
>>= flip verify
Expand Down Expand Up @@ -859,11 +876,29 @@ spec = describe "SHELLEY_STAKE_POOLS" $ do
[ expectField #delegation (`shouldBe` delegating pool [])
]

quitStakePool @n ctx (w, fixturePassphrase) >>= flip verify
rQuit <- quitStakePool @n ctx (w, fixturePassphrase)
verify rQuit
[ expectResponseCode HTTP.status202
, expectField (#status . #getApiT) (`shouldBe` Pending)
, expectField (#direction . #getApiT) (`shouldBe` Outgoing)
, expectField #inputs $ \inputs' -> do
inputs' `shouldSatisfy` all (isJust . source)
]
eventually "Wallet is not delegating and it got his deposit back" $
do

let txId = getFromResponse #id rQuit
let link = Link.getTransaction @'Shelley w (ApiTxId txId)
eventually "quit transaction is in ledger" $ do
rSrc <- request @(ApiTransaction n) ctx link Default Empty
verify rSrc
[ expectResponseCode HTTP.status200
, expectField (#direction . #getApiT) (`shouldBe` Incoming)
, expectField (#status . #getApiT) (`shouldBe` InLedger)
, expectField (#metadata . #getApiTxMetadata) (`shouldBe` Nothing)
, expectField #inputs $ \inputs' -> do
inputs' `shouldSatisfy` all (isJust . source)
]

eventually "Wallet is not delegating and it got his deposit back" $ do
request @ApiWallet ctx (Link.getWallet @'Shelley w)
Default Empty >>= flip verify
[ expectField #delegation (`shouldBe` notDelegating [])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import Cardano.Wallet.Api.Types
, ApiT (..)
, ApiTransaction
, ApiTxId (..)
, ApiTxInput (..)
, ApiWallet
, DecodeAddress
, DecodeStakeAddress
Expand Down Expand Up @@ -66,7 +67,7 @@ import Data.Generics.Internal.VL.Lens
import Data.Generics.Product.Typed
( HasType )
import Data.Maybe
( fromJust, fromMaybe, isJust )
( fromJust, fromMaybe, isJust, isNothing )
import Data.Quantity
( Quantity (..) )
import Data.Text
Expand Down Expand Up @@ -292,55 +293,87 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do
insertedAt tx' `shouldBe` Nothing
pendingSince tx' `shouldBe` pendingSince tx

it "TRANS_CREATE_01 - Single Output Transaction" $ \ctx -> runResourceT $ do
(wa, wb) <- (,) <$> fixtureWallet ctx <*> fixtureWallet ctx
it "TRANS_CREATE_01x - Single Output Transaction" $ \ctx -> runResourceT $ do
let initialAmt = 2*minUTxOValue
wa <- fixtureWalletWith @n ctx [initialAmt]
wb <- fixtureWalletWith @n ctx [initialAmt]
let amt = (minUTxOValue :: Natural)

payload <- liftIO $ mkTxPayload ctx wb amt fixturePassphrase

(_, ApiFee (Quantity feeMin) (Quantity feeMax) _) <- unsafeRequest ctx
(Link.getTransactionFee @'Shelley wa) payload

r <- request @(ApiTransaction n) ctx
rTx <- request @(ApiTransaction n) ctx
(Link.createTransaction @'Shelley wa) Default payload
ra <- request @ApiWallet ctx
(Link.getWallet @'Shelley wa) Default Empty

verify r
verify rTx
[ expectSuccess
, expectResponseCode HTTP.status202
, expectField (#amount . #getQuantity) $
between (feeMin + amt, feeMax + amt)
, expectField #inputs $ \inputs' -> do
inputs' `shouldSatisfy` all (isJust . source)
, expectField (#direction . #getApiT) (`shouldBe` Outgoing)
, expectField (#status . #getApiT) (`shouldBe` Pending)
, expectField (#metadata . #getApiTxMetadata) (`shouldBe` Nothing)
]

ra <- request @ApiWallet ctx (Link.getWallet @'Shelley wa) Default Empty
verify ra
[ expectSuccess
, expectField (#balance . #getApiT . #total) $
between
( Quantity (faucetAmt - feeMax - amt)
, Quantity (faucetAmt - feeMin - amt)
( Quantity (initialAmt - feeMax - amt)
, Quantity (initialAmt - feeMin - amt)
)
, expectField
(#balance . #getApiT . #available)
(.>= Quantity (faucetAmt - faucetUtxoAmt))
(`shouldBe` Quantity 0)
]

let txid = getFromResponse #id rTx
let linkSrc = Link.getTransaction @'Shelley wa (ApiTxId txid)
eventually "transaction is no longer pending on source wallet" $ do
rSrc <- request @(ApiTransaction n) ctx linkSrc Default Empty
verify rSrc
[ expectResponseCode HTTP.status200
, expectField (#amount . #getQuantity) $
between (feeMin + amt, feeMax + amt)
, expectField #inputs $ \inputs' -> do
inputs' `shouldSatisfy` all (isJust . source)
, expectField (#direction . #getApiT) (`shouldBe` Outgoing)
, expectField (#status . #getApiT) (`shouldBe` InLedger)
, expectField (#metadata . #getApiTxMetadata) (`shouldBe` Nothing)
]

let linkDest = Link.getTransaction @'Shelley wb (ApiTxId txid)
eventually "transaction is discovered by destination wallet" $ do
rDst <- request @(ApiTransaction n) ctx linkDest Default Empty
verify rDst
[ expectResponseCode HTTP.status200
, expectField (#amount . #getQuantity) (`shouldBe` amt)
, expectField #inputs $ \inputs' -> do
inputs' `shouldSatisfy` all (isNothing . source)
, expectField (#direction . #getApiT) (`shouldBe` Incoming)
, expectField (#status . #getApiT) (`shouldBe` InLedger)
, expectField (#metadata . #getApiTxMetadata) (`shouldBe` Nothing)
]

eventually "wa and wb balances are as expected" $ do
rb <- request @ApiWallet ctx
(Link.getWallet @'Shelley wb) Default Empty
expectField
(#balance . #getApiT . #available)
(`shouldBe` Quantity (faucetAmt + amt)) rb
(`shouldBe` Quantity (initialAmt + amt)) rb

ra2 <- request @ApiWallet ctx
(Link.getWallet @'Shelley wa) Default Empty
expectField
(#balance . #getApiT . #available)
(`shouldBe` Quantity (faucetAmt - feeMax - amt)) ra2
(`shouldBe` Quantity (initialAmt - feeMax - amt)) ra2

it "TRANS_CREATE_02 - Multiple Output Tx to single wallet" $ \ctx -> runResourceT $ do
it "TRANS_CREATE_02x - Multiple Output Tx to single wallet" $ \ctx -> runResourceT $ do
wSrc <- fixtureWallet ctx
wDest <- emptyWallet ctx
addrs <- listAddresses @n ctx wDest
Expand Down Expand Up @@ -373,13 +406,17 @@ spec = describe "SHELLEY_TRANSACTIONS" $ do
(Link.createTransaction @'Shelley wSrc) Default payload

ra <- request @ApiWallet ctx (Link.getWallet @'Shelley wSrc) Default Empty

verify r
[ expectResponseCode HTTP.status202
, expectField (#amount . #getQuantity) $
between (feeMin + (2*amt), feeMax + (2*amt))
, expectField (#direction . #getApiT) (`shouldBe` Outgoing)
, expectField (#status . #getApiT) (`shouldBe` Pending)
, expectField #inputs $ \inputs' -> do
inputs' `shouldSatisfy` all (isJust . source)
]

verify ra
[ expectField (#balance . #getApiT . #total) $
between
Expand Down

0 comments on commit 37ff0b2

Please sign in to comment.