Safe Haskell | None |
---|---|
Language | Haskell2010 |
Synopsis
- type family ApplyTxErr blk :: Type
- data family GenTx blk :: Type
- type GenTxId blk = TxId ( GenTx blk)
- class ( Show ( TxId tx), Ord ( TxId tx), NoThunks ( TxId tx)) => HasTxId tx where
-
class
HasTxs
blk
where
- extractTxs :: blk -> [ GenTx blk]
-
class
(
UpdateLedger
blk,
NoThunks
(
GenTx
blk),
NoThunks
(
Validated
(
GenTx
blk)),
NoThunks
(
Ticked
(
LedgerState
blk)),
Show
(
GenTx
blk),
Show
(
Validated
(
GenTx
blk)),
Show
(
ApplyTxErr
blk)) =>
LedgerSupportsMempool
blk
where
- txInvariant :: GenTx blk -> Bool
- applyTx :: LedgerConfig blk -> WhetherToIntervene -> SlotNo -> GenTx blk -> TickedLedgerState blk -> Except ( ApplyTxErr blk) ( TickedLedgerState blk, Validated ( GenTx blk))
- reapplyTx :: HasCallStack => LedgerConfig blk -> SlotNo -> Validated ( GenTx blk) -> TickedLedgerState blk -> Except ( ApplyTxErr blk) ( TickedLedgerState blk)
- txsMaxBytes :: TickedLedgerState blk -> Word32
- txInBlockSize :: GenTx blk -> Word32
- txForgetValidated :: Validated ( GenTx blk) -> GenTx blk
- data family TxId tx :: Type
- data family Validated x :: Type
- data WhetherToIntervene
Documentation
type family ApplyTxErr blk :: Type Source #
Updating the ledger with a single transaction may result in a different error type as when updating it with a block
Instances
type ApplyTxErr ( HardForkBlock xs) Source # | |
|
|
type ApplyTxErr ( DualBlock m a) Source # | |
Defined in Ouroboros.Consensus.Ledger.Dual |
data family GenTx blk :: Type Source #
Generalized transaction
The mempool (and, accordingly, blocks) consist of "generalized transactions"; this could be "proper" transactions (transferring funds) but also other kinds of things such as update proposals, delegations, etc.
Instances
class ( Show ( TxId tx), Ord ( TxId tx), NoThunks ( TxId tx)) => HasTxId tx where Source #
Transactions with an identifier
The mempool will use these to locate transactions, so two different transactions should have different identifiers.
txId :: tx -> TxId tx Source #
NOTE: a
TxId
must be unique up to ledger rules, i.e., two
GenTx
s with
the same
TxId
must be the same transaction
according to the ledger
.
However, we do not assume that a
TxId
uniquely determines a
GenTx
:
two
GenTx
s with the same
TxId
can differ in, e.g., witnesses.
Should be cheap as this will be called often.
Instances
Bridge m a => HasTxId ( GenTx ( DualBlock m a)) Source # | |
CanHardFork xs => HasTxId ( GenTx ( HardForkBlock xs)) Source # | |
Defined in Ouroboros.Consensus.HardFork.Combinator.Mempool txId :: GenTx ( HardForkBlock xs) -> TxId ( GenTx ( HardForkBlock xs)) Source # |
class HasTxs blk where Source #
Collect all transactions from a block
This is used for tooling only. We don't require it as part of RunNode (and cannot, because we cannot give an instance for the dual ledger).
extractTxs :: blk -> [ GenTx blk] Source #
Return the transactions part of the given block in no particular order.
Instances
All HasTxs xs => HasTxs ( HardForkBlock xs) Source # | |
Defined in Ouroboros.Consensus.HardFork.Combinator.Mempool extractTxs :: HardForkBlock xs -> [ GenTx ( HardForkBlock xs)] Source # |
class ( UpdateLedger blk, NoThunks ( GenTx blk), NoThunks ( Validated ( GenTx blk)), NoThunks ( Ticked ( LedgerState blk)), Show ( GenTx blk), Show ( Validated ( GenTx blk)), Show ( ApplyTxErr blk)) => LedgerSupportsMempool blk where Source #
txInvariant :: GenTx blk -> Bool Source #
Check whether the internal invariants of the transaction hold.
:: LedgerConfig blk | |
-> WhetherToIntervene | |
-> SlotNo |
Slot number of the block containing the tx |
-> GenTx blk | |
-> TickedLedgerState blk | |
-> Except ( ApplyTxErr blk) ( TickedLedgerState blk, Validated ( GenTx blk)) |
Apply an unvalidated transaction
:: HasCallStack | |
=> LedgerConfig blk | |
-> SlotNo |
Slot number of the block containing the tx |
-> Validated ( GenTx blk) | |
-> TickedLedgerState blk | |
-> Except ( ApplyTxErr blk) ( TickedLedgerState blk) |
Apply a previously validated transaction to a potentially different ledger state
When we re-apply a transaction to a potentially different ledger state expensive checks such as cryptographic hashes can be skipped, but other checks (such as checking for double spending) must still be done.
txsMaxBytes :: TickedLedgerState blk -> Word32 Source #
The maximum number of bytes worth of transactions that can be put into a block according to the currently adopted protocol parameters of the ledger state.
This is (conservatively) computed by subtracting the header size and any other fixed overheads from the maximum block size.
txInBlockSize :: GenTx blk -> Word32 Source #
Return the post-serialisation size in bytes of a
GenTx
/when it is
embedded in a block/. This size might differ from the size of the
serialisation used to send and receive the transaction across the
network.
This size is used to compute how many transaction we can put in a block when forging one.
For example, CBOR-in-CBOR could be used when sending the transaction across the network, requiring a few extra bytes compared to the actual in-block serialisation. Another example is the transaction of the hard-fork combinator which will include an envelope indicating its era when sent across the network. However, when embedded in the respective era's block, there is no need for such envelope.
Can be implemented by serialising the
GenTx
, but, ideally, this is
implement more efficiently. E.g., by returning the length of the
annotation.
txForgetValidated :: Validated ( GenTx blk) -> GenTx blk Source #
Discard the evidence that transaction has been previously validated
Instances
data family TxId tx :: Type Source #
A generalized transaction,
GenTx
, identifier.
Instances
data family Validated x :: Type Source #
" Validated " transaction or block
The ledger defines how to validate transactions and blocks. It's possible the type before and after validation may be distinct (eg Alonzo transactions), which originally motivated this family.
We also gain the related benefit that certain interface functions, such as those that reapply blocks, can have a more precise type now. TODO
Similarly, the Node-to-Client mini protocols can explicitly indicate that the
client trusts the blocks from the local server, by having the server send
Validated
blocks to the client. TODO
Note that validation has different implications for a transaction than for a block. In particular, a validated transaction can be " reapplied " to different ledger states, whereas a validated block must only be " reapplied " to the exact same ledger state (eg as part of rebuilding from an on-disk ledger snapshot).
Since the ledger defines validation, see the ledger details for concrete
examples of what determines the validity (wrt to a
LedgerState
) of a
transaction and/or block. Example properties include: a transaction's claimed
inputs exist and are still unspent, a block carries a sufficient
cryptographic signature, etc.
Instances
data WhetherToIntervene Source #
A flag indicating whether the mempool should reject a valid-but-problematic transaction, in order to to protect its author from penalties etc
The primary example is that, as of the Alonzo ledger, a valid transaction can carry an invalid script. If a remote peer sends us such a transaction (over a Node-to-Node protocol), we include it in a block so that the ledger will penalize them them for the invalid script: they wasted our resources by forcing us to run the script to determine it's invalid. But if our local wallet -- which we trust by assumption -- sends us such a transaction (over a Node-to-Client protocol), we would be a good neighbor by rejecting that transaction: they must have made some sort of mistake, and we don't want the ledger to penalize them.
DoNotIntervene |
We do not trust remote peers, so if a problematic-yet-valid transaction arrives over NTN, we accept it; it will end up in a block and the ledger will penalize them for it. |
Intervene |
We trust local clients, so if a problematic-yet-valid transaction arrives over NTC, we reject it in order to avoid the ledger penalizing them for it. |