{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}

module Cardano.CLI.Byron.Tx
  ( ByronTxError (..)
  , Tx
  , TxFile
  , NewTxFile (..)
  , prettyAddress
  , readByronTx
  , normalByronTxToGenTx
  , txSpendGenesisUTxOByronPBFT
  , txSpendUTxOByronPBFT
  , nodeSubmitTx
  , renderByronTxError
  -- TODO: remove when they are exported from the ledger
  , fromCborTxAux
  , toCborTxAux
  , ScriptValidity (..)
  )
where

import           Cardano.Api
import           Cardano.Api.Byron
import qualified Cardano.Api.Ledger as L

import qualified Cardano.Binary as Binary
import qualified Cardano.Chain.Common as Common
import           Cardano.Chain.Genesis as Genesis
import qualified Cardano.Chain.UTxO as UTxO
import           Cardano.CLI.Byron.Key (byronWitnessToVerKey)
import           Cardano.CLI.Types.Common (TxFile)
import qualified Cardano.Crypto.Signing as Crypto
import           Ouroboros.Consensus.Byron.Ledger (ByronBlock, GenTx (..))
import qualified Ouroboros.Consensus.Byron.Ledger as Byron
import           Ouroboros.Consensus.Cardano.Block (EraMismatch (..))
import qualified Ouroboros.Network.Protocol.LocalTxSubmission.Client as Net.Tx

import           Data.Bifunctor (Bifunctor (..))
import           Data.ByteString (ByteString)
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as LB
import qualified Data.List as List
import           Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import           Data.Maybe (fromMaybe, mapMaybe)
import           Data.String (IsString)
import           Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Text.IO as Text
import           Formatting (sformat, (%))
import           GHC.Exts (IsList (..))

data ByronTxError
  = TxDeserialisationFailed !FilePath !Binary.DecoderError
  | ByronTxSubmitError !Text
  | ByronTxSubmitErrorEraMismatch !EraMismatch
  deriving Int -> ByronTxError -> ShowS
[ByronTxError] -> ShowS
ByronTxError -> [Char]
(Int -> ByronTxError -> ShowS)
-> (ByronTxError -> [Char])
-> ([ByronTxError] -> ShowS)
-> Show ByronTxError
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ByronTxError -> ShowS
showsPrec :: Int -> ByronTxError -> ShowS
$cshow :: ByronTxError -> [Char]
show :: ByronTxError -> [Char]
$cshowList :: [ByronTxError] -> ShowS
showList :: [ByronTxError] -> ShowS
Show

renderByronTxError :: ByronTxError -> Doc ann
renderByronTxError :: forall ann. ByronTxError -> Doc ann
renderByronTxError = \case
  ByronTxSubmitError Text
res -> Doc ann
"Error while submitting tx: " Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Text -> Doc ann
forall ann. Text -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Text
res
  ByronTxSubmitErrorEraMismatch EraMismatch{Text
ledgerEraName :: Text
ledgerEraName :: EraMismatch -> Text
ledgerEraName, Text
otherEraName :: Text
otherEraName :: EraMismatch -> Text
otherEraName} ->
    Doc ann
"The era of the node and the tx do not match. "
      Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Doc ann
"The node is running in the "
      Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Text -> Doc ann
forall ann. Text -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Text
ledgerEraName
      Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Doc ann
" era, but the transaction is for the "
      Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Text -> Doc ann
forall ann. Text -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Text
otherEraName
      Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Doc ann
" era."
  TxDeserialisationFailed [Char]
txFp DecoderError
decErr ->
    Doc ann
"Transaction deserialisation failed at " Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> [Char] -> Doc ann
forall a ann. Show a => a -> Doc ann
pshow [Char]
txFp Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Doc ann
" Error: " Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> DecoderError -> Doc ann
forall a ann. Show a => a -> Doc ann
pshow DecoderError
decErr

newtype NewTxFile
  = NewTxFile FilePath
  deriving (NewTxFile -> NewTxFile -> Bool
(NewTxFile -> NewTxFile -> Bool)
-> (NewTxFile -> NewTxFile -> Bool) -> Eq NewTxFile
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: NewTxFile -> NewTxFile -> Bool
== :: NewTxFile -> NewTxFile -> Bool
$c/= :: NewTxFile -> NewTxFile -> Bool
/= :: NewTxFile -> NewTxFile -> Bool
Eq, Eq NewTxFile
Eq NewTxFile =>
(NewTxFile -> NewTxFile -> Ordering)
-> (NewTxFile -> NewTxFile -> Bool)
-> (NewTxFile -> NewTxFile -> Bool)
-> (NewTxFile -> NewTxFile -> Bool)
-> (NewTxFile -> NewTxFile -> Bool)
-> (NewTxFile -> NewTxFile -> NewTxFile)
-> (NewTxFile -> NewTxFile -> NewTxFile)
-> Ord NewTxFile
NewTxFile -> NewTxFile -> Bool
NewTxFile -> NewTxFile -> Ordering
NewTxFile -> NewTxFile -> NewTxFile
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: NewTxFile -> NewTxFile -> Ordering
compare :: NewTxFile -> NewTxFile -> Ordering
$c< :: NewTxFile -> NewTxFile -> Bool
< :: NewTxFile -> NewTxFile -> Bool
$c<= :: NewTxFile -> NewTxFile -> Bool
<= :: NewTxFile -> NewTxFile -> Bool
$c> :: NewTxFile -> NewTxFile -> Bool
> :: NewTxFile -> NewTxFile -> Bool
$c>= :: NewTxFile -> NewTxFile -> Bool
>= :: NewTxFile -> NewTxFile -> Bool
$cmax :: NewTxFile -> NewTxFile -> NewTxFile
max :: NewTxFile -> NewTxFile -> NewTxFile
$cmin :: NewTxFile -> NewTxFile -> NewTxFile
min :: NewTxFile -> NewTxFile -> NewTxFile
Ord, Int -> NewTxFile -> ShowS
[NewTxFile] -> ShowS
NewTxFile -> [Char]
(Int -> NewTxFile -> ShowS)
-> (NewTxFile -> [Char])
-> ([NewTxFile] -> ShowS)
-> Show NewTxFile
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> NewTxFile -> ShowS
showsPrec :: Int -> NewTxFile -> ShowS
$cshow :: NewTxFile -> [Char]
show :: NewTxFile -> [Char]
$cshowList :: [NewTxFile] -> ShowS
showList :: [NewTxFile] -> ShowS
Show, [Char] -> NewTxFile
([Char] -> NewTxFile) -> IsString NewTxFile
forall a. ([Char] -> a) -> IsString a
$cfromString :: [Char] -> NewTxFile
fromString :: [Char] -> NewTxFile
IsString)

-- | Pretty-print an address in its Base58 form, and also
--   its full structure.
prettyAddress :: Address ByronAddr -> Text
prettyAddress :: Address ByronAddr -> Text
prettyAddress (ByronAddress Address
addr) =
  Format Text (Address -> Address -> Text)
-> Address -> Address -> Text
forall a. Format Text a -> a
sformat
    (Format (Address -> Text) (Address -> Address -> Text)
forall r. Format r (Address -> r)
Common.addressF Format (Address -> Text) (Address -> Address -> Text)
-> Format Text (Address -> Text)
-> Format Text (Address -> Address -> Text)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format (Address -> Text) (Address -> Text)
"\n" Format (Address -> Text) (Address -> Text)
-> Format Text (Address -> Text) -> Format Text (Address -> Text)
forall r a r'. Format r a -> Format r' r -> Format r' a
% Format Text (Address -> Text)
forall r. Format r (Address -> r)
Common.addressDetailedF)
    Address
addr
    Address
addr

-- TODO: Move to cardano-api
readByronTx :: TxFile In -> ExceptT ByronTxError IO (UTxO.ATxAux ByteString)
readByronTx :: TxFile 'In -> ExceptT ByronTxError IO (ATxAux ByteString)
readByronTx (File [Char]
fp) = do
  ByteString
txBS <- IO ByteString -> ExceptT ByronTxError IO ByteString
forall a. IO a -> ExceptT ByronTxError IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ByteString -> ExceptT ByronTxError IO ByteString)
-> IO ByteString -> ExceptT ByronTxError IO ByteString
forall a b. (a -> b) -> a -> b
$ [Char] -> IO ByteString
LB.readFile [Char]
fp
  case ByteString -> Either DecoderError (ATxAux ByteString)
fromCborTxAux ByteString
txBS of
    Left DecoderError
e -> ByronTxError -> ExceptT ByronTxError IO (ATxAux ByteString)
forall (m :: * -> *) x a. Monad m => x -> ExceptT x m a
left (ByronTxError -> ExceptT ByronTxError IO (ATxAux ByteString))
-> ByronTxError -> ExceptT ByronTxError IO (ATxAux ByteString)
forall a b. (a -> b) -> a -> b
$ [Char] -> DecoderError -> ByronTxError
TxDeserialisationFailed [Char]
fp DecoderError
e
    Right ATxAux ByteString
tx -> ATxAux ByteString -> ExceptT ByronTxError IO (ATxAux ByteString)
forall a. a -> ExceptT ByronTxError IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ATxAux ByteString
tx

-- | The 'GenTx' is all the kinds of transactions that can be submitted
-- and \"normal\" Byron transactions are just one of the kinds.
normalByronTxToGenTx :: UTxO.ATxAux ByteString -> GenTx ByronBlock
normalByronTxToGenTx :: ATxAux ByteString -> GenTx ByronBlock
normalByronTxToGenTx ATxAux ByteString
tx' = TxId -> ATxAux ByteString -> GenTx ByronBlock
Byron.ByronTx (ATxAux ByteString -> TxId
Byron.byronIdTx ATxAux ByteString
tx') ATxAux ByteString
tx'

-- | Given a genesis, and a pair of a genesis public key and address,
--   reconstruct a TxIn corresponding to the genesis UTxO entry.
genesisUTxOTxIn :: Genesis.Config -> Crypto.VerificationKey -> Common.Address -> UTxO.TxIn
genesisUTxOTxIn :: Config -> VerificationKey -> Address -> TxIn
genesisUTxOTxIn Config
gc VerificationKey
vk Address
genAddr =
  Maybe TxIn -> TxIn
handleMissingAddr (Maybe TxIn -> TxIn) -> Maybe TxIn -> TxIn
forall a b. (a -> b) -> a -> b
$ (TxIn, TxOut) -> TxIn
forall a b. (a, b) -> a
fst ((TxIn, TxOut) -> TxIn) -> Maybe (TxIn, TxOut) -> Maybe TxIn
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Address -> Map Address (TxIn, TxOut) -> Maybe (TxIn, TxOut)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Address
genAddr Map Address (TxIn, TxOut)
initialUtxo
 where
  initialUtxo :: Map Common.Address (UTxO.TxIn, UTxO.TxOut)
  initialUtxo :: Map Address (TxIn, TxOut)
initialUtxo =
    [(Address, (TxIn, TxOut))] -> Map Address (TxIn, TxOut)
[Item (Map Address (TxIn, TxOut))] -> Map Address (TxIn, TxOut)
forall l. IsList l => [Item l] -> l
fromList
      ([(Address, (TxIn, TxOut))] -> Map Address (TxIn, TxOut))
-> (Config -> [(Address, (TxIn, TxOut))])
-> Config
-> Map Address (TxIn, TxOut)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((TxIn, TxOut) -> Maybe (Address, (TxIn, TxOut)))
-> [(TxIn, TxOut)] -> [(Address, (TxIn, TxOut))]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (\(TxIn
inp, TxOut
out) -> TxIn -> Address -> TxOut -> (Address, (TxIn, TxOut))
mkEntry TxIn
inp Address
genAddr (TxOut -> (Address, (TxIn, TxOut)))
-> Maybe TxOut -> Maybe (Address, (TxIn, TxOut))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> VerificationKey -> TxOut -> Maybe TxOut
keyMatchesUTxO VerificationKey
vk TxOut
out)
      ([(TxIn, TxOut)] -> [(Address, (TxIn, TxOut))])
-> (Config -> [(TxIn, TxOut)])
-> Config
-> [(Address, (TxIn, TxOut))]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(CompactTxIn, CompactTxOut)] -> [(TxIn, TxOut)]
fromCompactTxInTxOutList
      ([(CompactTxIn, CompactTxOut)] -> [(TxIn, TxOut)])
-> (Config -> [(CompactTxIn, CompactTxOut)])
-> Config
-> [(TxIn, TxOut)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map CompactTxIn CompactTxOut -> [(CompactTxIn, CompactTxOut)]
Map CompactTxIn CompactTxOut
-> [Item (Map CompactTxIn CompactTxOut)]
forall l. IsList l => l -> [Item l]
toList
      (Map CompactTxIn CompactTxOut -> [(CompactTxIn, CompactTxOut)])
-> (Config -> Map CompactTxIn CompactTxOut)
-> Config
-> [(CompactTxIn, CompactTxOut)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UTxO -> Map CompactTxIn CompactTxOut
UTxO.unUTxO
      (UTxO -> Map CompactTxIn CompactTxOut)
-> (Config -> UTxO) -> Config -> Map CompactTxIn CompactTxOut
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Config -> UTxO
UTxO.genesisUtxo
      (Config -> Map Address (TxIn, TxOut))
-> Config -> Map Address (TxIn, TxOut)
forall a b. (a -> b) -> a -> b
$ Config
gc
   where
    mkEntry
      :: UTxO.TxIn
      -> Common.Address
      -> UTxO.TxOut
      -> (Common.Address, (UTxO.TxIn, UTxO.TxOut))
    mkEntry :: TxIn -> Address -> TxOut -> (Address, (TxIn, TxOut))
mkEntry TxIn
inp Address
addr TxOut
out = (Address
addr, (TxIn
inp, TxOut
out))

  fromCompactTxInTxOutList
    :: [(UTxO.CompactTxIn, UTxO.CompactTxOut)]
    -> [(UTxO.TxIn, UTxO.TxOut)]
  fromCompactTxInTxOutList :: [(CompactTxIn, CompactTxOut)] -> [(TxIn, TxOut)]
fromCompactTxInTxOutList =
    ((CompactTxIn, CompactTxOut) -> (TxIn, TxOut))
-> [(CompactTxIn, CompactTxOut)] -> [(TxIn, TxOut)]
forall a b. (a -> b) -> [a] -> [b]
map ((CompactTxIn -> TxIn)
-> (CompactTxOut -> TxOut)
-> (CompactTxIn, CompactTxOut)
-> (TxIn, TxOut)
forall a b c d. (a -> b) -> (c -> d) -> (a, c) -> (b, d)
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap CompactTxIn -> TxIn
UTxO.fromCompactTxIn CompactTxOut -> TxOut
UTxO.fromCompactTxOut)

  keyMatchesUTxO :: Crypto.VerificationKey -> UTxO.TxOut -> Maybe UTxO.TxOut
  keyMatchesUTxO :: VerificationKey -> TxOut -> Maybe TxOut
keyMatchesUTxO VerificationKey
key TxOut
out =
    if VerificationKey -> Address -> Bool
Common.checkVerKeyAddress VerificationKey
key (TxOut -> Address
UTxO.txOutAddress TxOut
out)
      then TxOut -> Maybe TxOut
forall a. a -> Maybe a
Just TxOut
out
      else Maybe TxOut
forall a. Maybe a
Nothing

  handleMissingAddr :: Maybe UTxO.TxIn -> UTxO.TxIn
  handleMissingAddr :: Maybe TxIn -> TxIn
handleMissingAddr =
    TxIn -> Maybe TxIn -> TxIn
forall a. a -> Maybe a -> a
fromMaybe (TxIn -> Maybe TxIn -> TxIn)
-> ([Char] -> TxIn) -> [Char] -> Maybe TxIn -> TxIn
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> TxIn
forall a. HasCallStack => [Char] -> a
error ([Char] -> Maybe TxIn -> TxIn) -> [Char] -> Maybe TxIn -> TxIn
forall a b. (a -> b) -> a -> b
$
      [Char]
"\nGenesis UTxO has no address\n"
        [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> Text -> [Char]
Text.unpack (Address ByronAddr -> Text
prettyAddress (Address -> Address ByronAddr
ByronAddress Address
genAddr))
        [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> [Char]
"\n\nIt has the following, though:\n\n"
        [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> (Address -> [Char]) -> [Address] -> [Char]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
List.concatMap (Text -> [Char]
Text.unpack (Text -> [Char]) -> (Address -> Text) -> Address -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Address ByronAddr -> Text
prettyAddress (Address ByronAddr -> Text)
-> (Address -> Address ByronAddr) -> Address -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Address -> Address ByronAddr
ByronAddress) (Map Address (TxIn, TxOut) -> [Address]
forall k a. Map k a -> [k]
Map.keys Map Address (TxIn, TxOut)
initialUtxo)

-- | Generate a transaction spending genesis UTxO at a given address,
--   to given outputs, signed by the given key.
txSpendGenesisUTxOByronPBFT
  :: Genesis.Config
  -> NetworkId
  -> SomeByronSigningKey
  -> Address ByronAddr
  -> [TxOut CtxTx ByronEra]
  -> ATxAux ByteString
txSpendGenesisUTxOByronPBFT :: Config
-> NetworkId
-> SomeByronSigningKey
-> Address ByronAddr
-> [TxOut CtxTx ByronEra]
-> ATxAux ByteString
txSpendGenesisUTxOByronPBFT Config
gc NetworkId
nId SomeByronSigningKey
sk (ByronAddress Address
bAddr) [TxOut CtxTx ByronEra]
outs =
  let txins :: [(TxIn, BuildTxWith BuildTx (Witness WitCtxTxIn era))]
txins = [(TxIn -> TxIn
fromByronTxIn TxIn
txIn, Witness WitCtxTxIn era
-> BuildTxWith BuildTx (Witness WitCtxTxIn era)
forall a. a -> BuildTxWith BuildTx a
BuildTxWith (KeyWitnessInCtx WitCtxTxIn -> Witness WitCtxTxIn era
forall witctx era. KeyWitnessInCtx witctx -> Witness witctx era
KeyWitness KeyWitnessInCtx WitCtxTxIn
KeyWitnessForSpending))]
   in case TxIns BuildTx ByronEra
-> [TxOut CtxTx ByronEra]
-> Either TxBodyError (Annotated Tx ByteString)
makeByronTransactionBody TxIns BuildTx ByronEra
forall {era}.
[(TxIn, BuildTxWith BuildTx (Witness WitCtxTxIn era))]
txins [TxOut CtxTx ByronEra]
outs of
        Left TxBodyError
err -> [Char] -> ATxAux ByteString
forall a. HasCallStack => [Char] -> a
error ([Char] -> ATxAux ByteString) -> [Char] -> ATxAux ByteString
forall a b. (a -> b) -> a -> b
$ [Char]
"Error occurred while creating a Byron genesis based UTxO transaction: " [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> TxBodyError -> [Char]
forall a. Show a => a -> [Char]
show TxBodyError
err
        Right Annotated Tx ByteString
txBody ->
          let bWit :: KeyWitness ByronEra
bWit = SomeByronSigningKey
-> NetworkId -> Annotated Tx ByteString -> KeyWitness ByronEra
fromByronWitness SomeByronSigningKey
sk NetworkId
nId Annotated Tx ByteString
txBody
           in [KeyWitness ByronEra]
-> Annotated Tx ByteString -> ATxAux ByteString
forall era.
[KeyWitness era] -> Annotated Tx ByteString -> ATxAux ByteString
makeSignedByronTransaction [KeyWitness ByronEra
bWit] Annotated Tx ByteString
txBody
 where
  ByronVerificationKey VerificationKey
vKey = SomeByronSigningKey -> VerificationKey ByronKey
byronWitnessToVerKey SomeByronSigningKey
sk

  txIn :: UTxO.TxIn
  txIn :: TxIn
txIn = Config -> VerificationKey -> Address -> TxIn
genesisUTxOTxIn Config
gc VerificationKey
vKey Address
bAddr

-- | Generate a transaction from given Tx inputs to outputs,
--   signed by the given key.
txSpendUTxOByronPBFT
  :: NetworkId
  -> SomeByronSigningKey
  -> [TxIn]
  -> [TxOut CtxTx ByronEra]
  -> ATxAux ByteString
txSpendUTxOByronPBFT :: NetworkId
-> SomeByronSigningKey
-> [TxIn]
-> [TxOut CtxTx ByronEra]
-> ATxAux ByteString
txSpendUTxOByronPBFT NetworkId
nId SomeByronSigningKey
sk [TxIn]
txIns [TxOut CtxTx ByronEra]
outs = do
  let apiTxIns :: TxIns BuildTx ByronEra
apiTxIns = [(TxIn
txIn, Witness WitCtxTxIn ByronEra
-> BuildTxWith BuildTx (Witness WitCtxTxIn ByronEra)
forall a. a -> BuildTxWith BuildTx a
BuildTxWith (KeyWitnessInCtx WitCtxTxIn -> Witness WitCtxTxIn ByronEra
forall witctx era. KeyWitnessInCtx witctx -> Witness witctx era
KeyWitness KeyWitnessInCtx WitCtxTxIn
KeyWitnessForSpending)) | TxIn
txIn <- [TxIn]
txIns]

  case TxIns BuildTx ByronEra
-> [TxOut CtxTx ByronEra]
-> Either TxBodyError (Annotated Tx ByteString)
makeByronTransactionBody TxIns BuildTx ByronEra
apiTxIns [TxOut CtxTx ByronEra]
outs of
    Left TxBodyError
err -> [Char] -> ATxAux ByteString
forall a. HasCallStack => [Char] -> a
error ([Char] -> ATxAux ByteString) -> [Char] -> ATxAux ByteString
forall a b. (a -> b) -> a -> b
$ [Char]
"Error occurred while creating a Byron genesis based UTxO transaction: " [Char] -> ShowS
forall a. Semigroup a => a -> a -> a
<> TxBodyError -> [Char]
forall a. Show a => a -> [Char]
show TxBodyError
err
    Right Annotated Tx ByteString
txBody ->
      let bWit :: KeyWitness ByronEra
bWit = SomeByronSigningKey
-> NetworkId -> Annotated Tx ByteString -> KeyWitness ByronEra
fromByronWitness SomeByronSigningKey
sk NetworkId
nId Annotated Tx ByteString
txBody
       in [KeyWitness ByronEra]
-> Annotated Tx ByteString -> ATxAux ByteString
forall era.
[KeyWitness era] -> Annotated Tx ByteString -> ATxAux ByteString
makeSignedByronTransaction [KeyWitness ByronEra
bWit] Annotated Tx ByteString
txBody

fromByronWitness
  :: SomeByronSigningKey -> NetworkId -> L.Annotated L.Tx ByteString -> KeyWitness ByronEra
fromByronWitness :: SomeByronSigningKey
-> NetworkId -> Annotated Tx ByteString -> KeyWitness ByronEra
fromByronWitness SomeByronSigningKey
bw NetworkId
nId Annotated Tx ByteString
txBody =
  case SomeByronSigningKey
bw of
    AByronSigningKeyLegacy SigningKey ByronKeyLegacy
sk -> NetworkId
-> Annotated Tx ByteString
-> SigningKey ByronKeyLegacy
-> KeyWitness ByronEra
forall key.
IsByronKey key =>
NetworkId
-> Annotated Tx ByteString -> SigningKey key -> KeyWitness ByronEra
makeByronKeyWitness NetworkId
nId Annotated Tx ByteString
txBody SigningKey ByronKeyLegacy
sk
    AByronSigningKey SigningKey ByronKey
sk' -> NetworkId
-> Annotated Tx ByteString
-> SigningKey ByronKey
-> KeyWitness ByronEra
forall key.
IsByronKey key =>
NetworkId
-> Annotated Tx ByteString -> SigningKey key -> KeyWitness ByronEra
makeByronKeyWitness NetworkId
nId Annotated Tx ByteString
txBody SigningKey ByronKey
sk'

-- | Submit a transaction to a node specified by topology info.
nodeSubmitTx
  :: SocketPath
  -> NetworkId
  -> GenTx ByronBlock
  -> ExceptT ByronTxError IO ()
nodeSubmitTx :: SocketPath
-> NetworkId -> GenTx ByronBlock -> ExceptT ByronTxError IO ()
nodeSubmitTx SocketPath
nodeSocketPath NetworkId
network GenTx ByronBlock
gentx = do
  let connctInfo :: LocalNodeConnectInfo
connctInfo =
        LocalNodeConnectInfo
          { localNodeSocketPath :: SocketPath
localNodeSocketPath = SocketPath
nodeSocketPath
          , localNodeNetworkId :: NetworkId
localNodeNetworkId = NetworkId
network
          , localConsensusModeParams :: ConsensusModeParams
localConsensusModeParams = EpochSlots -> ConsensusModeParams
CardanoModeParams (Word64 -> EpochSlots
EpochSlots Word64
21600)
          }
  SubmitResult TxValidationErrorInCardanoMode
res <- IO (SubmitResult TxValidationErrorInCardanoMode)
-> ExceptT
     ByronTxError IO (SubmitResult TxValidationErrorInCardanoMode)
forall a. IO a -> ExceptT ByronTxError IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (SubmitResult TxValidationErrorInCardanoMode)
 -> ExceptT
      ByronTxError IO (SubmitResult TxValidationErrorInCardanoMode))
-> IO (SubmitResult TxValidationErrorInCardanoMode)
-> ExceptT
     ByronTxError IO (SubmitResult TxValidationErrorInCardanoMode)
forall a b. (a -> b) -> a -> b
$ LocalNodeConnectInfo
-> TxInMode -> IO (SubmitResult TxValidationErrorInCardanoMode)
forall (m :: * -> *).
MonadIO m =>
LocalNodeConnectInfo
-> TxInMode -> m (SubmitResult TxValidationErrorInCardanoMode)
submitTxToNodeLocal LocalNodeConnectInfo
connctInfo (GenTx ByronBlock -> TxInMode
TxInByronSpecial GenTx ByronBlock
gentx)
  case SubmitResult TxValidationErrorInCardanoMode
res of
    SubmitResult TxValidationErrorInCardanoMode
Net.Tx.SubmitSuccess -> IO () -> ExceptT ByronTxError IO ()
forall a. IO a -> ExceptT ByronTxError IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT ByronTxError IO ())
-> IO () -> ExceptT ByronTxError IO ()
forall a b. (a -> b) -> a -> b
$ Text -> IO ()
Text.putStrLn Text
"Transaction successfully submitted."
    Net.Tx.SubmitFail TxValidationErrorInCardanoMode
reason ->
      case TxValidationErrorInCardanoMode
reason of
        TxValidationErrorInCardanoMode TxValidationError era
err -> ByronTxError -> ExceptT ByronTxError IO ()
forall (m :: * -> *) x a. Monad m => x -> ExceptT x m a
left (ByronTxError -> ExceptT ByronTxError IO ())
-> ([Char] -> ByronTxError) -> [Char] -> ExceptT ByronTxError IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByronTxError
ByronTxSubmitError (Text -> ByronTxError)
-> ([Char] -> Text) -> [Char] -> ByronTxError
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Text
Text.pack ([Char] -> ExceptT ByronTxError IO ())
-> [Char] -> ExceptT ByronTxError IO ()
forall a b. (a -> b) -> a -> b
$ TxValidationError era -> [Char]
forall a. Show a => a -> [Char]
show TxValidationError era
err
        TxValidationEraMismatch EraMismatch
mismatchErr -> ByronTxError -> ExceptT ByronTxError IO ()
forall (m :: * -> *) x a. Monad m => x -> ExceptT x m a
left (ByronTxError -> ExceptT ByronTxError IO ())
-> ByronTxError -> ExceptT ByronTxError IO ()
forall a b. (a -> b) -> a -> b
$ EraMismatch -> ByronTxError
ByronTxSubmitErrorEraMismatch EraMismatch
mismatchErr

  () -> ExceptT ByronTxError IO ()
forall a. a -> ExceptT ByronTxError IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- TODO: remove these local definitions when the updated ledger lib is available
fromCborTxAux :: LB.ByteString -> Either Binary.DecoderError (UTxO.ATxAux B.ByteString)
fromCborTxAux :: ByteString -> Either DecoderError (ATxAux ByteString)
fromCborTxAux ByteString
lbs =
  ByteString -> ATxAux ByteSpan -> ATxAux ByteString
forall (f :: * -> *).
Functor f =>
ByteString -> f ByteSpan -> f ByteString
annotationBytes ByteString
lbs
    (ATxAux ByteSpan -> ATxAux ByteString)
-> Either DecoderError (ATxAux ByteSpan)
-> Either DecoderError (ATxAux ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text
-> (forall s. Decoder s (ATxAux ByteSpan))
-> ByteString
-> Either DecoderError (ATxAux ByteSpan)
forall a.
Text
-> (forall s. Decoder s a) -> ByteString -> Either DecoderError a
Binary.decodeFullDecoder
      Text
"Cardano.Chain.UTxO.TxAux.fromCborTxAux"
      Decoder s (ATxAux ByteSpan)
forall s. Decoder s (ATxAux ByteSpan)
forall a s. FromCBOR a => Decoder s a
Binary.fromCBOR
      ByteString
lbs
 where
  annotationBytes :: Functor f => LB.ByteString -> f L.ByteSpan -> f B.ByteString
  annotationBytes :: forall (f :: * -> *).
Functor f =>
ByteString -> f ByteSpan -> f ByteString
annotationBytes ByteString
bytes = (ByteSpan -> ByteString) -> f ByteSpan -> f ByteString
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ByteString -> ByteString
LB.toStrict (ByteString -> ByteString)
-> (ByteSpan -> ByteString) -> ByteSpan -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteSpan -> ByteString
L.slice ByteString
bytes)

toCborTxAux :: UTxO.ATxAux ByteString -> LB.ByteString
toCborTxAux :: ATxAux ByteString -> ByteString
toCborTxAux = ByteString -> ByteString
LB.fromStrict (ByteString -> ByteString)
-> (ATxAux ByteString -> ByteString)
-> ATxAux ByteString
-> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ATxAux ByteString -> ByteString
forall a. ATxAux a -> a
UTxO.aTaAnnotation -- The ByteString anotation is the CBOR encoded version.