Skip to content
This repository has been archived by the owner on Aug 18, 2020. It is now read-only.

[CO-354] Fix SafeCopy instance for AddrAttributes #3685

Merged
merged 5 commits into from
Oct 2, 2018
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions core/src/Pos/Core/Common/Address.hs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ module Pos.Core.Common.Address
-- * Construction
, IsBootstrapEraAddr (..)
, makeAddress
, makeAddress'
, makePubKeyAddress
, makePubKeyAddressBoot
, makeRootPubKeyAddress
Expand Down Expand Up @@ -170,6 +171,8 @@ decodeTextAddress = decodeAddress . encodeUtf8
----------------------------------------------------------------------------
-- Constructors
----------------------------------------------------------------------------
{-# ANN makeAddress ("HLint: ignore Reduce duplication" :: Text) #-}
{-# ANN makeAddress' ("HLint: ignore Reduce duplication" :: Text) #-}

-- | Make an 'Address' from spending data and attributes.
makeAddress :: AddrSpendingData -> AddrAttributes -> Address
Expand All @@ -184,6 +187,14 @@ makeAddress spendingData attributesUnwrapped =
attributes = mkAttributes attributesUnwrapped
address' = Address' (addrType', spendingData, attributes)

-- | Make an 'Address'' from spending data and attributes.
makeAddress' :: AddrSpendingData -> AddrAttributes -> Address'
makeAddress' spendingData attributesUnwrapped = address'
where
addrType' = addrSpendingDataToType spendingData
attributes = mkAttributes attributesUnwrapped
address' = Address' (addrType', spendingData, attributes)

-- | This newtype exists for clarity. It is used to tell pubkey
-- address creation functions whether an address is intended for
-- bootstrap era.
Expand Down
107 changes: 100 additions & 7 deletions core/test/Test/Pos/Core/ExampleHelpers.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ module Test.Pos.Core.ExampleHelpers
, exampleAddress2
, exampleAddress3
, exampleAddress4
, exampleAddress5
, exampleAddress6
, exampleAddress7
, exampleAddress'
, exampleAddress'1
, exampleAddress'2
, exampleAddress'3
, exampleAddress'4
, exampleAddress'5
, exampleAddress'6
, exampleAddress'7
, exampleBlockVersion
, exampleBlockVersionData0
, exampleBlockVersionData1
Expand Down Expand Up @@ -122,13 +133,13 @@ import qualified Serokell.Util.Base16 as B16
import qualified Cardano.Crypto.Wallet as CC
import Pos.Binary.Class (Raw (..), asBinary)
import Pos.Core.Common (AddrAttributes (..), AddrSpendingData (..),
AddrStakeDistribution (..), Address (..), BlockCount (..),
ChainDifficulty (..), Coeff (..), Coin (..), CoinPortion (..),
IsBootstrapEraAddr (..), Script (..), ScriptVersion,
SharedSeed (..), SlotLeaders, StakeholderId, StakesList,
TxFeePolicy (..), TxSizeLinear (..), addressHash,
coinPortionDenominator, makeAddress, makePubKeyAddress,
mkMultiKeyDistr)
AddrStakeDistribution (..), Address (..), Address' (..),
BlockCount (..), ChainDifficulty (..), Coeff (..), Coin (..),
CoinPortion (..), IsBootstrapEraAddr (..), Script (..),
ScriptVersion, SharedSeed (..), SlotLeaders, StakeholderId,
StakesList, TxFeePolicy (..), TxSizeLinear (..), addressHash,
coinPortionDenominator, makeAddress, makeAddress',
makePubKeyAddress, mkMultiKeyDistr)
import Pos.Core.Configuration
import Pos.Core.Delegation (HeavyDlgIndex (..), LightDlgIndices (..), ProxySKBlockInfo,
ProxySKHeavy)
Expand Down Expand Up @@ -171,6 +182,8 @@ import Test.Pos.Core.Gen (genProtocolConstants)
import Test.Pos.Crypto.Bi (getBytes)
import Test.Pos.Crypto.Gen (genProtocolMagic, genProtocolMagicId)

{-# ANN module ("HLint: ignore Reduce duplication" :: Text) #-}

--------------------------------------------------------------------------------
-- Helpers
--------------------------------------------------------------------------------
Expand Down Expand Up @@ -733,6 +746,86 @@ exampleAddress4 = makeAddress easd attrs
attrs = AddrAttributes Nothing (SingleKeyDistr sId) NMNothing
[sId] = exampleStakeholderIds 7 1

exampleAddress5 :: Address
exampleAddress5 = makeAddress easd attrs
where
easd = ScriptASD exampleScript
attrs = AddrAttributes hap exampleMultiKeyDistr (NMJust 12345)
hap = Just (HDAddressPayload (getBytes 10 32))

exampleAddress6 :: Address
exampleAddress6 = makeAddress easd attrs
where
easd = UnknownASD 200 "test value"
attrs = AddrAttributes Nothing (SingleKeyDistr sId) (NMJust 31337)
[sId] = exampleStakeholderIds 10 1

exampleAddress7 :: Address
exampleAddress7 = makeAddress easd attrs
where
easd = PubKeyASD pk
[pk] = examplePublicKeys 16 1
attrs = AddrAttributes hap BootstrapEraDistr (NMJust (- 559038737))
hap = Nothing

exampleAddress' :: Address'
exampleAddress' = makeAddress' exampleAddrSpendingData_PubKey attrs
where
attrs = AddrAttributes hap BootstrapEraDistr NMNothing
hap = Just (HDAddressPayload (getBytes 32 32))

exampleAddress'1 :: Address'
exampleAddress'1 = makeAddress' easd attrs
where
easd = PubKeyASD pk
[pk] = examplePublicKeys 24 1
attrs = AddrAttributes hap BootstrapEraDistr NMNothing
hap = Nothing

exampleAddress'2 :: Address'
exampleAddress'2 = makeAddress' easd attrs
where
easd = RedeemASD exampleRedeemPublicKey
attrs = AddrAttributes hap asd NMNothing
hap = Just (HDAddressPayload (getBytes 15 32))
asd = SingleKeyDistr exampleStakeholderId

exampleAddress'3 :: Address'
exampleAddress'3 = makeAddress' easd attrs
where
easd = ScriptASD exampleScript
attrs = AddrAttributes hap exampleMultiKeyDistr NMNothing
hap = Just (HDAddressPayload (getBytes 17 32))

exampleAddress'4 :: Address'
exampleAddress'4 = makeAddress' easd attrs
where
easd = UnknownASD 7 "test value"
attrs = AddrAttributes Nothing (SingleKeyDistr sId) NMNothing
[sId] = exampleStakeholderIds 7 1

exampleAddress'5 :: Address'
exampleAddress'5 = makeAddress' easd attrs
where
easd = ScriptASD exampleScript
attrs = AddrAttributes hap exampleMultiKeyDistr (NMJust 12345)
hap = Just (HDAddressPayload (getBytes 10 32))

exampleAddress'6 :: Address'
exampleAddress'6 = makeAddress' easd attrs
where
easd = UnknownASD 200 "test value"
attrs = AddrAttributes Nothing (SingleKeyDistr sId) (NMJust 31337)
[sId] = exampleStakeholderIds 10 1

exampleAddress'7 :: Address'
exampleAddress'7 = makeAddress' easd attrs
where
easd = PubKeyASD pk
[pk] = examplePublicKeys 16 1
attrs = AddrAttributes hap BootstrapEraDistr (NMJust (- 559038737))
hap = Nothing

exampleMultiKeyDistr :: AddrStakeDistribution
exampleMultiKeyDistr = case mkMultiKeyDistr (M.fromList pairs) of
Left err -> error $
Expand Down
3 changes: 3 additions & 0 deletions lib/cardano-sl.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ test-suite cardano-test
Test.Pos.MerkleSpec
Test.Pos.Infra.Slotting.TypesSpec
Test.Pos.Types.BlockSpec
Test.Pos.Types.Golden.SafeCopy
Test.Pos.Types.Identity.SafeCopySpec
Test.Pos.Types.Identity.ShowReadSpec
Test.Pos.Update.Identity.SafeCopySpec
Expand Down Expand Up @@ -321,6 +322,7 @@ test-suite cardano-test
, cardano-sl-util
, cardano-sl-util-test
, cborg
, cereal
, containers
, cryptonite
, data-default
Expand All @@ -330,6 +332,7 @@ test-suite cardano-test
, fmt
, formatting
, generic-arbitrary
, hedgehog
, hspec
, lens
, log-warper
Expand Down
39 changes: 37 additions & 2 deletions lib/src/Pos/SafeCopy.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import qualified Cardano.Crypto.Wallet as CC
import qualified Cardano.Crypto.Wallet.Encrypted as CC
import qualified Crypto.Math.Edwards25519 as ED25519
import qualified Crypto.Sign.Ed25519 as EDS25519
import qualified Data.ByteString.Lazy as BSL
import Data.SafeCopy (Contained, SafeCopy (..), base, contain, deriveSafeCopySimple,
safeGet, safePut)
import qualified Data.Serialize as Cereal
Expand All @@ -29,6 +30,7 @@ import Pos.Core.Common (AddrAttributes (..), AddrSpendingData (..),
Coin, CoinPortion (..), Script (..), SharedSeed (..),
TxFeePolicy (..), TxSizeLinear (..))
import Pos.Core.Delegation (DlgPayload (..), HeavyDlgIndex (..), LightDlgIndices (..))
import Pos.Core.NetworkMagic (NetworkMagic (..))
import Pos.Core.Slotting (EpochIndex (..), EpochOrSlot (..), LocalSlotIndex (..),
SlotCount (..), SlotId (..))
import Pos.Core.Ssc (Commitment (..), CommitmentsMap, Opening (..), SscPayload (..),
Expand All @@ -48,7 +50,7 @@ import Pos.Crypto.Signing.Redeem (RedeemPublicKey (..), RedeemSecretKe
import Pos.Crypto.Signing.Signing (ProxyCert (..), ProxySecretKey (..),
ProxySignature (..), PublicKey (..), SecretKey (..),
Signature (..), Signed (..))
import Pos.Data.Attributes (Attributes (..), UnparsedFields)
import Pos.Data.Attributes (Attributes (..), UnparsedFields, mkAttributes)
import Pos.Merkle (MerkleNode (..), MerkleRoot (..), MerkleTree (..))
import qualified Pos.Util.Modifier as MM
import Pos.Util.Util (cerealError, toCerealError)
Expand Down Expand Up @@ -137,7 +139,40 @@ deriveSafeCopySimple 0 'base ''HDAddressPayload
deriveSafeCopySimple 0 'base ''AddrType -- ☃
deriveSafeCopySimple 0 'base ''AddrStakeDistribution
deriveSafeCopySimple 0 'base ''AddrSpendingData
deriveSafeCopySimple 0 'base ''AddrAttributes

instance SafeCopy AddrAttributes where
-- Since there is only a Bi instance for (Attributes AddrAttributes),
-- we wrap our AddrAttributes before we serialize it.
putCopy aa = contain $ do
let bs = Bi.serialize (mkAttributes aa)
safePut bs

getCopy = contain $ do
let label = Cereal.label "Pos.Core.Common.AddrAttributes.AddrAttributes:"

let getLegacy =
(\apdp asd -> AddrAttributes apdp asd NMNothing)
<$> safeGet
<*> safeGet

-- ByteStrings are prefixed with a Int64 length. We cheat here and read the length as
-- thought it were a safePut-encoded Int64, so we know how long the ByteString will be.
--
-- 4[version] + 8[Int64] + <bytesLen>
-- bytesLen == length of AddrAttributes bytestring
bytesLen <- Cereal.lookAhead safeGet
bytes <- BSL.fromStrict <$> Cereal.uncheckedLookAhead (fromIntegral bytesLen + 12)
let _aaaVersionBytes = BSL.take 4 bytes
attrAddrAttrBytes = BSL.drop 12 bytes
label $ if BSL.length attrAddrAttrBytes /= bytesLen
then getLegacy
else case Bi.decodeFull attrAddrAttrBytes of
Left _ -> getLegacy
Right attrAddrAttrs -> do
-- seek ahead since we passed our bytes
Cereal.uncheckedSkip (12 + fromIntegral bytesLen)
pure (attrData attrAddrAttrs)

deriveSafeCopySimple 0 'base ''Address'
deriveSafeCopySimple 0 'base ''Address
deriveSafeCopySimple 0 'base ''TxInWitness
Expand Down
5 changes: 5 additions & 0 deletions lib/test/Test.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ import Test.Hspec (hspec)
import Spec (spec)

import Test.Pos.Configuration (defaultTestConf)
import qualified Test.Pos.Types.Golden.SafeCopy (tests)
import Test.Pos.Util.Tripping (runTests)

main :: IO ()
main = do
putText $ "default configuration: " <> show defaultTestConf
hspec spec
runTests
[ Test.Pos.Types.Golden.SafeCopy.tests
]
123 changes: 123 additions & 0 deletions lib/test/Test/Pos/Types/Golden/SafeCopy.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
module Test.Pos.Types.Golden.SafeCopy where

import Universum

import Hedgehog (Property)
import qualified Hedgehog as H

import Pos.SafeCopy ()

import Test.Pos.Core.ExampleHelpers (exampleAddress, exampleAddress', exampleAddress'1,
exampleAddress'2, exampleAddress'3, exampleAddress'4,
exampleAddress'5, exampleAddress'6, exampleAddress'7,
exampleAddress1, exampleAddress2, exampleAddress3,
exampleAddress4, exampleAddress5, exampleAddress6,
exampleAddress7)
import Test.Pos.Util.Golden (discoverGolden, goldenTestSafeCopy, goldenTestSafeCopyDec)

--------------------------------------------------------------------------------
-- Address
--------------------------------------------------------------------------------

golden_Address0 :: Property
golden_Address0 =
goldenTestSafeCopyDec
exampleAddress
"test/golden/safecopy/Address0"

golden_Address1 :: Property
golden_Address1 =
goldenTestSafeCopyDec
exampleAddress1
"test/golden/safecopy/Address1"

golden_Address2 :: Property
golden_Address2 =
goldenTestSafeCopyDec
exampleAddress2
"test/golden/safecopy/Address2"

golden_Address3 :: Property
golden_Address3 =
goldenTestSafeCopyDec
exampleAddress3
"test/golden/safecopy/Address3"

golden_Address4 :: Property
golden_Address4 =
goldenTestSafeCopyDec
exampleAddress4
"test/golden/safecopy/Address4"

golden_Address5 :: Property
golden_Address5 =
goldenTestSafeCopy
exampleAddress5
"test/golden/safecopy/Address5"

golden_Address6 :: Property
golden_Address6 =
goldenTestSafeCopy
exampleAddress6
"test/golden/safecopy/Address6"

golden_Address7 :: Property
golden_Address7 =
goldenTestSafeCopy
exampleAddress7
"test/golden/safecopy/Address7"

--------------------------------------------------------------------------------
-- Address'
--------------------------------------------------------------------------------

golden_Address'0 :: Property
golden_Address'0 =
goldenTestSafeCopyDec
exampleAddress'
"test/golden/safecopy/Address'0"

golden_Address'1 :: Property
golden_Address'1 =
goldenTestSafeCopyDec
exampleAddress'1
"test/golden/safecopy/Address'1"

golden_Address'2 :: Property
golden_Address'2 =
goldenTestSafeCopyDec
exampleAddress'2
"test/golden/safecopy/Address'2"

golden_Address'3 :: Property
golden_Address'3 =
goldenTestSafeCopyDec
exampleAddress'3
"test/golden/safecopy/Address'3"

golden_Address'4 :: Property
golden_Address'4 =
goldenTestSafeCopyDec
exampleAddress'4
"test/golden/safecopy/Address'4"

golden_Address'5 :: Property
golden_Address'5 =
goldenTestSafeCopy
exampleAddress'5
"test/golden/safecopy/Address'5"

golden_Address'6 :: Property
golden_Address'6 =
goldenTestSafeCopy
exampleAddress'6
"test/golden/safecopy/Address'6"

golden_Address'7 :: Property
golden_Address'7 =
goldenTestSafeCopy
exampleAddress'7
"test/golden/safecopy/Address'7"

tests :: IO Bool
tests = H.checkSequential $$discoverGolden
Loading