Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SignedTransaction type #529

Merged
merged 19 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions concordium-base.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ test-suite test
Types.AmountSpec
Types.ParametersSpec
Types.PayloadSerializationSpec
Types.PayloadSpec
Types.TransactionSerializationSpec
Types.TransactionSummarySpec
Types.UpdatesSpec
Expand Down
11 changes: 6 additions & 5 deletions haskell-src/Concordium/Cost.hs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{-# LANGUAGE DerivingVia, TypeFamilies #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE TypeFamilies #-}

-- |
-- Definition of cost functions for the different transactions.
Expand Down Expand Up @@ -237,11 +238,11 @@ initializeContractInstanceCreateCost = 200
updateContractInstanceBaseCost :: Energy
updateContractInstanceBaseCost = 300

-- |Maximum amount of nested V1 contract calls. That is, the maximum amount of
-- execution frames that need to be kept alive at the same time.
-- | Maximum amount of nested V1 contract calls. That is, the maximum amount of
-- execution frames that need to be kept alive at the same time.
--
-- Since each frame that is kept alive can consume up to 32MB of memory this limits
-- the worst case memory use of contract calls.
-- Since each frame that is kept alive can consume up to 32MB of memory this limits
-- the worst case memory use of contract calls.
allowedContractCallDepth :: SProtocolVersion pv -> Word -> Bool
allowedContractCallDepth spv n = demoteProtocolVersion spv <= P6 || n < 384

Expand Down
17 changes: 17 additions & 0 deletions haskell-src/Concordium/Crypto/EncryptedTransfers.hs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,15 @@ instance FromJSON EncryptedAmountTransferData where
eatdProof <- v .: "proof"
return EncryptedAmountTransferData{..}

instance ToJSON EncryptedAmountTransferData where
toJSON EncryptedAmountTransferData{..} =
object
[ "remainingAmount" .= eatdRemainingAmount,
"transferAmount" .= eatdTransferAmount,
"index" .= eatdIndex,
"proof" .= eatdProof
]

withEncryptedAmountTransferData ::
EncryptedAmountTransferData ->
(Ptr ElgamalCipher -> Ptr ElgamalCipher -> Ptr ElgamalCipher -> Ptr ElgamalCipher -> EncryptedAmountAggIndex -> Word64 -> Ptr CChar -> IO a) ->
Expand Down Expand Up @@ -491,6 +500,14 @@ instance FromJSON SecToPubAmountTransferData where
stpatdProof <- v .: "proof"
return SecToPubAmountTransferData{..}

instance ToJSON SecToPubAmountTransferData where
toJSON SecToPubAmountTransferData{..} =
object
[ "remainingAmount" .= stpatdRemainingAmount,
"transferAmount" .= stpatdTransferAmount,
"index" .= stpatdIndex,
"proof" .= stpatdProof
]
withSecToPubAmountTransferData ::
SecToPubAmountTransferData ->
(Ptr ElgamalCipher -> Ptr ElgamalCipher -> Word64 -> EncryptedAmountAggIndex -> Word64 -> Ptr CChar -> IO a) ->
Expand Down
8 changes: 8 additions & 0 deletions haskell-src/Concordium/ID/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,7 @@ instance Serialize CredentialDeploymentInformation where
instance Eq CredentialDeploymentInformation where
cdi1 == cdi2 = cdiValues cdi1 == cdiValues cdi2

-- Implement `FromJSON` instance for `CredentialDeploymentInformation`.
instance FromJSON CredentialDeploymentInformation where
parseJSON = withObject "CredentialDeploymentInformation" $ \x -> do
cdiValues <- parseJSON (Object x)
Expand All @@ -797,6 +798,13 @@ instance FromJSON CredentialDeploymentInformation where
}
Left _ -> fail "\"proofs\" is not a valid base16 string."

-- Implement `ToJSON` instance for `CredentialDeploymentInformation`.
instance ToJSON CredentialDeploymentInformation where
toJSON CredentialDeploymentInformation{..} =
object $
("proofs" .= cdiProofs)
: credentialDeploymentValuesList cdiValues

-- | Information about the account that should be created as part of the initial
-- credential deployment.
data InitialCredentialAccount = InitialCredentialAccount
Expand Down
3 changes: 2 additions & 1 deletion haskell-src/Concordium/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ instance Show Address where

-- | Time in seconds since the unix epoch
newtype TransactionTime = TransactionTime {ttsSeconds :: Word64}
deriving (Show, Read, Eq, Num, Ord, FromJSON, ToJSON, Real, Enum, Integral) via Word64
deriving (Show, Read, Eq, Num, Ord, Real, FromJSON, ToJSON, Enum, Integral) via Word64

instance S.Serialize TransactionTime where
put = P.putWord64be . ttsSeconds
Expand Down Expand Up @@ -996,6 +996,7 @@ instance S.Serialize PayloadSize where
-- | Serialized payload of the transaction
newtype EncodedPayload = EncodedPayload {_spayload :: BSS.ShortByteString}
deriving (Eq, Show)
deriving (AE.ToJSON, AE.FromJSON) via BSH.ByteStringHex
DOBEN marked this conversation as resolved.
Show resolved Hide resolved

-- | There is no corresponding getter (to fit into the Serialize instance) since
-- encoded payload does not encode its own length. See 'getPayload' below.
Expand Down
144 changes: 144 additions & 0 deletions haskell-src/Concordium/Types/Execution.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NamedFieldPuns #-}
DOBEN marked this conversation as resolved.
Show resolved Hide resolved
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE TemplateHaskell #-}
Expand All @@ -18,6 +19,7 @@ import Concordium.Utils.Serialization
import Data.Aeson ((.:), (.=))
import qualified Data.Aeson as AE
import Data.Aeson.TH
import Data.Aeson.Types (Parser)
import Data.Bits
import qualified Data.ByteString as BS
import qualified Data.ByteString.Short as BSS
Expand Down Expand Up @@ -46,6 +48,7 @@ import Concordium.Types.Execution.TH
import Concordium.Types.Updates
import Concordium.Utils
import qualified Concordium.Wasm as Wasm
import Data.Char (isLower)

-- | We assume that the list is non-empty and at most 255 elements long.
newtype AccountOwnershipProof = AccountOwnershipProof [(KeyIndex, Dlog25519Proof)]
Expand Down Expand Up @@ -159,6 +162,14 @@ bakerKeysWithProofsSize :: Int
bakerKeysWithProofsSize =
VRF.publicKeySize + dlogProofSize + Sig.publicKeySize + dlogProofSize + Bls.publicKeySize + Bls.proofSize

-- Implement `FromJSON` and `ToJSON` instances for `BakerKeysWithProofs`.
$( deriveJSON
defaultOptions
{ AE.fieldLabelModifier = firstLower . dropWhile isLower
}
''BakerKeysWithProofs
)

DOBEN marked this conversation as resolved.
Show resolved Hide resolved
-- | The transaction payload. Defines the supported kinds of transactions.
--
-- * @SPEC: <$DOCS/Transactions#transaction-body>
Expand Down Expand Up @@ -404,6 +415,139 @@ instance S.Serialize TransactionType where
20 -> return TTConfigureDelegation
n -> fail $ "Unrecognized TransactionType tag: " ++ show n

instance AE.ToJSON Payload where
-- `mod` was renamed to `module`
toJSON DeployModule{dmMod} = AE.object ["module" AE..= dmMod, "transactionType" AE..= AE.String "deployModule"]
DOBEN marked this conversation as resolved.
Show resolved Hide resolved
toJSON InitContract{icAmount, icModRef, icInitName, icParam} = AE.object ["amount" AE..= icAmount, "modRef" AE..= icModRef, "initName" AE..= icInitName, "param" AE..= icParam, "transactionType" AE..= AE.String "initContract"]
toJSON Update{uAmount, uAddress, uReceiveName, uMessage} = AE.object ["amount" AE..= uAmount, "address" AE..= uAddress, "receiveName" AE..= uReceiveName, "message" AE..= uMessage, "transactionType" AE..= AE.String "update"]
toJSON Transfer{tToAddress, tAmount} = AE.object ["toAddress" AE..= tToAddress, "amount" AE..= tAmount, "transactionType" AE..= AE.String "transfer"]
toJSON UpdateCredentialKeys{uckCredId, uckKeys} = AE.object ["credId" AE..= uckCredId, "keys" AE..= uckKeys, "transactionType" AE..= AE.String "updateCredentialKeys"]
toJSON EncryptedAmountTransfer{eatTo, eatData} = AE.object ["to" AE..= eatTo, "data" AE..= eatData, "transactionType" AE..= AE.String "encryptedAmountTransfer"]
toJSON TransferToEncrypted{tteAmount} = AE.object ["amount" AE..= tteAmount, "transactionType" AE..= AE.String "transferToEncrypted"]
toJSON TransferToPublic{ttpData} = AE.object ["data" AE..= ttpData, "transactionType" AE..= AE.String "transferToPublic"]
toJSON TransferWithSchedule{twsTo, twsSchedule} = AE.object ["to" AE..= twsTo, "schedule" AE..= twsSchedule, "transactionType" AE..= AE.String "transferWithSchedule"]
toJSON UpdateCredentials{ucNewCredInfos, ucRemoveCredIds, ucNewThreshold} = AE.object ["newCredInfos" AE..= ucNewCredInfos, "removeCredIds" AE..= ucRemoveCredIds, "newThreshold" AE..= ucNewThreshold, "transactionType" AE..= AE.String "updateCredentials"]
toJSON RegisterData{rdData} = AE.object ["data" AE..= rdData, "transactionType" AE..= AE.String "registerData"]
toJSON TransferWithMemo{twmToAddress, twmMemo, twmAmount} = AE.object ["toAddress" AE..= twmToAddress, "memo" AE..= twmMemo, "amount" AE..= twmAmount, "transactionType" AE..= AE.String "transferWithMemo"]
toJSON EncryptedAmountTransferWithMemo{eatwmTo, eatwmMemo, eatwmData} = AE.object ["to" AE..= eatwmTo, "memo" AE..= eatwmMemo, "data" AE..= eatwmData, "transactionType" AE..= AE.String "encryptedAmountTransferWithMemo"]
toJSON TransferWithScheduleAndMemo{twswmTo, twswmMemo, twswmSchedule} = AE.object ["to" AE..= twswmTo, "memo" AE..= twswmMemo, "schedule" AE..= twswmSchedule, "transactionType" AE..= AE.String "transferWithScheduleAndMemo"]
-- `configureBaker` was renamed to `configureValidator`
toJSON ConfigureBaker{cbCapital, cbRestakeEarnings, cbOpenForDelegation, cbKeysWithProofs, cbMetadataURL, cbTransactionFeeCommission, cbBakingRewardCommission, cbFinalizationRewardCommission} = AE.object ["capital" AE..= cbCapital, "restakeEarnings" AE..= cbRestakeEarnings, "openForDelegation" AE..= cbOpenForDelegation, "keysWithProofs" AE..= cbKeysWithProofs, "metadataURL" AE..= cbMetadataURL, "transactionFeeCommission" AE..= cbTransactionFeeCommission, "bakingRewardCommission" AE..= cbBakingRewardCommission, "finalizationRewardCommission" AE..= cbFinalizationRewardCommission, "transactionType" AE..= AE.String "configureValidator"]
toJSON ConfigureDelegation{cdCapital, cdRestakeEarnings, cdDelegationTarget} = AE.object ["capital" AE..= cdCapital, "restakeEarnings" AE..= cdRestakeEarnings, "delegationTarget" AE..= cdDelegationTarget, "transactionType" AE..= AE.String "configureDelegation"]
toJSON AddBaker{abElectionVerifyKey, abSignatureVerifyKey, abAggregationVerifyKey, abProofSig, abProofElection, abProofAggregation, abBakingStake, abRestakeEarnings} = AE.object ["electionVerifyKey" AE..= abElectionVerifyKey, "signatureVerifyKey" AE..= abSignatureVerifyKey, "aggregationVerifyKey" AE..= abAggregationVerifyKey, "proofSig" AE..= abProofSig, "proofElection" AE..= abProofElection, "proofAggregation" AE..= abProofAggregation, "bakingStake" AE..= abBakingStake, "restakeEarnings" AE..= abRestakeEarnings, "transactionType" AE..= AE.String "addBaker"]
toJSON RemoveBaker = AE.object ["transactionType" AE..= AE.String "removeBaker"]
toJSON UpdateBakerStake{ubsStake} = AE.object ["stake" AE..= ubsStake, "transactionType" AE..= AE.String "updateBakerStake"]
toJSON UpdateBakerRestakeEarnings{ubreRestakeEarnings} = AE.object ["restakeEarnings" AE..= ubreRestakeEarnings, "transactionType" AE..= AE.String "updateBakerRestakeEarnings"]
toJSON UpdateBakerKeys{ubkElectionVerifyKey, ubkSignatureVerifyKey, ubkAggregationVerifyKey, ubkProofSig, ubkProofElection, ubkProofAggregation} = AE.object ["electionVerifyKey" AE..= ubkElectionVerifyKey, "signatureVerifyKey" AE..= ubkSignatureVerifyKey, "aggregationVerifyKey" AE..= ubkAggregationVerifyKey, "proofSig" AE..= ubkProofSig, "proofElection" AE..= ubkProofElection, "proofAggregation" AE..= ubkProofAggregation, "transactionType" AE..= AE.String "updateBakerKeys"]

instance AE.FromJSON Payload where
parseJSON = AE.withObject "payload" $ \obj -> do
transactionType <- obj AE..: "transactionType" :: Parser String

case transactionType of
"deployModule" -> do
dmMod <- obj AE..: "module"
return DeployModule{dmMod}
"initContract" -> do
icAmount <- obj AE..: "amount"
icModRef <- obj AE..: "modRef"
icInitName <- obj AE..: "initName"
icParam <- obj AE..: "param"
return InitContract{icAmount, icModRef, icInitName, icParam}
"update" -> do
uAmount <- obj AE..: "amount"
uAddress <- obj AE..: "address"
uReceiveName <- obj AE..: "receiveName"
uMessage <- obj AE..: "message"
return Update{uAmount, uAddress, uReceiveName, uMessage}
"transfer" -> do
tToAddress <- obj AE..: "toAddress"
tAmount <- obj AE..: "amount"
return Transfer{tToAddress, tAmount}
"UpdateBakerStake" -> do
ubsStake <- obj AE..: "stake"
return UpdateBakerStake{ubsStake}
"updateBakerRestakeEarnings" -> do
ubreRestakeEarnings <- obj AE..: "restakeEarnings"
return UpdateBakerRestakeEarnings{ubreRestakeEarnings}
"updateBakerKeys" -> do
ubkElectionVerifyKey <- obj AE..: "electionVerifyKey"
ubkSignatureVerifyKey <- obj AE..: "signatureVerifyKey"
ubkAggregationVerifyKey <- obj AE..: "aggregationVerifyKey"
ubkProofSig <- obj AE..: "proofSig"
ubkProofElection <- obj AE..: "proofElection"
ubkProofAggregation <- obj AE..: "proofAggregation"
return UpdateBakerKeys{ubkElectionVerifyKey, ubkSignatureVerifyKey, ubkAggregationVerifyKey, ubkProofSig, ubkProofElection, ubkProofAggregation}
"updateCredentialKeys" -> do
uckCredId <- obj AE..: "credId"
uckKeys <- obj AE..: "keys"
return UpdateCredentialKeys{uckCredId, uckKeys}
"removeBaker" -> do
return RemoveBaker
"addBaker" -> do
abElectionVerifyKey <- obj AE..: "electionVerifyKey"
abSignatureVerifyKey <- obj AE..: "signatureVerifyKey"
abAggregationVerifyKey <- obj AE..: "aggregationVerifyKey"
abProofSig <- obj AE..: "proofSig"
abProofElection <- obj AE..: "proofElection"
abProofAggregation <- obj AE..: "proofAggregation"
abBakingStake <- obj AE..: "bakingStake"
abRestakeEarnings <- obj AE..: "restakeEarnings"
return AddBaker{abElectionVerifyKey, abSignatureVerifyKey, abAggregationVerifyKey, abProofSig, abProofElection, abProofAggregation, abBakingStake, abRestakeEarnings}
"encryptedAmountTransfer" -> do
eatTo <- obj AE..: "to"
eatData <- obj AE..: "data"
return EncryptedAmountTransfer{eatTo, eatData}
"transferToEncrypted" -> do
tteAmount <- obj AE..: "amount"
return TransferToEncrypted{tteAmount}
"transferToPublic" -> do
ttpData <- obj AE..: "data"
return TransferToPublic{ttpData}
"transferWithSchedule" -> do
twsTo <- obj AE..: "to"
twsSchedule <- obj AE..: "schedule"
return TransferWithSchedule{twsTo, twsSchedule}
"updateCredentials" -> do
ucNewCredInfos <- obj AE..: "newCredInfos"
ucRemoveCredIds <- obj AE..: "removeCredIds"
ucNewThreshold <- obj AE..: "newThreshold"
return UpdateCredentials{ucNewCredInfos, ucRemoveCredIds, ucNewThreshold}
"registerData" -> do
rdData <- obj AE..: "data"
return RegisterData{rdData}
"transferWithMemo" -> do
twmToAddress <- obj AE..: "toAddress"
twmMemo <- obj AE..: "memo"
twmAmount <- obj AE..: "amount"
return TransferWithMemo{twmToAddress, twmMemo, twmAmount}
"encryptedAmountTransferWithMemo" -> do
eatwmTo <- obj AE..: "to"
eatwmMemo <- obj AE..: "memo"
eatwmData <- obj AE..: "data"
return EncryptedAmountTransferWithMemo{eatwmTo, eatwmMemo, eatwmData}
"transferWithScheduleAndMemo" -> do
twswmTo <- obj AE..: "to"
twswmMemo <- obj AE..: "memo"
twswmSchedule <- obj AE..: "schedule"
return TransferWithScheduleAndMemo{twswmTo, twswmMemo, twswmSchedule}
"configureValidator" -> do
cbCapital <- obj AE..: "capital"
cbRestakeEarnings <- obj AE..: "restakeEarnings"
cbOpenForDelegation <- obj AE..: "openForDelegation"
cbKeysWithProofs <- obj AE..: "keysWithProofs"
cbMetadataURL <- obj AE..: "metadataURL"
cbTransactionFeeCommission <- obj AE..: "transactionFeeCommission"
cbBakingRewardCommission <- obj AE..: "bakingRewardCommission"
cbFinalizationRewardCommission <- obj AE..: "finalizationRewardCommission"
return ConfigureBaker{cbCapital, cbRestakeEarnings, cbOpenForDelegation, cbKeysWithProofs, cbMetadataURL, cbTransactionFeeCommission, cbBakingRewardCommission, cbFinalizationRewardCommission}
"configureDelegation" -> do
cdCapital <- obj AE..: "capital"
cdRestakeEarnings <- obj AE..: "restakeEarnings"
cdDelegationTarget <- obj AE..: "delegationTarget"
return ConfigureDelegation{cdCapital, cdRestakeEarnings, cdDelegationTarget}
_ -> fail "Unrecognized 'TransactionType' tag"

-- | Payload serialization according to
--
-- * @SPEC: <$DOCS/Transactions#transaction-body>
Expand Down
Loading
Loading