packages feed

cardano-transactions-1.0.0: test/Data/UTxO/Transaction/Cardano/ByronSpec.hs

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}

{-# OPTIONS_GHC -fno-warn-orphans #-}

module Data.UTxO.Transaction.Cardano.ByronSpec
    ( spec
    ) where

import Prelude

import Cardano.Chain.UTxO
    ( TxIn (..), TxInWitness (..), TxOut (..), TxSigData (..) )
import Cardano.Crypto.ProtocolMagic
    ( ProtocolMagicId (..) )
import Control.Monad
    ( foldM )
import Data.ByteString
    ( ByteString )
import Data.Function
    ( (&) )
import Data.List.NonEmpty
    ( NonEmpty )
import Data.Maybe
    ( fromJust, fromMaybe, isNothing )
import Data.Text
    ( Text )
import Data.UTxO.Transaction
    ( ErrMkPayment (..), MkPayment (..) )
import Data.UTxO.Transaction.Cardano.Byron
    ( Byron
    , decodeCoinSel
    , decodeTx
    , encodeCoinSel
    , encodeTx
    , fromBase16
    , fromBase58
    , fromBase64
    , mainnetMagic
    , mkInit
    , mkInput
    , mkOutput
    , mkSignKey
    , testnetMagic
    )
import Data.Word
    ( Word32, Word64 )
import Numeric.Natural
    ( Natural )
import System.Process
    ( readProcess )
import Test.Cardano.Chain.UTxO.Gen
    ( genTxIn, genTxInWitness, genTxOut, genTxSigData )
import Test.Hspec
    ( Spec, describe, expectationFailure, it, shouldBe )
import Test.Hspec.QuickCheck
    ( prop )
import Test.QuickCheck
    ( Arbitrary (..)
    , NonEmptyList (..)
    , Property
    , conjoin
    , counterexample
    , elements
    , forAll
    , listOf
    , oneof
    , property
    , quickCheck
    , suchThat
    , withMaxSuccess
    , (===)
    )
import Test.QuickCheck.Hedgehog
    ( hedgehog )

import qualified Codec.CBOR.Decoding as CBOR
import qualified Codec.CBOR.Encoding as CBOR
import qualified Codec.CBOR.Pretty as CBOR
import qualified Codec.CBOR.Read as CBOR
import qualified Codec.CBOR.Write as CBOR
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BL
import qualified Data.List.NonEmpty as NE
import qualified Data.Text as T
import qualified Data.UTxO.Transaction as Tx

{-# ANN spec ("HLint: ignore Use head" :: String) #-}

spec :: Spec
spec = do
    describe "CBOR roundtrips" $ do
        it "CoinSel Byron" $ withMaxSuccess 500 $ property $
            prop_RoundTripCBOR encodeCoinSel decodeCoinSel

        it "Tx Byron" $ withMaxSuccess 500 $ property $
            prop_RoundTripCBOR encodeTx decodeTx

    describe "(Mainnet) Golden Tests Transaction Construction" $ do
        it "1 input, 1 output (DSL)" $ do
            compareGolden goldenMainnet__1_1 $ Tx.empty mainnetMagic
                & Tx.addInput (unsafeMkInput 0 (txids !! 0))
                & Tx.addOutput (unsafeMkOutput 42 (addrs !! 0))
                & Tx.lock
                & Tx.signWith (unsafeMkSignKey (keys !! 0))
                & Tx.serialize

        it "1 input, 1 output (CLI)" $ do
            state <- cardanoTx [ "empty", mainnetMagicT ] ""
                 >>= cardanoTx [ "add-input", "0", txids !! 0 ]
                 >>= cardanoTx [ "add-output", "42", addrs !! 0 ]
                 >>= cardanoTx [ "lock" ]
                 >>= cardanoTx [ "sign-with", keys !! 0 ]

            defaul <- fromBase64E <$> cardanoTx [ "serialize" ] state
            base16 <- fromBase16E <$> cardanoTx [ "serialize", "--base16" ] state
            base64 <- fromBase64E <$> cardanoTx [ "serialize", "--base64" ] state
            compareGolden goldenMainnet__1_1 base16
            compareGolden goldenMainnet__1_1 base64
            compareGolden goldenMainnet__1_1 defaul

        it "2 inputs, 2 outputs (DSL)" $ do
            compareGolden goldenMainnet__2_2 $ Tx.empty mainnetMagic
                & Tx.addInput (unsafeMkInput 0 (txids !! 0))
                & Tx.addInput (unsafeMkInput 1 (txids !! 0))
                & Tx.addOutput (unsafeMkOutput 42 (addrs !! 0))
                & Tx.addOutput (unsafeMkOutput 14 (addrs !! 1))
                & Tx.lock
                & Tx.signWith (unsafeMkSignKey (keys !! 0))
                & Tx.signWith (unsafeMkSignKey (keys !! 1))
                & Tx.serialize

        it "2 inputs, 2 outputs (CLI)" $ do
            state <- cardanoTx [ "empty", mainnetMagicT ] ""
                 >>= cardanoTx [ "add-input", "0", txids !! 0 ]
                 >>= cardanoTx [ "add-input", "1", txids !! 0 ]
                 >>= cardanoTx [ "add-output", "42", addrs !! 0 ]
                 >>= cardanoTx [ "add-output", "14", addrs !! 1 ]
                 >>= cardanoTx [ "lock" ]
                 >>= cardanoTx [ "sign-with", keys !! 0 ]
                 >>= cardanoTx [ "sign-with", keys !! 1 ]

            defaul <- fromBase64E <$> cardanoTx [ "serialize" ] state
            base16 <- fromBase16E <$> cardanoTx [ "serialize", "--base16" ] state
            base64 <- fromBase64E <$> cardanoTx [ "serialize", "--base64" ] state
            compareGolden goldenMainnet__2_2 base16
            compareGolden goldenMainnet__2_2 base64
            compareGolden goldenMainnet__2_2 defaul

        it "1 input, 25 outputs (DSL)" $ do
            compareGolden goldenMainnet__25_1 $ Tx.empty mainnetMagic
                & Tx.addInput (unsafeMkInput 0 (txids !! 0))
                & flip (foldr Tx.addOutput) (replicate 25 $ unsafeMkOutput 14 (addrs !! 0))
                & Tx.lock
                & Tx.signWith (unsafeMkSignKey (keys !! 0))
                & Tx.serialize

        it "1 input, 25 outputs (CLI)" $ do
            state <- cardanoTx [ "empty", mainnetMagicT ] ""
                 >>= cardanoTx [ "add-input", "0", txids !! 0 ]
                 >>= flip (foldM (&)) (replicate 25 $ cardanoTx [ "add-output", "14", addrs !! 0])
                 >>= cardanoTx [ "lock" ]
                 >>= cardanoTx [ "sign-with", keys !! 0 ]

            defaul <- fromBase64E <$> cardanoTx [ "serialize" ] state
            base16 <- fromBase16E <$> cardanoTx [ "serialize", "--base16" ] state
            base64 <- fromBase64E <$> cardanoTx [ "serialize", "--base64" ] state
            compareGolden goldenMainnet__25_1 base16
            compareGolden goldenMainnet__25_1 base64
            compareGolden goldenMainnet__25_1 defaul

    describe "(Testnet) Golden Tests Transaction Construction" $ do
        it "1 input, 1 output (DSL)" $ do
            compareGolden goldenTestnet__1_1 $ Tx.empty testnetMagic
                & Tx.addInput (unsafeMkInput 0 (txids !! 0))
                & Tx.addOutput (unsafeMkOutput 42 (addrs !! 2))
                & Tx.lock
                & Tx.signWith (unsafeMkSignKey (keys !! 0))
                & Tx.serialize

        it "1 input, 1 output (CLI)" $ do
            state <- cardanoTx [ "empty", testnetMagicT ] ""
                 >>= cardanoTx [ "add-input", "0", txids !! 0 ]
                 >>= cardanoTx [ "add-output", "42", addrs !! 2 ]
                 >>= cardanoTx [ "lock" ]
                 >>= cardanoTx [ "sign-with", keys !! 0 ]

            defaul <- fromBase64E <$> cardanoTx [ "serialize" ] state
            base16 <- fromBase16E <$> cardanoTx [ "serialize", "--base16" ] state
            base64 <- fromBase64E <$> cardanoTx [ "serialize", "--base64" ] state
            compareGolden goldenTestnet__1_1 base16
            compareGolden goldenTestnet__1_1 base64
            compareGolden goldenTestnet__1_1 defaul


        it "2 inputs, 2 outputs (DSL)" $ do
            compareGolden goldenTestnet__2_2 $ Tx.empty testnetMagic
                & Tx.addInput (unsafeMkInput 0 (txids !! 0))
                & Tx.addInput (unsafeMkInput 1 (txids !! 0))
                & Tx.addOutput (unsafeMkOutput 42 (addrs !! 2))
                & Tx.addOutput (unsafeMkOutput 14 (addrs !! 3))
                & Tx.lock
                & Tx.signWith (unsafeMkSignKey (keys !! 0))
                & Tx.signWith (unsafeMkSignKey (keys !! 1))
                & Tx.serialize

        it "2 inputs, 2 outputs (CLI)" $ do
            state <- cardanoTx [ "empty", testnetMagicT ] ""
                 >>= cardanoTx [ "add-input", "0", txids !! 0 ]
                 >>= cardanoTx [ "add-input", "1", txids !! 0 ]
                 >>= cardanoTx [ "add-output", "42", addrs !! 2 ]
                 >>= cardanoTx [ "add-output", "14", addrs !! 3 ]
                 >>= cardanoTx [ "lock" ]
                 >>= cardanoTx [ "sign-with", keys !! 0 ]
                 >>= cardanoTx [ "sign-with", keys !! 1 ]

            defaul <- fromBase64E <$> cardanoTx [ "serialize" ] state
            base16 <- fromBase16E <$> cardanoTx [ "serialize", "--base16" ] state
            base64 <- fromBase64E <$> cardanoTx [ "serialize", "--base64" ] state
            compareGolden goldenTestnet__2_2 base16
            compareGolden goldenTestnet__2_2 base64
            compareGolden goldenTestnet__2_2 defaul

        it "1 input, 25 outputs (DSL)" $ do
            compareGolden goldenTestnet__25_1 $ Tx.empty testnetMagic
                & Tx.addInput (unsafeMkInput 0 (txids !! 0))
                & flip (foldr Tx.addOutput) (replicate 25 $ unsafeMkOutput 14 (addrs !! 2))
                & Tx.lock
                & Tx.signWith (unsafeMkSignKey (keys !! 0))
                & Tx.serialize


        it "1 input, 25 outputs (CLI)" $ do
            state <- cardanoTx [ "empty", testnetMagicT ] ""
                 >>= cardanoTx [ "add-input", "0", txids !! 0 ]
                 >>= flip (foldM (&)) (replicate 25 $ cardanoTx [ "add-output", "14", addrs !! 2])
                 >>= cardanoTx [ "lock" ]
                 >>= cardanoTx [ "sign-with", keys !! 0 ]

            defaul <- fromBase64E <$> cardanoTx [ "serialize" ] state
            base16 <- fromBase16E <$> cardanoTx [ "serialize", "--base16" ] state
            base64 <- fromBase64E <$> cardanoTx [ "serialize", "--base64" ] state
            compareGolden goldenTestnet__25_1 base16
            compareGolden goldenTestnet__25_1 base64
            compareGolden goldenTestnet__25_1 defaul


    describe "Negative tests" $ do
        prop "Invalid Input" $ \ix -> do
            let len = 32
            let genInvalidId = oneof
                    [ pure ""
                    , pure $ BS.replicate (len - 1) 0
                    , pure $ BS.replicate (len + 1) 0
                    , (BS.pack <$> arbitrary) `suchThat` ((/= len) . BS.length)
                    ]
            forAll genInvalidId (isNothing . mkInput ix)

        prop "Invalid Output" $ \(coin :: Word64) -> do
            let genInvalidAddress = BS.pack <$> arbitrary
            forAll genInvalidAddress (isNothing . mkOutput (fromIntegral coin))

        prop "Invalid SignKey" $ do
            let len = 96
            let genInvalidSignKey =
                    (BS.pack <$> arbitrary) `suchThat` ((/= len) . BS.length)
            forAll genInvalidSignKey (isNothing . mkSignKey)

        it "Missing Input" $ do
            let result = Tx.empty mainnetMagic
                       & Tx.addOutput (unsafeMkOutput 14 (addrs !! 0))
                       & Tx.lock
                       & Tx.serialize
            result `shouldBe` Left MissingInput

        it "Missing Output" $ do
            let result = Tx.empty mainnetMagic
                       & Tx.addInput (unsafeMkInput 0 (txids !! 0))
                       & Tx.lock
                       & Tx.serialize
            result `shouldBe` Left MissingOutput

        it "Missing Signature" $ do
            let result = Tx.empty mainnetMagic
                       & Tx.addInput (unsafeMkInput 0 (txids !! 0))
                       & Tx.addOutput (unsafeMkOutput 14 (addrs !! 0))
                       & Tx.lock
                       & Tx.serialize
            result `shouldBe` Left MissingSignature

--
-- Property: Roundtrip CBOR
--

prop_RoundTripCBOR
    :: (Show a, Eq a)
    => (a -> CBOR.Encoding)
    -> (forall s. CBOR.Decoder s a)
    -> a
    -> Property
prop_RoundTripCBOR encode decode a =
    result === Right (mempty, a)
  where
    bytes  = CBOR.toStrictByteString (encode a)
    result = CBOR.deserialiseFromBytes decode (BL.fromStrict bytes)

instance Arbitrary ProtocolMagicId where
    arbitrary = mkInit <$> arbitrary

instance Arbitrary TxIn where
    arbitrary = hedgehog genTxIn

instance Arbitrary TxOut where
    arbitrary = hedgehog genTxOut

instance Arbitrary TxSigData where
    arbitrary = hedgehog genTxSigData

instance Arbitrary ErrMkPayment where
    arbitrary = elements [ MissingInput, MissingOutput, MissingSignature ]

instance {-# OVERLAPS #-}
    ( Arbitrary a, Arbitrary b, Arbitrary c)
    => Arbitrary (ProtocolMagicId, NonEmpty a, NonEmpty b, c, [TxInWitness])
  where
    arbitrary = do
        pm   <- arbitrary
        wits <- listOf (hedgehog $ genTxInWitness pm)
        (,,,,)
            <$> pure pm
            <*> fmap (NE.fromList . getNonEmpty) arbitrary
            <*> fmap (NE.fromList . getNonEmpty) arbitrary
            <*> arbitrary
            <*> pure wits

--
-- Golden
--

compareGolden
    :: Show e
    => ByteString
        -- ^ An expected encoded result
    -> Either e ByteString
        -- ^ The actual string received
    -> IO ()
compareGolden _want (Left e)   = expectationFailure (show e)
compareGolden want (Right got) = quickCheck $ withMaxSuccess 1 $
    -- NOTE Using QuickCheck here simply for getting better counter examples
    -- than HSpec in case of failure...
    conjoin (uncurry (===) <$> zip (lines prettyWant) (lines prettyGot))
        & counterexample ("Got:  " <> prettyGot)
        & counterexample ("Want: " <> prettyWant)
  where
    prettyWant =
        CBOR.prettyHexEnc $ CBOR.encodePreEncoded want
    prettyGot  =
        CBOR.prettyHexEnc $ CBOR.encodePreEncoded got

--
-- Internal
--

unsafeMkInput :: Word32 -> Text -> Input Byron
unsafeMkInput ix str = fromJust $ mkInput ix (unsafeB16 str)

unsafeMkOutput :: Natural -> Text -> Output Byron
unsafeMkOutput n str = fromJust $ mkOutput n (unsafeB58 str)

unsafeMkSignKey :: Text -> SignKey Byron
unsafeMkSignKey str = fromJust $ mkSignKey (unsafeB16 str)

unsafeB16 :: Text -> ByteString
unsafeB16 = fromMaybe (error msg) . fromBase16
  where msg = "unable to decode base16 string."

unsafeB58 :: Text -> ByteString
unsafeB58 = fromMaybe (error msg) . fromBase58
  where msg = "unable to decode base58 string."

fromBase64E :: Text -> Either String ByteString
fromBase64E = maybe (Left msg) Right . fromBase64
  where msg = "unable to decode base64 string."

fromBase16E :: Text -> Either String ByteString
fromBase16E = maybe (Left msg) Right . fromBase16
  where msg = "unable to decode base16 string."

mainnetMagicT :: Text
mainnetMagicT = T.pack $ show $ unProtocolMagicId mainnetMagic

testnetMagicT :: Text
testnetMagicT = T.pack $ show $ unProtocolMagicId testnetMagic

cardanoTx
    :: [Text]
        -- ^ Arguments
    -> Text
        -- ^ stdin
    -> IO Text
        -- ^ stdout
cardanoTx args =
    fmap T.pack . readProcess "cardano-tx" (T.unpack <$> args) . T.unpack

--
-- Test Vectors
--

txids :: [Text]
txids =
    [ "3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7"
    ]

addrs :: [Text]
addrs =
    -- Mainnet
    [ "Ae2tdPwUPEZETXfbQxKMkMJQY1MoHCBS7bkw6TmhLjRvi9LZh1uDnXy319f"
    , "Ae2tdPwUPEZ69HTPqLpnFFw2MAfwdEoV5cpVQP5Uy1bPijSEHQmMXUfT3q5"

    -- Testnet
    , "2cWKMJemoBajc46Wu4Z7e6bG48myZWfB7Z6pD77L6PrJQWt9HZ3Yv7o8CYZTBMqHTPTkv"
    , "2cWKMJemoBaiLiNB8QpHKjkQhnPdQSyxaLb8JJFUQYpiVzgEJE59fN7V7StqnyDuDjHYJ"
    ]

keys :: [Text]
keys =
    [ "e0860dab46f13e74ab834142e8877b80bf22044cae8ebab7a21ed1b8dc00c155\
      \f6b78eee2a5bbd453ce7e7711b2964abb6a36837e475271f18ff36ae5fc8af73\
      \e25db39fb78e74d4b53fb51776d0f5eb360e62d09b853f3a87ac25bf834ee1fb"

    , "00bc08703e4bb4d9fe6edf4ad2ccb1ffc6fb8d555d96805d643e5d06afde605c\
      \e7d41d056def11417b17d3fb7415392b5f329877f372e55b0959c71b2bd2b447\
      \1bbf1c6081545b1ab140578d7b5c035bf904d05dd8e9b79b34d3160f86206bfc"
    ]

goldenMainnet__1_1 :: ByteString
goldenMainnet__1_1 = unsafeB16
    "82839f8200d81858248258203b40265111d8bb3c3c608d95b3a0bf83461ace3\
    \2d79336579a1939b3aad1c0b700ff9f8282d818582183581cb0e693cbc97272\
    \bd42aacf3b443ecac68b96b4fa20159186a4a38883a0001a497c15c6182affa\
    \0818200d81858858258408e620235b2a427259cc1a1c63af9ef179cb3b6e396\
    \da182e01d65dd3ed7be94be25db39fb78e74d4b53fb51776d0f5eb360e62d09\
    \b853f3a87ac25bf834ee1fb58403684501a21346ba3c19a6dc3479180e80a14\
    \e5edc0ffb4b1469abe0332e7e1caf291d50cb8d2c47ee37f6b44b7fbfcc5a1b\
    \01bc262038e93969b9a728a2b3500"

goldenMainnet__2_2 :: ByteString
goldenMainnet__2_2 = unsafeB16
    "82839f8200d81858248258203b40265111d8bb3c3c608d95b3a0bf83461ace32\
    \d79336579a1939b3aad1c0b7008200d81858248258203b40265111d8bb3c3c60\
    \8d95b3a0bf83461ace32d79336579a1939b3aad1c0b701ff9f8282d818582183\
    \581cb0e693cbc97272bd42aacf3b443ecac68b96b4fa20159186a4a38883a000\
    \1a497c15c6182a8282d818582183581c5d9254c4b41dbdc10f9c3b4517630497\
    \6e5e210decc38792ab2b50c9a0001ab537acfc0effa0828200d8185885825840\
    \8e620235b2a427259cc1a1c63af9ef179cb3b6e396da182e01d65dd3ed7be94b\
    \e25db39fb78e74d4b53fb51776d0f5eb360e62d09b853f3a87ac25bf834ee1fb\
    \5840a214bef8191aca0b41c109101c420deb131f5eff63394285dc18fc39726f\
    \b24a7bc34adce5a6e234360aae398b431a47d9b9d9a71cdcea6bd21bac7ed816\
    \53068200d81858858258402cf36a269802da7cc0408308bda9a0015e7e819121\
    \17013c93edeefa9b62bbb61bbf1c6081545b1ab140578d7b5c035bf904d05dd8\
    \e9b79b34d3160f86206bfc58403cb09514f2d27f5dab76480ec010b4e89c0c50\
    \f583c00bca487e0a45643e4c2854842c57d87f93961efad7037be8de5100d0fc\
    \e2383e8a11e20cb9762731da0c"

goldenMainnet__25_1 :: ByteString
goldenMainnet__25_1 = unsafeB16
    "82839f8200d81858248258203b40265111d8bb3c3c608d95b3a0bf83461ace32\
    \d79336579a1939b3aad1c0b700ff9f8282d818582183581cb0e693cbc97272bd\
    \42aacf3b443ecac68b96b4fa20159186a4a38883a0001a497c15c60e8282d818\
    \582183581cb0e693cbc97272bd42aacf3b443ecac68b96b4fa20159186a4a388\
    \83a0001a497c15c60e8282d818582183581cb0e693cbc97272bd42aacf3b443e\
    \cac68b96b4fa20159186a4a38883a0001a497c15c60e8282d818582183581cb0\
    \e693cbc97272bd42aacf3b443ecac68b96b4fa20159186a4a38883a0001a497c\
    \15c60e8282d818582183581cb0e693cbc97272bd42aacf3b443ecac68b96b4fa\
    \20159186a4a38883a0001a497c15c60e8282d818582183581cb0e693cbc97272\
    \bd42aacf3b443ecac68b96b4fa20159186a4a38883a0001a497c15c60e8282d8\
    \18582183581cb0e693cbc97272bd42aacf3b443ecac68b96b4fa20159186a4a3\
    \8883a0001a497c15c60e8282d818582183581cb0e693cbc97272bd42aacf3b44\
    \3ecac68b96b4fa20159186a4a38883a0001a497c15c60e8282d818582183581c\
    \b0e693cbc97272bd42aacf3b443ecac68b96b4fa20159186a4a38883a0001a49\
    \7c15c60e8282d818582183581cb0e693cbc97272bd42aacf3b443ecac68b96b4\
    \fa20159186a4a38883a0001a497c15c60e8282d818582183581cb0e693cbc972\
    \72bd42aacf3b443ecac68b96b4fa20159186a4a38883a0001a497c15c60e8282\
    \d818582183581cb0e693cbc97272bd42aacf3b443ecac68b96b4fa20159186a4\
    \a38883a0001a497c15c60e8282d818582183581cb0e693cbc97272bd42aacf3b\
    \443ecac68b96b4fa20159186a4a38883a0001a497c15c60e8282d81858218358\
    \1cb0e693cbc97272bd42aacf3b443ecac68b96b4fa20159186a4a38883a0001a\
    \497c15c60e8282d818582183581cb0e693cbc97272bd42aacf3b443ecac68b96\
    \b4fa20159186a4a38883a0001a497c15c60e8282d818582183581cb0e693cbc9\
    \7272bd42aacf3b443ecac68b96b4fa20159186a4a38883a0001a497c15c60e82\
    \82d818582183581cb0e693cbc97272bd42aacf3b443ecac68b96b4fa20159186\
    \a4a38883a0001a497c15c60e8282d818582183581cb0e693cbc97272bd42aacf\
    \3b443ecac68b96b4fa20159186a4a38883a0001a497c15c60e8282d818582183\
    \581cb0e693cbc97272bd42aacf3b443ecac68b96b4fa20159186a4a38883a000\
    \1a497c15c60e8282d818582183581cb0e693cbc97272bd42aacf3b443ecac68b\
    \96b4fa20159186a4a38883a0001a497c15c60e8282d818582183581cb0e693cb\
    \c97272bd42aacf3b443ecac68b96b4fa20159186a4a38883a0001a497c15c60e\
    \8282d818582183581cb0e693cbc97272bd42aacf3b443ecac68b96b4fa201591\
    \86a4a38883a0001a497c15c60e8282d818582183581cb0e693cbc97272bd42aa\
    \cf3b443ecac68b96b4fa20159186a4a38883a0001a497c15c60e8282d8185821\
    \83581cb0e693cbc97272bd42aacf3b443ecac68b96b4fa20159186a4a38883a0\
    \001a497c15c60e8282d818582183581cb0e693cbc97272bd42aacf3b443ecac6\
    \8b96b4fa20159186a4a38883a0001a497c15c60effa0818200d8185885825840\
    \8e620235b2a427259cc1a1c63af9ef179cb3b6e396da182e01d65dd3ed7be94b\
    \e25db39fb78e74d4b53fb51776d0f5eb360e62d09b853f3a87ac25bf834ee1fb\
    \58402b01895a50681f18418da48bf6cf9d70ad465018bb9276f6f0aa9b58ff2d\
    \2f273d584e4f27e228cd57a6f96009d5c27525fd92647db708185e488713d40d\
    \d402"

goldenTestnet__1_1 :: ByteString
goldenTestnet__1_1 = unsafeB16
    "82839f8200d81858248258203b40265111d8bb3c3c608d95b3a0bf83461ace32d7\
    \9336579a1939b3aad1c0b700ff9f8282d818582883581c946480eb45fa900e84d1\
    \f25141589468ca1d38bbb4e6c3abec7d1ea0a102451a4170cb17001a16bbe0ab18\
    \2affa0818200d81858858258408e620235b2a427259cc1a1c63af9ef179cb3b6e3\
    \96da182e01d65dd3ed7be94be25db39fb78e74d4b53fb51776d0f5eb360e62d09b\
    \853f3a87ac25bf834ee1fb584081b55eff4aa66b01c339ba2ec04dbad9d14bd049\
    \f6e8ae46211a2870c839966bfc721ca80c3b71d3719e468dcd16c877ff68a3cff8\
    \887ac9f3546da99e6bba00"

goldenTestnet__2_2 :: ByteString
goldenTestnet__2_2 = unsafeB16
    "82839f8200d81858248258203b40265111d8bb3c3c608d95b3a0bf83461ace32d7\
    \9336579a1939b3aad1c0b7008200d81858248258203b40265111d8bb3c3c608d95\
    \b3a0bf83461ace32d79336579a1939b3aad1c0b701ff9f8282d818582883581c94\
    \6480eb45fa900e84d1f25141589468ca1d38bbb4e6c3abec7d1ea0a102451a4170\
    \cb17001a16bbe0ab182a8282d818582883581c48a08edee8a9f586263d5f4e2288\
    \ac1a6e33656bfa2570fb8618c5c4a102451a4170cb17001ab30d9d270effa08282\
    \00d81858858258408e620235b2a427259cc1a1c63af9ef179cb3b6e396da182e01\
    \d65dd3ed7be94be25db39fb78e74d4b53fb51776d0f5eb360e62d09b853f3a87ac\
    \25bf834ee1fb5840fb812923b3b5a15a9d7005ef0b2ef714ed188c48f0ec16a7ef\
    \5e3661f92aebb203d3717fafbb10b4de6bf4fa6ad064b5ad65434a449983741182\
    \1af434d0280f8200d81858858258402cf36a269802da7cc0408308bda9a0015e7e\
    \81912117013c93edeefa9b62bbb61bbf1c6081545b1ab140578d7b5c035bf904d0\
    \5dd8e9b79b34d3160f86206bfc5840a57a996c2a1185f117db5e21aed47c54eccf\
    \263bf1e978114b1a2731086b4e8d189700c918b1ce04cd77316a15fb22f3a2cbed\
    \7de16fb4fc83d4cc4b11a3860b"

goldenTestnet__25_1 :: ByteString
goldenTestnet__25_1 = unsafeB16
    "82839f8200d81858248258203b40265111d8bb3c3c608d95b3a0bf83461ace32d7\
    \9336579a1939b3aad1c0b700ff9f8282d818582883581c946480eb45fa900e84d1\
    \f25141589468ca1d38bbb4e6c3abec7d1ea0a102451a4170cb17001a16bbe0ab0e\
    \8282d818582883581c946480eb45fa900e84d1f25141589468ca1d38bbb4e6c3ab\
    \ec7d1ea0a102451a4170cb17001a16bbe0ab0e8282d818582883581c946480eb45\
    \fa900e84d1f25141589468ca1d38bbb4e6c3abec7d1ea0a102451a4170cb17001a\
    \16bbe0ab0e8282d818582883581c946480eb45fa900e84d1f25141589468ca1d38\
    \bbb4e6c3abec7d1ea0a102451a4170cb17001a16bbe0ab0e8282d818582883581c\
    \946480eb45fa900e84d1f25141589468ca1d38bbb4e6c3abec7d1ea0a102451a41\
    \70cb17001a16bbe0ab0e8282d818582883581c946480eb45fa900e84d1f2514158\
    \9468ca1d38bbb4e6c3abec7d1ea0a102451a4170cb17001a16bbe0ab0e8282d818\
    \582883581c946480eb45fa900e84d1f25141589468ca1d38bbb4e6c3abec7d1ea0\
    \a102451a4170cb17001a16bbe0ab0e8282d818582883581c946480eb45fa900e84\
    \d1f25141589468ca1d38bbb4e6c3abec7d1ea0a102451a4170cb17001a16bbe0ab\
    \0e8282d818582883581c946480eb45fa900e84d1f25141589468ca1d38bbb4e6c3\
    \abec7d1ea0a102451a4170cb17001a16bbe0ab0e8282d818582883581c946480eb\
    \45fa900e84d1f25141589468ca1d38bbb4e6c3abec7d1ea0a102451a4170cb1700\
    \1a16bbe0ab0e8282d818582883581c946480eb45fa900e84d1f25141589468ca1d\
    \38bbb4e6c3abec7d1ea0a102451a4170cb17001a16bbe0ab0e8282d81858288358\
    \1c946480eb45fa900e84d1f25141589468ca1d38bbb4e6c3abec7d1ea0a102451a\
    \4170cb17001a16bbe0ab0e8282d818582883581c946480eb45fa900e84d1f25141\
    \589468ca1d38bbb4e6c3abec7d1ea0a102451a4170cb17001a16bbe0ab0e8282d8\
    \18582883581c946480eb45fa900e84d1f25141589468ca1d38bbb4e6c3abec7d1e\
    \a0a102451a4170cb17001a16bbe0ab0e8282d818582883581c946480eb45fa900e\
    \84d1f25141589468ca1d38bbb4e6c3abec7d1ea0a102451a4170cb17001a16bbe0\
    \ab0e8282d818582883581c946480eb45fa900e84d1f25141589468ca1d38bbb4e6\
    \c3abec7d1ea0a102451a4170cb17001a16bbe0ab0e8282d818582883581c946480\
    \eb45fa900e84d1f25141589468ca1d38bbb4e6c3abec7d1ea0a102451a4170cb17\
    \001a16bbe0ab0e8282d818582883581c946480eb45fa900e84d1f25141589468ca\
    \1d38bbb4e6c3abec7d1ea0a102451a4170cb17001a16bbe0ab0e8282d818582883\
    \581c946480eb45fa900e84d1f25141589468ca1d38bbb4e6c3abec7d1ea0a10245\
    \1a4170cb17001a16bbe0ab0e8282d818582883581c946480eb45fa900e84d1f251\
    \41589468ca1d38bbb4e6c3abec7d1ea0a102451a4170cb17001a16bbe0ab0e8282\
    \d818582883581c946480eb45fa900e84d1f25141589468ca1d38bbb4e6c3abec7d\
    \1ea0a102451a4170cb17001a16bbe0ab0e8282d818582883581c946480eb45fa90\
    \0e84d1f25141589468ca1d38bbb4e6c3abec7d1ea0a102451a4170cb17001a16bb\
    \e0ab0e8282d818582883581c946480eb45fa900e84d1f25141589468ca1d38bbb4\
    \e6c3abec7d1ea0a102451a4170cb17001a16bbe0ab0e8282d818582883581c9464\
    \80eb45fa900e84d1f25141589468ca1d38bbb4e6c3abec7d1ea0a102451a4170cb\
    \17001a16bbe0ab0e8282d818582883581c946480eb45fa900e84d1f25141589468\
    \ca1d38bbb4e6c3abec7d1ea0a102451a4170cb17001a16bbe0ab0effa0818200d8\
    \1858858258408e620235b2a427259cc1a1c63af9ef179cb3b6e396da182e01d65d\
    \d3ed7be94be25db39fb78e74d4b53fb51776d0f5eb360e62d09b853f3a87ac25bf\
    \834ee1fb5840e0f9591bfd7b67738db6b689d514bba1fe8c730491f9bdad7fbe05\
    \58974e57c1ef62c331da2ad528ff829b5406638d384a0b4d0b40b378f4063acb73\
    \851d3906"