Skip to content

Commit

Permalink
adding error guarding patching when delegation template missing
Browse files Browse the repository at this point in the history
  • Loading branch information
paweljakubas committed Apr 15, 2021
1 parent 1ce8742 commit f0d6e69
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 9 deletions.
10 changes: 9 additions & 1 deletion lib/core-integration/src/Test/Integration/Framework/TestData.hs
Expand Up @@ -80,6 +80,7 @@ module Test.Integration.Framework.TestData
, errMsg403OutputTokenBundleSizeExceedsLimit
, errMsg403OutputTokenQuantityExceedsLimit
, errMsg403NotPendingWallet
, errMsg403NoDelegationTemplate
) where

import Prelude
Expand Down Expand Up @@ -499,7 +500,14 @@ errMsg403OutputTokenQuantityExceedsLimit

errMsg403NotPendingWallet :: String
errMsg403NotPendingWallet = mconcat
[ "It looks like you've tried to update cosigner key for "
[ "It looks like you've tried to add cosigner key for "
, "shared wallet that is active. This can be done only for "
, "pending shared wallets."
]

errMsg403NoDelegationTemplate :: String
errMsg403NoDelegationTemplate = mconcat
[ "It looks like you've tried to add cosigner key for "
, "shared wallet for delegation template. This cannot be done as "
, "the shared wallets does not have a delegation template."
]
Expand Up @@ -82,7 +82,7 @@ import Test.Integration.Framework.DSL
, verify
)
import Test.Integration.Framework.TestData
( errMsg403NotPendingWallet )
( errMsg403NoDelegationTemplate, errMsg403NotPendingWallet )

import qualified Data.Map.Strict as Map
import qualified Data.Text.Encoding as T
Expand Down Expand Up @@ -355,9 +355,7 @@ spec = describe "SHARED_WALLETS" $ do
} |]
rPost <- postSharedWallet ctx Default payloadCreate
expectResponseCode HTTP.status201 rPost
let wal@(ApiSharedWallet (Right activeWal)) = getFromResponse id rPost
let cosignerKeysPost = activeWal ^. #paymentScriptTemplate
liftIO $ cosigners cosignerKeysPost `shouldBe` Map.fromList [(Cosigner 0,accXPub0)]
let wal@(ApiSharedWallet (Right _activeWal)) = getFromResponse id rPost

let payloadPatch = Json [json| {
"account_public_key": #{accXPub1},
Expand All @@ -367,6 +365,68 @@ spec = describe "SHARED_WALLETS" $ do
rPatch <- patchSharedWallet ctx wal Payment payloadPatch
expectResponseCode HTTP.status403 rPatch
expectErrorMessage errMsg403NotPendingWallet rPatch

it "SHARED_WALLETS_PATCH_04 - Cannot add cosigner key when delegation script missing and cannot add already existant key to other cosigner" $ \ctx -> runResourceT $ do
let payloadCreate = Json [json| {
"name": "Shared Wallet",
"account_public_key": #{accXPubTxt0},
"account_index": "30H",
"payment_script_template":
{ "cosigners":
{ "cosigner#0": #{accXPubTxt0} },
"template":
{ "all":
[ "cosigner#0",
"cosigner#1",
{ "active_from": 120 }
]
}
}
} |]
rPost <- postSharedWallet ctx Default payloadCreate
expectResponseCode HTTP.status201 rPost
let wal@(ApiSharedWallet (Left _pendingWal)) = getFromResponse id rPost

let payloadPatch = Json [json| {
"account_public_key": #{accXPub1},
"cosigner": "cosigner#1"
} |]

rPatch <- patchSharedWallet ctx wal Delegation payloadPatch
expectResponseCode HTTP.status403 rPatch
expectErrorMessage errMsg403NoDelegationTemplate rPatch

it "SHARED_WALLETS_PATCH_05 - Can update key of cosigner in pending state" $ \ctx -> runResourceT $ do
let payloadCreate = Json [json| {
"name": "Shared Wallet",
"account_public_key": #{accXPubTxt0},
"account_index": "30H",
"payment_script_template":
{ "cosigners":
{ "cosigner#0": #{accXPubTxt0} },
"template":
{ "all":
[ "cosigner#0",
"cosigner#1",
{ "active_from": 120 }
]
}
}
} |]
rPost <- postSharedWallet ctx Default payloadCreate
expectResponseCode HTTP.status201 rPost
let wal@(ApiSharedWallet (Left _pendingWal)) = getFromResponse id rPost

let payloadPatch = Json [json| {
"account_public_key": #{accXPub1},
"cosigner": "cosigner#0"
} |]

rPatch <- patchSharedWallet ctx wal Payment payloadPatch
expectResponseCode HTTP.status200 rPatch
let (ApiSharedWallet (Left pendingWal)) = getFromResponse id rPatch
let cosignerKeysPatch = pendingWal ^. #paymentScriptTemplate
liftIO $ cosigners cosignerKeysPatch `shouldBe` Map.fromList [(Cosigner 0,accXPub1)]
where
xpubFromText :: Text -> Maybe XPub
xpubFromText = fmap eitherToMaybe fromHexText >=> xpubFromBytes
Expand Down
16 changes: 13 additions & 3 deletions lib/core/src/Cardano/Wallet.hs
Expand Up @@ -255,7 +255,11 @@ import Cardano.Wallet.Primitive.AddressDiscovery.Sequential
, shrinkPool
)
import Cardano.Wallet.Primitive.AddressDiscovery.SharedState
( SharedState (SharedState), SharedStateFields (..), addCosignerAccXPub )
( SharedState (SharedState)
, SharedStateFields (..)
, SharedStatePending (..)
, addCosignerAccXPub
)
import Cardano.Wallet.Primitive.CoinSelection.MA.RoundRobin
( SelectionError (..)
, SelectionResult (..)
Expand Down Expand Up @@ -405,7 +409,7 @@ import Data.List
import Data.List.NonEmpty
( NonEmpty (..) )
import Data.Maybe
( fromMaybe, mapMaybe )
( fromMaybe, isNothing, mapMaybe )
import Data.Proxy
( Proxy )
import Data.Quantity
Expand Down Expand Up @@ -2119,7 +2123,9 @@ updateCosigner ctx wid accXPub cosigner cred = db & \DBLayer{..} -> do
readCheckpoint (PrimaryKey wid)
let s@(SharedState _ st) = getState cp
case st of
PendingFields _ -> do
PendingFields (SharedStatePending _ _pT dTM _) -> do
when (cred == Delegation && isNothing dTM)$
throwE ErrAddCosignerKeyNoDelegationTemplate
let s' = addCosignerAccXPub accXPub cosigner cred s
withExceptT ErrAddCosignerKeyNoSuchWallet $
putCheckpoint (PrimaryKey wid) (updateState s' cp)
Expand Down Expand Up @@ -2153,6 +2159,10 @@ data ErrAddCosignerKey
-- ^ The shared wallet doesn't exist?
| ErrAddCosignerKeyActiveWallet
-- ^ Adding is possible only to pending shared wallet
| ErrAddCosignerKeyAlreadyPresentKey CredentialType
-- ^ Adding the same key for different cosigners for a given script is not allowed.
| ErrAddCosignerKeyNoDelegationTemplate
-- ^ Adding key for a cosigner for a non-existant delegation template is not allowed.
deriving (Eq, Show)

data ErrReadAccountPublicKey
Expand Down
15 changes: 14 additions & 1 deletion lib/core/src/Cardano/Wallet/Api/Server.hs
Expand Up @@ -3058,10 +3058,23 @@ instance LiftHandler ErrAddCosignerKey where
ErrAddCosignerKeyNoSuchWallet e -> handler e
ErrAddCosignerKeyActiveWallet ->
apiError err403 SharedWalletNotPending $ mconcat
[ "It looks like you've tried to update cosigner key for "
[ "It looks like you've tried to add cosigner key for "
, "shared wallet that is active. This can be done only for "
, "pending shared wallets."
]
ErrAddCosignerKeyNoDelegationTemplate ->
apiError err403 SharedWalletNoDelegationTemplate $ mconcat
[ "It looks like you've tried to add cosigner key for "
, "shared wallet for delegation template. This cannot be done as "
, "the shared wallets does not have a delegation template."
]
ErrAddCosignerKeyAlreadyPresentKey cred ->
apiError err403 SharedWalletKeyAlreadyExists $ mconcat
[ "It looks like you've tried to add cosigner key for "
, "shared wallet for ", toText cred," template that already exists "
, "and is ascribed to another cosigner. Or you are updating with the same key. "
, "Make sure each cosigner has unique key withing each script template."
]

instance LiftHandler (ErrInvalidDerivationIndex 'Soft level) where
handler = \case
Expand Down
2 changes: 2 additions & 0 deletions lib/core/src/Cardano/Wallet/Api/Types.hs
Expand Up @@ -1159,6 +1159,8 @@ data ApiErrorCode
| OutputTokenBundleSizeExceedsLimit
| OutputTokenQuantityExceedsLimit
| SharedWalletNotPending
| SharedWalletNoDelegationTemplate
| SharedWalletKeyAlreadyExists
deriving (Eq, Generic, Show, Data, Typeable)
deriving anyclass NFData

Expand Down

0 comments on commit f0d6e69

Please sign in to comment.