Skip to content

Commit 2d1eb1a

Browse files
authored
Merge pull request #1330 from Concordium/fix-1329
Correctly construct account difference map for certified blocks
2 parents 5dcc2b4 + ed37fed commit 2d1eb1a

File tree

4 files changed

+35
-4
lines changed

4 files changed

+35
-4
lines changed

CHANGELOG.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
# Changelog
22

33
## Unreleased changes
4+
45
- Replace `BufferedRef` with `HashedBufferedRef` in `PoolRewards`
56
`bakerPoolRewardDetails::LFMBTree` field to cache computed hashes.
6-
77
- Improvements to the loading of modules. This particularly improves the performance of
88
`GetModuleSource` in certain cases, and can also reduce start-up time.
9+
- Fix a bug that affects setting up the account map correctly for non-finalized certified blocks
10+
that contain account creations (#1329).
911

1012
## 8.0.3
1113

concordium-consensus/src/Concordium/GlobalState/BlockState.hs

+2
Original file line numberDiff line numberDiff line change
@@ -1608,6 +1608,8 @@ class (BlockStateOperations m, FixedSizeSerialization (BlockStateRef m)) => Bloc
16081608
--
16091609
-- Preconditions:
16101610
-- * This function MUST only be called on a certified block.
1611+
-- * The block state MUST already be cached (with 'cacheBlockState'). Otherwise the update to
1612+
-- the difference map may not be retained.
16111613
-- * This function MUST only be called on a block state that does not already
16121614
-- have a difference map.
16131615
-- * The provided list of accounts MUST correspond to the accounts created in the block,

concordium-consensus/src/Concordium/GlobalState/Persistent/Accounts.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ mkNewChildDifferenceMap accts@Accounts{..} = do
173173
return accts{accountDiffMapRef = newDiffMapRef}
174174

175175
-- | Create and set the 'DiffMap.DifferenceMap' for the provided @Accounts pv@.
176-
-- This function constructs the difference map for the block such that the assoicated difference map
176+
-- This function constructs the difference map for the block such that the associated difference map
177177
-- and lmdb backed account map are consistent with the account table.
178178
--
179179
-- The function is highly unsafe and can cause state invariant failures if not all of the

concordium-consensus/src/Concordium/KonsensusV1/TreeState/StartUp.hs

+29-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import Concordium.Types.Updates
2525
import Concordium.Utils
2626

2727
import qualified Concordium.GlobalState.AccountMap.DifferenceMap as DiffMap
28-
import Concordium.GlobalState.BlockState
28+
import Concordium.GlobalState.BlockState as BlockState
2929
import Concordium.GlobalState.Parameters hiding (getChainParameters)
3030
import qualified Concordium.GlobalState.Persistent.BlockState as PBS
3131
import qualified Concordium.GlobalState.Statistics as Stats
@@ -436,6 +436,11 @@ loadCertifiedBlocks = do
436436
_ -> Nothing
437437
loadCertBlock (storedBlock, qc) loadedBlocks = do
438438
blockPointer <- mkBlockPointer storedBlock
439+
let bh = getHash @BlockHash blockPointer
440+
-- Cache the block state first, as this is required for reconstructing the account
441+
-- difference map.
442+
cacheBlockState (bpState blockPointer)
443+
439444
-- As only finalized accounts are stored in the account map, then
440445
-- we need to reconstruct the 'DiffMap.DifferenceMap' here for the certified block we're loading.
441446
let accountsToInsert = mapMaybe getAccountAddressFromDeployment (blockTransactions storedBlock)
@@ -456,7 +461,29 @@ loadCertifiedBlocks = do
456461
-- append to the accumulator with this new difference map reference
457462
let loadedBlocks' = HM.insert (getHash storedBlock) newDifferenceMap loadedBlocks
458463

459-
cacheBlockState (bpState blockPointer)
464+
-- Validate that the 'accountsToInsert' are now accessible.
465+
-- This should never fail, but it is worth verifying here since there are likely to be
466+
-- few such accounts and it is better to catch any bug here than end up with a corrupted
467+
-- account map.
468+
forM_ accountsToInsert $ \addr -> do
469+
BlockState.getAccount (bpState blockPointer) addr >>= \case
470+
Nothing ->
471+
throwM . TreeStateInvariantViolation $
472+
"Account "
473+
++ show addr
474+
++ " not found after loading certified block "
475+
++ show bh
476+
Just (_, acc) -> do
477+
actualAddr <- getAccountCanonicalAddress acc
478+
unless (actualAddr == addr) $
479+
throwM . TreeStateInvariantViolation $
480+
"Account address mismatch ("
481+
++ show actualAddr
482+
++ " != "
483+
++ show addr
484+
++ ") after loading certified block "
485+
++ show bh
486+
460487
blockTable . liveMap . at' (getHash blockPointer) ?=! blockPointer
461488
addToBranches blockPointer
462489
forM_ (blockTransactions blockPointer) $ \tr -> do

0 commit comments

Comments
 (0)