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

Remove shielded transfers #307

Merged
merged 1 commit into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 5 additions & 3 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

## Unreleased

- Rename subcommand `TransactionSubmit` to `TransactionSignAndSubmit`.
- Add subcommand `TransactionSubmit` to submit a signed transaction on chain.
- Add subcommand `TransactionAddSignature` to add a signature to a partially-signed transaction.
- Remove command `transaction send-shielded` to disable the transfer of CCD from the shielded balance of the account to the shielded balance of another account.
- Remove command `account shield` to disable the transfer of CCD from the public balance to the shielded balance of an account.
- Rename command `transaction submit` to `transaction sign-and-submit`.
- Add command `transaction submit` to submit a signed transaction on chain.
- Add command `transaction add-signature` to add a signature to a partially-signed transaction.
- Add optional `--out` flag to all transaction-creating commands to output a partially-singed transaction to a file.
- Update GHC version to 9.6.4 (lts-22.9).
- Update Rust version to 1.73.
Expand Down
47 changes: 0 additions & 47 deletions src/Concordium/Client/Commands.hs
Original file line number Diff line number Diff line change
Expand Up @@ -216,17 +216,6 @@ data TransactionCmd
{ tdcFile :: !FilePath,
tdcInteractionOpts :: !InteractionOpts
}
| TransactionEncryptedTransfer
{ tetTransactionOpts :: !(TransactionOpts (Maybe Energy)),
-- | Address of the receiver.
tetReceiver :: !Text,
-- | Amount to send.
tetAmount :: !Amount,
-- | Which indices to use as inputs to the encrypted amount transfer.
-- If none are provided all existing ones will be used.
tetIndex :: !(Maybe Int),
tetMemo :: !(Maybe MemoInput)
}
| -- | Register data on chain.
TransactionRegisterData
{ -- | File containing the data.
Expand All @@ -250,13 +239,6 @@ data AccountCmd
aukCredId :: !CredentialRegistrationID,
aukTransactionOpts :: !(TransactionOpts (Maybe Energy))
}
| -- | Transfer part of the public balance to the encrypted balance of the
-- account.
AccountEncrypt
{ aeTransactionOpts :: !(TransactionOpts (Maybe Energy)),
-- | Amount to transfer from public to encrypted balance.
aeAmount :: !Amount
}
| -- | Transfer part of the encrypted balance to the public balance of the
-- account.
AccountDecrypt
Expand Down Expand Up @@ -720,7 +702,6 @@ transactionCmds =
<> transactionSendCcdCmd
<> transactionWithScheduleCmd
<> transactionDeployCredentialCmd
<> transactionEncryptedTransferCmd
<> transactionRegisterDataCmd
)
)
Expand Down Expand Up @@ -920,21 +901,6 @@ transactionWithScheduleCmd =
Nothing -> Left "Starting point could not be read."
Just time -> return (utcTimeToTimestamp time)

transactionEncryptedTransferCmd :: Mod CommandFields TransactionCmd
transactionEncryptedTransferCmd = command "send-shielded" sendEncryptedInfo
where
sendEncryptedInfo :: ParserInfo TransactionCmd
sendEncryptedInfo =
info
( TransactionEncryptedTransfer
<$> transactionOptsParser
<*> strOption (long "receiver" <> metavar "RECEIVER-ACCOUNT" <> help "Address of the receiver.")
<*> option (eitherReader amountFromStringInform) (long "amount" <> metavar "CCD-AMOUNT" <> help "Amount of CCDs to send.")
<*> optional (option auto (long "index" <> metavar "INDEX" <> help "Optionally specify the index up to which incoming shielded amounts should be used."))
<*> memoInputParser
)
(progDesc "Transfer CCD from the shielded balance of the account to the shielded balance of another account.")

transactionRegisterDataCmd :: Mod CommandFields TransactionCmd
transactionRegisterDataCmd =
command
Expand All @@ -958,7 +924,6 @@ accountCmds =
<> accountListCmd
<> accountUpdateKeysCmd
<> accountUpdateCredentialsCmd
<> accountEncryptCmd
<> accountDecryptCmd
<> accountShowAliasCmd
)
Expand Down Expand Up @@ -991,18 +956,6 @@ accountListCmd =
(progDesc "List all accounts.")
)

accountEncryptCmd :: Mod CommandFields AccountCmd
accountEncryptCmd =
command
"shield"
( info
( AccountEncrypt
<$> transactionOptsParser
<*> option (eitherReader amountFromStringInform) (long "amount" <> metavar "CCD-AMOUNT" <> help "The amount to transfer to shielded balance.")
)
(progDesc "Transfer an amount from public to shielded balance of the account.")
)

accountDecryptCmd :: Mod CommandFields AccountCmd
accountDecryptCmd =
command
Expand Down
163 changes: 1 addition & 162 deletions src/Concordium/Client/Runner.hs
Original file line number Diff line number Diff line change
Expand Up @@ -883,52 +883,6 @@ processTransactionCmd action baseCfgDir verbose backend =
let outFile = toOutFile txOpts
liftIO $ transferWithScheduleTransactionConfirm ttxCfg (ioConfirm intOpts)
signAndProcessTransaction_ verbose txCfg pl intOpts outFile backend
TransactionEncryptedTransfer txOpts receiver amount index maybeMemo -> do
baseCfg <- getBaseConfig baseCfgDir verbose
when verbose $ do
runPrinter $ printBaseConfig baseCfg
putStrLn ""

accCfg <- getAccountCfgFromTxOpts baseCfg txOpts
let senderAddr = esdAddress accCfg

encryptedSecretKey <-
case esdEncryptionKey accCfg of
Nothing ->
logFatal ["Missing account encryption secret key for account: " ++ show senderAddr]
Just x -> return x
secretKey <- decryptAccountEncryptionSecretKeyInteractive encryptedSecretKey `withLogFatalIO` ("Couldn't decrypt account encryption secret key: " ++)

receiverAcc <- getAccountAddressArg (bcAccountNameMap baseCfg) receiver

withClient backend $ do
transferData <- getEncryptedAmountTransferData (naAddr senderAddr) receiverAcc amount index secretKey
cs <- getResponseValueOrDie =<< getConsensusInfo
payload <- liftIO $ do
res <- case maybeMemo of
Nothing -> return $ Types.EncryptedAmountTransfer (naAddr receiverAcc) transferData
Just memoInput -> do
memo <- checkAndGetMemo memoInput $ Queries.csProtocolVersion cs
return $ Types.EncryptedAmountTransferWithMemo (naAddr receiverAcc) memo transferData
return $ Types.encodePayload res
let nrgCost _ = return $ Just $ encryptedTransferEnergyCost $ Types.payloadSize payload
txCfg <- liftIO (getTransactionCfg baseCfg txOpts nrgCost)

let ettCfg =
EncryptedTransferTransactionConfig
{ ettTransferData = transferData,
ettTransactionCfg = txCfg,
ettReceiver = receiverAcc,
ettAmount = amount
}
liftIO $ when verbose $ do
runPrinter $ printSelectedKeyConfig $ tcEncryptedSigningData txCfg
putStrLn ""

let intOpts = toInteractionOpts txOpts
let outFile = toOutFile txOpts
encryptedTransferTransactionConfirm ettCfg (ioConfirm intOpts)
signAndProcessTransaction_ verbose txCfg payload intOpts outFile backend
TransactionRegisterData file txOpts -> do
baseCfg <- getBaseConfig baseCfgDir verbose
rdCfg <- getRegisterDataTransactionCfg baseCfg txOpts file
Expand Down Expand Up @@ -1191,52 +1145,6 @@ data TransferWithScheduleTransactionConfig = TransferWithScheduleTransactionConf
twstcSchedule :: [(Time.Timestamp, Types.Amount)]
}

data EncryptedTransferTransactionConfig = EncryptedTransferTransactionConfig
{ ettTransactionCfg :: TransactionConfig,
ettReceiver :: NamedAddress,
ettAmount :: Types.Amount,
ettTransferData :: !Enc.EncryptedAmountTransferData
}

getEncryptedAmountTransferData :: ID.AccountAddress -> NamedAddress -> Types.Amount -> Maybe Int -> ElgamalSecretKey -> ClientMonad IO Enc.EncryptedAmountTransferData
getEncryptedAmountTransferData senderAddr ettReceiver ettAmount idx secretKey = do
-- get encrypted amounts for the sender
bbHash <- extractResponseValueOrDie Queries.biBlockHash =<< getBlockInfo Best
Types.AccountInfo{aiAccountEncryptedAmount = [email protected]{..}} <-
getResponseValueOrDie =<< getAccountInfo (Types.AccAddress senderAddr) (Given bbHash)
let listOfEncryptedAmounts = Types.getIncomingAmountsList a
taker <- case idx of
Nothing -> return id
Just v ->
if v < fromIntegral _startIndex
|| v > fromIntegral _startIndex + length listOfEncryptedAmounts
then logFatal ["The index provided must be at least the index of the first incoming amount on the account and at most `start index + number of incoming amounts`"]
else return $ take (v - fromIntegral _startIndex)
-- get receiver's public encryption key
air <- getResponseValueOrDie =<< getAccountInfo (Types.AccAddress $ naAddr ettReceiver) (Given bbHash)
globalContext <- getResponseValueOrDie =<< getCryptographicParameters (Given bbHash)
let receiverPk = ID._elgamalPublicKey $ Types.aiAccountEncryptionKey air
-- precomputed table for speeding up decryption
let table = Enc.computeTable globalContext (2 ^ (16 :: Int))
decoder = Enc.decryptAmount table secretKey
selfDecrypted = decoder _selfAmount
-- aggregation of idx encrypted amounts
inputEncAmounts = taker listOfEncryptedAmounts
aggAmounts = foldl' (<>) _selfAmount inputEncAmounts
totalEncryptedAmount = foldl' (+) selfDecrypted $ fmap decoder inputEncAmounts
unless (totalEncryptedAmount >= ettAmount) $
logFatal [printf "The requested transfer (%s) is more than the total encrypted balance (%s)." (Types.amountToString ettAmount) (Types.amountToString totalEncryptedAmount)]
-- index indicating which encrypted amounts we used as input
let aggIndex = case idx of
Nothing -> Enc.EncryptedAmountAggIndex (Enc.theAggIndex _startIndex + fromIntegral (length listOfEncryptedAmounts))
Just idx' -> Enc.EncryptedAmountAggIndex (fromIntegral idx')
-- we use the supplied index if given. We already checked above that it is within bounds.
aggAmount = Enc.makeAggregatedDecryptedAmount aggAmounts totalEncryptedAmount aggIndex
liftIO $
Enc.makeEncryptedAmountTransferData globalContext receiverPk secretKey aggAmount ettAmount >>= \case
Nothing -> logFatal ["Could not create transfer. Likely the provided secret key is incorrect."]
Just ettTransferData -> return ettTransferData

-- | Returns the UTCTime date when the baker cooldown on reducing stake/removing a baker will end, using on chain parameters
getBakerCooldown :: Queries.EChainParametersAndKeys -> ClientMonad IO UTCTime
getBakerCooldown (Queries.EChainParametersAndKeys (ecpParams :: ChainParameters' cpv) _) = do
Expand Down Expand Up @@ -1318,27 +1226,12 @@ data AccountUpdateCredentialsTransactionCfg = AccountUpdateCredentialsTransactio
auctcNewThreshold :: ID.AccountThreshold
}

-- | Resolved configuration for transferring from public to encrypted balance.
data AccountEncryptTransactionConfig = AccountEncryptTransactionConfig
{ aeTransactionCfg :: TransactionConfig,
aeAmount :: Types.Amount
}

-- | Resolved configuration for transferring from encrypted to public balance.
data AccountDecryptTransactionConfig = AccountDecryptTransactionConfig
{ adTransactionCfg :: TransactionConfig,
adTransferData :: Enc.SecToPubAmountTransferData
}

-- | Resolve configuration for transferring an amount from public to encrypted
-- balance of an account.
getAccountEncryptTransactionCfg :: BaseConfig -> TransactionOpts (Maybe Types.Energy) -> Types.Amount -> Types.PayloadSize -> IO AccountEncryptTransactionConfig
getAccountEncryptTransactionCfg baseCfg txOpts aeAmount payloadSize = do
aeTransactionCfg <- getTransactionCfg baseCfg txOpts nrgCost
return AccountEncryptTransactionConfig{..}
where
nrgCost _ = return $ Just $ accountEncryptEnergyCost payloadSize

-- | Resolve configuration for transferring an amount from encrypted to public
-- balance of an account.
getAccountDecryptTransferData :: ID.AccountAddress -> Types.Amount -> ElgamalSecretKey -> Maybe Int -> ClientMonad IO Enc.SecToPubAmountTransferData
Expand Down Expand Up @@ -1446,25 +1339,6 @@ transferWithScheduleTransactionConfirm ttxCfg confirm = do
confirmed <- askConfirmation Nothing
unless confirmed exitTransactionCancelled

encryptedTransferTransactionConfirm :: (MonadIO m) => EncryptedTransferTransactionConfig -> Bool -> m ()
encryptedTransferTransactionConfirm EncryptedTransferTransactionConfig{..} confirm = do
let TransactionConfig
{ tcEnergy = energy,
tcExpiry = expiry,
tcEncryptedSigningData = EncryptedSigningData{esdAddress = addr}
} =
ettTransactionCfg

logInfo
[ printf "transferring %s CCD from shielded balance of account %s to %s" (Types.amountToString ettAmount) (showNamedAddress addr) (showNamedAddress ettReceiver),
printf "allowing up to %s to be spent as transaction fee" (showNrg energy),
printf "transaction expires on %s" (showTimeFormatted $ timeFromTransactionExpiryTime expiry)
]

when confirm $ do
confirmed <- askConfirmation Nothing
unless confirmed exitTransactionCancelled

-- | Query the chain for the minimum baker stake threshold.
-- Die printing an error message containing the nature of the error if such occured.
getBakerStakeThresholdOrDie :: ClientMonad IO Types.Amount
Expand Down Expand Up @@ -1552,25 +1426,6 @@ accountUpdateCredentialsTransactionConfirm AccountUpdateCredentialsTransactionCf
confirmed <- askConfirmation Nothing
unless confirmed exitTransactionCancelled

accountEncryptTransactionConfirm :: AccountEncryptTransactionConfig -> Bool -> IO ()
accountEncryptTransactionConfirm AccountEncryptTransactionConfig{..} confirm = do
let TransactionConfig
{ tcEnergy = energy,
tcExpiry = expiry,
tcEncryptedSigningData = EncryptedSigningData{esdAddress = addr}
} =
aeTransactionCfg

logInfo $
[ printf "transferring %s CCD from public to shielded balance of account %s" (Types.amountToString aeAmount) (showNamedAddress addr),
printf "allowing up to %s to be spent as transaction fee" (showNrg energy),
printf "transaction expires on %s" (showTimeFormatted $ timeFromTransactionExpiryTime expiry)
]

when confirm $ do
confirmed <- askConfirmation Nothing
unless confirmed exitTransactionCancelled

accountDecryptTransactionConfirm :: (MonadIO m) => AccountDecryptTransactionConfig -> Bool -> m ()
accountDecryptTransactionConfirm AccountDecryptTransactionConfig{..} confirm = do
let TransactionConfig
Expand Down Expand Up @@ -1970,23 +1825,6 @@ processAccountCmd action baseCfgDir verbose backend =
}
liftIO $ accountUpdateCredentialsTransactionConfirm aucCfg (ioConfirm intOpts)
signAndProcessTransaction_ verbose txCfg epayload intOpts (toOutFile txOpts) backend
AccountEncrypt{..} -> do
baseCfg <- getBaseConfig baseCfgDir verbose
when verbose $ do
runPrinter $ printBaseConfig baseCfg
putStrLn ""

let pl = Types.encodePayload $ Types.TransferToEncrypted aeAmount

aetxCfg <- getAccountEncryptTransactionCfg baseCfg aeTransactionOpts aeAmount (Types.payloadSize pl)
let txCfg = aeTransactionCfg aetxCfg
when verbose $ do
runPrinter $ printSelectedKeyConfig $ tcEncryptedSigningData txCfg
putStrLn ""

let intOpts = toInteractionOpts aeTransactionOpts
accountEncryptTransactionConfirm aetxCfg (ioConfirm intOpts)
withClient backend $ signAndProcessTransaction_ verbose txCfg pl intOpts (toOutFile aeTransactionOpts) backend
AccountDecrypt{..} -> do
baseCfg <- getBaseConfig baseCfgDir verbose
when verbose $ do
Expand Down Expand Up @@ -4649,6 +4487,7 @@ convertTransactionJsonPayload = \case
return $ Types.Transfer transferTo transferAmount
CT.RemoveBaker -> return $ Types.RemoveBaker
CT.TransferToPublic{..} -> return $ Types.TransferToPublic{..}
-- Note: The following two types are not supported anymore in protocol version 7 or above.
-- FIXME: The following two should have the inputs changed so that they are usable.
-- They should only specify the amount and the index, and possibly the input encrypted amounts,
-- but the proofs should be automatically generated here.
Expand Down
Loading