| Safe Haskell | Safe-Inferred |
|---|---|
| Language | GHC2021 |
Hydra.Chain.Direct.Handlers
Description
Provide infrastructure-independent "handlers" for posting transactions and following the chain.
This module encapsulates the transformation logic between cardano transactions and HydraNode abstractions
PostChainTx and OnChainTx, and maintenance of on-chain relevant state.
Synopsis
- data LocalChainState m tx = LocalChainState {
- getLatest :: STM m (ChainStateType tx)
- pushNew :: ChainStateType tx -> STM m ()
- rollback :: ChainSlot -> STM m (ChainStateType tx)
- history :: STM m (ChainStateHistory tx)
- newLocalChainState :: forall m tx. (IsChainState tx, MonadLabelledSTM m) => ChainStateHistory tx -> m (LocalChainState m tx)
- type SubmitTx m = Tx -> m ()
- type GetTimeHandle m = m TimeHandle
- mkChain :: (MonadSTM m, MonadThrow (STM m)) => Tracer m CardanoChainLog -> GetTimeHandle m -> TinyWallet m -> ChainContext -> LocalChainState m Tx -> SubmitTx m -> Chain Tx m
- rejectLowDeposits :: PParams LedgerEra -> UTxO -> Either (PostTxError Tx) ()
- rejectByronAddresses :: UTxO -> Either (PostTxError Tx) ()
- rejectOversizedDeposit :: PParams LedgerEra -> ChainContext -> UTxO -> HeadId -> ConfirmedSnapshot Tx -> Tx -> SlotNo -> Either (PostTxError Tx) ()
- serializedValueSize :: PParams LedgerEra -> Value -> Natural
- incrementTxBalancingMargin :: Natural
- finalizeTx :: MonadThrow m => TinyWallet m -> ChainContext -> UTxO -> UTxO -> Tx -> m Tx
- data ChainSyncHandler m = ChainSyncHandler {
- onRollForward :: BlockHeader -> [Tx] -> m ()
- onRollBackward :: ChainPoint -> m ()
- data TimeConversionException = TimeConversionException {}
- chainSyncHandler :: forall m. (MonadSTM m, MonadThrow m) => Tracer m CardanoChainLog -> ChainCallback Tx m -> (SlotNo -> GetTimeHandle m) -> ChainContext -> LocalChainState m Tx -> ChainSyncHandler m
- convertObservation :: TimeHandle -> HeadObservation -> Maybe (OnChainTx Tx)
- prepareTxToPost :: forall m. (MonadSTM m, MonadThrow (STM m)) => TimeHandle -> ChainContext -> UTxOType Tx -> PostChainTx Tx -> STM m Tx
- findLargestFitting :: Monad m => (Int -> m (Maybe tx)) -> Int -> m (Either () tx)
- fitsTx :: Monad m => Tracer m CardanoChainLog -> (Tx -> m Bool) -> (Tx -> UTxO -> m (Either EvaluationError EvaluationReport)) -> UTxO -> Tx -> m Bool
- findFittingFanoutTx :: forall m. MonadThrow m => Tracer m CardanoChainLog -> TinyWallet m -> ChainContext -> UTxO -> TxIn -> Maybe Tx -> UTxO -> UTxO -> Int -> SlotNo -> m Tx
- maxGraceTime :: NominalDiffTime
- data StartingDecision
- = FromProvided ChainPoint
- | FromTip ChainPoint
- | FromPersisted {
- chainPoint :: ChainPoint
- startChainFromSet :: Bool
- data CardanoChainLog
- = ToPost {
- toPost :: PostChainTx Tx
- | PostingTx {
- txId :: TxId
- | PostedTx {
- txId :: TxId
- | PostingFailed {
- tx :: Tx
- postTxError :: PostTxError Tx
- | RolledForward {
- point :: ChainPoint
- receivedTxIds :: [TxId]
- | RolledBackward {
- point :: ChainPoint
- | Wallet TinyWalletLog
- | StartingChainDecision StartingDecision
- | BlockfrostTransientError {
- reason :: Text
- retryDelay :: Int
- | PartialFanoutFailed {
- reason :: Text
- = ToPost {
Documentation
data LocalChainState m tx Source #
Handle of a mutable local chain state that is kept in the direct chain layer.
Constructors
| LocalChainState | |
Fields
| |
newLocalChainState :: forall m tx. (IsChainState tx, MonadLabelledSTM m) => ChainStateHistory tx -> m (LocalChainState m tx) Source #
Initialize a new local chain state from a given chain state history.
Posting Transactions
type GetTimeHandle m = m TimeHandle Source #
A way to acquire a TimeHandle
Arguments
| :: (MonadSTM m, MonadThrow (STM m)) | |
| => Tracer m CardanoChainLog | |
| -> GetTimeHandle m | Means to acquire a new |
| -> TinyWallet m | |
| -> ChainContext | |
| -> LocalChainState m Tx | |
| -> SubmitTx m | |
| -> Chain Tx m |
Create a Chain component for posting "real" cardano transactions.
This component does not actually interact with a cardano-node, but creates
cardano transactions from PostChainTx transactions emitted by a
HydraNode, balancing and signing them using given TinyWallet, before
handing it off to the given SubmitTx callback. There is also a draftTx
option for drafting a commit tx on behalf of the user using their selected
utxo.
NOTE: Given the constraints on m this function should work within IOSim
and does not require any actual IO to happen which makes it highly suitable
for simulations and testing.
rejectLowDeposits :: PParams LedgerEra -> UTxO -> Either (PostTxError Tx) () Source #
rejectByronAddresses :: UTxO -> Either (PostTxError Tx) () Source #
Reject any UTxO containing a Byron address, which cannot be represented in the Hydra head protocol.
rejectOversizedDeposit Source #
Arguments
| :: PParams LedgerEra | Layer 1 protocol parameters (from |
| -> ChainContext | |
| -> UTxO | Spendable UTxO containing the current head output. |
| -> HeadId | |
| -> ConfirmedSnapshot Tx | Current confirmed snapshot, basis for the dry-run increment. |
| -> Tx | Drafted (unbalanced) deposit transaction. |
| -> SlotNo | Upper validity slot for the dry-run increment. |
| -> Either (PostTxError Tx) () |
Reject deposits which could never be claimed: builds a dry-run increment
transaction for the drafted deposit and rejects with DepositTooLarge when
it would violate layer 1 ledger limits - the maximum transaction size, or
the maximum serialized value size of the merged head output.
serializedValueSize :: PParams LedgerEra -> Value -> Natural Source #
Serialized size of a value, computed exactly like the ledger's
OutputTooBigUTxO check. NOTE: Keep in sync with
validateOutputTooBigUTxO.
incrementTxBalancingMargin :: Natural Source #
Byte headroom added to the unbalanced dry-run increment transaction when
comparing against the maximum transaction size, covering what $sel:coverFee:TinyWallet and
$sel:sign:TinyWallet add to the real increment: a fee input (~40 bytes), a collateral
input (~40 bytes), an ada-only change output (~70 bytes), the script
integrity hash (~37 bytes), the fee field (~5 bytes), one key witness (~102
bytes), and wider integer encodings for the estimated execution units,
snapshot number and validity slot (~40 bytes) - around 334 bytes in total.
We add some overhead and use 512 just to be more safe.
finalizeTx :: MonadThrow m => TinyWallet m -> ChainContext -> UTxO -> UTxO -> Tx -> m Tx Source #
Balance and sign the given partial transaction.
Following the Chain
data ChainSyncHandler m Source #
A handler that takes care of following the chain.
Constructors
| ChainSyncHandler | |
Fields
| |
data TimeConversionException Source #
Conversion of a slot number to a time failed. This can be usually be considered an internal error and may be happening because the used era history is too old.
Constructors
| TimeConversionException | |
Instances
| Exception TimeConversionException Source # | |
Defined in Hydra.Chain.Direct.Handlers | |
| Show TimeConversionException Source # | |
Defined in Hydra.Chain.Direct.Handlers | |
| Eq TimeConversionException Source # | |
Defined in Hydra.Chain.Direct.Handlers Methods (==) :: TimeConversionException -> TimeConversionException -> Bool Source # (/=) :: TimeConversionException -> TimeConversionException -> Bool Source # | |
Arguments
| :: forall m. (MonadSTM m, MonadThrow m) | |
| => Tracer m CardanoChainLog | Tracer for logging |
| -> ChainCallback Tx m | |
| -> (SlotNo -> GetTimeHandle m) | Means to acquire a |
| -> ChainContext | Contextual information about our chain connection. |
| -> LocalChainState m Tx | |
| -> ChainSyncHandler m | A chain-sync handler to use in a local-chain-sync client. |
Creates a ChainSyncHandler that can notify the given callback of events happening
on-chain.
This forms the other half of a ChainComponent along with mkChain but is decoupled from
actual interactions with the chain.
A TimeHandle is needed to do `SlotNo -> POSIXTime` conversions for Tick events.
Throws TimeConversionException when a received block's SlotNo cannot be
converted to a UTCTime with the given TimeHandle.
convertObservation :: TimeHandle -> HeadObservation -> Maybe (OnChainTx Tx) Source #
Arguments
| :: forall m. (MonadSTM m, MonadThrow (STM m)) | |
| => TimeHandle | |
| -> ChainContext | |
| -> UTxOType Tx | Spendable UTxO |
| -> PostChainTx Tx | |
| -> STM m Tx |
Arguments
| :: Monad m | |
| => (Int -> m (Maybe tx)) | Construct and check a transaction; Just tx = fits, Nothing = doesn't fit; may throw on structural failure |
| -> Int | Upper bound of chunk sizes to search (inclusive) |
| -> m (Either () tx) |
Binary search for the largest chunk size in [1..maxChunk] for which
tryTx returns Just. Assumes the predicate is monotone: if size n fits,
all sizes < n also fit. Uses upper-mid so the search terminates correctly
when hi = lo + 1. Returns 'Left ()' if no size fits. tryTx may throw to
abort the search early.
fitsTx :: Monad m => Tracer m CardanoChainLog -> (Tx -> m Bool) -> (Tx -> UTxO -> m (Either EvaluationError EvaluationReport)) -> UTxO -> Tx -> m Bool Source #
Check whether a transaction fits within protocol size and script execution limits. Size check is cheap so it short-circuits before the expensive UPLC evaluation. Structural errors (script failures, protocol parameter conversion errors) are traced via the provided tracer; transient misses (size exceeded, budget overrun) are silent.
Arguments
| :: forall m. MonadThrow m | |
| => Tracer m CardanoChainLog | |
| -> TinyWallet m | |
| -> ChainContext | |
| -> UTxO | Spendable UTxO containing head output |
| -> TxIn | Seed TxIn |
| -> Maybe Tx | Preferred tx to try first (FanoutTx or FinalPartialFanoutTx); |
| -> UTxO | UTxO for the accumulator check in the partial-fanout fallback (matches the on-chain datum) |
| -> UTxO | UTxOs to distribute in the partial-fanout fallback |
| -> Int | Upper bound (inclusive) of chunk sizes to search in the fallback. For the
final/full fanout fallback this is |
| -> SlotNo | Contestation deadline as SlotNo |
| -> m Tx |
Try the preferred transaction first; if it doesn't fit within the script execution budget or exceeds the maximum transaction size, fall back to a binary search over partial fanout chunk sizes. Returns the largest chunk that fits, minimising the number of fanout steps.
Error mapping:
* StaleChainState from partialFanout → StalePartialFanoutTx (race
condition; HeadLogic silently ignores it and the chain observation loop
triggers the correct next step).
* Any other PartialFanoutError → FailedToConstructPartialFanoutTx
(structural mismatch that will not resolve on retry).
* No chunk fits within budget → FailedToConstructPartialFanoutTx
(budget exhaustion; also not a race condition).
maxGraceTime :: NominalDiffTime Source #
Maximum delay we put on the upper bound of transactions to fit into a block. NOTE: This is highly depending on the network. If the security parameter and epoch length result in a short horizon, this is problematic.
data StartingDecision Source #
Constructors
| FromProvided ChainPoint | |
| FromTip ChainPoint | |
| FromPersisted | |
Fields
| |
Instances
data CardanoChainLog Source #
Constructors
| ToPost | |
Fields
| |
| PostingTx | |
Fields
| |
| PostedTx | |
Fields
| |
| PostingFailed | |
Fields
| |
| RolledForward | |
Fields
| |
| RolledBackward | |
Fields
| |
| Wallet TinyWalletLog | |
| StartingChainDecision StartingDecision | |
| BlockfrostTransientError | |
Fields
| |
| PartialFanoutFailed | |
Fields
| |