diff --git a/lib/byron/bench/Restore.hs b/lib/byron/bench/Restore.hs index 85372852746..2aa43a7798a 100644 --- a/lib/byron/bench/Restore.hs +++ b/lib/byron/bench/Restore.hs @@ -103,6 +103,7 @@ import Cardano.Wallet.Primitive.Types , Block (..) , BlockHeader (..) , ChimericAccount + , Coin (..) , GenesisParameters (..) , NetworkParameters (..) , SlotId (..) @@ -425,6 +426,7 @@ withBenchDBLayer tr action = migrationDefaultValues = Sqlite.DefaultFieldValues { Sqlite.defaultActiveSlotCoefficient = 1 , Sqlite.defaultDesiredNumberOfPool = 0 + , Sqlite.defaultMinimumUTxOValue = Coin 0 } -- This tweaks the DB support the AnyAddressState. diff --git a/lib/byron/src/Cardano/Wallet/Byron.hs b/lib/byron/src/Cardano/Wallet/Byron.hs index ac751e6fe76..4bdc2cf427b 100644 --- a/lib/byron/src/Cardano/Wallet/Byron.hs +++ b/lib/byron/src/Cardano/Wallet/Byron.hs @@ -277,6 +277,8 @@ serveWallet getActiveSlotCoefficient gp , defaultDesiredNumberOfPool = desiredNumberOfStakePools (protocolParameters np) + , defaultMinimumUTxOValue = + minimumUTxOvalue (protocolParameters np) } ) databaseDir diff --git a/lib/byron/src/Cardano/Wallet/Byron/Compatibility.hs b/lib/byron/src/Cardano/Wallet/Byron/Compatibility.hs index 7348a8b78e0..8c6f2fc6fbe 100644 --- a/lib/byron/src/Cardano/Wallet/Byron/Compatibility.hs +++ b/lib/byron/src/Cardano/Wallet/Byron/Compatibility.hs @@ -198,6 +198,7 @@ mainnetNetworkParameters = W.NetworkParameters Quantity 4096 } , desiredNumberOfStakePools = 0 + , minimumUTxOvalue = W.Coin 0 } } @@ -446,6 +447,7 @@ protocolParametersFromPP pp = W.ProtocolParameters , getTxMaxSize = fromMaxTxSize $ Update.ppMaxTxSize pp } , desiredNumberOfStakePools = 0 + , minimumUTxOvalue = W.Coin 0 } -- | Extract the protocol parameters relevant to the wallet out of the diff --git a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Network.hs b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Network.hs index a98b83416b6..daa7145b963 100644 --- a/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Network.hs +++ b/lib/core-integration/src/Test/Integration/Scenario/API/Shelley/Network.hs @@ -39,6 +39,9 @@ spec = do -- for Shelley desiredPoolNumber is node's nOpt protocol parameter -- in integration test setup it is 3 let nOpt = 3 + let minUtxoValue = Quantity 0 verify r [ expectField (#decentralizationLevel) (`shouldBe` d) - , expectField (#desiredPoolNumber) (`shouldBe` nOpt)] + , expectField (#desiredPoolNumber) (`shouldBe` nOpt) + , expectField (#minimumUtxoValue) (`shouldBe` minUtxoValue) + ] diff --git a/lib/core/src/Cardano/Wallet.hs b/lib/core/src/Cardano/Wallet.hs index da727e6508b..91b0bbc8f58 100644 --- a/lib/core/src/Cardano/Wallet.hs +++ b/lib/core/src/Cardano/Wallet.hs @@ -1123,10 +1123,11 @@ feeOpts :: TransactionLayer t k -> Maybe DelegationAction -> FeePolicy + -> W.Coin -> FeeOptions -feeOpts tl action feePolicy = FeeOptions +feeOpts tl action feePolicy minUtxo = FeeOptions { estimateFee = minimumFee tl feePolicy action - , dustThreshold = minBound + , dustThreshold = minUtxo , onDanglingChange = if allowUnbalancedTx tl then SaveMoney else PayAndBalance } @@ -1147,9 +1148,9 @@ selectCoinsForPayment -> Quantity "lovelace" Word64 -> ExceptT (ErrSelectForPayment e) IO CoinSelection selectCoinsForPayment ctx wid recipients withdrawal = do - (utxo, txp) <- withExceptT ErrSelectForPaymentNoSuchWallet $ + (utxo, txp, minUtxo) <- withExceptT ErrSelectForPaymentNoSuchWallet $ selectCoinsSetup @ctx @s @k ctx wid - selectCoinsForPaymentFromUTxO @ctx @t @k @e ctx utxo txp recipients withdrawal + selectCoinsForPaymentFromUTxO @ctx @t @k @e ctx utxo txp minUtxo recipients withdrawal -- | Retrieve wallet data which is needed for all types of coin selections. selectCoinsSetup @@ -1158,12 +1159,13 @@ selectCoinsSetup ) => ctx -> WalletId - -> ExceptT ErrNoSuchWallet IO (W.UTxO, W.TxParameters) + -> ExceptT ErrNoSuchWallet IO (W.UTxO, W.TxParameters, W.Coin) selectCoinsSetup ctx wid = do (wal, _, pending) <- readWallet @ctx @s @k ctx wid txp <- txParameters <$> readWalletProtocolParameters @ctx @s @k ctx wid + minUTxO <- minimumUTxOvalue <$> readWalletProtocolParameters @ctx @s @k ctx wid let utxo = availableUTxO @s pending wal - return (utxo, txp) + return (utxo, txp, minUTxO) selectCoinsForPaymentFromUTxO :: forall ctx t k e. @@ -1174,16 +1176,17 @@ selectCoinsForPaymentFromUTxO => ctx -> W.UTxO -> W.TxParameters + -> W.Coin -> NonEmpty TxOut -> Quantity "lovelace" Word64 -> ExceptT (ErrSelectForPayment e) IO CoinSelection -selectCoinsForPaymentFromUTxO ctx utxo txp recipients withdrawal = do +selectCoinsForPaymentFromUTxO ctx utxo txp minUtxo recipients withdrawal = do lift . traceWith tr $ MsgPaymentCoinSelectionStart utxo txp recipients (sel, utxo') <- withExceptT ErrSelectForPaymentCoinSelection $ do let opts = coinSelOpts tl (txp ^. #getTxMaxSize) CoinSelection.random opts recipients withdrawal utxo lift . traceWith tr $ MsgPaymentCoinSelection sel - let feePolicy = feeOpts tl Nothing (txp ^. #getFeePolicy) + let feePolicy = feeOpts tl Nothing (txp ^. #getFeePolicy) minUtxo withExceptT ErrSelectForPaymentFee $ do balancedSel <- adjustForFee feePolicy utxo' sel lift . traceWith tr $ MsgPaymentCoinSelectionAdjusted balancedSel @@ -1205,9 +1208,9 @@ selectCoinsForDelegation -> DelegationAction -> ExceptT ErrSelectForDelegation IO CoinSelection selectCoinsForDelegation ctx wid action = do - (utxo, txp) <- withExceptT ErrSelectForDelegationNoSuchWallet $ + (utxo, txp, minUtxo) <- withExceptT ErrSelectForDelegationNoSuchWallet $ selectCoinsSetup @ctx @s @k ctx wid - selectCoinsForDelegationFromUTxO @_ @t @k ctx utxo txp action + selectCoinsForDelegationFromUTxO @_ @t @k ctx utxo txp minUtxo action selectCoinsForDelegationFromUTxO :: forall ctx t k. @@ -1217,10 +1220,11 @@ selectCoinsForDelegationFromUTxO => ctx -> W.UTxO -> W.TxParameters + -> W.Coin -> DelegationAction -> ExceptT ErrSelectForDelegation IO CoinSelection -selectCoinsForDelegationFromUTxO ctx utxo txp action = do - let feePolicy = feeOpts tl (Just action) (txp ^. #getFeePolicy) +selectCoinsForDelegationFromUTxO ctx utxo txp minUtxo action = do + let feePolicy = feeOpts tl (Just action) (txp ^. #getFeePolicy) minUtxo let sel = initDelegationSelection tl (txp ^. #getFeePolicy) action withExceptT ErrSelectForDelegationFee $ do balancedSel <- adjustForFee feePolicy utxo sel @@ -1241,7 +1245,7 @@ estimateFeeForDelegation -> WalletId -> ExceptT ErrSelectForDelegation IO FeeEstimation estimateFeeForDelegation ctx wid = db & \DBLayer{..} -> do - (utxo, txp) <- withExceptT ErrSelectForDelegationNoSuchWallet + (utxo, txp, minUtxo) <- withExceptT ErrSelectForDelegationNoSuchWallet $ selectCoinsSetup @ctx @s @k ctx wid isKeyReg <- mapExceptT atomically @@ -1249,7 +1253,8 @@ estimateFeeForDelegation ctx wid = db & \DBLayer{..} -> do $ isStakeKeyRegistered (PrimaryKey wid) let action = if isKeyReg then Join pid else RegisterKeyAndJoin pid - let selectCoins = selectCoinsForDelegationFromUTxO @_ @t @k ctx utxo txp action + let selectCoins = + selectCoinsForDelegationFromUTxO @_ @t @k ctx utxo txp minUtxo action estimateFeeForCoinSelection $ Fee . feeBalance <$> selectCoins where db = ctx ^. dbLayer @s @k @@ -1272,9 +1277,9 @@ selectCoinsForMigration -- ^ The source wallet ID. -> ExceptT ErrSelectForMigration IO [CoinSelection] selectCoinsForMigration ctx wid = do - (utxo, txp) <- withExceptT ErrSelectForMigrationNoSuchWallet $ + (utxo, txp, minUtxo) <- withExceptT ErrSelectForMigrationNoSuchWallet $ selectCoinsSetup @ctx @s @k ctx wid - selectCoinsForMigrationFromUTxO @ctx @t @k ctx utxo txp wid + selectCoinsForMigrationFromUTxO @ctx @t @k ctx utxo txp minUtxo wid selectCoinsForMigrationFromUTxO :: forall ctx t k. @@ -1283,13 +1288,14 @@ selectCoinsForMigrationFromUTxO => ctx -> W.UTxO -> W.TxParameters + -> W.Coin -> WalletId -- ^ The source wallet ID. -> ExceptT ErrSelectForMigration IO [CoinSelection] -selectCoinsForMigrationFromUTxO ctx utxo txp wid = do +selectCoinsForMigrationFromUTxO ctx utxo txp minUtxo wid = do let feePolicy@(LinearFee (Quantity a) _ _) = txp ^. #getFeePolicy - let feeOptions = (feeOpts tl Nothing feePolicy) - { dustThreshold = Coin $ ceiling a } + let minUtxo' = max (Coin $ ceiling a) minUtxo + let feeOptions = feeOpts tl Nothing feePolicy minUtxo' let selOptions = coinSelOpts tl (txp ^. #getTxMaxSize) case depleteUTxO feeOptions (idealBatchSize selOptions) utxo of cs | not (null cs) -> pure cs @@ -1311,10 +1317,10 @@ estimateFeeForPayment -> Quantity "lovelace" Word64 -> ExceptT (ErrSelectForPayment e) IO FeeEstimation estimateFeeForPayment ctx wid recipients withdrawal = do - (utxo, txp) <- withExceptT ErrSelectForPaymentNoSuchWallet $ + (utxo, txp, minUtxo) <- withExceptT ErrSelectForPaymentNoSuchWallet $ selectCoinsSetup @ctx @s @k ctx wid let selectCoins = - selectCoinsForPaymentFromUTxO @ctx @t @k @e ctx utxo txp recipients withdrawal + selectCoinsForPaymentFromUTxO @ctx @t @k @e ctx utxo txp minUtxo recipients withdrawal estimateFeeForCoinSelection $ (Fee . feeBalance <$> selectCoins) `catchE` handleCannotCover utxo recipients diff --git a/lib/core/src/Cardano/Wallet/Api/Types.hs b/lib/core/src/Cardano/Wallet/Api/Types.hs index 29333bf20f0..8793aca46ab 100644 --- a/lib/core/src/Cardano/Wallet/Api/Types.hs +++ b/lib/core/src/Cardano/Wallet/Api/Types.hs @@ -505,6 +505,7 @@ data ApiNetworkParameters = ApiNetworkParameters , activeSlotCoefficient :: !(Quantity "percent" Double) , decentralizationLevel :: !(Quantity "percent" Percentage) , desiredPoolNumber :: !Word16 + , minimumUtxoValue :: !(Quantity "lovelace" Natural) } deriving (Eq, Generic, Show) toApiNetworkParameters :: NetworkParameters -> ApiNetworkParameters @@ -520,6 +521,7 @@ toApiNetworkParameters (NetworkParameters gp pp) = ApiNetworkParameters $ getActiveSlotCoefficient gp) (Quantity $ unDecentralizationLevel $ view #decentralizationLevel pp) (view #desiredNumberOfStakePools pp) + (Quantity $ fromIntegral $ getCoin $ view #minimumUTxOvalue pp) newtype ApiTxId = ApiTxId { id :: ApiT (Hash "Tx") diff --git a/lib/core/src/Cardano/Wallet/DB/Sqlite.hs b/lib/core/src/Cardano/Wallet/DB/Sqlite.hs index be59e864895..d02c4a05e0a 100644 --- a/lib/core/src/Cardano/Wallet/DB/Sqlite.hs +++ b/lib/core/src/Cardano/Wallet/DB/Sqlite.hs @@ -136,6 +136,8 @@ import Data.Proxy ( Proxy (..) ) import Data.Quantity ( Quantity (..) ) +import Data.Text + ( Text ) import Data.Text.Class ( ToText (..), fromText ) import Data.Typeable @@ -330,6 +332,8 @@ migrateManually tr defaultFieldValues = addDesiredPoolNumberIfMissing conn + addMinimumUTxOValueIfMissing conn + -- FIXME -- Temporary migration to fix Daedalus flight wallets. This should -- really be removed as soon as we have a fix for the cardano-sl:wallet @@ -420,25 +424,9 @@ migrateManually tr defaultFieldValues = -- it is missing. -- addActiveSlotCoefficientIfMissing :: Sqlite.Connection -> IO () - addActiveSlotCoefficientIfMissing conn = do - isFieldPresent conn activeSlotCoeff >>= \case - TableMissing -> - traceWith tr $ MsgManualMigrationNotNeeded activeSlotCoeff - ColumnMissing -> do - traceWith tr $ MsgManualMigrationNeeded activeSlotCoeff value - addColumn <- Sqlite.prepare conn $ T.unwords - [ "ALTER TABLE", tableName activeSlotCoeff - , "ADD COLUMN", fieldName activeSlotCoeff - , fieldType activeSlotCoeff, "NOT NULL", "DEFAULT", value - , ";" - ] - _ <- Sqlite.step addColumn - Sqlite.finalize addColumn - ColumnPresent -> - traceWith tr $ MsgManualMigrationNotNeeded activeSlotCoeff - + addActiveSlotCoefficientIfMissing conn = + addColumn conn (DBField CheckpointActiveSlotCoeff) value where - activeSlotCoeff = DBField CheckpointActiveSlotCoeff value = toText $ W.unActiveSlotCoefficient $ defaultActiveSlotCoefficient defaultFieldValues @@ -448,25 +436,19 @@ migrateManually tr defaultFieldValues = -- addDesiredPoolNumberIfMissing :: Sqlite.Connection -> IO () addDesiredPoolNumberIfMissing conn = do - isFieldPresent conn desiredPoolNumber >>= \case - TableMissing -> - traceWith tr $ MsgManualMigrationNotNeeded desiredPoolNumber - ColumnMissing -> do - traceWith tr $ MsgManualMigrationNeeded desiredPoolNumber value - addColumn <- Sqlite.prepare conn $ T.unwords - [ "ALTER TABLE", tableName desiredPoolNumber - , "ADD COLUMN", fieldName desiredPoolNumber - , fieldType desiredPoolNumber, "NOT NULL", "DEFAULT", value - , ";" - ] - _ <- Sqlite.step addColumn - Sqlite.finalize addColumn - ColumnPresent -> - traceWith tr $ MsgManualMigrationNotNeeded desiredPoolNumber + addColumn conn (DBField ProtocolParametersDesiredNumberOfPools) value where - desiredPoolNumber = DBField ProtocolParametersDesiredNumberOfPools value = T.pack $ show $ defaultDesiredNumberOfPool defaultFieldValues + -- | Adds an 'minimum_utxo_value' column to the 'protocol_parameters' + -- table if it is missing. + -- + addMinimumUTxOValueIfMissing :: Sqlite.Connection -> IO () + addMinimumUTxOValueIfMissing conn = do + addColumn conn (DBField ProtocolParametersMinimumUtxoValue) value + where + value = T.pack $ show $ defaultMinimumUTxOValue defaultFieldValues + -- | This table became @protocol_parameters@. removeOldTxParametersTable :: Sqlite.Connection -> IO () removeOldTxParametersTable conn = do @@ -491,12 +473,37 @@ migrateManually tr defaultFieldValues = | otherwise -> ColumnMissing _ -> TableMissing + -- | A migration for adding a non-existing column to a table. Factor out as + -- it's a common use-case. + addColumn + :: Sqlite.Connection + -> DBField + -> Text + -> IO () + addColumn conn field value = do + isFieldPresent conn field >>= \case + TableMissing -> + traceWith tr $ MsgManualMigrationNotNeeded field + ColumnMissing -> do + traceWith tr $ MsgManualMigrationNeeded field value + query <- Sqlite.prepare conn $ T.unwords + [ "ALTER TABLE", tableName field + , "ADD COLUMN", fieldName field + , fieldType field, "NOT NULL", "DEFAULT", value + , ";" + ] + _ <- Sqlite.step query + Sqlite.finalize query + ColumnPresent -> + traceWith tr $ MsgManualMigrationNotNeeded field + -- | A set of default field values that can be consulted when performing a -- database migration. -- data DefaultFieldValues = DefaultFieldValues { defaultActiveSlotCoefficient :: W.ActiveSlotCoefficient , defaultDesiredNumberOfPool :: Word16 + , defaultMinimumUTxOValue :: W.Coin } -- | Sets up a connection to the SQLite database. @@ -1061,22 +1068,24 @@ mkProtocolParametersEntity -> W.ProtocolParameters -> ProtocolParameters mkProtocolParametersEntity wid pp = - ProtocolParameters wid fp (getQuantity mx) dl desiredPoolNum + ProtocolParameters wid fp (getQuantity mx) dl desiredPoolNum minUTxO where (W.ProtocolParameters (W.DecentralizationLevel dl) (W.TxParameters fp mx) desiredPoolNum + minUTxO ) = pp protocolParametersFromEntity :: ProtocolParameters -> W.ProtocolParameters -protocolParametersFromEntity (ProtocolParameters _ fp mx dl poolNum) = +protocolParametersFromEntity (ProtocolParameters _ fp mx dl poolNum minUTxO) = W.ProtocolParameters (W.DecentralizationLevel dl) (W.TxParameters fp (Quantity mx)) poolNum + minUTxO {------------------------------------------------------------------------------- DB Queries diff --git a/lib/core/src/Cardano/Wallet/DB/Sqlite/TH.hs b/lib/core/src/Cardano/Wallet/DB/Sqlite/TH.hs index 15fc9ca388d..a5eb623b333 100644 --- a/lib/core/src/Cardano/Wallet/DB/Sqlite/TH.hs +++ b/lib/core/src/Cardano/Wallet/DB/Sqlite/TH.hs @@ -152,6 +152,7 @@ ProtocolParameters protocolParametersTxMaxSize Word16 sql=tx_max_size protocolParametersDecentralizationLevel Percentage sql=decentralization_level protocolParametersDesiredNumberOfPools Word16 sql=desired_pool_number + protocolParametersMinimumUtxoValue W.Coin sql=minimum_utxo_value Primary protocolParametersWalletId Foreign Wallet fk_wallet_protocol_parameters protocolParametersWalletId ! ON DELETE CASCADE deriving Show Generic diff --git a/lib/core/src/Cardano/Wallet/Primitive/Types.hs b/lib/core/src/Cardano/Wallet/Primitive/Types.hs index ed5e73c02e0..3068fa7a0c1 100644 --- a/lib/core/src/Cardano/Wallet/Primitive/Types.hs +++ b/lib/core/src/Cardano/Wallet/Primitive/Types.hs @@ -1399,6 +1399,9 @@ data ProtocolParameters = ProtocolParameters :: Word16 -- ^ The current desired number of stakepools in the network. -- Also known as k parameter. + , minimumUTxOvalue + :: Coin + -- ^ The minimu UTxO value. } deriving (Eq, Generic, Show) instance NFData ProtocolParameters @@ -1408,6 +1411,7 @@ instance Buildable ProtocolParameters where [ "Decentralization level: " <> build (pp ^. #decentralizationLevel) , "Transaction parameters: " <> build (pp ^. #txParameters) , "Desired number of pools: " <> build (pp ^. #desiredNumberOfStakePools) + , "Minimum UTxO value: " <> build (pp ^. #minimumUTxOvalue) ] -- | Indicates the current level of decentralization in the network. diff --git a/lib/core/test/bench/db/Main.hs b/lib/core/test/bench/db/Main.hs index 324a50a2040..4c7a90d4448 100644 --- a/lib/core/test/bench/db/Main.hs +++ b/lib/core/test/bench/db/Main.hs @@ -344,6 +344,7 @@ defaultFieldValues :: DefaultFieldValues defaultFieldValues = DefaultFieldValues { defaultActiveSlotCoefficient = ActiveSlotCoefficient 1.0 , defaultDesiredNumberOfPool = 50 + , defaultMinimumUTxOValue = Coin 0 -- NOTE value in the genesis when at the time this migration was needed. } diff --git a/lib/core/test/data/Cardano/Wallet/Api/ApiNetworkParameters.json b/lib/core/test/data/Cardano/Wallet/Api/ApiNetworkParameters.json index 14cdce545e5..c201d07c3de 100644 --- a/lib/core/test/data/Cardano/Wallet/Api/ApiNetworkParameters.json +++ b/lib/core/test/data/Cardano/Wallet/Api/ApiNetworkParameters.json @@ -1,254 +1,294 @@ { - "seed": -1984240878940569186, + "seed": -1802592071269241418, "samples": [ { "slot_length": { - "quantity": 8804, + "quantity": 1457, "unit": "second" }, "decentralization_level": { - "quantity": 27.44, + "quantity": 31.07, "unit": "percent" }, "epoch_stability": { - "quantity": 14698, + "quantity": 2906, "unit": "block" }, - "genesis_block_hash": "2d0c106c427d16063756bb255d31250cc923325c6b5f19645266814c794e3e09", - "blockchain_start_time": "1881-08-19T09:40:33.993547684331Z", - "desired_pool_number": 32038, + "genesis_block_hash": "710412c35e162e5a0a3140129b38492504e600004f4b402a5508516d131c032e", + "blockchain_start_time": "1879-02-23T17:28:54.017963646932Z", + "desired_pool_number": 3369, "epoch_length": { - "quantity": 21008, + "quantity": 32352, "unit": "slot" }, "active_slot_coefficient": { - "quantity": 24.109475832319728, + "quantity": 51.43218368270883, "unit": "percent" + }, + "minimum_utxo_value": { + "quantity": 168, + "unit": "lovelace" } }, { "slot_length": { - "quantity": 8092, + "quantity": 3541, "unit": "second" }, "decentralization_level": { - "quantity": 10.18, + "quantity": 72.16, "unit": "percent" }, "epoch_stability": { - "quantity": 1843, + "quantity": 28887, "unit": "block" }, - "genesis_block_hash": "0353fdf93759307c230d19ba4a7d3b1a315d813161770866ff6f023a2f494b32", - "blockchain_start_time": "1877-07-19T22:03:55.536832695831Z", - "desired_pool_number": 27299, + "genesis_block_hash": "640126365806772277e13e100f306e5a2c1d1a4dcc645f10703f42857c5e6e07", + "blockchain_start_time": "1882-07-16T22:00:00Z", + "desired_pool_number": 27172, "epoch_length": { - "quantity": 32442, + "quantity": 20034, "unit": "slot" }, "active_slot_coefficient": { - "quantity": 35.782018645281, + "quantity": 56.27366141373169, "unit": "percent" + }, + "minimum_utxo_value": { + "quantity": 224, + "unit": "lovelace" } }, { "slot_length": { - "quantity": 9154, + "quantity": 1105, "unit": "second" }, "decentralization_level": { - "quantity": 14.08, + "quantity": 87.22, "unit": "percent" }, "epoch_stability": { - "quantity": 23685, + "quantity": 9941, "unit": "block" }, - "genesis_block_hash": "050f4e400e13552f2535e51557662c0306335024723e42625958b34578716a5b", - "blockchain_start_time": "1906-01-23T04:00:00Z", - "desired_pool_number": 30831, + "genesis_block_hash": "55275e2d2975335b137124455c52100e7c04566056702141d66d4b5d680eec87", + "blockchain_start_time": "1863-05-17T19:33:06.87009001763Z", + "desired_pool_number": 9204, "epoch_length": { - "quantity": 722, + "quantity": 9306, "unit": "slot" }, "active_slot_coefficient": { - "quantity": 45.505485658621616, + "quantity": 49.59216226142475, "unit": "percent" + }, + "minimum_utxo_value": { + "quantity": 15, + "unit": "lovelace" } }, { "slot_length": { - "quantity": 6902, + "quantity": 5183, "unit": "second" }, "decentralization_level": { - "quantity": 36.38, + "quantity": 5.3, "unit": "percent" }, "epoch_stability": { - "quantity": 13954, + "quantity": 17873, "unit": "block" }, - "genesis_block_hash": "7a3b7c3d6b0a2215222f511ba967037a17556823633c495542cf207632005714", - "blockchain_start_time": "1889-05-02T20:01:52.165487876522Z", - "desired_pool_number": 18465, + "genesis_block_hash": "333c254df207df7e713c2d57720a2e4d3a485b53696e378c284a2a5b1e797e52", + "blockchain_start_time": "1872-05-20T22:03:07Z", + "desired_pool_number": 15474, "epoch_length": { - "quantity": 2100, + "quantity": 4047, "unit": "slot" }, "active_slot_coefficient": { - "quantity": 36.52505119563008, + "quantity": 4.244555796460114, "unit": "percent" + }, + "minimum_utxo_value": { + "quantity": 201, + "unit": "lovelace" } }, { "slot_length": { - "quantity": 6939, + "quantity": 1812, "unit": "second" }, "decentralization_level": { - "quantity": 50.83, + "quantity": 85.35, "unit": "percent" }, "epoch_stability": { - "quantity": 14689, + "quantity": 27399, "unit": "block" }, - "genesis_block_hash": "461826053f5339281c3e7e799c71080a1aea304c1c3f682f10b457563c545714", - "blockchain_start_time": "1876-12-05T11:38:02.49568317573Z", - "desired_pool_number": 6799, + "genesis_block_hash": "26785e107e4305341a19036e464c5455071c625e6151526e08575316612c1e7f", + "blockchain_start_time": "1872-03-25T09:55:13Z", + "desired_pool_number": 1961, "epoch_length": { - "quantity": 6181, + "quantity": 8695, "unit": "slot" }, "active_slot_coefficient": { - "quantity": 95.30023564427918, + "quantity": 41.719805322193, "unit": "percent" + }, + "minimum_utxo_value": { + "quantity": 184, + "unit": "lovelace" } }, { "slot_length": { - "quantity": 4158, + "quantity": 2247, "unit": "second" }, "decentralization_level": { - "quantity": 86.74, + "quantity": 10.24, "unit": "percent" }, "epoch_stability": { - "quantity": 11252, + "quantity": 23848, "unit": "block" }, - "genesis_block_hash": "0c4816ac577b75a94a6010457544043859286c74424b4792724a55535233ce0f", - "blockchain_start_time": "1895-06-12T18:38:51.613463116487Z", - "desired_pool_number": 6332, + "genesis_block_hash": "414c7b5b51692b764a0b6f3e375e2403622075472768507d52602d4143256263", + "blockchain_start_time": "1861-04-19T22:15:51.537303729012Z", + "desired_pool_number": 12888, "epoch_length": { - "quantity": 6203, + "quantity": 4669, "unit": "slot" }, "active_slot_coefficient": { - "quantity": 59.013819454586034, + "quantity": 23.230933166018875, "unit": "percent" + }, + "minimum_utxo_value": { + "quantity": 115, + "unit": "lovelace" } }, { "slot_length": { - "quantity": 4545, + "quantity": 3265, "unit": "second" }, "decentralization_level": { - "quantity": 35.19, + "quantity": 56.86, "unit": "percent" }, "epoch_stability": { - "quantity": 10310, + "quantity": 19930, "unit": "block" }, - "genesis_block_hash": "8ecbf461186f4638d4097425387c357d392976a2705c62791d361667692293cf", - "blockchain_start_time": "1906-01-18T09:34:53.923334751052Z", - "desired_pool_number": 2936, + "genesis_block_hash": "97817765614d461e3875541e5c232444002412236d807b72333d7167244acd7f", + "blockchain_start_time": "1901-07-30T12:16:33Z", + "desired_pool_number": 8459, "epoch_length": { - "quantity": 19601, + "quantity": 2418, "unit": "slot" }, "active_slot_coefficient": { - "quantity": 41.975201347713764, + "quantity": 46.933747834177595, "unit": "percent" + }, + "minimum_utxo_value": { + "quantity": 203, + "unit": "lovelace" } }, { "slot_length": { - "quantity": 3194, + "quantity": 5577, "unit": "second" }, "decentralization_level": { - "quantity": 65.66, + "quantity": 40.84, "unit": "percent" }, "epoch_stability": { - "quantity": 21442, + "quantity": 28400, "unit": "block" }, - "genesis_block_hash": "4f7f286d773a3b5176653631117b251a1d1b776609011e1c17666959b4046427", - "blockchain_start_time": "1876-02-24T02:04:56Z", - "desired_pool_number": 10647, + "genesis_block_hash": "130e487b3001364f0da83d3e3e3d6d35d63b254b0b6c4e40f1595d4b3d787f05", + "blockchain_start_time": "1877-03-22T20:00:00Z", + "desired_pool_number": 21071, "epoch_length": { - "quantity": 2455, + "quantity": 29499, "unit": "slot" }, "active_slot_coefficient": { - "quantity": 95.08852182419434, + "quantity": 26.184108066972435, "unit": "percent" + }, + "minimum_utxo_value": { + "quantity": 145, + "unit": "lovelace" } }, { "slot_length": { - "quantity": 4415, + "quantity": 4478, "unit": "second" }, "decentralization_level": { - "quantity": 19.99, + "quantity": 52.52, "unit": "percent" }, "epoch_stability": { - "quantity": 20840, + "quantity": 16171, "unit": "block" }, - "genesis_block_hash": "6b245905223c1b36063a61e815556e1f73033a9b3021213737680f797057444a", - "blockchain_start_time": "1879-08-09T17:36:30.572650906619Z", - "desired_pool_number": 19374, + "genesis_block_hash": "3d7f551e196e3e7f5014143c2f3166281b242048503b0239f954084f30066040", + "blockchain_start_time": "1907-12-20T10:00:00Z", + "desired_pool_number": 6901, "epoch_length": { - "quantity": 24669, + "quantity": 18865, "unit": "slot" }, "active_slot_coefficient": { - "quantity": 8.427169510319887, + "quantity": 30.103625697966574, "unit": "percent" + }, + "minimum_utxo_value": { + "quantity": 184, + "unit": "lovelace" } }, { "slot_length": { - "quantity": 9912, + "quantity": 4136, "unit": "second" }, "decentralization_level": { - "quantity": 39.97, + "quantity": 74.5, "unit": "percent" }, "epoch_stability": { - "quantity": 26046, + "quantity": 14924, "unit": "block" }, - "genesis_block_hash": "c51d5d2506519e71265b672f622aa51b2d6e434d7e7a4a1103715f25de426e50", - "blockchain_start_time": "1879-07-02T14:07:16.914969860618Z", - "desired_pool_number": 16799, + "genesis_block_hash": "6637227c6737317f5e0a36092da83d295e992b4c3e0c5b5f46024a14161b1826", + "blockchain_start_time": "1890-05-25T19:00:00Z", + "desired_pool_number": 5091, "epoch_length": { - "quantity": 77, + "quantity": 1368, "unit": "slot" }, "active_slot_coefficient": { - "quantity": 22.710583012744756, + "quantity": 39.368603800409204, "unit": "percent" + }, + "minimum_utxo_value": { + "quantity": 86, + "unit": "lovelace" } } ] diff --git a/lib/core/test/shared/Cardano/Wallet/DummyTarget/Primitive/Types.hs b/lib/core/test/shared/Cardano/Wallet/DummyTarget/Primitive/Types.hs index 2e983841924..f32cd3f7114 100644 --- a/lib/core/test/shared/Cardano/Wallet/DummyTarget/Primitive/Types.hs +++ b/lib/core/test/shared/Cardano/Wallet/DummyTarget/Primitive/Types.hs @@ -99,6 +99,7 @@ dummyProtocolParameters = ProtocolParameters { decentralizationLevel = minBound , txParameters = dummyTxParameters , desiredNumberOfStakePools = 100 + , minimumUTxOvalue = Coin 0 } -- | Construct a @Tx@, computing its hash using the dummy @mkTxId@. diff --git a/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs b/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs index d0f1d3c8779..6b22b31018b 100644 --- a/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs +++ b/lib/core/test/unit/Cardano/Wallet/Api/TypesSpec.hs @@ -781,6 +781,8 @@ spec = do decentralizationLevel (x :: ApiNetworkParameters) , desiredPoolNumber = desiredPoolNumber (x :: ApiNetworkParameters) + , minimumUtxoValue = + minimumUtxoValue (x :: ApiNetworkParameters) } in x' === x .&&. show x' === show x diff --git a/lib/core/test/unit/Cardano/Wallet/DB/Arbitrary.hs b/lib/core/test/unit/Cardano/Wallet/DB/Arbitrary.hs index 6f1a94aa9ce..7853d8de6aa 100644 --- a/lib/core/test/unit/Cardano/Wallet/DB/Arbitrary.hs +++ b/lib/core/test/unit/Cardano/Wallet/DB/Arbitrary.hs @@ -574,6 +574,7 @@ instance Arbitrary ProtocolParameters where <$> arbitrary <*> arbitrary <*> arbitrary + <*> arbitrary shrink = genericShrink instance Arbitrary TxParameters where diff --git a/lib/core/test/unit/Cardano/Wallet/DB/SqliteSpec.hs b/lib/core/test/unit/Cardano/Wallet/DB/SqliteSpec.hs index 0c00ae0f32e..ee3380667c8 100644 --- a/lib/core/test/unit/Cardano/Wallet/DB/SqliteSpec.hs +++ b/lib/core/test/unit/Cardano/Wallet/DB/SqliteSpec.hs @@ -729,6 +729,7 @@ defaultFieldValues :: DefaultFieldValues defaultFieldValues = DefaultFieldValues { defaultActiveSlotCoefficient = ActiveSlotCoefficient 1.0 , defaultDesiredNumberOfPool = 0 + , defaultMinimumUTxOValue = Coin 0 } newDBLayer' diff --git a/lib/jormungandr/src/Cardano/Wallet/Jormungandr.hs b/lib/jormungandr/src/Cardano/Wallet/Jormungandr.hs index 0537f7cdf52..cbefc3d4e46 100644 --- a/lib/jormungandr/src/Cardano/Wallet/Jormungandr.hs +++ b/lib/jormungandr/src/Cardano/Wallet/Jormungandr.hs @@ -288,6 +288,8 @@ serveWallet Tracers{..} sTolerance databaseDir hostPref listen backend beforeMai getActiveSlotCoefficient (genesisParameters np) , defaultDesiredNumberOfPool = desiredNumberOfStakePools (protocolParameters np) + , defaultMinimumUTxOValue = + minimumUTxOvalue (protocolParameters np) } ) databaseDir diff --git a/lib/jormungandr/src/Cardano/Wallet/Jormungandr/Api/Client.hs b/lib/jormungandr/src/Cardano/Wallet/Jormungandr/Api/Client.hs index 4f2e725eea2..fc8a5e8a2d5 100644 --- a/lib/jormungandr/src/Cardano/Wallet/Jormungandr/Api/Client.hs +++ b/lib/jormungandr/src/Cardano/Wallet/Jormungandr/Api/Client.hs @@ -78,6 +78,7 @@ import Cardano.Wallet.Primitive.Types ( ActiveSlotCoefficient (..) , Block (..) , BlockHeader (..) + , Coin (..) , EpochNo (..) , GenesisParameters (..) , Hash (..) @@ -327,6 +328,7 @@ mkJormungandrClient mgr baseUrl = JormungandrClient , getTxMaxSize = softTxMaxSize } , desiredNumberOfStakePools = fromIntegral poolcapping + , minimumUTxOvalue = Coin 0 } } ) diff --git a/lib/jormungandr/test/unit/Cardano/Pool/Jormungandr/MetricsSpec.hs b/lib/jormungandr/test/unit/Cardano/Pool/Jormungandr/MetricsSpec.hs index 8cbbb6ce87a..97f48674e30 100644 --- a/lib/jormungandr/test/unit/Cardano/Pool/Jormungandr/MetricsSpec.hs +++ b/lib/jormungandr/test/unit/Cardano/Pool/Jormungandr/MetricsSpec.hs @@ -508,6 +508,7 @@ genesisProtocolParameters = ProtocolParameters { decentralizationLevel = minBound , txParameters = genesisTxParameters , desiredNumberOfStakePools = 10 + , minimumUTxOvalue = Coin 0 } genesisTxParameters :: TxParameters diff --git a/lib/jormungandr/test/unit/Cardano/Wallet/Jormungandr/NetworkSpec.hs b/lib/jormungandr/test/unit/Cardano/Wallet/Jormungandr/NetworkSpec.hs index 6c52ffcc5ca..e7a7bf75248 100644 --- a/lib/jormungandr/test/unit/Cardano/Wallet/Jormungandr/NetworkSpec.hs +++ b/lib/jormungandr/test/unit/Cardano/Wallet/Jormungandr/NetworkSpec.hs @@ -29,6 +29,7 @@ import Cardano.Wallet.Network.BlockHeaders ( BlockHeaders, emptyBlockHeaders, greatestCommonBlockHeader ) import Cardano.Wallet.Primitive.Types ( BlockHeader (..) + , Coin (..) , GenesisParameters (..) , Hash (..) , NetworkParameters (..) @@ -423,6 +424,7 @@ mockJormungandrClient logLine = JormungandrClient , getTxMaxSize = error "mock gp" } , desiredNumberOfStakePools = 10 + , minimumUTxOvalue = Coin 0 } }) diff --git a/lib/shelley/src/Cardano/Wallet/Shelley.hs b/lib/shelley/src/Cardano/Wallet/Shelley.hs index 281bff0c403..fca3a8f4986 100644 --- a/lib/shelley/src/Cardano/Wallet/Shelley.hs +++ b/lib/shelley/src/Cardano/Wallet/Shelley.hs @@ -329,6 +329,8 @@ serveWallet getActiveSlotCoefficient gp , defaultDesiredNumberOfPool = desiredNumberOfStakePools (protocolParameters np) + , defaultMinimumUTxOValue = + minimumUTxOvalue (protocolParameters np) } ) databaseDir diff --git a/lib/shelley/src/Cardano/Wallet/Shelley/Compatibility.hs b/lib/shelley/src/Cardano/Wallet/Shelley/Compatibility.hs index e62ec7e356f..8175575b610 100644 --- a/lib/shelley/src/Cardano/Wallet/Shelley/Compatibility.hs +++ b/lib/shelley/src/Cardano/Wallet/Shelley/Compatibility.hs @@ -463,6 +463,8 @@ fromPParams pp = W.ProtocolParameters txParametersFromPParams pp , desiredNumberOfStakePools = desiredNumberOfStakePoolsFromPParams pp + , minimumUTxOvalue = + minimumUTxOvalueFromPParams pp } -- | Extract the current network decentralization level from the given set of @@ -513,6 +515,11 @@ desiredNumberOfStakePoolsFromPParams -> Word16 desiredNumberOfStakePoolsFromPParams pp = fromIntegral (SL._nOpt pp) +minimumUTxOvalueFromPParams + :: SL.PParams + -> W.Coin +minimumUTxOvalueFromPParams pp = W.Coin . fromIntegral $ SL._minUTxOValue pp + -- | Convert genesis data into blockchain params and an initial set of UTxO fromGenesisData :: ShelleyGenesis TPraosStandardCrypto diff --git a/lib/shelley/test/unit/Cardano/Wallet/Shelley/TransactionSpec.hs b/lib/shelley/test/unit/Cardano/Wallet/Shelley/TransactionSpec.hs index 3e1a840d7e3..6533b276071 100644 --- a/lib/shelley/test/unit/Cardano/Wallet/Shelley/TransactionSpec.hs +++ b/lib/shelley/test/unit/Cardano/Wallet/Shelley/TransactionSpec.hs @@ -224,7 +224,7 @@ testCoinSelOpts :: CoinSelectionOptions () testCoinSelOpts = coinSelOpts testTxLayer (Quantity 4096) testFeeOpts :: FeeOptions -testFeeOpts = feeOpts testTxLayer Nothing feePolicy +testFeeOpts = feeOpts testTxLayer Nothing feePolicy (Coin 0) where feePolicy = LinearFee (Quantity 155381) (Quantity 44) (Quantity 0) diff --git a/specifications/api/swagger.yaml b/specifications/api/swagger.yaml index 40fe06b3f93..c2d3b90640f 100644 --- a/specifications/api/swagger.yaml +++ b/specifications/api/swagger.yaml @@ -818,6 +818,7 @@ components: - active_slot_coefficient - decentralization_level - desired_pool_number + - minimum_utxo_value properties: genesis_block_hash: *blockId blockchain_start_time: *date @@ -827,6 +828,7 @@ components: active_slot_coefficient: *percentage decentralization_level: *percentage desired_pool_number: *stakePoolsNumber + minimum_utxo_value: *amount ApiSelectCoinsData: &ApiSelectCoinsData type: object