Skip to content

Commit

Permalink
outlaw changing wallet's cosigner
Browse files Browse the repository at this point in the history
  • Loading branch information
paweljakubas committed Apr 15, 2021
1 parent 60bfb37 commit fc291f3
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 12 deletions.
Expand Up @@ -83,6 +83,7 @@ module Test.Integration.Framework.TestData
, errMsg403NoDelegationTemplate
, errMsg403KeyAlreadyPresent
, errMsg403NoSuchCosigner
, errMsg403CannotUpdateThisCosigner
) where

import Prelude
Expand Down Expand Up @@ -527,3 +528,9 @@ errMsg403NoSuchCosigner cred cosigner = mconcat
, unpack cred, " template to a non-existing cosigner index: "
, show cosigner, "."
]

errMsg403CannotUpdateThisCosigner :: String
errMsg403CannotUpdateThisCosigner = mconcat
[ "It looks like you've tried to update the key of a cosigner having "
, "the shared wallet's account key. Only other cosigner key(s) can be updated."
]
Expand Up @@ -84,7 +84,8 @@ import Test.Integration.Framework.DSL
, verify
)
import Test.Integration.Framework.TestData
( errMsg403KeyAlreadyPresent
( errMsg403CannotUpdateThisCosigner
, errMsg403KeyAlreadyPresent
, errMsg403NoDelegationTemplate
, errMsg403NoSuchCosigner
, errMsg403WalletAlreadyActive
Expand Down Expand Up @@ -409,7 +410,7 @@ spec = describe "SHARED_WALLETS" $ do
"account_index": "30H",
"payment_script_template":
{ "cosigners":
{ "cosigner#0": #{accXPubTxt0} },
{ "cosigner#0": #{accXPubTxt1} },
"template":
{ "all":
[ "cosigner#0",
Expand All @@ -424,15 +425,15 @@ spec = describe "SHARED_WALLETS" $ do
let wal@(ApiSharedWallet (Left _pendingWal)) = getFromResponse id rPost

let payloadPatch = Json [json| {
"account_public_key": #{accXPub1},
"account_public_key": #{accXPub0},
"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)]
liftIO $ cosigners cosignerKeysPatch `shouldBe` Map.fromList [(Cosigner 0,accXPub0)]

it "SHARED_WALLETS_PATCH_06 - Can add the same cosigner key for delegation script template but not payment one" $ \ctx -> runResourceT $ do
let payloadCreate = Json [json| {
Expand All @@ -441,7 +442,7 @@ spec = describe "SHARED_WALLETS" $ do
"account_index": "30H",
"payment_script_template":
{ "cosigners":
{ "cosigner#0": #{accXPubTxt0} },
{ "cosigner#0": #{accXPubTxt2} },
"template":
{ "all":
[ "cosigner#0",
Expand All @@ -468,22 +469,22 @@ spec = describe "SHARED_WALLETS" $ do
let wal@(ApiSharedWallet (Left _pendingWal)) = getFromResponse id rPost

let payloadPatch1 = Json [json| {
"account_public_key": #{accXPub0},
"account_public_key": #{accXPub2},
"cosigner": "cosigner#1"
} |]
rPatch1 <- patchSharedWallet ctx wal Delegation payloadPatch1
expectResponseCode HTTP.status200 rPatch1

let payloadPatch2 = Json [json| {
"account_public_key": #{accXPub0},
"account_public_key": #{accXPub2},
"cosigner": "cosigner#0"
} |]
rPatch2 <- patchSharedWallet ctx wal Payment payloadPatch2
expectResponseCode HTTP.status403 rPatch2
expectErrorMessage (errMsg403KeyAlreadyPresent (toText Payment)) rPatch2

let payloadPatch3 = Json [json| {
"account_public_key": #{accXPub0},
"account_public_key": #{accXPub2},
"cosigner": "cosigner#1"
} |]
rPatch3 <- patchSharedWallet ctx wal Payment payloadPatch3
Expand All @@ -505,6 +506,35 @@ spec = describe "SHARED_WALLETS" $ do
rPatch5 <- patchSharedWallet ctx wal Payment payloadPatch5
expectResponseCode HTTP.status403 rPatch5
expectErrorMessage (errMsg403NoSuchCosigner (toText Payment) 7) rPatch5

it "SHARED_WALLETS_PATCH_07 - Cannot update cosigner key in a pending shared wallet having the shared wallet's account key" $ \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.status403 rPatch
expectErrorMessage errMsg403CannotUpdateThisCosigner rPatch
where
xpubFromText :: Text -> Maybe XPub
xpubFromText = fmap eitherToMaybe fromHexText >=> xpubFromBytes
Expand All @@ -518,5 +548,8 @@ spec = describe "SHARED_WALLETS" $ do
accXPubTxt1 = "1423856bc91c49e928f6f30f4e8d665d53eb4ab6028bd0ac971809d514c92db11423856bc91c49e928f6f30f4e8d665d53eb4ab6028bd0ac971809d514c92db8"
(Just accXPub1) = xpubFromText accXPubTxt1

accXPubTxt2 = "1423856bc91c49e928f6f30f4e8d665d53eb4ab6028bd0ac971809d514c92db11423856bc91c49e928f6f30f4e8d665d53eb4ab6028bd0ac971809d514c92db7"
(Just accXPub2) = xpubFromText accXPubTxt2

instance ToJSON XPub where
toJSON = toJSON . T.decodeLatin1 . hex . xpubToBytes
5 changes: 5 additions & 0 deletions lib/core/src/Cardano/Wallet/Api/Server.hs
Expand Up @@ -3082,6 +3082,11 @@ instance IsServerError ErrAddCosignerKey where
, "shared wallet's ", toText cred, " template to a "
, "non-existing cosigner index: ", pretty c,"."
]
ErrAddCosignerKey CannotUpdateSharedWalletKey ->
apiError err403 SharedWalletCannotUpdateKey $ mconcat
[ "It looks like you've tried to update the key of a cosigner having "
, "the shared wallet's account key. Only other cosigner key(s) can be updated."
]

instance IsServerError (ErrInvalidDerivationIndex 'Soft level) where
toServerError = \case
Expand Down
1 change: 1 addition & 0 deletions lib/core/src/Cardano/Wallet/Api/Types.hs
Expand Up @@ -1162,6 +1162,7 @@ data ApiErrorCode
| SharedWalletNoDelegationTemplate
| SharedWalletKeyAlreadyExists
| SharedWalletNoSuchCosigner
| SharedWalletCannotUpdateKey
deriving (Eq, Generic, Show, Data, Typeable)
deriving anyclass NFData

Expand Down
Expand Up @@ -6,7 +6,6 @@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeApplications #-}
Expand Down Expand Up @@ -299,6 +298,9 @@ data ErrAddCosigner
-- not allowed.
| WalletAlreadyActive
-- ^ Adding is possible only to pending shared wallet.
| CannotUpdateSharedWalletKey
-- ^ Updating key is possible only for other cosigners, not cosigner
-- belonging to the shared wallet.
deriving (Eq, Show)

-- | The cosigner with his account public key is updated per template.
Expand All @@ -324,23 +326,29 @@ addCosignerAccXPub
addCosignerAccXPub accXPub cosigner cred st = case fields st of
ReadyFields _ ->
Left WalletAlreadyActive
PendingFields (SharedStatePending _ paymentTmpl delegTmpl _) ->
PendingFields (SharedStatePending walletKey paymentTmpl delegTmpl _) ->
case (cred, paymentTmpl, delegTmpl) of
(Payment, pt, _)
| tryingUpdateWalletCosigner walletKey pt -> Left CannotUpdateSharedWalletKey
| isCosignerMissing pt -> Left $ NoSuchCosigner cred cosigner
| isKeyAlreadyPresent pt -> Left $ KeyAlreadyPresent cred
(Delegation, _, Just dt)
| tryingUpdateWalletCosigner walletKey dt -> Left CannotUpdateSharedWalletKey
| isCosignerMissing dt -> Left $ NoSuchCosigner cred cosigner
| isKeyAlreadyPresent dt -> Left $ KeyAlreadyPresent cred
(Delegation, _, Nothing) -> Left NoDelegationTemplate
_ -> Right $
updateSharedState st $
addCosignerAccXPubPending accXPub cosigner cred
updateSharedState st $
addCosignerAccXPubPending accXPub cosigner cred
where
isKeyAlreadyPresent (ScriptTemplate cosignerKeys _) =
getRawKey accXPub `F.elem` cosignerKeys
isCosignerMissing (ScriptTemplate _ script') =
cosigner `notElem` retrieveAllCosigners script'
tryingUpdateWalletCosigner walletKey (ScriptTemplate cosignerKeys _) =
case Map.lookup cosigner cosignerKeys of
Nothing -> False
Just key' -> key' == getRawKey walletKey

addCosignerAccXPubPending
:: WalletKey k
Expand Down

0 comments on commit fc291f3

Please sign in to comment.