@@ -11,29 +11,40 @@ module Cardano.Sieve.Node.Decode
1111 , selectedOutputs
1212 , spentInputs
1313 , encodeOutputRef
14+ , byronOutputsInTx
15+ , byronTxSpends
1416 )
1517where
1618
1719import Cardano.Api
18- ( AddressAny
20+ ( Address (ByronAddress )
21+ , AddressAny (AddressByron )
22+ , Block (ByronBlock , ShelleyBlock )
1923 , BlockInMode (BlockInMode )
2024 , ShelleyBasedEra (.. )
2125 , Tx (ShelleyTx )
26+ , TxId
2227 , TxIn (TxIn )
2328 , TxIx (TxIx )
2429 , Value
30+ , fromByronLovelace
31+ , fromByronTxIn
2532 , fromLedgerValue
2633 , fromShelleyAddrToAny
2734 , fromShelleyScriptHash
2835 , fromShelleyTxIn
2936 , getBlockTxs
3037 , getTxIdShelley
38+ , lovelaceToValue
3139 , serialiseToRawBytes
3240 , shelleyBasedEraConstraints
3341 )
42+ import Cardano.Api.Consensus qualified as Consensus
3443import Cardano.Api.Experimental.Tx (TxOut (TxOut ))
3544import Cardano.Api.Ledger qualified as L
3645
46+ import Cardano.Chain.Block qualified as CC
47+ import Cardano.Chain.UTxO qualified as Utxo
3748import Cardano.Ledger.Alonzo.Core (originalBytes , scriptPrefixTag )
3849import Cardano.Ledger.Alonzo.Scripts
3950 ( AsIx (AsIx )
@@ -82,11 +93,12 @@ data DecodedOutput = DecodedOutput
8293 -- so every output of the same transaction carries the same set; empty if none.
8394 }
8495
85- -- | Every output of every transaction in a block. Byron blocks contribute
86- -- nothing ('getBlockTxs' is @[]@ for them) .
96+ -- | Every output of every transaction in a block. 'getBlockTxs' is @[]@ for a
97+ -- Byron block and there is no @Tx ByronEra@, so Byron has its own arm .
8798outputsInBlock :: BlockInMode -> [DecodedOutput ]
88- outputsInBlock (BlockInMode _ block) =
89- concat (zipWith outputsInTx [0 .. ] (getBlockTxs block))
99+ outputsInBlock (BlockInMode _ block) = case block of
100+ ByronBlock b -> concat (zipWith byronOutputsInTx [0 .. ] (byronTxs b))
101+ ShelleyBlock {} -> concat (zipWith outputsInTx [0 .. ] (getBlockTxs block))
90102
91103-- | Decode every output of one transaction. Each output carries the
92104-- transaction's id (in its output reference), its position within the block, and
@@ -190,7 +202,9 @@ outputsInTx txIx (ShelleyTx sbe ledgerTx) =
190202-- block produced a matched output. Without that condition every datum and
191203-- script on the chain would be stored no matter how narrow the selectors.
192204datumsAndScriptsInBlock :: BlockInMode -> DatumsAndScripts
193- datumsAndScriptsInBlock (BlockInMode _ block) = foldMap datumsAndScriptsInTx (getBlockTxs block)
205+ datumsAndScriptsInBlock (BlockInMode _ block) = case block of
206+ ByronBlock {} -> mempty -- Byron has neither
207+ ShelleyBlock {} -> foldMap datumsAndScriptsInTx (getBlockTxs block)
194208
195209-- | The datums and scripts of one transaction.
196210datumsAndScriptsInTx :: Tx era -> DatumsAndScripts
@@ -264,8 +278,10 @@ selectedOutputs selectors blk =
264278-- for /all/ inputs (an input carries no data to run a selector against); the
265279-- writer keeps only the ones whose consumed output is tracked.
266280spentInputs :: RedeemerCapture -> BlockInMode -> [SpentInput ]
267- spentInputs capture (BlockInMode _ block) =
268- concatMap (txSpends capture) (getBlockTxs block)
281+ spentInputs capture (BlockInMode _ block) = case block of
282+ -- No redeemers in Byron, so 'capture' does not reach this arm.
283+ ByronBlock b -> concatMap byronTxSpends (byronTxs b)
284+ ShelleyBlock {} -> concatMap (txSpends capture) (getBlockTxs block)
269285
270286-- | The consumed inputs of one transaction, each tagged with the spending
271287-- transaction's id, the input's index, and (when asked for) the redeemer that
@@ -349,3 +365,60 @@ encodeOutputRef :: TxIn -> ByteString
349365encodeOutputRef (TxIn txid (TxIx ix)) =
350366 serialiseToRawBytes txid
351367 <> LBS. toStrict (toLazyByteString (word64BE (fromIntegral ix)))
368+
369+ -- * Byron
370+
371+ -- | The transaction payload of a Byron block; the other three payloads
372+ -- (delegation, update proposals, votes) are not outputs. Epoch boundary blocks
373+ -- carry none.
374+ --
375+ -- This order is the @transaction_index@ reported for Byron outputs.
376+ byronTxs :: Consensus. ByronBlock -> [Utxo. ATxAux ByteString ]
377+ byronTxs blk = case Consensus. byronBlockRaw blk of
378+ CC. ABOBBoundary _ebb -> []
379+ CC. ABOBBlock b -> Utxo. aUnTxPayload (CC. blockTxPayload b)
380+
381+ -- | The transaction's id. 'Consensus.byronIdTx' hashes its annotated bytes
382+ -- rather than re-serialising. The reference is a detour: cardano-api exposes
383+ -- the Byron id conversion only through 'fromByronTxIn', so the index below is a
384+ -- placeholder.
385+ byronTxId :: Utxo. ATxAux ByteString -> TxId
386+ byronTxId atx =
387+ case fromByronTxIn (Utxo. TxInUtxo (Consensus. byronIdTx atx) 0 ) of
388+ TxIn txid _ix -> txid
389+
390+ -- | Decode every output of one Byron transaction, given its position in its
391+ -- block. A Byron output is an address and an ada-only value: no datum, no
392+ -- reference script, no metadata. The address is a bootstrap one, so
393+ -- 'Cardano.Sieve.Node.Encode.toStored' stores NULL for both credential columns.
394+ byronOutputsInTx :: Word64 -> Utxo. ATxAux ByteString -> [DecodedOutput ]
395+ byronOutputsInTx txIx atx =
396+ zipWith mkOutput [0 .. ] (F. toList (Utxo. txOutputs (Utxo. taTx atx)))
397+ where
398+ txid = byronTxId atx
399+ mkOutput ix o =
400+ DecodedOutput
401+ { doOutputRef = TxIn txid (TxIx ix)
402+ , doTransactionIndex = txIx
403+ , doAddress = AddressByron (ByronAddress (Utxo. txOutAddress o))
404+ , doValue = lovelaceToValue (fromByronLovelace (Utxo. txOutValue o))
405+ , doDatum = Nothing
406+ , doReferenceScriptHash = Nothing
407+ , doMetadataTags = Set. empty
408+ }
409+
410+ -- | The consumed inputs of one Byron transaction. With no redeemers there is no
411+ -- pointer for 'siInputIndex' to line up with, so it is the input's position in
412+ -- the transaction — the order Byron's UTxO rule consumes them in.
413+ byronTxSpends :: Utxo. ATxAux ByteString -> [SpentInput ]
414+ byronTxSpends atx =
415+ zipWith mkSpend [0 .. ] (F. toList (Utxo. txInputs (Utxo. taTx atx)))
416+ where
417+ txid = serialiseToRawBytes (byronTxId atx)
418+ mkSpend ix i =
419+ SpentInput
420+ { siConsumed = encodeOutputRef (fromByronTxIn i)
421+ , siSpendingTxId = txid
422+ , siInputIndex = ix
423+ , siRedeemer = Nothing
424+ }
0 commit comments