Skip to content

Commit 03405b6

Browse files
committed
cli: read/write byron tx files in the right binary format
This is sadly a little confusing. In Byron there are 4 kinds of on-chain objects, and only one of those is normal txs. So we have a type called GenTx ByronBlock that is the "generalised tx" that covers all four cases. This is the type that is sent between mempools. But the actual on-chain Byron tx type is a TxAux. The cli code for generating txs and writing them out to file was using the GenTx format. And them same for reading them back in again. While this is self consistent this is also very unhelpful, since we should use the real format as it exists on the chain, not the intermediate wrapper format. Doing it this way means we can submit them directly to the tx-submission service, We can decode and print them, check their hashes etc. The code isn't perfect. We can do better by handling this GenTx vs Tx distinction in a more general way so that we can write the CLI code more generically between Byron, Shelley and mock protocols & ledgers.
1 parent 3fa5fe1 commit 03405b6

File tree

4 files changed

+51
-38
lines changed

4 files changed

+51
-38
lines changed

cardano-node/src/Cardano/CLI/Ops.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import qualified Data.Text as T
3232
import qualified Text.JSON.Canonical as CanonicalJSON
3333

3434
import Cardano.Crypto (RequiresNetworkMagic, SigningKey (..))
35+
import Cardano.Binary (DecoderError)
3536
import Codec.CBOR.Read (DeserialiseFailure, deserialiseFromBytes)
3637
import Codec.CBOR.Write (toLazyByteString)
3738
import qualified Cardano.Crypto.Signing as Crypto
@@ -101,7 +102,7 @@ data CliError
101102
| SigningKeyDeserialisationFailed !FilePath !DeserialiseFailure
102103
| VerificationKeyDeserialisationFailed !FilePath !Text
103104
| DlgCertificateDeserialisationFailed !FilePath !Text
104-
| TxDeserialisationFailed !FilePath !DeserialiseFailure
105+
| TxDeserialisationFailed !FilePath !DecoderError
105106
-- TODO: sadly, VerificationKeyParseError isn't exported from Cardano.Crypto.Signing/*
106107
-- Inconsistencies
107108
| DelegationError !Genesis.GenesisDelegationError

cardano-node/src/Cardano/CLI/Run.hs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ module Cardano.CLI.Run (
2929

3030
import Cardano.Prelude hiding (option, trace)
3131

32-
import Codec.Serialise (serialise)
3332
import Control.Monad.Trans.Except (ExceptT)
3433
import Control.Monad.Trans.Except.Extra (hoistEither, firstExceptT)
3534
import qualified Data.ByteString.Lazy as LB
@@ -272,7 +271,7 @@ runCommand (SpendGenesisUTxO ptcl genFile genHash (NewTxFile ctTx) ctKey genRich
272271
update
273272
ptcl
274273
sk
275-
liftIO . ensureNewFileLBS ctTx $ serialise tx
274+
liftIO . ensureNewFileLBS ctTx $ toCborTxAux tx
276275

277276
runCommand (SpendUTxO ptcl genFile genHash (NewTxFile ctTx) ctKey ins outs) = do
278277
sk <- readSigningKey ptcl ctKey
@@ -292,7 +291,7 @@ runCommand (SpendUTxO ptcl genFile genHash (NewTxFile ctTx) ctKey ins outs) = do
292291
update
293292
ptcl
294293
sk
295-
liftIO . ensureNewFileLBS ctTx $ serialise gTx
294+
liftIO . ensureNewFileLBS ctTx $ toCborTxAux gTx
296295

297296
runCommand (GenerateTxs
298297
logConfigFp

cardano-node/src/Cardano/CLI/Tx.hs

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,25 @@ module Cardano.CLI.Tx
99
, NewTxFile(..)
1010
, prettyAddress
1111
, readByronTx
12+
, normalByronTxToGenTx
1213
, txSpendGenesisUTxOByronPBFT
1314
, issueGenesisUTxOExpenditure
1415
, txSpendUTxOByronPBFT
1516
, issueUTxOExpenditure
1617
, nodeSubmitTx
18+
19+
--TODO: remove when they are exported from the ledger
20+
, fromCborTxAux
21+
, toCborTxAux
1722
)
1823
where
1924

20-
import Prelude (error, show)
21-
import Cardano.Prelude hiding (option, show, trace, (%))
25+
import Prelude (error)
26+
import Cardano.Prelude hiding (option, trace, (%))
2227

23-
import Codec.Serialise (deserialiseOrFail)
24-
import Control.Monad.Trans.Except.Extra (left, right)
28+
import Control.Monad.Trans.Except.Extra (right)
2529
import qualified Data.ByteString.Lazy as LB
30+
import qualified Data.ByteString as B
2631
import qualified Data.Map.Strict as Map
2732
import Data.String (IsString)
2833
import Data.Text (Text)
@@ -31,10 +36,11 @@ import Formatting ((%), sformat)
3136

3237
import Control.Tracer (traceWith, stdoutTracer)
3338

39+
import qualified Cardano.Binary as Binary
40+
3441
import Cardano.Chain.Common (Address)
3542
import qualified Cardano.Chain.Common as Common
3643
import Cardano.Chain.Genesis as Genesis
37-
import qualified Cardano.Chain.MempoolPayload as CC.Mempool
3844
import Cardano.Chain.UTxO ( mkTxAux, annotateTxAux
3945
, Tx(..), TxId, TxIn, TxOut)
4046
import qualified Cardano.Chain.UTxO as UTxO
@@ -77,9 +83,14 @@ prettyAddress addr = sformat
7783
readByronTx :: TxFile -> IO (GenTx ByronBlock)
7884
readByronTx (TxFile fp) = do
7985
txBS <- LB.readFile fp
80-
case deserialiseOrFail txBS of
86+
case fromCborTxAux txBS of
8187
Left e -> throwIO $ TxDeserialisationFailed fp e
82-
Right tx -> pure tx
88+
Right tx -> pure (normalByronTxToGenTx tx)
89+
90+
-- | The 'GenTx' is all the kinds of transactions that can be submitted
91+
-- and \"normal\" Byron transactions are just one of the kinds.
92+
normalByronTxToGenTx :: UTxO.ATxAux ByteString -> GenTx ByronBlock
93+
normalByronTxToGenTx tx' = Byron.ByronTx (Byron.byronIdTx tx') tx'
8394

8495
-- | Given a Tx id, produce a UTxO Tx input witness, by signing it
8596
-- with respect to a given protocol magic.
@@ -139,10 +150,9 @@ txSpendGenesisUTxOByronPBFT
139150
-> SigningKey
140151
-> Address
141152
-> NonEmpty TxOut
142-
-> GenTx ByronBlock
153+
-> UTxO.ATxAux ByteString
143154
txSpendGenesisUTxOByronPBFT gc sk genAddr outs =
144-
Byron.fromMempoolPayload
145-
$ CC.Mempool.MempoolTx $ annotateTxAux $ mkTxAux tx (pure wit)
155+
annotateTxAux $ mkTxAux tx (pure wit)
146156
where
147157
tx = UnsafeTx (pure txIn) outs txattrs
148158

@@ -167,7 +177,7 @@ issueGenesisUTxOExpenditure
167177
-> Update
168178
-> Protocol
169179
-> Crypto.SigningKey
170-
-> ExceptT RealPBFTError IO (GenTx ByronBlock)
180+
-> ExceptT RealPBFTError IO (UTxO.ATxAux ByteString)
171181
issueGenesisUTxOExpenditure
172182
genRichAddr
173183
outs
@@ -182,14 +192,9 @@ issueGenesisUTxOExpenditure
182192
sk =
183193
withRealPBFT gHash genFile nMagic sigThresh delCertFp sKeyFp update ptcl
184194
$ \(Consensus.ProtocolRealPBFT gc _ _ _ _)-> do
185-
case txSpendGenesisUTxOByronPBFT gc sk genRichAddr outs of
186-
tx@(ByronTx txid _) -> do
187-
putStrLn $ sformat ("TxId: "%Crypto.hashHexF) txid
188-
right tx
189-
x -> left . InvariantViolation
190-
. T.pack
191-
$ "A non-ByronTx GenTx out of 'txSpendUTxOByronPBFT': "
192-
<> show x
195+
let tx = txSpendGenesisUTxOByronPBFT gc sk genRichAddr outs
196+
traceWith stdoutTracer ("TxId: " ++ condense (Byron.byronIdTx tx))
197+
right tx
193198

194199
-- | Generate a transaction from given Tx inputs to outputs,
195200
-- signed by the given key.
@@ -198,10 +203,9 @@ txSpendUTxOByronPBFT
198203
-> SigningKey
199204
-> NonEmpty TxIn
200205
-> NonEmpty TxOut
201-
-> GenTx ByronBlock
206+
-> UTxO.ATxAux ByteString
202207
txSpendUTxOByronPBFT gc sk ins outs =
203-
Byron.fromMempoolPayload
204-
$ CC.Mempool.MempoolTx $ annotateTxAux $ mkTxAux tx (pure wit)
208+
annotateTxAux $ mkTxAux tx (pure wit)
205209
where
206210
tx = UnsafeTx ins outs txattrs
207211

@@ -223,7 +227,7 @@ issueUTxOExpenditure
223227
-> Update
224228
-> Protocol
225229
-> Crypto.SigningKey
226-
-> ExceptT RealPBFTError IO (GenTx ByronBlock)
230+
-> ExceptT RealPBFTError IO (UTxO.ATxAux ByteString)
227231
issueUTxOExpenditure
228232
ins
229233
outs
@@ -238,15 +242,9 @@ issueUTxOExpenditure
238242
key = do
239243
withRealPBFT gHash genFile nMagic sigThresh delCertFp sKeyFp update ptcl $
240244
\(Consensus.ProtocolRealPBFT gc _ _ _ _)-> do
241-
case txSpendUTxOByronPBFT gc key ins outs of
242-
tx@(ByronTx txid _) -> do
243-
putStrLn $ sformat ("TxId: "%Crypto.hashHexF) txid
244-
pure tx
245-
x ->
246-
left . InvariantViolation
247-
. T.pack
248-
$ "A non-ByronTx GenTx out of 'txSpendUTxOByronPBFT': "
249-
<> show x
245+
let tx = txSpendUTxOByronPBFT gc key ins outs
246+
traceWith stdoutTracer ("TxId: " ++ condense (Byron.byronIdTx tx))
247+
pure tx
250248

251249
-- | Submit a transaction to a node specified by topology info.
252250
nodeSubmitTx
@@ -283,3 +281,17 @@ nodeSubmitTx
283281
(node topology)
284282
gentx
285283
stdoutTracer
284+
285+
--TODO: remove these local definitions when the updated ledger lib is available
286+
fromCborTxAux :: LB.ByteString -> Either Binary.DecoderError (UTxO.ATxAux B.ByteString)
287+
fromCborTxAux lbs =
288+
fmap (annotationBytes lbs)
289+
$ Binary.decodeFullDecoder "Cardano.Chain.UTxO.TxAux.fromCborTxAux"
290+
Binary.fromCBOR lbs
291+
where
292+
annotationBytes :: Functor f => LB.ByteString -> f Binary.ByteSpan -> f B.ByteString
293+
annotationBytes bytes = fmap (LB.toStrict . Binary.slice bytes)
294+
295+
toCborTxAux :: UTxO.ATxAux ByteString -> LB.ByteString
296+
toCborTxAux = LB.fromStrict . UTxO.aTaAnnotation -- The ByteString anotation is the CBOR encoded version.
297+

cardano-node/src/Cardano/CLI/Tx/Generation.hs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ import qualified Cardano.Crypto as Crypto
6666
import Cardano.Config.Topology (NodeAddress (..),
6767
NodeHostAddress(..))
6868
import Cardano.CLI.Ops
69-
import Cardano.CLI.Tx (txSpendGenesisUTxOByronPBFT)
69+
import Cardano.CLI.Tx (txSpendGenesisUTxOByronPBFT, normalByronTxToGenTx)
7070
import Cardano.CLI.Tx.BenchmarkingTxSubmission (ROEnv (..),
7171
TraceBenchTxSubmit (..),
7272
bulkSubmission)
@@ -407,7 +407,8 @@ prepareInitialFunds llTracer
407407
}
408408

409409
let genesisTx :: GenTx ByronBlock
410-
genesisTx = txSpendGenesisUTxOByronPBFT genesisConfig
410+
genesisTx = normalByronTxToGenTx $
411+
txSpendGenesisUTxOByronPBFT genesisConfig
411412
signingKey
412413
genesisAddress
413414
(NE.fromList [outForBig])

0 commit comments

Comments
 (0)