Skip to content

Commit 9f6ab7a

Browse files
authored
Merge pull request #201 from input-output-hk/erikd/word128-outsum
db: Fix for the outsum column of the epoch table
2 parents f0fe25d + db4c760 commit 9f6ab7a

File tree

7 files changed

+58
-3
lines changed

7 files changed

+58
-3
lines changed

cardano-db/cardano-db.cabal

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ library
4242
Cardano.Db.Run
4343
Cardano.Db.Schema
4444
Cardano.Db.Schema.Types
45+
Cardano.Db.Schema.Orphans
4546
Cardano.Db.Types
4647

4748

@@ -76,6 +77,7 @@ library
7677
, transformers
7778
-- This is never intended to run on non-POSIX systems.
7879
, unix
80+
, wide-word
7981

8082
executable cardano-db-tool
8183
default-language: Haskell2010
@@ -133,7 +135,9 @@ test-suite test
133135
, aeson
134136
, cardano-db
135137
, cardano-ledger
138+
, persistent
136139
, hedgehog
140+
, wide-word
137141

138142
test-suite test-db
139143
default-language: Haskell2010

cardano-db/src/Cardano/Db/Schema.hs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@
1616

1717
module Cardano.Db.Schema where
1818

19+
import Cardano.Db.Schema.Orphans ()
20+
1921
import Data.ByteString.Char8 (ByteString)
2022
import Data.Int (Int64)
2123
import Data.Text (Text)
2224
import Data.Time.Clock (UTCTime)
2325
import Data.Word (Word16, Word64)
26+
import Data.WideWord.Word128 (Word128)
2427

2528
-- Do not use explicit imports from this module as the imports can change
2629
-- from version to version due to changes to the TH code in Persistent.
@@ -128,7 +131,7 @@ share
128131
-- hold 204 times the total Lovelace distribution. The chance of that much being transacted
129132
-- in a single epoch is relatively low.
130133
Epoch
131-
outSum Word64 sqltype=outsum
134+
outSum Word128 sqltype=word128
132135
txCount Word64 sqltype=uinteger
133136
blkCount Word64 sqltype=uinteger
134137
no Word64 sqltype=uinteger
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{-# LANGUAGE OverloadedStrings #-}
2+
3+
{-# OPTIONS_GHC -Wno-orphans #-}
4+
5+
module Cardano.Db.Schema.Orphans where
6+
7+
import Data.WideWord.Word128 (Word128)
8+
9+
import qualified Data.Text as Text
10+
11+
import Database.Persist.Class (PersistField (..))
12+
import Database.Persist.Types (PersistValue (..))
13+
14+
15+
instance PersistField Word128 where
16+
toPersistValue = PersistText . Text.pack . show
17+
fromPersistValue (PersistText bs) = Right $ read (Text.unpack bs)
18+
fromPersistValue x =
19+
Left $ mconcat [ "Failed to parse Haskell type Word128: ", Text.pack (show x) ]
20+

cardano-db/test/Test/Property/Cardano/Db/Types.hs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import Cardano.Chain.Common (maxLovelaceVal)
99

1010
import qualified Data.Aeson as Aeson
1111
import Data.Word (Word64)
12+
import Data.WideWord.Word128 (Word128 (..))
13+
14+
import Database.Persist.Class (PersistField (..))
1215

1316
import Cardano.Db
1417

@@ -24,6 +27,12 @@ prop_roundtrip_Ada_via_JSON =
2427
mv <- H.forAll genAda
2528
H.tripping mv Aeson.encode Aeson.eitherDecode
2629

30+
prop_roundtrip_Word128_PersistField :: Property
31+
prop_roundtrip_Word128_PersistField =
32+
H.withTests 5000 . H.property $ do
33+
w128 <- H.forAll genWord128
34+
H.tripping w128 toPersistValue fromPersistValue
35+
2736
-- -----------------------------------------------------------------------------
2837

2938
genAda :: Gen Ada
@@ -38,6 +47,17 @@ genAda =
3847
, Gen.word64 (Range.linear (maxLovelaceVal - 5000) maxLovelaceVal) -- Near max.
3948
]
4049

50+
genWord128 :: Gen Word128
51+
genWord128 = Word128 <$> genWord64 <*> genWord64
52+
53+
genWord64 :: Gen Word64
54+
genWord64 =
55+
Gen.choice
56+
[ Gen.word64 Range.constantBounded
57+
, Gen.word64 (Range.linear 0 5000) -- Small values
58+
, Gen.word64 (Range.linear (maxBound - 5000) maxBound) -- Near max.
59+
]
60+
4161
-- -----------------------------------------------------------------------------
4262

4363
tests :: IO Bool

cardano-db/test/cardano-db-test.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,4 @@ library
6161
, transformers
6262
-- This is never intended to run on non-POSIX systems.
6363
, unix
64+
, wide-word

schema/migration-1-0001-20190730.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ BEGIN
2121
-- Stake addresses are a 28 byte hash prepended with a byte describing the address.
2222
EXECUTE 'CREATE DOMAIN addr29type AS bytea CHECK (octet_length (VALUE) = 29);';
2323

24+
-- 'maxBound :: Word128' as a decimal has 39 digits, so we only need to check that it
25+
-- is positive.
26+
EXECUTE 'CREATE DOMAIN word128type AS numeric (38, 0) CHECK (VALUE >= 0);';
27+
2428
UPDATE "schema_version" SET stage_one = 1;
2529
RAISE NOTICE 'DB has been migrated to stage_one version %', next_version;
2630
END IF;

schema/migration-1-0003-20200211.sql

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@ BEGIN
99
SELECT stage_one + 1 INTO next_version FROM "schema_version";
1010
IF next_version = 2 THEN
1111
-- Used as the sum of tx outputs for an epoch.
12-
-- Need this to catch possible overflow.
13-
EXECUTE 'CREATE DOMAIN outsum AS bigint CHECK (VALUE >= 0);';
12+
-- Persistent does not support more precision than 'Int64' (support for 'Word64'
13+
-- is done as a 'cast' to/from 'Int64' resulting in values greater than
14+
-- 'maxBound :: Int64' being represented in the database as negative values.
15+
-- Instead we we use 'Word128'.
16+
EXECUTE 'CREATE DOMAIN outsum AS word128type;';
1417

1518
UPDATE "schema_version" SET stage_one = next_version;
1619
RAISE NOTICE 'DB has been migrated to stage_one version %', next_version;

0 commit comments

Comments
 (0)