diff --git a/CHANGELOG.md b/CHANGELOG.md index 1aa4021551..14e7379293 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ of the consensus, at consensus version 1. - Update Rust version to 1.82. - Update GHC version to 9.6.6 (LTS-22.39). +- Add `GetScheduledReleaseAccounts` endpoint for querying the list of accounts that + have scheduled releases. +- Add `GetCooldownAccounts`, `GetPreCooldownAccounts` and `GetPrePreCooldownAccounts` + endpoints for querying the lists of accounts that have pending cooldowns in protocol + version 7 onwards. ## 7.0.5 diff --git a/concordium-base b/concordium-base index 58f871e57a..5cdba7ce64 160000 --- a/concordium-base +++ b/concordium-base @@ -1 +1 @@ -Subproject commit 58f871e57ab8543ae499d3cccc14ff7ce7b4842a +Subproject commit 5cdba7ce64f6f4c36f7b0bad10cb3f62a190fcbf diff --git a/concordium-consensus/lib.def b/concordium-consensus/lib.def index 77b1537b29..a3f4a45c56 100644 --- a/concordium-consensus/lib.def +++ b/concordium-consensus/lib.def @@ -56,6 +56,10 @@ EXPORTS getBlockTransactionEventsV2 getBlockSpecialEventsV2 getBlockPendingUpdatesV2 + getScheduledReleaseAccountsV2 + getCooldownAccountsV2 + getPreCooldownAccountsV2 + getPrePreCooldownAccountsV2 getNextUpdateSequenceNumbersV2 getBlockChainParametersV2 getBlockFinalizationSummaryV2 diff --git a/concordium-consensus/src-lib/Concordium/External/GRPC2.hs b/concordium-consensus/src-lib/Concordium/External/GRPC2.hs index dda04e65b4..1fb1655ca9 100644 --- a/concordium-consensus/src-lib/Concordium/External/GRPC2.hs +++ b/concordium-consensus/src-lib/Concordium/External/GRPC2.hs @@ -1,5 +1,6 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE NumericUnderscores #-} +{-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} @@ -147,12 +148,7 @@ getAccountListV2 :: Ptr Word8 -> FunPtr (Ptr SenderChannel -> Ptr Word8 -> Int64 -> IO Int32) -> IO Int64 -getAccountListV2 cptr channel blockType blockHashPtr outHash cbk = do - Ext.ConsensusRunner mvr <- deRefStablePtr cptr - let sender = callChannelSendCallback cbk - bhi <- decodeBlockHashInput blockType blockHashPtr - response <- runMVR (Q.getAccountList bhi) mvr - returnStreamWithBlock (sender channel) outHash response +getAccountListV2 = blockStreamHelper Q.getAccountList getModuleListV2 :: StablePtr Ext.ConsensusRunner -> @@ -165,12 +161,7 @@ getModuleListV2 :: Ptr Word8 -> FunPtr (Ptr SenderChannel -> Ptr Word8 -> Int64 -> IO Int32) -> IO Int64 -getModuleListV2 cptr channel blockType blockHashPtr outHash cbk = do - Ext.ConsensusRunner mvr <- deRefStablePtr cptr - let sender = callChannelSendCallback cbk - bhi <- decodeBlockHashInput blockType blockHashPtr - response <- runMVR (Q.getModuleList bhi) mvr - returnStreamWithBlock (sender channel) outHash response +getModuleListV2 = blockStreamHelper Q.getModuleList getModuleSourceV2 :: StablePtr Ext.ConsensusRunner -> @@ -205,12 +196,7 @@ getInstanceListV2 :: Ptr Word8 -> FunPtr (Ptr SenderChannel -> Ptr Word8 -> Int64 -> IO Int32) -> IO Int64 -getInstanceListV2 cptr channel blockType blockHashPtr outHash cbk = do - Ext.ConsensusRunner mvr <- deRefStablePtr cptr - let sender = callChannelSendCallback cbk - bhi <- decodeBlockHashInput blockType blockHashPtr - response <- runMVR (Q.getInstanceList bhi) mvr - returnStreamWithBlock (sender channel) outHash response +getInstanceListV2 = blockStreamHelper Q.getInstanceList getInstanceInfoV2 :: StablePtr Ext.ConsensusRunner -> @@ -541,12 +527,7 @@ getBakerListV2 :: Ptr Word8 -> FunPtr ChannelSendCallback -> IO Int64 -getBakerListV2 cptr channel blockType blockHashPtr outHash cbk = do - Ext.ConsensusRunner mvr <- deRefStablePtr cptr - let sender = callChannelSendCallback cbk - bhi <- decodeBlockHashInput blockType blockHashPtr - response <- runMVR (Q.getRegisteredBakers bhi) mvr - returnStreamWithBlock (sender channel) outHash response +getBakerListV2 = blockStreamHelper Q.getRegisteredBakers getPoolInfoV2 :: StablePtr Ext.ConsensusRunner -> @@ -803,12 +784,7 @@ getIdentityProvidersV2 :: Ptr Word8 -> FunPtr ChannelSendCallback -> IO Int64 -getIdentityProvidersV2 cptr channel blockType blockHashPtr outHash cbk = do - Ext.ConsensusRunner mvr <- deRefStablePtr cptr - let sender = callChannelSendCallback cbk - bhi <- decodeBlockHashInput blockType blockHashPtr - response <- runMVR (Q.getAllIdentityProviders bhi) mvr - returnStreamWithBlock (sender channel) outHash response +getIdentityProvidersV2 = blockStreamHelper Q.getAllIdentityProviders getAnonymityRevokersV2 :: StablePtr Ext.ConsensusRunner -> @@ -821,12 +797,7 @@ getAnonymityRevokersV2 :: Ptr Word8 -> FunPtr ChannelSendCallback -> IO Int64 -getAnonymityRevokersV2 cptr channel blockType blockHashPtr outHash cbk = do - Ext.ConsensusRunner mvr <- deRefStablePtr cptr - let sender = callChannelSendCallback cbk - bhi <- decodeBlockHashInput blockType blockHashPtr - response <- runMVR (Q.getAllAnonymityRevokers bhi) mvr - returnStreamWithBlock (sender channel) outHash response +getAnonymityRevokersV2 = blockStreamHelper Q.getAllAnonymityRevokers getAccountNonFinalizedTransactionsV2 :: StablePtr Ext.ConsensusRunner -> @@ -855,12 +826,7 @@ getBlockItemsV2 :: Ptr Word8 -> FunPtr ChannelSendCallback -> IO Int64 -getBlockItemsV2 cptr channel blockType blockHashPtr outHash cbk = do - Ext.ConsensusRunner mvr <- deRefStablePtr cptr - let sender = callChannelSendCallback cbk - bhi <- decodeBlockHashInput blockType blockHashPtr - response <- runMVR (Q.getBlockItems bhi) mvr - returnStreamWithBlock (sender channel) outHash response +getBlockItemsV2 = blockStreamHelper Q.getBlockItems getBlockTransactionEventsV2 :: StablePtr Ext.ConsensusRunner -> @@ -918,12 +884,7 @@ getBlockPendingUpdatesV2 :: Ptr Word8 -> FunPtr ChannelSendCallback -> IO Int64 -getBlockPendingUpdatesV2 cptr channel blockType blockHashPtr outHash cbk = do - Ext.ConsensusRunner mvr <- deRefStablePtr cptr - let sender = callChannelSendCallback cbk - bhi <- decodeBlockHashInput blockType blockHashPtr - response <- runMVR (Q.getBlockPendingUpdates bhi) mvr - returnStreamWithBlock (sender channel) outHash response +getBlockPendingUpdatesV2 = blockStreamHelper Q.getBlockPendingUpdates getNextUpdateSequenceNumbersV2 :: StablePtr Ext.ConsensusRunner -> @@ -944,6 +905,58 @@ getNextUpdateSequenceNumbersV2 cptr blockType blockHashPtr outHash outVec copier result <- runMVR (Q.getNextUpdateSequenceNumbers bhi) mvr returnMessageWithBlock (copier outVec) outHash result +getScheduledReleaseAccountsV2 :: + StablePtr Ext.ConsensusRunner -> + Ptr SenderChannel -> + -- | Block type. + Word8 -> + -- | Block hash. + Ptr Word8 -> + -- | Out pointer for writing the block hash that was used. + Ptr Word8 -> + FunPtr ChannelSendCallback -> + IO Int64 +getScheduledReleaseAccountsV2 = blockStreamHelper Q.getScheduledReleaseAccounts + +getCooldownAccountsV2 :: + StablePtr Ext.ConsensusRunner -> + Ptr SenderChannel -> + -- | Block type. + Word8 -> + -- | Block hash. + Ptr Word8 -> + -- | Out pointer for writing the block hash that was used. + Ptr Word8 -> + FunPtr ChannelSendCallback -> + IO Int64 +getCooldownAccountsV2 = blockStreamHelper Q.getCooldownAccounts + +getPreCooldownAccountsV2 :: + StablePtr Ext.ConsensusRunner -> + Ptr SenderChannel -> + -- | Block type. + Word8 -> + -- | Block hash. + Ptr Word8 -> + -- | Out pointer for writing the block hash that was used. + Ptr Word8 -> + FunPtr ChannelSendCallback -> + IO Int64 +getPreCooldownAccountsV2 = blockStreamHelper Q.getPreCooldownAccounts + +getPrePreCooldownAccountsV2 :: + StablePtr Ext.ConsensusRunner -> + Ptr SenderChannel -> + -- | Block type. + Word8 -> + -- | Block hash. + Ptr Word8 -> + -- | Out pointer for writing the block hash that was used. + Ptr Word8 -> + FunPtr ChannelSendCallback -> + IO Int64 +getPrePreCooldownAccountsV2 = blockStreamHelper Q.getPrePreCooldownAccounts + getBlockChainParametersV2 :: StablePtr Ext.ConsensusRunner -> -- | Block type. @@ -1130,6 +1143,32 @@ returnMessageRaw copier v = do BS.unsafeUseAsCStringLen encoded (\(ptr, len) -> copier (castPtr ptr) (fromIntegral len)) return $ queryResultCode QRSuccess +-- | A helper for defining queries that take a block hash input and return a stream of +-- protobuf messages. +blockStreamHelper :: + (Proto.Message (Output a), ToProto a) => + -- | Wrapped query function. + (forall finconf. BlockHashInput -> MVR finconf (Q.BHIQueryResponse [a])) -> + -- | Consensus pointer. + StablePtr Ext.ConsensusRunner -> + -- | Channel to send messages to. + Ptr SenderChannel -> + -- | Block type. + Word8 -> + -- | Block hash. + Ptr Word8 -> + -- | Out pointer for writing the block hash that was used. + Ptr Word8 -> + -- | Callback to output data to the channel. + FunPtr ChannelSendCallback -> + IO Int64 +blockStreamHelper query cptr channel blockType blockHashPtr outHash cbk = do + Ext.ConsensusRunner mvr <- deRefStablePtr cptr + let sender = callChannelSendCallback cbk + bhi <- decodeBlockHashInput blockType blockHashPtr + response <- runMVR (query bhi) mvr + returnStreamWithBlock (sender channel) outHash response + returnStreamWithBlock :: (Proto.Message (Output a), ToProto a) => (Ptr Word8 -> Int64 -> IO Int32) -> @@ -1667,6 +1706,58 @@ foreign export ccall FunPtr CopyToVecCallback -> IO Int64 +foreign export ccall + getScheduledReleaseAccountsV2 :: + StablePtr Ext.ConsensusRunner -> + Ptr SenderChannel -> + -- | Block type. + Word8 -> + -- | Block hash. + Ptr Word8 -> + -- | Out pointer for writing the block hash that was used. + Ptr Word8 -> + FunPtr ChannelSendCallback -> + IO Int64 + +foreign export ccall + getCooldownAccountsV2 :: + StablePtr Ext.ConsensusRunner -> + Ptr SenderChannel -> + -- | Block type. + Word8 -> + -- | Block hash. + Ptr Word8 -> + -- | Out pointer for writing the block hash that was used. + Ptr Word8 -> + FunPtr ChannelSendCallback -> + IO Int64 + +foreign export ccall + getPreCooldownAccountsV2 :: + StablePtr Ext.ConsensusRunner -> + Ptr SenderChannel -> + -- | Block type. + Word8 -> + -- | Block hash. + Ptr Word8 -> + -- | Out pointer for writing the block hash that was used. + Ptr Word8 -> + FunPtr ChannelSendCallback -> + IO Int64 + +foreign export ccall + getPrePreCooldownAccountsV2 :: + StablePtr Ext.ConsensusRunner -> + Ptr SenderChannel -> + -- | Block type. + Word8 -> + -- | Block hash. + Ptr Word8 -> + -- | Out pointer for writing the block hash that was used. + Ptr Word8 -> + FunPtr ChannelSendCallback -> + IO Int64 + foreign export ccall getBlockChainParametersV2 :: StablePtr Ext.ConsensusRunner -> diff --git a/concordium-consensus/src/Concordium/GlobalState/BlockState.hs b/concordium-consensus/src/Concordium/GlobalState/BlockState.hs index 4abf69dc47..fd2b2c9a5c 100644 --- a/concordium-consensus/src/Concordium/GlobalState/BlockState.hs +++ b/concordium-consensus/src/Concordium/GlobalState/BlockState.hs @@ -663,6 +663,18 @@ class (ContractStateOperations m, AccountOperations m, ModuleQuery m) => BlockSt BlockState m -> m PassiveDelegationStatus + -- | Get the index of accounts with scheduled releases. + getScheduledReleaseAccounts :: BlockState m -> m (Map.Map Timestamp (Set.Set AccountIndex)) + + -- | Get the index of accounts with stake in cooldown. + getCooldownAccounts :: BlockState m -> m (Map.Map Timestamp (Set.Set AccountIndex)) + + -- | Get the index of accounts in pre-cooldown. + getPreCooldownAccounts :: BlockState m -> m [AccountIndex] + + -- | Get the index of accounts in pre-pre-cooldown. + getPrePreCooldownAccounts :: BlockState m -> m [AccountIndex] + -- | Distribution of newly-minted GTU. data MintAmounts = MintAmounts { -- | Minted amount allocated to the BakingRewardAccount @@ -1669,6 +1681,10 @@ instance (Monad (t m), MonadTrans t, BlockStateQuery m) => BlockStateQuery (MGST getPaydayEpoch = lift . getPaydayEpoch getPoolStatus s = lift . getPoolStatus s getPassiveDelegationStatus = lift . getPassiveDelegationStatus + getScheduledReleaseAccounts = lift . getScheduledReleaseAccounts + getCooldownAccounts = lift . getCooldownAccounts + getPreCooldownAccounts = lift . getPreCooldownAccounts + getPrePreCooldownAccounts = lift . getPrePreCooldownAccounts {-# INLINE getModule #-} {-# INLINE getAccount #-} {-# INLINE accountExists #-} @@ -1703,6 +1719,10 @@ instance (Monad (t m), MonadTrans t, BlockStateQuery m) => BlockStateQuery (MGST {-# INLINE getUpdateKeysCollection #-} {-# INLINE getExchangeRates #-} {-# INLINE getChainParameters #-} + {-# INLINE getScheduledReleaseAccounts #-} + {-# INLINE getCooldownAccounts #-} + {-# INLINE getPreCooldownAccounts #-} + {-# INLINE getPrePreCooldownAccounts #-} instance (Monad (t m), MonadTrans t, AccountOperations m) => AccountOperations (MGSTrans t m) where getAccountCanonicalAddress = lift . getAccountCanonicalAddress diff --git a/concordium-consensus/src/Concordium/GlobalState/Persistent/BlockState.hs b/concordium-consensus/src/Concordium/GlobalState/Persistent/BlockState.hs index ef5b872b8c..be7e964934 100644 --- a/concordium-consensus/src/Concordium/GlobalState/Persistent/BlockState.hs +++ b/concordium-consensus/src/Concordium/GlobalState/Persistent/BlockState.hs @@ -4118,6 +4118,59 @@ doSetRewardAccounts pbs rewards = do bsp <- loadPBS pbs storePBS pbs bsp{bspBank = bspBank bsp & unhashed . Rewards.rewardAccounts .~ rewards} +-- | Get the index of accounts with scheduled releases. +doGetScheduledReleaseAccounts :: (SupportsPersistentState pv m) => PersistentBlockState pv -> m (Map.Map Timestamp (Set.Set AccountIndex)) +doGetScheduledReleaseAccounts pbs = do + bsp <- loadPBS pbs + let resolveAddress addr = do + mIndex <- Accounts.getAccountIndex addr (bspAccounts bsp) + case mIndex of + Just index -> return index + Nothing -> error "Invariant violation: account address not found" + releasesMap resolveAddress (bspReleaseSchedule bsp) + +-- | Get the index of accounts with stake in cooldown. +doGetCooldownAccounts :: + forall pv m. + (SupportsPersistentState pv m) => + PersistentBlockState pv -> + m (Map.Map Timestamp (Set.Set AccountIndex)) +doGetCooldownAccounts pbs = case sSupportsFlexibleCooldown sav of + STrue -> do + bsp <- loadPBS pbs + newReleasesMap (bspAccountsInCooldown bsp ^. accountsInCooldown . cooldown) + SFalse -> return Map.empty + where + sav = sAccountVersionFor (protocolVersion @pv) + +-- | Get the index of accounts in pre-cooldown. +doGetPreCooldownAccounts :: + forall pv m. + (SupportsPersistentState pv m) => + PersistentBlockState pv -> + m [AccountIndex] +doGetPreCooldownAccounts pbs = case sSupportsFlexibleCooldown sav of + STrue -> do + bsp <- loadPBS pbs + loadAccountList $ bspAccountsInCooldown bsp ^. accountsInCooldown . preCooldown + SFalse -> return [] + where + sav = sAccountVersionFor (protocolVersion @pv) + +-- | Get the index of accounts in pre-pre-cooldown. +doGetPrePreCooldownAccounts :: + forall pv m. + (SupportsPersistentState pv m) => + PersistentBlockState pv -> + m [AccountIndex] +doGetPrePreCooldownAccounts pbs = case sSupportsFlexibleCooldown sav of + STrue -> do + bsp <- loadPBS pbs + loadAccountList $ bspAccountsInCooldown bsp ^. accountsInCooldown . prePreCooldown + SFalse -> return [] + where + sav = sAccountVersionFor (protocolVersion @pv) + -- | Context that supports the persistent block state. data PersistentBlockStateContext pv = PersistentBlockStateContext { -- | The 'BlobStore' used for storing the persistent state. @@ -4251,6 +4304,10 @@ instance (IsProtocolVersion pv, PersistentState av pv r m) => BlockStateQuery (P getPaydayEpoch = doGetPaydayEpoch . hpbsPointers getPoolStatus = doGetPoolStatus . hpbsPointers getPassiveDelegationStatus = doGetPassiveDelegationStatus . hpbsPointers + getScheduledReleaseAccounts = doGetScheduledReleaseAccounts . hpbsPointers + getCooldownAccounts = doGetCooldownAccounts . hpbsPointers + getPreCooldownAccounts = doGetPreCooldownAccounts . hpbsPointers + getPrePreCooldownAccounts = doGetPrePreCooldownAccounts . hpbsPointers instance (MonadIO m, PersistentState av pv r m) => ContractStateOperations (PersistentBlockStateMonad pv r m) where thawContractState (Instances.InstanceStateV0 inst) = return inst diff --git a/concordium-consensus/src/Concordium/GlobalState/Persistent/ReleaseSchedule.hs b/concordium-consensus/src/Concordium/GlobalState/Persistent/ReleaseSchedule.hs index 51a9c7140d..6eb00344a0 100644 --- a/concordium-consensus/src/Concordium/GlobalState/Persistent/ReleaseSchedule.hs +++ b/concordium-consensus/src/Concordium/GlobalState/Persistent/ReleaseSchedule.hs @@ -426,6 +426,9 @@ releasesMap :: releasesMap resolveAddr (ReleaseScheduleP0 rsRef) = do LegacyReleaseSchedule{..} <- refLoad rsRef forM lrsMap $ fmap Set.fromList . mapM resolveAddr . Set.toList -releasesMap _ (ReleaseScheduleP5 rs) = do +releasesMap _ (ReleaseScheduleP5 rs) = newReleasesMap rs + +newReleasesMap :: (MonadBlobStore m) => NewReleaseSchedule -> m (Map Timestamp (Set AccountIndex)) +newReleasesMap rs = do m <- Trie.toMap (nrsMap rs) return (theAccountSet <$> m) diff --git a/concordium-consensus/src/Concordium/Queries.hs b/concordium-consensus/src/Concordium/Queries.hs index 203f89af42..8226573488 100644 --- a/concordium-consensus/src/Concordium/Queries.hs +++ b/concordium-consensus/src/Concordium/Queries.hs @@ -934,6 +934,46 @@ getNextUpdateSequenceNumbers = liftSkovQueryStateBHI query updates <- BS.getUpdates bs return $ updateQueuesNextSequenceNumbers $ UQ._pendingUpdates updates +-- | Get the index of accounts with scheduled releases. +getScheduledReleaseAccounts :: + forall finconf. + BlockHashInput -> + MVR finconf (BHIQueryResponse [AccountPending]) +getScheduledReleaseAccounts = liftSkovQueryStateBHI query + where + query bs = do + releases <- BS.getScheduledReleaseAccounts bs + let processAtTimestamp ts accs = ([AccountPending acc ts | acc <- Set.toList accs] ++) + return $ Map.foldrWithKey processAtTimestamp [] releases + +-- | Get the index of accounts with stake in cooldown. +getCooldownAccounts :: + forall finconf. + BlockHashInput -> + MVR finconf (BHIQueryResponse [AccountPending]) +getCooldownAccounts = liftSkovQueryStateBHI query + where + query bs = do + cooldowns <- BS.getCooldownAccounts bs + let processAtTimestamp ts accs = ([AccountPending acc ts | acc <- Set.toList accs] ++) + -- Right-fold here ensures that the set at each timestamp is converted lazily as + -- the resulting list is consumed. + return $ Map.foldrWithKey processAtTimestamp [] cooldowns + +-- | Get the index of accounts in pre-cooldown. +getPreCooldownAccounts :: + forall finconf. + BlockHashInput -> + MVR finconf (BHIQueryResponse [AccountIndex]) +getPreCooldownAccounts = liftSkovQueryStateBHI BS.getPreCooldownAccounts + +-- | Get the index of accounts in pre-pre-cooldown. +getPrePreCooldownAccounts :: + forall finconf. + BlockHashInput -> + MVR finconf (BHIQueryResponse [AccountIndex]) +getPrePreCooldownAccounts = liftSkovQueryStateBHI BS.getPrePreCooldownAccounts + -- | Get the total amount of CCD in existence and status of the reward accounts. getRewardStatus :: BlockHashInput -> MVR finconf (BHIQueryResponse RewardStatus) getRewardStatus = diff --git a/concordium-node/build.rs b/concordium-node/build.rs index aa4e63862b..5d97869b11 100644 --- a/concordium-node/build.rs +++ b/concordium-node/build.rs @@ -495,6 +495,46 @@ fn build_grpc2(proto_root_input: &str) -> std::io::Result<()> { .codec_path("crate::grpc2::RawCodec") .build(), ) + .method( + tonic_build::manual::Method::builder() + .name("get_scheduled_release_accounts") + .route_name("GetScheduledReleaseAccounts") + .input_type("crate::grpc2::types::BlockHashInput") + .output_type("Vec") + .codec_path("crate::grpc2::RawCodec") + .server_streaming() + .build(), + ) + .method( + tonic_build::manual::Method::builder() + .name("get_cooldown_accounts") + .route_name("GetCooldownAccounts") + .input_type("crate::grpc2::types::BlockHashInput") + .output_type("Vec") + .codec_path("crate::grpc2::RawCodec") + .server_streaming() + .build(), + ) + .method( + tonic_build::manual::Method::builder() + .name("get_pre_cooldown_accounts") + .route_name("GetPreCooldownAccounts") + .input_type("crate::grpc2::types::BlockHashInput") + .output_type("Vec") + .codec_path("crate::grpc2::RawCodec") + .server_streaming() + .build(), + ) + .method( + tonic_build::manual::Method::builder() + .name("get_pre_pre_cooldown_accounts") + .route_name("GetPrePreCooldownAccounts") + .input_type("crate::grpc2::types::BlockHashInput") + .output_type("Vec") + .codec_path("crate::grpc2::RawCodec") + .server_streaming() + .build(), + ) .method( tonic_build::manual::Method::builder() .name("get_baker_earliest_win_time") diff --git a/concordium-node/src/consensus_ffi/ffi.rs b/concordium-node/src/consensus_ffi/ffi.rs index 18ebeb0705..da09968d11 100644 --- a/concordium-node/src/consensus_ffi/ffi.rs +++ b/concordium-node/src/consensus_ffi/ffi.rs @@ -1299,6 +1299,107 @@ extern "C" { copier: CopyToVecCallback, ) -> i64; + /// Get all accounts that have scheduled releases, with the timestamp of the + /// first pending scheduled release for that account. + /// The stream will end when all the accounts that have scheduled releases + /// have been returned. + /// + /// * `consensus` - Pointer to the current consensus. + /// * `stream` - Pointer to the response stream. + /// * `block_id_type` - Type of block identifier. + /// * `block_id` - Location with the block identifier. Length must match the + /// corresponding type of block identifier. + /// * `out_hash` - Location to write the block hash used in the query. + /// * `callback` - Callback for writing to the response stream. + pub fn getScheduledReleaseAccountsV2( + consensus: *mut consensus_runner, + stream: *mut futures::channel::mpsc::Sender, tonic::Status>>, + block_id_type: u8, + block_id: *const u8, + out_hash: *mut u8, + callback: extern "C" fn( + *mut futures::channel::mpsc::Sender, tonic::Status>>, + *const u8, + i64, + ) -> i32, + ) -> i64; + + /// Get all accounts that have stake in cooldown, with the timestamp of the + /// first pending cooldown expiry for each account. + /// The stream will end when all the accounts that have stake in cooldown + /// have been returned. + /// Prior to protocol version 7, the resulting stream will always be empty. + /// + /// * `consensus` - Pointer to the current consensus. + /// * `stream` - Pointer to the response stream. + /// * `block_id_type` - Type of block identifier. + /// * `block_id` - Location with the block identifier. Length must match the + /// corresponding type of block identifier. + /// * `out_hash` - Location to write the block hash used in the query. + /// * `callback` - Callback for writing to the response stream. + pub fn getCooldownAccountsV2( + consensus: *mut consensus_runner, + stream: *mut futures::channel::mpsc::Sender, tonic::Status>>, + block_id_type: u8, + block_id: *const u8, + out_hash: *mut u8, + callback: extern "C" fn( + *mut futures::channel::mpsc::Sender, tonic::Status>>, + *const u8, + i64, + ) -> i32, + ) -> i64; + + /// Get all accounts (by account index) that have stake in pre-cooldown. + /// The stream will end when all the accounts that have stake in + /// pre-cooldown have been returned. + /// Prior to protocol version 7, the resulting stream will always be empty. + /// + /// * `consensus` - Pointer to the current consensus. + /// * `stream` - Pointer to the response stream. + /// * `block_id_type` - Type of block identifier. + /// * `block_id` - Location with the block identifier. Length must match the + /// corresponding type of block identifier. + /// * `out_hash` - Location to write the block hash used in the query. + /// * `callback` - Callback for writing to the response stream. + pub fn getPreCooldownAccountsV2( + consensus: *mut consensus_runner, + stream: *mut futures::channel::mpsc::Sender, tonic::Status>>, + block_id_type: u8, + block_id: *const u8, + out_hash: *mut u8, + callback: extern "C" fn( + *mut futures::channel::mpsc::Sender, tonic::Status>>, + *const u8, + i64, + ) -> i32, + ) -> i64; + + /// Get all accounts (by account index) that have stake in pre-pre-cooldown. + /// The stream will end when all the accounts that have stake in + /// pre-pre-cooldown have been returned. + /// Prior to protocol version 7, the resulting stream will always be empty. + /// + /// * `consensus` - Pointer to the current consensus. + /// * `stream` - Pointer to the response stream. + /// * `block_id_type` - Type of block identifier. + /// * `block_id` - Location with the block identifier. Length must match the + /// corresponding type of block identifier. + /// * `out_hash` - Location to write the block hash used in the query. + /// * `callback` - Callback for writing to the response stream. + pub fn getPrePreCooldownAccountsV2( + consensus: *mut consensus_runner, + stream: *mut futures::channel::mpsc::Sender, tonic::Status>>, + block_id_type: u8, + block_id: *const u8, + out_hash: *mut u8, + callback: extern "C" fn( + *mut futures::channel::mpsc::Sender, tonic::Status>>, + *const u8, + i64, + ) -> i32, + ) -> i64; + /// Get the chain parameters that are in effect in the given block. /// /// * `consensus` - Pointer to the current consensus. @@ -3200,6 +3301,121 @@ impl ConsensusContainer { Ok((out_hash, out_data)) } + /// Get accounts with scheduled releases at the end of a given block. + /// The stream will end when all accounts with scheduled releases have been + /// returned. + pub fn get_scheduled_release_accounts_v2( + &self, + request: &crate::grpc2::types::BlockHashInput, + sender: futures::channel::mpsc::Sender, tonic::Status>>, + ) -> Result<[u8; 32], tonic::Status> { + use crate::grpc2::Require; + let sender = Box::new(sender); + let consensus = self.consensus.load(Ordering::SeqCst); + let mut buf = [0u8; 32]; + let bhi = crate::grpc2::types::block_hash_input_to_ffi(request).require()?; + let (block_id_type, block_hash) = bhi.to_ptr(); + let response: ConsensusQueryResponse = unsafe { + getScheduledReleaseAccountsV2( + consensus, + Box::into_raw(sender), + block_id_type, + block_hash.as_ptr(), + buf.as_mut_ptr(), + enqueue_bytearray_callback, + ) + } + .try_into()?; + response.ensure_ok("block")?; + Ok(buf) + } + + /// Get accounts in cooldown at the end of a given block. + /// The stream will end when all accounts in cooldown have been returned. + pub fn get_cooldown_accounts_v2( + &self, + request: &crate::grpc2::types::BlockHashInput, + sender: futures::channel::mpsc::Sender, tonic::Status>>, + ) -> Result<[u8; 32], tonic::Status> { + use crate::grpc2::Require; + let sender = Box::new(sender); + let consensus = self.consensus.load(Ordering::SeqCst); + let mut buf = [0u8; 32]; + let bhi = crate::grpc2::types::block_hash_input_to_ffi(request).require()?; + let (block_id_type, block_hash) = bhi.to_ptr(); + let response: ConsensusQueryResponse = unsafe { + getCooldownAccountsV2( + consensus, + Box::into_raw(sender), + block_id_type, + block_hash.as_ptr(), + buf.as_mut_ptr(), + enqueue_bytearray_callback, + ) + } + .try_into()?; + response.ensure_ok("block")?; + Ok(buf) + } + + /// Get accounts in pre-cooldown at the end of a given block. + /// The stream will end when all accounts in pre-cooldown have been + /// returned. + pub fn get_pre_cooldown_accounts_v2( + &self, + request: &crate::grpc2::types::BlockHashInput, + sender: futures::channel::mpsc::Sender, tonic::Status>>, + ) -> Result<[u8; 32], tonic::Status> { + use crate::grpc2::Require; + let sender = Box::new(sender); + let consensus = self.consensus.load(Ordering::SeqCst); + let mut buf = [0u8; 32]; + let bhi = crate::grpc2::types::block_hash_input_to_ffi(request).require()?; + let (block_id_type, block_hash) = bhi.to_ptr(); + let response: ConsensusQueryResponse = unsafe { + getPreCooldownAccountsV2( + consensus, + Box::into_raw(sender), + block_id_type, + block_hash.as_ptr(), + buf.as_mut_ptr(), + enqueue_bytearray_callback, + ) + } + .try_into()?; + response.ensure_ok("block")?; + Ok(buf) + } + + /// Get accounts in pre-pre-cooldown at the end of a given block. + /// The stream will end when all accounts in pre-pre-cooldown have been + /// returned. + pub fn get_pre_pre_cooldown_accounts_v2( + &self, + request: &crate::grpc2::types::BlockHashInput, + sender: futures::channel::mpsc::Sender, tonic::Status>>, + ) -> Result<[u8; 32], tonic::Status> { + use crate::grpc2::Require; + let sender = Box::new(sender); + let consensus = self.consensus.load(Ordering::SeqCst); + let mut buf = [0u8; 32]; + let bhi = crate::grpc2::types::block_hash_input_to_ffi(request).require()?; + let (block_id_type, block_hash) = bhi.to_ptr(); + let response: ConsensusQueryResponse = unsafe { + getPrePreCooldownAccountsV2( + consensus, + Box::into_raw(sender), + block_id_type, + block_hash.as_ptr(), + buf.as_mut_ptr(), + enqueue_bytearray_callback, + ) + } + .try_into()?; + response.ensure_ok("block")?; + Ok(buf) + } + /// Get chain parameters for the given block. pub fn get_block_chain_parameters_v2( &self, diff --git a/concordium-node/src/grpc2.rs b/concordium-node/src/grpc2.rs index d726a31ad9..2c8206e87e 100644 --- a/concordium-node/src/grpc2.rs +++ b/concordium-node/src/grpc2.rs @@ -676,6 +676,14 @@ struct ServiceConfig { #[serde(default)] get_next_update_sequence_numbers: bool, #[serde(default)] + get_scheduled_release_accounts: bool, + #[serde(default)] + get_cooldown_accounts: bool, + #[serde(default)] + get_pre_cooldown_accounts: bool, + #[serde(default)] + get_pre_pre_cooldown_accounts: bool, + #[serde(default)] get_block_chain_parameters: bool, #[serde(default)] get_block_finalization_summary: bool, @@ -758,6 +766,10 @@ impl ServiceConfig { get_block_special_events: true, get_block_pending_updates: true, get_next_update_sequence_numbers: true, + get_scheduled_release_accounts: true, + get_cooldown_accounts: true, + get_pre_cooldown_accounts: true, + get_pre_pre_cooldown_accounts: true, get_block_chain_parameters: true, get_block_finalization_summary: true, shutdown: true, @@ -1342,6 +1354,9 @@ pub mod server { /// Return type for the 'Blocks' method. type GetBlocksStream = tokio_stream::wrappers::ReceiverStream, tonic::Status>>; + /// Return type for the 'GetCooldownAccounts' method. + type GetCooldownAccountsStream = + futures::channel::mpsc::Receiver, tonic::Status>>; /// Return type for the 'FinalizedBlocks' method. type GetFinalizedBlocksStream = tokio_stream::wrappers::ReceiverStream, tonic::Status>>; @@ -1369,6 +1384,15 @@ pub mod server { /// Return type for the 'GetPoolDelegators' method. type GetPoolDelegatorsStream = futures::channel::mpsc::Receiver, tonic::Status>>; + /// Return type for the 'GetPreCooldownAccounts' method. + type GetPreCooldownAccountsStream = + futures::channel::mpsc::Receiver, tonic::Status>>; + /// Return type for the 'GetPrePreCooldowneleaseAccounts' method. + type GetPrePreCooldownAccountsStream = + futures::channel::mpsc::Receiver, tonic::Status>>; + /// Return type for the 'GetScheduledReleaseAccounts' method. + type GetScheduledReleaseAccountsStream = + futures::channel::mpsc::Receiver, tonic::Status>>; /// Return type for the 'GetWinningBakersEpoch' method. type GetWinningBakersEpochStream = futures::channel::mpsc::Receiver, tonic::Status>>; @@ -2101,6 +2125,85 @@ pub mod server { Ok(response) } + async fn get_scheduled_release_accounts( + &self, + request: tonic::Request, + ) -> Result, tonic::Status> + { + if !self.service_config.get_scheduled_release_accounts { + return Err(tonic::Status::unimplemented( + "`GetScheduledReleaseAccounts` is not enabled.", + )); + } + let (sender, receiver) = futures::channel::mpsc::channel(10); + let hash = self + .run_blocking(move |consensus| { + consensus.get_scheduled_release_accounts_v2(request.get_ref(), sender) + }) + .await?; + let mut response = tonic::Response::new(receiver); + add_hash(&mut response, hash)?; + Ok(response) + } + + async fn get_cooldown_accounts( + &self, + request: tonic::Request, + ) -> Result, tonic::Status> { + if !self.service_config.get_cooldown_accounts { + return Err(tonic::Status::unimplemented("`GetCooldownAccounts` is not enabled.")); + } + let (sender, receiver) = futures::channel::mpsc::channel(10); + let hash = self + .run_blocking(move |consensus| { + consensus.get_cooldown_accounts_v2(request.get_ref(), sender) + }) + .await?; + let mut response = tonic::Response::new(receiver); + add_hash(&mut response, hash)?; + Ok(response) + } + + async fn get_pre_cooldown_accounts( + &self, + request: tonic::Request, + ) -> Result, tonic::Status> { + if !self.service_config.get_pre_cooldown_accounts { + return Err(tonic::Status::unimplemented( + "`GetPreCooldownAccounts` is not enabled.", + )); + } + let (sender, receiver) = futures::channel::mpsc::channel(10); + let hash = self + .run_blocking(move |consensus| { + consensus.get_pre_cooldown_accounts_v2(request.get_ref(), sender) + }) + .await?; + let mut response = tonic::Response::new(receiver); + add_hash(&mut response, hash)?; + Ok(response) + } + + async fn get_pre_pre_cooldown_accounts( + &self, + request: tonic::Request, + ) -> Result, tonic::Status> { + if !self.service_config.get_pre_pre_cooldown_accounts { + return Err(tonic::Status::unimplemented( + "`GetPrePreCooldownAccounts` is not enabled.", + )); + } + let (sender, receiver) = futures::channel::mpsc::channel(10); + let hash = self + .run_blocking(move |consensus| { + consensus.get_pre_pre_cooldown_accounts_v2(request.get_ref(), sender) + }) + .await?; + let mut response = tonic::Response::new(receiver); + add_hash(&mut response, hash)?; + Ok(response) + } + async fn get_block_chain_parameters( &self, request: tonic::Request, diff --git a/docs/grpc2.md b/docs/grpc2.md index 26d412ef9b..180a37cd17 100644 --- a/docs/grpc2.md +++ b/docs/grpc2.md @@ -87,6 +87,10 @@ If these are enabled then the following options become available get_block_special_events = true get_block_pending_updates = true get_next_update_sequence_numbers = true + get_scheduled_release_accounts = true + get_cooldown_accounts = true + get_pre_cooldown_accounts = true + get_pre_pre_cooldown_accounts = true get_block_chain_parameters = true get_block_finalization_summary = true get_baker_earliest_win_time = true