Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add block heights in various places of the API (network info, transaction date ...) #825

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions lib/core-integration/src/Test/Integration/Framework/DSL.hs
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ syncProgress =
_set :: HasType (ApiT SyncProgress) s => (s, SyncProgress) -> s
_set (s, v) = set typed (ApiT v) s


--
-- Helpers
--
Expand Down
16 changes: 14 additions & 2 deletions lib/core-integration/src/Test/Integration/Scenario/API/Network.hs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

Expand All @@ -9,11 +10,15 @@ module Test.Integration.Scenario.API.Network
import Prelude

import Cardano.Wallet.Api.Types
( ApiNetworkInformation )
( ApiBlockReference (..), ApiNetworkInformation )
import Cardano.Wallet.Primitive.Types
( SyncProgress (..) )
import Control.Monad
( forM_ )
import Data.Generics.Labels
()
import Data.Quantity
( Quantity (..) )
import Test.Hspec
( SpecWith, describe, it )
import Test.Integration.Framework.DSL
Expand All @@ -22,8 +27,10 @@ import Test.Integration.Framework.DSL
, Payload (..)
, eventually
, expectErrorMessage
, expectFieldBetween
, expectFieldEqual
, expectResponseCode
, getFromResponse
, request
, syncProgress
, verify
Expand All @@ -39,7 +46,12 @@ spec = do
let endpoint = ("GET", "v2/network/information")
eventually $ do
r <- request @ApiNetworkInformation ctx endpoint Default Empty
verify r [ expectFieldEqual syncProgress Ready ]
let (ApiBlockReference _ sl _) = getFromResponse #tip r
verify r
[ expectFieldEqual syncProgress Ready
, expectFieldBetween (#tip . #height)
(Quantity 0, Quantity $ fromIntegral $ sl + 1)
]

describe "NETWORK - v2/network/information - Methods Not Allowed" $ do
let matrix = ["POST", "CONNECT", "TRACE", "OPTIONS"]
Expand Down
17 changes: 10 additions & 7 deletions lib/core/src/Cardano/Wallet.hs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ import Cardano.Wallet.Primitive.Types
, WalletPassphraseInfo (..)
, computeUtxoStatistics
, log10
, slotDifference
, slotRangeFromTimeRange
, slotStartTime
, syncProgress
Expand Down Expand Up @@ -552,9 +551,9 @@ restoreBlocks ctx wid blocks nodeTip = do
let localTip = currentTip $ NE.last cps

meta' <- liftIO $ calculateMetadata bp localTip meta
let unstable = sparseCheckpoints k (blockHeight nodeTip)
let unstable = sparseCheckpoints k (nodeTip ^. #blockHeight)
forM_ (NE.init cps) $ \cp -> do
let (Quantity h) = blockHeight $ currentTip cp
let (Quantity h) = currentTip cp ^. #blockHeight
when (fromIntegral h `elem` unstable) (makeCheckpoint cp)
makeCheckpoint (NE.last cps)
DB.prune db (PrimaryKey wid)
Expand Down Expand Up @@ -792,6 +791,7 @@ signTx ctx wid pwd (CoinSelection ins outs chgs) =
{ status = Pending
, direction = Outgoing
, slotId = (currentTip cp) ^. #slotId
, blockHeight = (currentTip cp) ^. #blockHeight
, amount = Quantity (amtInps - amtChng)
}
return (tx, meta, wit)
Expand Down Expand Up @@ -856,7 +856,7 @@ listTransactions
listTransactions ctx wid mStart mEnd order = do
cp <- withExceptT ErrListTransactionsNoSuchWallet $
readWalletCheckpoint @ctx @s @t @k ctx wid
let tip = currentTip cp ^. #slotId
let tip = currentTip cp
let sp = fromBlockchainParameters (blockchainParameters cp)
maybe (pure []) (listTransactionsWithinRange sp tip) =<< (getSlotRange sp)
where
Expand All @@ -883,7 +883,7 @@ listTransactions ctx wid mStart mEnd order = do

listTransactionsWithinRange
:: SlotParameters
-> SlotId
-> BlockHeader
-> Range SlotId
-> ExceptT ErrListTransactions IO [TransactionInfo]
listTransactionsWithinRange sp tip sr = do
Expand All @@ -896,7 +896,7 @@ listTransactions ctx wid mStart mEnd order = do
-- applying blocks, but that is future work (issue #573).
assemble
:: SlotParameters
-> SlotId
-> BlockHeader
-> [(Tx t, TxMeta)]
-> [TransactionInfo]
assemble sp tip txs = map mkTxInfo txs
Expand All @@ -908,9 +908,12 @@ listTransactions ctx wid mStart mEnd order = do
, txInfoOutputs = W.outputs @t tx
, txInfoMeta = meta
, txInfoDepth =
slotDifference sp tip (meta ^. #slotId)
Quantity $ fromIntegral $ if tipH > txH then tipH - txH else 0
, txInfoTime = txTime (meta ^. #slotId)
}
where
txH = getQuantity (meta ^. #blockHeight)
tipH = getQuantity (tip ^. #blockHeight)
txOuts = Map.fromList
[ (txId @t tx, W.outputs @t tx)
| ((tx, _)) <- txs
Expand Down
10 changes: 9 additions & 1 deletion lib/core/src/Cardano/Wallet/Api/Server.hs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ import Data.Time
( UTCTime )
import Data.Time.Clock
( getCurrentTime )
import Data.Word
( Word32 )
import Fmt
( Buildable, pretty )
import Network.HTTP.Media.RenderHeader
Expand All @@ -201,6 +203,8 @@ import Network.Wai.Middleware.Logging
( newApiLoggerSettings, obfuscateKeys, withApiLogger )
import Network.Wai.Middleware.ServantError
( handleRawError )
import Numeric.Natural
( Natural )
import Servant
( (:<|>) (..)
, (:>)
Expand Down Expand Up @@ -672,6 +676,7 @@ network ctx = do
ApiBlockReference
{ epochNumber = nTip ^. (#slotId . #epochNumber)
, slotNumber = nTip ^. (#slotId . #slotNumber)
, height = natural (nTip ^. #blockHeight)
}
}
where
Expand Down Expand Up @@ -823,18 +828,21 @@ mkApiTransaction txid ins outs (meta, timestamp) setTimeReference =
, block = ApiBlockReference
{ slotNumber = meta ^. (#slotId . #slotNumber)
, epochNumber = meta ^. (#slotId . #epochNumber)
, height = natural (meta ^. #blockHeight)
}
}

toAddressAmount :: TxOut -> AddressAmount t
toAddressAmount (TxOut addr (Coin c)) =
AddressAmount (ApiT addr, Proxy @t) (Quantity $ fromIntegral c)


coerceCoin :: AddressAmount t -> TxOut
coerceCoin (AddressAmount (ApiT addr, _) (Quantity c)) =
TxOut addr (Coin $ fromIntegral c)

natural :: Quantity q Word32 -> Quantity q Natural
natural = Quantity . fromIntegral . getQuantity

getWalletWithCreationTime
:: forall ctx s t k.
( DefineTx t
Expand Down
8 changes: 2 additions & 6 deletions lib/core/src/Cardano/Wallet/Api/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ data ApiTransaction t = ApiTransaction
, amount :: !(Quantity "lovelace" Natural)
, insertedAt :: !(Maybe ApiTimeReference)
, pendingSince :: !(Maybe ApiTimeReference)
, depth :: !(Quantity "slot" Natural)
, depth :: !(Quantity "block" Natural)
, direction :: !(ApiT Direction)
, inputs :: ![ApiTxInput t]
, outputs :: !(NonEmpty (AddressAmount t))
Expand All @@ -278,11 +278,7 @@ data ApiTimeReference = ApiTimeReference
data ApiBlockReference = ApiBlockReference
{ epochNumber :: !Word64
, slotNumber :: !Word16
-- FIXME
-- Make this available, it'll require to also store the block height with
-- TxMeta to make it properly available for transactions.
--
-- , blockHeight :: !(Quantity "block" Word32)
, height :: !(Quantity "block" Natural)
} deriving (Eq, Generic, Show)

data ApiNetworkInformation = ApiNetworkInformation
Expand Down
23 changes: 12 additions & 11 deletions lib/core/src/Cardano/Wallet/DB/Sqlite.hs
Original file line number Diff line number Diff line change
Expand Up @@ -344,14 +344,14 @@ newDBLayer logConfig trace fp = do
]
updateTxMetas wid
[ TxMetaDirection ==. W.Outgoing
, TxMetaSlotId >. point
, TxMetaSlot >. point
]
[ TxMetaStatus =. W.Pending
, TxMetaSlotId =. nearestPoint
, TxMetaSlot =. nearestPoint
]
deleteTxMetas wid
[ TxMetaDirection ==. W.Incoming
, TxMetaSlotId >. point
, TxMetaSlot >. point
]

, prune = \(PrimaryKey wid) -> ExceptT $ runQuery $
Expand Down Expand Up @@ -395,8 +395,8 @@ newDBLayer logConfig trace fp = do

, readTxHistory = \(PrimaryKey wid) order range status -> runQuery $
selectTxHistory @t wid order $ catMaybes
[ (TxMetaSlotId >=.) <$> W.inclusiveLowerBound range
, (TxMetaSlotId <=.) <$> W.inclusiveUpperBound range
[ (TxMetaSlot >=.) <$> W.inclusiveLowerBound range
, (TxMetaSlot <=.) <$> W.inclusiveUpperBound range
, (TxMetaStatus ==.) <$> status
]

Expand Down Expand Up @@ -617,10 +617,10 @@ mkTxMetaEntity wid txid meta = TxMeta
, txMetaWalletId = wid
, txMetaStatus = meta ^. #status
, txMetaDirection = meta ^. #direction
, txMetaSlotId = meta ^. #slotId
, txMetaAmount = getAmount (meta ^. #amount)
, txMetaSlot = meta ^. #slotId
, txMetaBlockHeight = getQuantity (meta ^. #blockHeight)
, txMetaAmount = getQuantity (meta ^. #amount)
}
where getAmount (Quantity n) = n

-- note: TxIn records must already be sorted by order
-- and TxOut records must already be sorted by index
Expand Down Expand Up @@ -651,7 +651,8 @@ txHistoryFromEntity metas ins outs = map mkItem metas
mkTxMeta m = W.TxMeta
{ W.status = txMetaStatus m
, W.direction = txMetaDirection m
, W.slotId = txMetaSlotId m
, W.slotId = txMetaSlot m
, W.blockHeight = Quantity (txMetaBlockHeight m)
, W.amount = Quantity (txMetaAmount m)
}

Expand Down Expand Up @@ -791,8 +792,8 @@ selectTxHistory wid order conditions = do
-- The secondary sort by TxId is to make the ordering stable
-- so that testing with random data always works.
sortOpt = case order of
W.Ascending -> [Asc TxMetaSlotId, Desc TxMetaTxId]
W.Descending -> [Desc TxMetaSlotId, Asc TxMetaTxId]
W.Ascending -> [Asc TxMetaSlot, Desc TxMetaTxId]
W.Descending -> [Desc TxMetaSlot, Asc TxMetaTxId]

selectPrivateKey
:: (MonadIO m, PersistKey k)
Expand Down
13 changes: 7 additions & 6 deletions lib/core/src/Cardano/Wallet/DB/Sqlite/TH.hs
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,13 @@ PrivateKey sql=private_key
-- transaction with different metadata values. The associated inputs and outputs
-- of the transaction are in the TxIn and TxOut tables.
TxMeta
txMetaTxId TxId sql=tx_id
txMetaWalletId W.WalletId sql=wallet_id
txMetaStatus W.TxStatus sql=status
txMetaDirection W.Direction sql=direction
txMetaSlotId W.SlotId sql=slot
txMetaAmount Natural sql=amount
txMetaTxId TxId sql=tx_id
txMetaWalletId W.WalletId sql=wallet_id
txMetaStatus W.TxStatus sql=status
txMetaDirection W.Direction sql=direction
txMetaSlot W.SlotId sql=slot
txMetaBlockHeight Word32 sql=block_height
txMetaAmount Natural sql=amount

Primary txMetaTxId txMetaWalletId
Foreign Wallet fk_wallet_tx_meta txMetaWalletId ! ON DELETE CASCADE
Expand Down
1 change: 1 addition & 0 deletions lib/core/src/Cardano/Wallet/Primitive/Model.hs
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ prefilterBlock proxy b u0 = runState $ do
{ status = InLedger
, direction = dir
, slotId = b ^. #header . #slotId
, blockHeight = b ^. #header . #blockHeight
, amount = Quantity amt
}
applyTx
Expand Down
9 changes: 5 additions & 4 deletions lib/core/src/Cardano/Wallet/Primitive/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -621,17 +621,18 @@ data TxMeta = TxMeta
{ status :: !TxStatus
, direction :: !Direction
, slotId :: !SlotId
, blockHeight :: !(Quantity "block" Word32)
, amount :: !(Quantity "lovelace" Natural)
} deriving (Show, Eq, Ord, Generic)

instance NFData TxMeta

instance Buildable TxMeta where
build (TxMeta s d sl (Quantity a)) = mempty
build (TxMeta s d sl (Quantity bh) (Quantity a)) = mempty
<> (case d of; Incoming -> "+"; Outgoing -> "-")
<> fixedF @Double 6 (fromIntegral a / 1e6)
<> " " <> build s
<> " since " <> build sl
<> " since " <> build sl <> "#" <> build bh

data TxStatus
= Pending
Expand Down Expand Up @@ -687,7 +688,7 @@ data TransactionInfo = TransactionInfo
-- ^ Payment destination.
, txInfoMeta :: !TxMeta
-- ^ Other information calculated from the transaction.
, txInfoDepth :: Quantity "slot" Natural
, txInfoDepth :: Quantity "block" Natural
-- ^ Number of slots since the transaction slot.
, txInfoTime :: UTCTime
-- ^ Creation time of the block including this transaction.
Expand Down Expand Up @@ -1043,7 +1044,7 @@ syncProgress
-> SyncProgress
syncProgress epochLength tip slotNow =
let
bhTip = fromIntegral . getQuantity $ blockHeight tip
bhTip = fromIntegral . getQuantity $ tip ^. #blockHeight
n0 = flatSlot epochLength (tip ^. #slotId)
n1 = flatSlot epochLength slotNow
tolerance = 5
Expand Down
6 changes: 5 additions & 1 deletion lib/core/test/bench/db/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ import Cardano.Wallet.Primitive.Types
, EpochLength (..)
, Hash (..)
, Range (..)
, SlotId (..)
, SortOrder (..)
, SyncProgress (..)
, TxIn (..)
Expand Down Expand Up @@ -386,12 +387,15 @@ mkTxHistory numTx numInputs numOutputs range =
, force TxMeta
{ status = [InLedger, Pending, Invalidated] !! (i `mod` 3)
, direction = Incoming
, slotId = fromFlatSlot epochLength (range !! (i `mod` length range))
, slotId = sl i
, blockHeight = Quantity $ fromIntegral $ slotNumber $ sl i
, amount = Quantity (fromIntegral numOutputs)
}
)
| !i <- [1..numTx]
]
where
sl i = fromFlatSlot epochLength (range !! (i `mod` length range))

mkInputs :: Int -> Int -> [TxIn]
mkInputs prefix n =
Expand Down
Loading