| 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 -> DepositPeriod -> LocalChainState m Tx -> SubmitTx m -> Chain Tx m
- rejectUnobservableDeposit :: NetworkId -> Tx -> Either (PostTxError Tx) ()
- 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
- canBeVerifiedOnChain :: Int -> Bool
- 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 | |
| -> DepositPeriod | Configured deposit period, bounding the validity of deposit txs. |
| -> 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.
rejectUnobservableDeposit :: NetworkId -> Tx -> Either (PostTxError Tx) () Source #
Reject a drafted deposit the node would never observe on chain.
observeDepositTx requires the deposit output's value to equal the value
recorded in its datum. Balancing tops every output up to its minimum ADA,
and the deposit output needs more than the deposited outputs themselves
because its inline datum embeds them. The datum keeps the original value,
so the finalized transaction would be ignored by every node, never reach
L2 and only be recoverable by hand. Report how much ADA is missing instead.
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 |
canBeVerifiedOnChain :: Int -> Bool Source #
Whether a fanout distributing this many outputs can be verified on chain at all, and so is worth building.
Above deployedFanoutBatchSize the head validator rejects the
membership proof however cheap the transaction is, and building the
transaction means computing that proof over the whole set — discarded on every
fanout step. Callers guard on this rather than passing the built transaction
and discarding it, so the expensive call is unreachable rather than merely
unforced.
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 preparePartialFanout → 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
| |