Skip to content

Commit ad0375a

Browse files
drsk0drsktd202
authored
COR-1345: verification for CreatePLT in TransactionVerifier (#1431)
* COR-1345: verify tx for CreatePLT in TransactionVerifier We add an additional check in the verifyChainUpdate function for txs with payloads of type CreatePLTUpdatePayload and assert that the effective time of the transaction is zero in this case. * update changelog * address review comments * new unit tests for transaction verification At this point this only tests the new verification for CreatePLT. * Update concordium-consensus/tests/consensus/ConcordiumTests/KonsensusV1/TransactionProcessingTest.hs Co-authored-by: Thomas Dinsdale-Young <td202@users.noreply.github.com> * add guard for spv >= P9 * add P7 back in tests --------- Co-authored-by: drsk <rsk@concordium.com> Co-authored-by: Thomas Dinsdale-Young <td202@users.noreply.github.com>
1 parent 485cfc8 commit ad0375a

File tree

6 files changed

+92
-9
lines changed

6 files changed

+92
-9
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Changelog
22

33
## Unreleased changes
4+
- Protocol-level tokens:
5+
- Additional check in transaction verification asserting that the effective
6+
time equals zero of CreatePLT update transactions.
47

58
- Add P8 -> P9 update.
69
- Update GHC version to 9.10.2 (lts-24.0).

concordium-consensus/src/Concordium/Scheduler.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ checkTransactionVerificationResult (TVer.NotOk TVer.NormalTransactionDepositInsu
210210
checkTransactionVerificationResult (TVer.NotOk (TVer.NormalTransactionDuplicateNonce nonce)) = Left $ NonSequentialNonce nonce
211211
checkTransactionVerificationResult (TVer.NotOk TVer.Expired) = Left ExpiredTransaction
212212
checkTransactionVerificationResult (TVer.NotOk TVer.InvalidPayloadSize) = Left InvalidPayloadSize
213+
checkTransactionVerificationResult (TVer.NotOk TVer.ChainUpdateEffectiveTimeNonZeroForCreatePLT) = Left InvalidUpdateTime
213214

214215
-- | Execute a transaction on the current block state, charging valid accounts
215216
-- for the resulting energy cost.

concordium-consensus/src/Concordium/Skov/Monad.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ transactionVerificationResultToUpdateResult (TV.NotOk TV.NormalTransactionDeposi
140140
transactionVerificationResultToUpdateResult (TV.NotOk (TV.NormalTransactionDuplicateNonce _)) = ResultDuplicateNonce
141141
transactionVerificationResultToUpdateResult (TV.NotOk TV.Expired) = ResultStale
142142
transactionVerificationResultToUpdateResult (TV.NotOk TV.InvalidPayloadSize) = ResultSerializationFail
143+
transactionVerificationResultToUpdateResult (TV.NotOk TV.ChainUpdateEffectiveTimeNonZeroForCreatePLT) = ResultChainUpdateInvalidEffectiveTime
143144

144145
class
145146
( Monad m,

concordium-consensus/src/Concordium/TransactionVerification.hs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ data NotOkResult
130130
CredentialDeploymentInvalidSignatures
131131
| -- | The 'ChainUpdate' had an expiry set too late.
132132
ChainUpdateEffectiveTimeBeforeTimeout
133+
| -- | The 'ChainUpdate' is creating a PLT, but its effective time is non-zero.
134+
ChainUpdateEffectiveTimeNonZeroForCreatePLT
133135
| -- | The `UpdateSequenceNumber` of the 'ChainUpdate' was too old.
134136
-- Reason for 'NotOk': the UpdateSequenceNumber can never be valid in a later block if the
135137
-- nonce is already used.
@@ -271,6 +273,11 @@ verifyChainUpdate ui@Updates.UpdateInstruction{..} =
271273
unless (Types.validatePayloadSize (Types.protocolVersion @(Types.MPV m)) (Updates.updatePayloadSize uiHeader)) $
272274
throwError $
273275
NotOk InvalidPayloadSize
276+
case uiPayload of
277+
Updates.CreatePLTUpdatePayload _
278+
| Updates.updateEffectiveTime uiHeader > 0 ->
279+
throwError $ NotOk ChainUpdateEffectiveTimeNonZeroForCreatePLT
280+
_otherwise -> return ()
274281
-- Check that the timeout is no later than the effective time,
275282
-- or the update is immediate
276283
when (Updates.updateTimeout uiHeader >= Updates.updateEffectiveTime uiHeader && Updates.updateEffectiveTime uiHeader /= 0) $

concordium-consensus/tests/consensus/ConcordiumTests/KonsensusV1/Common.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ forEveryProtocolVersion check =
150150
check SP5 "P5",
151151
check SP6 "P6",
152152
check SP7 "P7"
153+
-- check SP8 "P8",
154+
-- check SP9 "P9"
153155
]
154156

155157
-- | Run tests for each protocol version using consensus v1 (P6 and onwards).

concordium-consensus/tests/consensus/ConcordiumTests/KonsensusV1/TransactionProcessingTest.hs

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ import Concordium.Types.Option
7171
import Concordium.Types.Parameters
7272
import Concordium.Types.TransactionOutcomes
7373
import Concordium.Types.Transactions
74+
import Concordium.Types.Updates
75+
import Concordium.Utils
7476

7577
import Concordium.GlobalState.Transactions
7678
import Concordium.KonsensusV1.Transactions
@@ -329,8 +331,8 @@ dummyAccountAddress = fst $ randomAccountAddress (mkStdGen 42)
329331
-- relation to the tree state in this test, hence
330332
-- when processed it will fail on looking up the sender.
331333
-- Note. that the signature is not correct either.
332-
dummyTransaction :: Transaction
333-
dummyTransaction =
334+
dummyNormalTransaction :: Transaction
335+
dummyNormalTransaction =
334336
addMetadata NormalTransaction 0 $
335337
makeAccountTransaction
336338
dummyTransactionSignature
@@ -347,9 +349,73 @@ dummyTransaction =
347349
}
348350
payload = encodePayload $ Transfer dummyAccountAddress 10
349351

350-
-- | The block item for 'dummyTransaction'.
351-
dummyTransactionBI :: BlockItem
352-
dummyTransactionBI = normalTransaction dummyTransaction
352+
-- | A dummy update instruction.
353+
dummyUpdateInstruction :: TransactionTime -> WithMetadata UpdateInstruction
354+
dummyUpdateInstruction effTime =
355+
addMetadata ChainUpdate 0 $
356+
makeUpdateInstruction
357+
RawUpdateInstruction
358+
{ ruiSeqNumber = 1,
359+
ruiEffectiveTime = effTime,
360+
ruiTimeout = 2,
361+
ruiPayload = cplt
362+
}
363+
(Map.singleton 0 dummyAuthorizationKeyPair)
364+
where
365+
cplt =
366+
CreatePLTUpdatePayload $
367+
CreatePLT
368+
{ _cpltTokenId = TokenId "dummyToken",
369+
_cpltTokenModule = TokenModuleRef $ Hash.hash "dummyToken",
370+
_cpltDecimals = 4,
371+
_cpltInitializationParameters = TokenParameter ""
372+
}
373+
374+
-- | The block item for 'dummyNormalTransaction'.
375+
dummyNormalTransactionBI :: BlockItem
376+
dummyNormalTransactionBI = normalTransaction dummyNormalTransaction
377+
378+
-- | The block item for 'dummyUpdateInstruction'.
379+
dummyChainUpdateBI :: TransactionTime -> BlockItem
380+
dummyChainUpdateBI effTime = chainUpdate $ dummyUpdateInstruction effTime
381+
382+
-- | Test for transaction verification
383+
testTransactionVerification ::
384+
forall pv.
385+
(IsConsensusV1 pv, IsProtocolVersion pv, PVSupportsPLT pv) =>
386+
SProtocolVersion pv ->
387+
Spec
388+
testTransactionVerification _ = describe "transaction verification" $ do
389+
it "ChainUpdate: CreatePLT: Ok" $ do
390+
(verResult, _) <- runMyTestMonad @pv myIdentityProviders theTime $
391+
do
392+
t <- utcTimeToTimestamp <$> currentTime
393+
ctx <- getCtx
394+
verifyBlockItem t (dummyChainUpdateBI 0) ctx
395+
assertEqual
396+
"A correct transaction should be verified"
397+
(TVer.Ok TVer.ChainUpdateSuccess{keysHash = getHash (dummyKeyCollection @(AuthorizationsVersionFor pv)), seqNumber = 1})
398+
verResult
399+
it "ChainUpdate: CreatePLT: Non-zero effective time for CreatePLT" $ do
400+
(verResult, _) <- runMyTestMonad @pv myIdentityProviders theTime $
401+
do
402+
t <- utcTimeToTimestamp <$> currentTime
403+
ctx <- getCtx
404+
verifyBlockItem t (dummyChainUpdateBI 1) ctx
405+
assertEqual
406+
"A CreatePLT update with non-zero effective time should be rejected"
407+
(TVer.NotOk TVer.ChainUpdateEffectiveTimeNonZeroForCreatePLT)
408+
verResult
409+
where
410+
-- Create a context suitable for verifying a transaction within a 'Individual' context.
411+
getCtx = do
412+
_ctxBs <- bpState <$> gets' _lastFinalized
413+
let chainParams = dummyChainParameters @(ChainParametersVersionFor pv)
414+
let _ctxMaxBlockEnergy = chainParams ^. cpConsensusParameters . cpBlockEnergyLimit
415+
return $! Context{_ctxTransactionOrigin = TVer.Individual, ..}
416+
417+
theTime :: UTCTime
418+
theTime = posixSecondsToUTCTime 1 -- after genesis
353419

354420
-- | Testing various cases for processing a block item individually.
355421
testProcessBlockItem ::
@@ -384,7 +450,7 @@ testProcessBlockItem _ = describe "processBlockItem" $ do
384450
it "MaybeOk transaction" $ do
385451
-- We use a normal transfer transaction here with an invalid sender as it will yield a
386452
-- 'MaybeOk' verification result.
387-
(pbiRes, sd') <- runMyTestMonad @pv dummyIdentityProviders theTime (processBlockItem dummyTransactionBI)
453+
(pbiRes, sd') <- runMyTestMonad @pv dummyIdentityProviders theTime (processBlockItem dummyNormalTransactionBI)
388454
assertEqual
389455
"The credential deployment should be rejected (the identity provider has correct id but wrong keys used for the credential deployment)"
390456
(NotAdded $ TVer.MaybeOk $ TVer.NormalTransactionInvalidSender dummyAccountAddress)
@@ -454,7 +520,7 @@ testProcessBlockItems sProtocolVersion = describe "processBlockItems" $ do
454520
it "A non verifiable transaction first in the block makes it fail and stop processing the rest" $ do
455521
(processed, sd') <-
456522
runMyTestMonad dummyIdentityProviders theTime $
457-
processBlockItems (blockToProcess [dummyCredentialDeployment, dummyTransactionBI]) =<< _lastFinalized <$> get
523+
processBlockItems (blockToProcess [dummyCredentialDeployment, dummyNormalTransactionBI]) =<< _lastFinalized <$> get
458524
assertBool
459525
"Block should not have been successfully processed"
460526
(null processed)
@@ -465,7 +531,7 @@ testProcessBlockItems sProtocolVersion = describe "processBlockItems" $ do
465531
it "A non verifiable transaction last in the block makes it fail but the valid ones have been put into the state." $ do
466532
(processed, sd') <-
467533
runMyTestMonad dummyIdentityProviders theTime $
468-
processBlockItems (blockToProcess [dummyTransactionBI, dummyCredentialDeployment]) =<< _lastFinalized <$> get
534+
processBlockItems (blockToProcess [dummyNormalTransactionBI, dummyCredentialDeployment]) =<< _lastFinalized <$> get
469535
assertBool
470536
"Block should not have been successfully processed"
471537
(null processed)
@@ -476,7 +542,7 @@ testProcessBlockItems sProtocolVersion = describe "processBlockItems" $ do
476542
it "A block consisting of verifiable transactions only is accepted" $ do
477543
(processed, sd') <-
478544
runMyTestMonad myIdentityProviders theTime $
479-
processBlockItems (blockToProcess [dummyTransactionBI, dummyCredentialDeployment]) =<< _lastFinalized <$> get
545+
processBlockItems (blockToProcess [dummyNormalTransactionBI, dummyCredentialDeployment]) =<< _lastFinalized <$> get
480546
assertBool
481547
"Block should have been successfully processed"
482548
(isJust processed)
@@ -550,3 +616,6 @@ tests = describe "KonsensusV1.TransactionProcessing" $ do
550616
testProcessBlockItem spv
551617
describe "Batch transaction processing" $ do
552618
testProcessBlockItems spv
619+
describe "P9" $ do
620+
describe "Transaction verification" $
621+
testTransactionVerification SP9

0 commit comments

Comments
 (0)