Skip to content

Commit

Permalink
add ErrConstructTxIncorrectRawMetadata
Browse files Browse the repository at this point in the history
  • Loading branch information
paweljakubas committed May 6, 2024
1 parent 9f330b2 commit 73216c9
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 5 deletions.
5 changes: 5 additions & 0 deletions lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,11 @@ instance IsServerError ErrConstructTx where
, "Please delegate again (in that case, the wallet will automatically vote to abstain), "
, "or make a vote transaction before the withdrawal transaction."
]
ErrConstructTxIncorrectRawMetadata ->
apiError err403 InvalidMetadataEncryption $ mconcat
[ "It looks like the metadata to be encrypted does not "
, "have `msg` field that is supposed to be encrypted."
]
ErrConstructTxNotImplemented ->
apiError err501 NotImplemented
"This feature is not yet implemented."
Expand Down
51 changes: 46 additions & 5 deletions lib/api/src/Cardano/Wallet/Api/Http/Shelley/Server.hs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ import Cardano.Wallet.Api.Types
, ApiConstructTransactionData (..)
, ApiDecodeTransactionPostData (..)
, ApiDecodedTransaction (..)
, ApiEncryptMetadata (..)
, ApiExternalInput (..)
, ApiFee (..)
, ApiForeignStakeKey (..)
Expand Down Expand Up @@ -2725,8 +2726,15 @@ constructTransaction api argGenChange knownPools poolStatus apiWalletId body = d
when (isJust (body ^. #encryptMetadata) && isNothing (body ^. #metadata) ) $
liftHandler $ throwE ErrConstructTxWrongPayload

when (isJust (body ^. #encryptMetadata)) $
liftHandler $ throwE ErrConstructTxNotImplemented
metadata <- case (body ^. #encryptMetadata, body ^. #metadata) of
(Just apiEncrypt, Just metadataWithSchema) ->
case toMetadataEncrypted apiEncrypt metadataWithSchema of
Left err ->
liftHandler $ throwE err
Right meta ->
pure $ Just meta
_ ->
pure $ body ^? #metadata . traverse . #txMetadataWithSchema_metadata

validityInterval <-
liftHandler $ parseValidityInterval ti $ body ^. #validityInterval
Expand All @@ -2740,9 +2748,6 @@ constructTransaction api argGenChange knownPools poolStatus apiWalletId body = d
delegationRequest <-
liftHandler $ traverse parseDelegationRequest $ body ^. #delegations

let metadata =
body ^? #metadata . traverse . #txMetadataWithSchema_metadata

withWorkerCtx api walletId liftE liftE $ \wrk -> do
let db = wrk ^. dbLayer
netLayer = wrk ^. networkLayer
Expand Down Expand Up @@ -3121,6 +3126,42 @@ constructTransaction api argGenChange knownPools poolStatus apiWalletId body = d
. Map.toList
. foldr (uncurry (Map.insertWith (<>))) Map.empty

-- When encryption is enabled we do the following:
-- (a) find field(s) `msg` in the first level value pairs for each key
-- (b) encrypt the 'msg' values if present, otherwise emit error
-- (c) and update value of `msg` with the encrypted initial value(s) encoded in base64
-- [TxMetaText base64_1, TxMetaText base64_2, ..., TxMetaText base64_n]
-- (d) add `enc` field with encryption method value ("base" or "chachapoly1305")
toMetadataEncrypted
:: ApiEncryptMetadata
-> TxMetadataWithSchema
-> Either ErrConstructTx Cardano.TxMetadata
toMetadataEncrypted _apiEncrypt payload = do
msgValues <- findMsgValues
undefined
where
getMsgValue (Cardano.TxMetaText metaField, metaValue) =
if metaField == "msg" then
Just metaValue
else Nothing
getMsgValue _ = Nothing
merge Nothing (Just val) = Just val
merge (Just val) Nothing = Just val
merge Nothing Nothing = Nothing
merge (Just _) (Just _) = error "only one 'msg' field expected"
-- assumption: `msg` is not embedded beyond the first level
-- we could change that in the future
inspectMetaPair (Cardano.TxMetaMap pairs) =
foldl merge Nothing (getMsgValue <$> pairs)
inspectMetaPair _ = Nothing
findMsgValues =
let (Cardano.TxMetadata themap) = payload ^. #txMetadataWithSchema_metadata
filteredMap = Map.filter (isJust . inspectMetaPair) themap
in if Map.size filteredMap >= 1 then
Right $ Map.toList filteredMap
else
Left ErrConstructTxIncorrectRawMetadata

toUsignedTxWdrl
:: c -> ApiWithdrawalGeneral n -> Maybe (RewardAccount, Coin, c)
toUsignedTxWdrl p = \case
Expand Down
1 change: 1 addition & 0 deletions lib/api/src/Cardano/Wallet/Api/Types/Error.hs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ data ApiErrorInfo
| InputsDepleted
| InsufficientCollateral
| InvalidCoinSelection
| InvalidMetadataEncryption
| InvalidValidityBounds
| InvalidWalletType
| KeyNotFoundForAddress
Expand Down
1 change: 1 addition & 0 deletions lib/wallet/src/Cardano/Wallet.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3672,6 +3672,7 @@ data ErrConstructTx
| ErrConstructTxDelegationInvalid
| ErrConstructTxVotingInWrongEra
| ErrConstructTxWithdrawalWithoutVoting
| ErrConstructTxIncorrectRawMetadata
| ErrConstructTxNotImplemented
deriving (Show, Eq)

Expand Down
12 changes: 12 additions & 0 deletions specifications/api/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4708,6 +4708,17 @@ x-errWithdrawalNotPossibleWithoutVote: &errWithdrawalNotPossibleWithoutVote
type: string
enum: ['withdrawal_not_possible_without_vote']

x-errInvalidMetadataEncryption: &errInvalidMetadataEncryption
<<: *responsesErr
title: invalid_metadata_encryption
properties:
message:
type: string
description: The metadata has either wrong structure or cannot be encrypted.
code:
type: string
enum: ['invalid_metadata_encryption']

x-errInputsDepleted: &errInputsDepleted
<<: *responsesErr
title: inputs_depleted
Expand Down Expand Up @@ -6052,6 +6063,7 @@ x-responsesConstructTransaction: &responsesConstructTransaction
- <<: *errDelegationInvalid
- <<: *errVotingInInvalidEra
- <<: *errWithdrawalNotPossibleWithoutVote
- <<: *errInvalidMetadataEncryption
<<: *responsesErr404WalletNotFound
<<: *responsesErr406
<<: *responsesErr415UnsupportedMediaType
Expand Down

0 comments on commit 73216c9

Please sign in to comment.