content: {-# LANGUAGE DataKinds #-}
  {-# LANGUAGE NumericUnderscores #-}
  {-# LANGUAGE RankNTypes #-}
  {-# LANGUAGE ScopedTypeVariables #-}
  {-# LANGUAGE TypeFamilies #-}
  
  -- | Part of the implementation of the GRPC2 interface. This module constructs
  --     responses to queries that are handled by the Haskell part of the code.
  --
  --    This module only provides foreign exports, and should not be imported from
  --    other Haskell code.
  module Concordium.External.GRPC2 () where
  
  import Concordium.GRPC2
  import Control.Concurrent
  import qualified Data.ByteString.Unsafe as BS
  import qualified Data.FixedByteString as FBS
  import Data.Foldable (toList)
  import Data.Functor
  import Data.Int
  import qualified Data.ProtoLens as Proto
  import qualified Data.ProtoLens.Combinators as Proto
  import qualified Data.Vector as Vec
  import Data.Word
  import Foreign
  import Lens.Micro.Platform
  import qualified Proto.V2.Concordium.Types as Proto
  import qualified Proto.V2.Concordium.Types_Fields as ProtoFields
  
  import qualified Concordium.GlobalState.ContractStateV1 as StateV1
  import qualified Concordium.Queries as Q
  import Concordium.Types
  
  import qualified Concordium.External as Ext
  import qualified Concordium.Logger as Logger
  import Concordium.MultiVersion (
      MVR (..),
      mvLog,
   )
  
  import Concordium.Crypto.SHA256 (Hash (Hash))
  import Concordium.External.Helpers
  import Concordium.GlobalState.Parameters (CryptographicParameters)
  import Concordium.ID.Parameters (withGlobalContext)
  import Concordium.Scheduler.ProtocolLevelTokens.Queries (QueryTokenInfoError (..))
  import qualified Concordium.Types.InvokeContract as InvokeContract
  import qualified Concordium.Wasm as Wasm
  
  -- | An opaque representation of a Rust vector. This is used by callbacks to copy
  --  the message generated by a query to Rust, so it can be forwarded back to the
  --  caller.
  data ReceiverVec
  
  -- | An opaque representation of Rust cryptographic parameters. This is used by callbacks to copy
  --  cryptographic parameters to Rust, so it can be forwarded back to the caller.
  data ReceiverCryptographicParameters
  
  -- | A type of callback that extends the given vector with the provided data.
  type CopyToVecCallback = Ptr ReceiverVec -> Ptr Word8 -> Int64 -> IO ()
  
  -- | A type of callback that extends the given vector with the provided data.
  type CopyCryptographicParametersCallback = Ptr ReceiverCryptographicParameters -> Ptr CryptographicParameters -> IO ()
  
  -- | An opaque representation of a channel to which streaming responses can write
  --  data. When a request is made to an endpoint with a streaming response then a
  --  channel is created in Rust code. One endpoint is passed to Haskell and the
  --  other end (the receiver) is kept by the request handler. Haskell code is
  --  meant to spawn a background thread that streams data into the channel, using
  --  the provided 'ChannelSendCallback' to write each item into the channel.
  data SenderChannel
  
  -- | The type of callbacks to enqueue the given data in the channel. The response
  --  code of 0 means data was successfully enqueued, 1 means that the channel is
  --  now full, so data was not enqueued. The sender should try again. Response of
  --  2 means the channel is dead. In this case the provided 'SenderChannel' is
  --  dropped, and the callback must not be invoked again.
  type ChannelSendCallback = Ptr SenderChannel -> Ptr Word8 -> Int64 -> IO Int32
  
  -- | Boilerplate wrapper to invoke C callbacks.
  foreign import ccall "dynamic" callChannelSendCallback :: FunPtr ChannelSendCallback -> ChannelSendCallback
  
  -- | Boilerplate wrapper to invoke C callbacks.
  foreign import ccall "dynamic" callCopyToVecCallback :: FunPtr CopyToVecCallback -> CopyToVecCallback
  
  -- | Boilerplate wrapper to invoke C callbacks.
  foreign import ccall "dynamic" callCopyCryptographicParametersCallback :: FunPtr CopyCryptographicParametersCallback -> CopyCryptographicParametersCallback
  
  -- | The result type of a gRPC2 query.
  data QueryResult
      = -- | An invalid argument was provided by the client.
        QRInvalidArgument
      | -- | An internal error occurred.
        QRInternalError
      | -- | The query succeeded.
        QRSuccess
      | -- | The requested data could not be found.
        QRNotFound
      | -- | The service is not available at the current protocol version.
        QRUnavailable
      | -- | The requested data is for a future epoch or genesis index.
        QRFutureEpoch
  
  -- | Convert a QueryResult to a result code.
  queryResultCode :: QueryResult -> Int64
  queryResultCode QRInvalidArgument = -2
  queryResultCode QRInternalError = -1
  queryResultCode QRSuccess = 0
  queryResultCode QRNotFound = 1
  queryResultCode QRUnavailable = 2
  queryResultCode QRFutureEpoch = 3
  
  getAccountInfoV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Identifier type, 0 for account address, 1 for credential, 2 for account index
      Word8 ->
      -- | Serialized identifier. Length determined by the type.
      Ptr Word8 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getAccountInfoV2 cptr blockType blockHashPtr accIdType accIdBytesPtr outHash outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      ai <- decodeAccountIdentifierInput accIdType accIdBytesPtr
      res <- runMVR (Q.getAccountInfo bhi ai) mvr
      returnMaybeMessageWithBlock (copier outVec) outHash res
  
  getTokenInfoV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Token ID.
      Ptr Word8 ->
      -- | Token ID length.
      Word8 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getTokenInfoV2 cptr blockType blockHashPtr tokenIdPtr tokenIdLen outHash outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      decodeTokenId tokenIdPtr tokenIdLen >>= \case
          Left _ -> return $ queryResultCode QRInvalidArgument
          Right tokenId -> do
              res <- runMVR (Q.getTokenInfo bhi tokenId) mvr
              case res of
                  Q.BQRBlock _ (Left QTIEUnknownToken) -> do
                      copyHashTo outHash res
                      return $ queryResultCode QRNotFound
                  Q.BQRBlock _ (Left e@QTIEInternal{}) -> do
                      mvLog mvr Logger.External Logger.LLError $
                          "Internal error processing GetTokenInfo: " ++ show e
                      return $ queryResultCode QRInternalError
                  Q.BQRBlock _ (Right r) ->
                      returnMessageWithBlock (copier outVec) outHash (res $> r)
                  Q.BQRNoBlock ->
                      return $ queryResultCode QRNotFound
  
  -- | Optionally copy a block hash (32 bytes) to a pointer.
  -- Used to provide back the block hash used in a given query, via the FFI.
  copyHashTo :: Ptr Word8 -> Q.BHIQueryResponse a -> IO ()
  copyHashTo _ Q.BQRNoBlock = return ()
  copyHashTo dest (Q.BQRBlock (BlockHash (Hash h)) _) = FBS.withPtrReadOnly h $ \p -> copyBytes dest p 32
  
  getAccountListV2 ::
      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 (Ptr SenderChannel -> Ptr Word8 -> Int64 -> IO Int32) ->
      IO Int64
  getAccountListV2 = blockStreamHelper Q.getAccountList
  
  getTokenListV2 ::
      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 (Ptr SenderChannel -> Ptr Word8 -> Int64 -> IO Int32) ->
      IO Int64
  getTokenListV2 = blockStreamHelper Q.getTokenList
  
  getModuleListV2 ::
      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 (Ptr SenderChannel -> Ptr Word8 -> Int64 -> IO Int32) ->
      IO Int64
  getModuleListV2 = blockStreamHelper Q.getModuleList
  
  getModuleSourceV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Module reference.
      Ptr Word8 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getModuleSourceV2 cptr blockType blockHashPtr moduleRefPtr outHash outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      modRef <- decodeModuleRefInput moduleRefPtr
      res <- runMVR (Q.getModuleSource bhi modRef) mvr
      returnMaybeMessageWithBlock (copier outVec) outHash res
  
  getInstanceListV2 ::
      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 (Ptr SenderChannel -> Ptr Word8 -> Int64 -> IO Int32) ->
      IO Int64
  getInstanceListV2 = blockStreamHelper Q.getInstanceList
  
  getInstanceInfoV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Smart contract instance index.
      Word64 ->
      -- | Smart contract instance subindex.
      Word64 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getInstanceInfoV2 cptr blockType blockHashPtr addrIndex addrSubindex outHash outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      let caddr = ContractAddress (ContractIndex addrIndex) (ContractSubindex addrSubindex)
      res <- runMVR (Q.getInstanceInfo bhi caddr) mvr
      returnMaybeMessageWithBlock (copier outVec) outHash res
  
  -- | An opaque representation of the place where we write the mutable state in the 'getInstanceStateV2' query.
  data PersistentStateReceiver
  
  -- | A type of callback that copies the V1 contract persistent state into the
  --  provided receveir.
  type PersistentStateCopier = Ptr PersistentStateReceiver -> Ptr StateV1.PersistentState -> StateV1.LoadCallback -> IO ()
  
  -- | Boilerplate wrapper to invoke C callbacks.
  foreign import ccall "dynamic" callPersistentStateCopier :: FunPtr PersistentStateCopier -> PersistentStateCopier
  
  getInstanceStateV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Smart contract instance index.
      Word64 ->
      -- | Smart contract instance subindex.
      Word64 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      -- | If the instance is a V0 instance its instance state is written to this vector.
      --  Otherwise this is unused.
      Ptr ReceiverVec ->
      -- | Callback to output data in case it is a V0 instance.
      FunPtr CopyToVecCallback ->
      -- | If the instance is a V1 instance its instance state and callbacks are written to this vector.
      Ptr PersistentStateReceiver ->
      -- | Callback to copy the persistent state into provided receiver. The
      --  ownership of the state is retained by Haskell, and a copy is given to
      --  Rust.
      FunPtr PersistentStateCopier ->
      IO Int64
  getInstanceStateV2 cptr blockType blockHashPtr addrIndex addrSubindex outHash outVec vecCopierCbk outMS msCopierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      bhi <- decodeBlockHashInput blockType blockHashPtr
      let caddr = ContractAddress (ContractIndex addrIndex) (ContractSubindex addrSubindex)
      response <- runMVR (Q.getInstanceState bhi caddr) mvr
      copyHashTo outHash response
      case response of
          Q.BQRBlock _ (Just iState) ->
              case iState of
                  Left v0State -> do
                      let copier = callCopyToVecCallback vecCopierCbk
                      BS.unsafeUseAsCStringLen (Wasm.contractState v0State) (\(ptr, len) -> copier outVec (castPtr ptr) (fromIntegral len))
                      return (queryResultCode QRSuccess)
                  Right (ps, sContext) -> do
                      let copier = callPersistentStateCopier msCopierCbk
                      StateV1.withPersistentState ps $ \psPtr -> do
                          copier outMS psPtr sContext
                      return (queryResultCode QRSuccess)
          _ -> return (queryResultCode QRNotFound)
  
  getNextAccountSequenceNumberV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Serialized account address. Length is 32 bytes.
      Ptr Word8 ->
      Ptr ReceiverVec ->
      FunPtr (Ptr ReceiverVec -> Ptr Word8 -> Int64 -> IO ()) ->
      IO Int64
  getNextAccountSequenceNumberV2 cptr accPtr outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      accountAddress <- decodeAccountAddress accPtr
      res <- runMVR (Q.getNextAccountNonce accountAddress) mvr
      returnMessage (copier outVec) res
  
  getConsensusInfoV2 ::
      StablePtr Ext.ConsensusRunner ->
      Ptr ReceiverVec ->
      FunPtr (Ptr ReceiverVec -> Ptr Word8 -> Int64 -> IO ()) ->
      IO Int64
  getConsensusInfoV2 cptr outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      consensusInfo <- runMVR Q.getConsensusStatus mvr
      returnMessage (copier outVec) consensusInfo
  
  getConsensusDetailedStatusV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Non-zero if the genesis index is explicitly specified
      Word8 ->
      -- | Genesis index
      Word32 ->
      Ptr ReceiverVec ->
      FunPtr CopyToVecCallback ->
      IO Int64
  getConsensusDetailedStatusV2 cptr explicitGenesisIndex genesisIndex outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      let maybeGI = if explicitGenesisIndex == 0 then Nothing else Just (GenesisIndex genesisIndex)
      runMVR (Q.getConsensusDetailedStatus maybeGI) mvr >>= \case
          Left Q.GCDSEUnknownEra -> return $ queryResultCode QRNotFound
          Left Q.GCDSEInvalidEra -> return $ queryResultCode QRInvalidArgument
          Right status -> returnMessageRaw (copier outVec) status
  
  getCryptographicParametersV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      Ptr ReceiverCryptographicParameters ->
      FunPtr CopyCryptographicParametersCallback ->
      IO Int64
  getCryptographicParametersV2 cptr blockType blockHashPtr outHash outPtr copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyCryptographicParametersCallback copierCbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      response <- runMVR (Q.getCryptographicParameters bhi) mvr
      copyHashTo outHash response
      case response of
          Q.BQRBlock _ cryptographicParameters -> do
              withGlobalContext cryptographicParameters (copier outPtr)
              return $ queryResultCode QRSuccess
          Q.BQRNoBlock -> return $ queryResultCode QRNotFound
  
  getAncestorsV2 ::
      StablePtr Ext.ConsensusRunner ->
      Ptr SenderChannel ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Amount of ancestors (depth).
      Word64 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      FunPtr (Ptr SenderChannel -> Ptr Word8 -> Int64 -> IO Int32) ->
      IO Int64
  getAncestorsV2 cptr channel blockType blockHashPtr depth outHash cbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let sender = callChannelSendCallback cbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      response <- runMVR (Q.getAncestors bhi (BlockHeight depth)) mvr
      returnStreamWithBlock (sender channel) outHash response
  
  getFirstBlockEpochV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Query type.
      Word8 ->
      -- | Query payload data.
      Ptr Word8 ->
      -- | Out pointer for the result block hash.
      Ptr Word8 ->
      IO Int64
  getFirstBlockEpochV2 cptr queryType queryDataPtr outHash = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      epochReq <- decodeEpochRequest queryType queryDataPtr
      response <- runMVR (Q.getFirstBlockEpoch epochReq) mvr
      case response of
          Left Q.EQEBlockNotFound -> return $ queryResultCode QRNotFound
          Left Q.EQEFutureEpoch -> return $ queryResultCode QRFutureEpoch
          Left Q.EQEInvalidEpoch -> return $ queryResultCode QRInvalidArgument
          Left Q.EQEInvalidGenesisIndex -> return $ queryResultCode QRInvalidArgument
          Right res -> do
              copyHashTo outHash (Q.BQRBlock res ())
              return $ queryResultCode QRSuccess
  
  getWinningBakersEpochV2 ::
      StablePtr Ext.ConsensusRunner ->
      Ptr SenderChannel ->
      -- | Query type.
      Word8 ->
      -- | Query payload data.
      Ptr Word8 ->
      -- | Stream callback.
      FunPtr (Ptr SenderChannel -> Ptr Word8 -> Int64 -> IO Int32) ->
      IO Int64
  getWinningBakersEpochV2 cptr channel queryType queryDataPtr cbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let sender = callChannelSendCallback cbk channel
      epochReq <- decodeEpochRequest queryType queryDataPtr
      response <- runMVR (Q.getWinningBakersEpoch epochReq) mvr
      case response of
          Left Q.EQEBlockNotFound -> return $ queryResultCode QRNotFound
          Left Q.EQEFutureEpoch -> return $ queryResultCode QRFutureEpoch
          Left Q.EQEInvalidEpoch -> return $ queryResultCode QRInvalidArgument
          Left Q.EQEInvalidGenesisIndex -> return $ queryResultCode QRInvalidArgument
          Right res -> do
              _ <- enqueueMessages sender res
              return $ queryResultCode QRSuccess
  
  getBlockItemStatusV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Transaction hash.
      Ptr Word8 ->
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getBlockItemStatusV2 cptr trxHashPtr outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      trxHash <- decodeTransactionHashInput trxHashPtr
      res <- runMVR (Q.getTransactionStatus trxHash) mvr
      case res of
          Nothing -> do
              return $ queryResultCode QRNotFound
          Just ts -> case toProto ts of
              Left e -> do
                  mvLog mvr Logger.External Logger.LLError $ "Internal conversion error occured for transaction '" ++ show trxHash ++ "': " ++ show e
                  return $ queryResultCode QRInternalError
              Right t -> do
                  let encoded = Proto.encodeMessage t
                  BS.unsafeUseAsCStringLen encoded (\(ptr, len) -> copier outVec (castPtr ptr) (fromIntegral len))
                  return $ queryResultCode QRSuccess
  
  invokeInstanceV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Block ID type.
      Word8 ->
      -- | Block ID pointer.
      Ptr Word8 ->
      -- | Contract index.
      Word64 ->
      -- | Contract subindex.
      Word64 ->
      -- | Invoker address tag.
      Word8 ->
      -- | Invoker account address pointer.
      Ptr Word8 ->
      -- | Invoker contract index.
      Word64 ->
      -- | Invoker contract subindex.
      Word64 ->
      -- | Amount.
      Word64 ->
      -- | ReceiveName pointer.
      Ptr Word8 ->
      -- | ReceiveName length.
      Word32 ->
      -- | Parameter pointer.
      Ptr Word8 ->
      -- | Parameter length.
      Word32 ->
      -- | Energy
      Word64 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      Ptr ReceiverVec ->
      FunPtr CopyToVecCallback ->
      IO Int64
  invokeInstanceV2 cptr blockIdType blockIdPtr contractIndex contractSubindex invokerAddressType invokerAccountAddressPtr invokerContractIndex invokerContractSubindex amount receiveNamePtr receiveNameLen parameterPtr parameterLen energy outHash outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      block <- decodeBlockHashInput blockIdType blockIdPtr
      maybeInvoker <- case invokerAddressType of
          0 -> return $ Nothing
          1 -> Just . AddressAccount <$> decodeAccountAddress invokerAccountAddressPtr
          _ -> return $ Just $ AddressContract $ ContractAddress (ContractIndex invokerContractIndex) (ContractSubindex invokerContractSubindex)
      method <- decodeReceiveName receiveNamePtr receiveNameLen
      parameter <- decodeParameter parameterPtr parameterLen
      let context =
              InvokeContract.ContractContext
                  { ccInvoker = maybeInvoker,
                    ccContract = ContractAddress (ContractIndex contractIndex) (ContractSubindex contractSubindex),
                    ccAmount = Amount amount,
                    ccMethod = method,
                    ccParameter = parameter,
                    ccEnergy = Energy energy
                  }
      response <- runMVR (Q.invokeContract block context) mvr
      copyHashTo outHash response
      case toProto <$> response of
          Q.BQRBlock _ (Left _) -> return $ queryResultCode QRInternalError
          Q.BQRBlock _ (Right proto) -> do
              let encoded = Proto.encodeMessage proto
              BS.unsafeUseAsCStringLen encoded (\(ptr, len) -> copier outVec (castPtr ptr) (fromIntegral len))
              return $ queryResultCode QRSuccess
          Q.BQRNoBlock -> return $ queryResultCode QRNotFound
  
  getBlockInfoV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getBlockInfoV2 cptr blockType blockHashPtr outHash outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      res <- runMVR (Q.getBlockInfo bhi) mvr
      returnMessageWithBlock (copier outVec) outHash res
  
  getBakerListV2 ::
      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
  getBakerListV2 = blockStreamHelper Q.getRegisteredBakers
  
  getPoolInfoV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Baker id of the pool owner.
      Word64 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getPoolInfoV2 cptr blockType blockHashPtr bakerId outHash outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      response <- runMVR (Q.getPoolStatus bhi (fromIntegral bakerId)) mvr
      copyHashTo outHash response
      case fmap toProto <$> response of
          Q.BQRBlock _ (Just proto) -> do
              let encoded = Proto.encodeMessage proto
              BS.unsafeUseAsCStringLen encoded (\(ptr, len) -> copier outVec (castPtr ptr) (fromIntegral len))
              return $ queryResultCode QRSuccess
          _ -> return $ queryResultCode QRNotFound
  
  getPassiveDelegationInfoV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getPassiveDelegationInfoV2 cptr blockType blockHashPtr outHash outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      response <- runMVR (Q.getPassiveDelegationStatus bhi) mvr
      copyHashTo outHash response
      case fmap toProto <$> response of
          Q.BQRBlock _ (Just proto) -> do
              let encoded = Proto.encodeMessage proto
              BS.unsafeUseAsCStringLen encoded (\(ptr, len) -> copier outVec (castPtr ptr) (fromIntegral len))
              return $ queryResultCode QRSuccess
          _ -> return $ queryResultCode QRNotFound
  
  getBlocksAtHeightV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Block height, is absolute if the genesis_index is 0, otherwise relative.
      Word64 ->
      -- | Genesis index to start from. Set to 0 to use absolute height.
      Word32 ->
      -- | Whether to return results only from the specified genesis index (1),
      -- or allow results from more recent genesis indices as well (0). Out pointer
      -- for writing the block hash that was used.
      Word8 ->
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getBlocksAtHeightV2 cptr height genIndex restrict outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      blocks <- runMVR (fmap fst <$> Q.getBlocksAtHeight (BlockHeight height) (GenesisIndex genIndex) (restrict /= 0)) mvr
      let proto :: Proto.BlocksAtHeightResponse = Proto.make $ ProtoFields.blocks .= maybe [] (fmap toProto) blocks
      let encoded = Proto.encodeMessage proto
      BS.unsafeUseAsCStringLen encoded (\(ptr, len) -> copier outVec (castPtr ptr) (fromIntegral len))
      return $ queryResultCode QRSuccess
  
  getTokenomicsInfoV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getTokenomicsInfoV2 cptr blockType blockHashPtr outHash outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      result <- runMVR (Q.getRewardStatus bhi) mvr
      returnMessageWithBlock (copier outVec) outHash result
  
  getPoolDelegatorsV2 ::
      StablePtr Ext.ConsensusRunner ->
      Ptr SenderChannel ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Baker id.
      Word64 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      FunPtr ChannelSendCallback ->
      IO Int64
  getPoolDelegatorsV2 cptr channel blockType blockHashPtr bakerId outHash cbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let sender = callChannelSendCallback cbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      response <- runMVR (Q.getDelegators bhi (Just $ fromIntegral bakerId)) mvr
      copyHashTo outHash response
      case response of
          Q.BQRBlock _ eitherDelegators ->
              case eitherDelegators of
                  Left Q.GDEUnsupportedProtocolVersion -> return $ queryResultCode QRInvalidArgument
                  Left Q.GDEPoolNotFound -> return $ queryResultCode QRNotFound
                  Right delegators -> do
                      _ <- enqueueMessages (sender channel) delegators
                      return (queryResultCode QRSuccess)
          _ -> return $ queryResultCode QRNotFound
  
  getPoolDelegatorsRewardPeriodV2 ::
      StablePtr Ext.ConsensusRunner ->
      Ptr SenderChannel ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Baker id.
      Word64 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      FunPtr ChannelSendCallback ->
      IO Int64
  getPoolDelegatorsRewardPeriodV2 cptr channel blockType blockHashPtr bakerId outHash cbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let sender = callChannelSendCallback cbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      response <- runMVR (Q.getDelegatorsRewardPeriod bhi (Just $ fromIntegral bakerId)) mvr
      copyHashTo outHash response
      case response of
          Q.BQRBlock _ eitherDelegators ->
              case eitherDelegators of
                  Left Q.GDEUnsupportedProtocolVersion -> return $ queryResultCode QRInvalidArgument
                  Left Q.GDEPoolNotFound -> return $ queryResultCode QRNotFound
                  Right delegators -> do
                      _ <- enqueueMessages (sender channel) delegators
                      return (queryResultCode QRSuccess)
          _ -> return $ queryResultCode QRNotFound
  
  getPassiveDelegatorsV2 ::
      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
  getPassiveDelegatorsV2 cptr channel blockType blockHashPtr outHash cbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let sender = callChannelSendCallback cbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      response <- runMVR (Q.getDelegators bhi Nothing) mvr
      copyHashTo outHash response
      case response of
          Q.BQRBlock _ eitherDelegators ->
              case eitherDelegators of
                  Left Q.GDEUnsupportedProtocolVersion -> return $ queryResultCode QRInvalidArgument
                  Left Q.GDEPoolNotFound -> return $ queryResultCode QRNotFound
                  Right delegators -> do
                      _ <- enqueueMessages (sender channel) delegators
                      return (queryResultCode QRSuccess)
          _ -> return $ queryResultCode QRNotFound
  
  getPassiveDelegatorsRewardPeriodV2 ::
      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
  getPassiveDelegatorsRewardPeriodV2 cptr channel blockType blockHashPtr outHash cbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let sender = callChannelSendCallback cbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      response <- runMVR (Q.getDelegatorsRewardPeriod bhi Nothing) mvr
      copyHashTo outHash response
      case response of
          Q.BQRBlock _ eitherDelegators ->
              case eitherDelegators of
                  Left Q.GDEUnsupportedProtocolVersion -> return $ queryResultCode QRInvalidArgument
                  Left Q.GDEPoolNotFound -> return $ queryResultCode QRNotFound
                  Right delegators -> do
                      _ <- enqueueMessages (sender channel) delegators
                      return (queryResultCode QRSuccess)
          _ -> return $ queryResultCode QRNotFound
  
  getBranchesV2 ::
      StablePtr Ext.ConsensusRunner ->
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getBranchesV2 cptr outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      result <- runMVR Q.getBranches mvr
      returnMessage (copier outVec) result
  
  getElectionInfoV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getElectionInfoV2 cptr blockType blockHashPtr outHash outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      response <- runMVR (Q.getBlockBirkParameters bhi) mvr
      copyHashTo outHash response
      case toProto <$> response of
          Q.BQRBlock _ Nothing -> return $ queryResultCode QRInternalError
          Q.BQRBlock _ (Just proto) -> do
              let encoded = Proto.encodeMessage proto
              BS.unsafeUseAsCStringLen encoded (\(ptr, len) -> copier outVec (castPtr ptr) (fromIntegral len))
              return $ queryResultCode QRSuccess
          Q.BQRNoBlock -> return $ queryResultCode QRNotFound
  
  getIdentityProvidersV2 ::
      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
  getIdentityProvidersV2 = blockStreamHelper Q.getAllIdentityProviders
  
  getAnonymityRevokersV2 ::
      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
  getAnonymityRevokersV2 = blockStreamHelper Q.getAllAnonymityRevokers
  
  getAccountNonFinalizedTransactionsV2 ::
      StablePtr Ext.ConsensusRunner ->
      Ptr SenderChannel ->
      -- | Serialized account address. Length is 32 bytes.
      Ptr Word8 ->
      FunPtr ChannelSendCallback ->
      IO Int64
  getAccountNonFinalizedTransactionsV2 cptr channel accPtr cbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let sender = callChannelSendCallback cbk
      accountAddress <- decodeAccountAddress accPtr
      res <- runMVR (Q.getAccountNonFinalizedTransactions accountAddress) mvr
      _ <- enqueueMessages (sender channel) res
      return (queryResultCode QRSuccess)
  
  -- | Get the block items for a block.
  getBlockItemsV2 ::
      StablePtr Ext.ConsensusRunner ->
      Ptr SenderChannel ->
      -- | Block type
      Word8 ->
      -- | Block hash ptr.
      Ptr Word8 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      FunPtr ChannelSendCallback ->
      IO Int64
  getBlockItemsV2 = blockStreamHelper Q.getBlockItems
  
  getBlockTransactionEventsV2 ::
      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
  getBlockTransactionEventsV2 cptr channel blockType blockHashPtr outHash cbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let sender = callChannelSendCallback cbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      response <- runMVR (Q.getBlockTransactionSummaries bhi) mvr
      copyHashTo outHash response
      case response of
          Q.BQRNoBlock -> return (queryResultCode QRNotFound)
          Q.BQRBlock bh (Left err) -> do
              mvLog mvr Logger.External Logger.LLError $
                  "Failed getting transaction summaries for block '" ++ show bh ++ "': " ++ err
              return $ queryResultCode QRInternalError
          Q.BQRBlock bh (Right events) -> case traverse toProto events of
              Left e -> do
                  mvLog mvr Logger.External Logger.LLError $ "Internal conversion error occured for block '" ++ show bh ++ "': " ++ show e
                  return $ queryResultCode QRInternalError
              Right proto -> do
                  _ <- enqueueProtoMessages (sender channel) $ Vec.toList proto
                  return (queryResultCode QRSuccess)
  
  getBlockSpecialEventsV2 ::
      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
  getBlockSpecialEventsV2 cptr channel blockType blockHashPtr outHash cbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let sender = callChannelSendCallback cbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      response <- runMVR (Q.getBlockSpecialEvents bhi) mvr
      returnStreamWithBlock (sender channel) outHash (toList <$> response)
  
  getBlockPendingUpdatesV2 ::
      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
  getBlockPendingUpdatesV2 = blockStreamHelper Q.getBlockPendingUpdates
  
  getNextUpdateSequenceNumbersV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getNextUpdateSequenceNumbersV2 cptr blockType blockHashPtr outHash outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      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.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getBlockChainParametersV2 cptr blockType blockHashPtr outHash outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      res <- runMVR (Q.getBlockChainParameters bhi) mvr
      returnMessageWithBlock (copier outVec) outHash res
  
  getBlockFinalizationSummaryV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getBlockFinalizationSummaryV2 cptr blockType blockHashPtr outHash outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      res <- runMVR (Q.getBlockFinalizationSummary bhi) mvr
      returnMessageWithBlock (copier outVec) outHash res
  
  -- | Get the slot time of the last finalized block.
  getLastFinalizedBlockSlotTimeV2 ::
      StablePtr Ext.ConsensusRunner ->
      IO Timestamp
  getLastFinalizedBlockSlotTimeV2 cptr = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      runMVR Q.getLastFinalizedSlotTime mvr
  
  getBlockCertificatesV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Block type.
      Word8 ->
      -- | Block hash.
      Ptr Word8 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getBlockCertificatesV2 cptr blockType blockHashPtr outHash outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      res <- runMVR (Q.getBlockCertificates bhi) mvr
      returnEitherMessageWithBlock (copier outVec) outHash res
  
  getBakersRewardPeriodV2 ::
      StablePtr Ext.ConsensusRunner ->
      Ptr SenderChannel ->
      -- | Block type
      Word8 ->
      -- | Block hash ptr.
      Ptr Word8 ->
      -- | Out pointer for writing the block hash that was used.
      Ptr Word8 ->
      FunPtr ChannelSendCallback ->
      IO Int64
  getBakersRewardPeriodV2 cptr channel blockType blockHashPtr outHash cbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let sender = callChannelSendCallback cbk
      bhi <- decodeBlockHashInput blockType blockHashPtr
      response <- runMVR (Q.getBakersRewardPeriod bhi) mvr
      copyHashTo outHash response
      case response of
          Q.BQRBlock _ eitherBakers ->
              case eitherBakers of
                  Left Q.GBRPUnsupportedProtocolVersion -> return $ queryResultCode QRInvalidArgument
                  Right bakers -> do
                      _ <- enqueueMessages (sender channel) bakers
                      return (queryResultCode QRSuccess)
          _ -> return $ queryResultCode QRNotFound
  
  -- | Get the earliest time in which a baker wins the lottery.
  --  Returns "unavailable" for consensus version 0.
  --  For consensus version 1, it will always return a result. If the baker ID does not correspond
  --  to a baker in the current reward period, the result will be the start of the following reward
  --  period.
  getBakerEarliestWinTimeV2 ::
      StablePtr Ext.ConsensusRunner ->
      -- | Baker ID.
      Word64 ->
      -- | Vector to write output to.
      Ptr ReceiverVec ->
      -- | Callback to output data.
      FunPtr CopyToVecCallback ->
      IO Int64
  getBakerEarliestWinTimeV2 cptr baker outVec copierCbk = do
      Ext.ConsensusRunner mvr <- deRefStablePtr cptr
      let copier = callCopyToVecCallback copierCbk outVec
      runMVR (Q.getBakerEarliestWinTime (fromIntegral baker)) mvr >>= \case
          Nothing -> return $ queryResultCode QRUnavailable
          Just ts -> returnMessage copier ts
  
  -- | Write the hash to the provided pointer, encode the message given and write it using the provided callback.
  returnMessageWithBlock ::
      (Proto.Message (Output a), ToProto a) =>
      (Ptr Word8 -> Int64 -> IO ()) ->
      -- | Out pointer where the hash is written.
      Ptr Word8 ->
      -- | The optionally the hash of the block to which the message belongs, and potentially a
      --  message.
      Q.BHIQueryResponse a ->
      IO Int64
  returnMessageWithBlock copier outHash response = do
      copyHashTo outHash response
      case response of
          Q.BQRNoBlock ->
              return $ queryResultCode QRNotFound
          Q.BQRBlock _ out ->
              returnMessage copier out
  
  -- | Write the hash to the provided pointer, and if the message is given encode and
  --  write it using the provided callback.
  returnMaybeMessageWithBlock ::
      (Proto.Message (Output a), ToProto a) =>
      (Ptr Word8 -> Int64 -> IO ()) ->
      -- | Out pointer where the hash is written.
      Ptr Word8 ->
      -- | The optionally the hash of the block to which the message belongs, and potentially a
      --  message.
      Q.BHIQueryResponse (Maybe a) ->
      IO Int64
  returnMaybeMessageWithBlock copier outHash response = do
      copyHashTo outHash response
      case response of
          Q.BQRBlock _ (Just out) ->
              returnMessage copier out
          _ ->
              return $ queryResultCode QRNotFound
  
  -- | Write the hash to the provided pointer, and if the message is given encode and
  --  write it using the provided callback.
  --  If the action resulted in a @Left@ value then return 'QRInvalidArgument'.
  returnEitherMessageWithBlock ::
      (Proto.Message (Output b), ToProto b) =>
      (Ptr Word8 -> Int64 -> IO ()) ->
      -- | Out pointer where the hash is written.
      Ptr Word8 ->
      -- | The optionally the hash of the block to which the message belongs, and potentially a
      --  message.
      Q.BHIQueryResponse (Either a b) ->
      IO Int64
  returnEitherMessageWithBlock copier outHash response = do
      copyHashTo outHash response
      case response of
          Q.BQRBlock _ (Right out) ->
              returnMessage copier out
          Q.BQRBlock _ (Left _) -> return $ queryResultCode QRInvalidArgument
          _ ->
              return $ queryResultCode QRNotFound
  
  -- | If the message is given encode and write it using the provided callback.
  returnMessage ::
      (Proto.Message (Output a), ToProto a) =>
      (Ptr Word8 -> Int64 -> IO ()) ->
      -- | The message.
      a ->
      IO Int64
  returnMessage copier = returnMessageRaw copier . toProto
  
  -- | Encode and write the given message using the provided callback.
  returnMessageRaw :: (Proto.Message msg) => (Ptr Word8 -> Int64 -> IO ()) -> msg -> IO Int64
  returnMessageRaw copier v = do
      let encoded = Proto.encodeMessage v
      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) ->
      -- | Out pointer where the hash is written.
      Ptr Word8 ->
      Q.BHIQueryResponse [a] ->
      IO Int64
  returnStreamWithBlock callback outHash response = do
      copyHashTo outHash response
      case response of
          Q.BQRBlock _ messages -> do
              _ <- enqueueMessages callback messages
              return (queryResultCode QRSuccess)
          Q.BQRNoBlock -> return (queryResultCode QRNotFound)
  
  enqueueMessages :: (Proto.Message (Output a), ToProto a) => (Ptr Word8 -> Int64 -> IO Int32) -> [a] -> IO ThreadId
  enqueueMessages callback = enqueueProtoMessages callback . fmap toProto
  
  -- | Spawn a new thread that will invoke the provided callback on the list of
  --  encoded messages. If the callback response indicates that the channel to
  --  which the callback is enqueueing is full, the thread will wait. The wait time
  --  follows exponential backoff strategy to a maximum of 10 seconds.
  enqueueProtoMessages :: (Proto.Message a) => (Ptr Word8 -> Int64 -> IO Int32) -> [a] -> IO ThreadId
  enqueueProtoMessages callback = forkIO . go 0 . map Proto.encodeMessage
    where
      go _ [] = () <$ callback nullPtr maxBound -- close the sender channel.
      go n msgs@(msg : msgs') =
          BS.unsafeUseAsCStringLen msg $ \(headPtr, len) -> do
              res <- callback (castPtr headPtr) (fromIntegral len)
              if res == 0
                  then go 0 msgs' -- reset wait time to 10ms.
                  else
                      if res == -1
                          then do
                              let delay = (2 ^ n) * 10_000
                              threadDelay delay
                              go (min (n + 1) (10 :: Int)) msgs -- maximum delay is 10 seconds
                          else return () -- the sender channel is now dropped, so we stop.
  
  -- * Foreign exports
  
  foreign export ccall
      getAccountInfoV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Identifier type, 0 for account address, 1 for credential, 2 for account index
          Word8 ->
          -- | Serialized identifier. Length determined by the type.
          Ptr Word8 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          Ptr ReceiverVec ->
          FunPtr (Ptr ReceiverVec -> Ptr Word8 -> Int64 -> IO ()) ->
          IO Int64
  
  foreign export ccall
      getTokenInfoV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Token ID.
          Ptr Word8 ->
          -- | Token ID length.
          Word8 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          Ptr ReceiverVec ->
          -- | Callback to output data.
          FunPtr CopyToVecCallback ->
          IO Int64
  
  foreign export ccall
      getAccountListV2 ::
          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 (Ptr SenderChannel -> Ptr Word8 -> Int64 -> IO Int32) ->
          IO Int64
  
  foreign export ccall
      getTokenListV2 ::
          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 (Ptr SenderChannel -> Ptr Word8 -> Int64 -> IO Int32) ->
          IO Int64
  
  foreign export ccall
      getModuleListV2 ::
          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 (Ptr SenderChannel -> Ptr Word8 -> Int64 -> IO Int32) ->
          IO Int64
  
  foreign export ccall
      getModuleSourceV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Module reference.
          Ptr Word8 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          Ptr ReceiverVec ->
          FunPtr (Ptr ReceiverVec -> Ptr Word8 -> Int64 -> IO ()) ->
          IO Int64
  
  foreign export ccall
      getInstanceListV2 ::
          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 (Ptr SenderChannel -> Ptr Word8 -> Int64 -> IO Int32) ->
          IO Int64
  
  foreign export ccall
      getAncestorsV2 ::
          StablePtr Ext.ConsensusRunner ->
          Ptr SenderChannel ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Amount of ancestors (depth).
          Word64 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          FunPtr (Ptr SenderChannel -> Ptr Word8 -> Int64 -> IO Int32) ->
          IO Int64
  
  foreign export ccall
      getFirstBlockEpochV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Query type.
          Word8 ->
          -- | Query payload data.
          Ptr Word8 ->
          -- | Out pointer for the result block hash.
          Ptr Word8 ->
          IO Int64
  
  foreign export ccall
      getWinningBakersEpochV2 ::
          StablePtr Ext.ConsensusRunner ->
          Ptr SenderChannel ->
          -- | Query type.
          Word8 ->
          -- | Query payload data.
          Ptr Word8 ->
          -- | Stream callback.
          FunPtr (Ptr SenderChannel -> Ptr Word8 -> Int64 -> IO Int32) ->
          IO Int64
  
  foreign export ccall
      getInstanceInfoV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Smart contract address index.
          Word64 ->
          -- | Smart contract address subindex.
          Word64 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          Ptr ReceiverVec ->
          FunPtr (Ptr ReceiverVec -> Ptr Word8 -> Int64 -> IO ()) ->
          IO Int64
  
  foreign export ccall
      getInstanceStateV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Smart contract instance index.
          Word64 ->
          -- | Smart contract instance subindex.
          Word64 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          -- | If the instance is a V0 instance its instance state is written to this vector.
          --  Otherwise this is unused.
          Ptr ReceiverVec ->
          -- | Callback to output data in case it is a V0 instance.
          FunPtr CopyToVecCallback ->
          -- | If the instance is a V1 instance its instance state and callbacks are written to this vector.
          Ptr PersistentStateReceiver ->
          -- | Callback to copy the persistent state into provided receiver. The
          --  ownership of the state is retained by Haskell, and a copy is given to
          --  Rust.
          FunPtr PersistentStateCopier ->
          IO Int64
  
  foreign export ccall
      getNextAccountSequenceNumberV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Serialized account address. Length must be 32 bytes.
          Ptr Word8 ->
          Ptr ReceiverVec ->
          FunPtr (Ptr ReceiverVec -> Ptr Word8 -> Int64 -> IO ()) ->
          IO Int64
  
  foreign export ccall
      getBlockItemStatusV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | TransactionHash. Length must be 32 bytes.
          Ptr Word8 ->
          Ptr ReceiverVec ->
          FunPtr (Ptr ReceiverVec -> Ptr Word8 -> Int64 -> IO ()) ->
          IO Int64
  
  foreign export ccall
      getConsensusInfoV2 ::
          StablePtr Ext.ConsensusRunner ->
          Ptr ReceiverVec ->
          FunPtr (Ptr ReceiverVec -> Ptr Word8 -> Int64 -> IO ()) ->
          IO Int64
  
  foreign export ccall
      getConsensusDetailedStatusV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Non-zero if the genesis index is explicitly specified
          Word8 ->
          -- | Genesis index
          Word32 ->
          Ptr ReceiverVec ->
          FunPtr (Ptr ReceiverVec -> Ptr Word8 -> Int64 -> IO ()) ->
          IO Int64
  
  foreign export ccall
      invokeInstanceV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Block ID type.
          Word8 ->
          -- | Block ID pointer.
          Ptr Word8 ->
          -- | Contract index.
          Word64 ->
          -- | Contract subindex.
          Word64 ->
          -- | Invoker address tag.
          Word8 ->
          -- | Invoker account address pointer.
          Ptr Word8 ->
          -- | Invoker contract index.
          Word64 ->
          -- | Invoker contract subindex.
          Word64 ->
          -- | Amount.
          Word64 ->
          -- | ReceiveName pointer.
          Ptr Word8 ->
          -- | ReceiveName length.
          Word32 ->
          -- | Parameter pointer.
          Ptr Word8 ->
          -- | Parameter length.
          Word32 ->
          -- | Energy
          Word64 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          Ptr ReceiverVec ->
          FunPtr CopyToVecCallback ->
          IO Int64
  
  foreign export ccall
      getCryptographicParametersV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          Ptr ReceiverCryptographicParameters ->
          FunPtr CopyCryptographicParametersCallback ->
          IO Int64
  
  foreign export ccall
      getBlockInfoV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          Ptr ReceiverVec ->
          FunPtr CopyToVecCallback ->
          IO Int64
  
  foreign export ccall
      getBakerListV2 ::
          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
      getPoolInfoV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Baker id of the pool owner.
          Word64 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          Ptr ReceiverVec ->
          FunPtr CopyToVecCallback ->
          IO Int64
  
  foreign export ccall
      getPassiveDelegationInfoV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          Ptr ReceiverVec ->
          FunPtr CopyToVecCallback ->
          IO Int64
  
  foreign export ccall
      getBlocksAtHeightV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Block height, is absolute if the genesis_index is 0, otherwise relative.
          Word64 ->
          -- | Genesis index to start from. Set to 0 to use absolute height.
          Word32 ->
          -- | Whether to return results only from the specified genesis index (1),
          -- or allow results from more recent genesis indices as well (0). Out pointer
          -- for writing the block hash that was used.
          Word8 ->
          Ptr ReceiverVec ->
          FunPtr CopyToVecCallback ->
          IO Int64
  
  foreign export ccall
      getTokenomicsInfoV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          Ptr ReceiverVec ->
          FunPtr CopyToVecCallback ->
          IO Int64
  
  foreign export ccall
      getPoolDelegatorsV2 ::
          StablePtr Ext.ConsensusRunner ->
          Ptr SenderChannel ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Baker id.
          Word64 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          FunPtr ChannelSendCallback ->
          IO Int64
  
  foreign export ccall
      getPoolDelegatorsRewardPeriodV2 ::
          StablePtr Ext.ConsensusRunner ->
          Ptr SenderChannel ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Baker id.
          Word64 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          FunPtr ChannelSendCallback ->
          IO Int64
  
  foreign export ccall
      getPassiveDelegatorsV2 ::
          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
      getPassiveDelegatorsRewardPeriodV2 ::
          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
      getBranchesV2 ::
          StablePtr Ext.ConsensusRunner ->
          Ptr ReceiverVec ->
          FunPtr CopyToVecCallback ->
          IO Int64
  
  foreign export ccall
      getElectionInfoV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          Ptr ReceiverVec ->
          FunPtr CopyToVecCallback ->
          IO Int64
  
  foreign export ccall
      getIdentityProvidersV2 ::
          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
      getAnonymityRevokersV2 ::
          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
      getAccountNonFinalizedTransactionsV2 ::
          StablePtr Ext.ConsensusRunner ->
          Ptr SenderChannel ->
          -- | Serialized account address. Length is 32 bytes.
          Ptr Word8 ->
          FunPtr ChannelSendCallback ->
          IO Int64
  
  foreign export ccall
      getBlockItemsV2 ::
          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
      getBlockTransactionEventsV2 ::
          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
      getBlockSpecialEventsV2 ::
          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
      getBlockPendingUpdatesV2 ::
          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
      getNextUpdateSequenceNumbersV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          Ptr ReceiverVec ->
          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 ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          Ptr ReceiverVec ->
          -- | Callback to output data.
          FunPtr CopyToVecCallback ->
          IO Int64
  
  foreign export ccall
      getBlockFinalizationSummaryV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          Ptr ReceiverVec ->
          -- | Callback to output data.
          FunPtr CopyToVecCallback ->
          IO Int64
  
  foreign export ccall
      getLastFinalizedBlockSlotTimeV2 ::
          StablePtr Ext.ConsensusRunner ->
          IO Timestamp
  
  foreign export ccall
      getBakersRewardPeriodV2 ::
          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
      getBlockCertificatesV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Block type.
          Word8 ->
          -- | Block hash.
          Ptr Word8 ->
          -- | Out pointer for writing the block hash that was used.
          Ptr Word8 ->
          Ptr ReceiverVec ->
          -- | Callback to output data.
          FunPtr CopyToVecCallback ->
          IO Int64
  
  foreign export ccall
      getBakerEarliestWinTimeV2 ::
          StablePtr Ext.ConsensusRunner ->
          -- | Baker ID.
          Word64 ->
          -- | Vector to write output to.
          Ptr ReceiverVec ->
          -- | Callback to output data.
          FunPtr CopyToVecCallback ->
          IO Int64
  