diff --git a/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs b/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs index 625d68acbed..e136aac3694 100644 --- a/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs +++ b/lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs @@ -64,6 +64,7 @@ import Cardano.Wallet , ErrStakePoolDelegation (..) , ErrStartTimeLaterThanEndTime (..) , ErrSubmitTransaction (..) + , ErrSubmitTransactionMissingWitnessCounts (..) , ErrSubmitTx (..) , ErrUpdatePassphrase (..) , ErrWalletAlreadyExists (..) @@ -646,20 +647,19 @@ instance IsServerError ErrSubmitTransaction where , "wallet and cannot be sent. Submit a transaction that has " , "either an input or a withdrawal belonging to the wallet." ] - ErrSubmitTransactionPartiallySignedOrNoSignedTx - expectedWitsNo foundWitsNo -> + ErrSubmitTransactionMissingWitnesses + ErrSubmitTransactionMissingWitnessCounts + {expectedNumberOfKeyWits, detectedNumberOfKeyWits} -> flip (apiError err403) message $ MissingWitnessesInTransaction ApiErrorMissingWitnessesInTransaction - { expectedNumberOfKeyWits = fromIntegral expectedWitsNo - , detectedNumberOfKeyWits = fromIntegral foundWitsNo - } + {expectedNumberOfKeyWits, detectedNumberOfKeyWits} where message = mconcat [ "The transaction expects " - , toText expectedWitsNo + , toText expectedNumberOfKeyWits , " witness(es) to be fully-signed but " - , toText foundWitsNo + , toText detectedNumberOfKeyWits , " was provided." , " Please submit a fully-signed transaction." ] diff --git a/lib/api/src/Cardano/Wallet/Api/Http/Shelley/Server.hs b/lib/api/src/Cardano/Wallet/Api/Http/Shelley/Server.hs index 32c8dc6f5fa..88fdd84134b 100644 --- a/lib/api/src/Cardano/Wallet/Api/Http/Shelley/Server.hs +++ b/lib/api/src/Cardano/Wallet/Api/Http/Shelley/Server.hs @@ -189,6 +189,7 @@ import Cardano.Wallet , ErrReadRewardAccount (..) , ErrSignPayment (..) , ErrSubmitTransaction (..) + , ErrSubmitTransactionMissingWitnessCounts (..) , ErrUpdatePassphrase (..) , ErrWalletAlreadyExists (..) , ErrWalletNotResponding (..) @@ -763,6 +764,9 @@ import Data.Generics.Labels import Data.Generics.Product ( typed ) +import Data.IntCast + ( intCastMaybe + ) import Data.List ( isInfixOf , sortOn @@ -855,6 +859,9 @@ import Network.Wai.Middleware.ServerError import Numeric.Natural ( Natural ) +import Safe + ( fromJustNote + ) import Servant ( Application , NoContent (..) @@ -3701,6 +3708,24 @@ toOut ((TxOut addr (TokenBundle c tmap)), (Just path)) = , derivationPath = NE.map ApiT path } +validateWitnessCounts + :: Monad m + => Int + -- ^ expected number of key witnesses + -> Int + -- ^ detected number of key witnesses + -> ExceptT ErrSubmitTransaction m () +validateWitnessCounts expected detected = + when (expected > detected) $ throwE $ + ErrSubmitTransactionMissingWitnesses $ + ErrSubmitTransactionMissingWitnessCounts + { expectedNumberOfKeyWits = toNatural expected + , detectedNumberOfKeyWits = toNatural detected + } + where + toNatural :: Int -> Natural + toNatural = fromJustNote "validateWitnessCounts.toNatural" . intCastMaybe + submitTransaction :: forall ctx s k n . ( ctx ~ ApiLayer s @@ -3747,10 +3772,7 @@ submitTransaction ctx apiw@(ApiT wid) apitx = do when (countJoinsQuits (apiDecoded ^. #certificates) > 1) $ liftHandler $ throwE ErrSubmitTransactionMultidelegationNotSupported - when (witsRequiredForInputs > totalNumberOfWits) - $ liftHandler . throwE - $ ErrSubmitTransactionPartiallySignedOrNoSignedTx - witsRequiredForInputs totalNumberOfWits + liftHandler $ validateWitnessCounts witsRequiredForInputs totalNumberOfWits void $ withWorkerCtx ctx wid liftE liftE $ \wrk -> do let tx = walletTx $ decodeTx tl era sealedTx @@ -3897,10 +3919,7 @@ submitSharedTransaction ctx apiw@(ApiT wid) apitx = do fromIntegral pWitsPerInput * witsRequiredForInputs let allWitsRequired = paymentWitsRequired + fromIntegral delegationWitsRequired - when (allWitsRequired > totalNumberOfWits) $ - liftHandler $ throwE $ - ErrSubmitTransactionPartiallySignedOrNoSignedTx - allWitsRequired totalNumberOfWits + liftHandler $ validateWitnessCounts allWitsRequired totalNumberOfWits let txCtx = defaultTransactionCtx { txValidityInterval = (Nothing, ttl) diff --git a/lib/wallet/src/Cardano/Wallet.hs b/lib/wallet/src/Cardano/Wallet.hs index 07eb6164376..b168b42b0e4 100644 --- a/lib/wallet/src/Cardano/Wallet.hs +++ b/lib/wallet/src/Cardano/Wallet.hs @@ -161,6 +161,7 @@ module Cardano.Wallet , ErrCannotQuit (..) , ErrCannotVote (..) , ErrSubmitTransaction (..) + , ErrSubmitTransactionMissingWitnessCounts (..) -- ** Migration , createMigrationPlan @@ -3651,10 +3652,18 @@ data ErrSignPayment -- | Errors that can occur when submitting a transaction. data ErrSubmitTransaction = ErrSubmitTransactionForeignWallet - | ErrSubmitTransactionPartiallySignedOrNoSignedTx Int Int + | ErrSubmitTransactionMissingWitnesses + !ErrSubmitTransactionMissingWitnessCounts | ErrSubmitTransactionMultidelegationNotSupported deriving (Show, Eq) +data ErrSubmitTransactionMissingWitnessCounts = + ErrSubmitTransactionMissingWitnessCounts + { expectedNumberOfKeyWits :: !Natural + , detectedNumberOfKeyWits :: !Natural + } + deriving (Show, Eq) + -- | Errors that can occur when constructing an unsigned transaction. data ErrConstructTx = ErrConstructTxWrongPayload