Skip to content

Commit

Permalink
Resolve PartialTx inputs over LSQ
Browse files Browse the repository at this point in the history
Includes squashed commits:
- Avoid querying node for `getUTxOByTxIn mempty`
- Move logic to `Write.forceUTxOInEra`
  • Loading branch information
Anviking committed Jun 27, 2024
1 parent a648280 commit ebe1412
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 9 deletions.
1 change: 1 addition & 0 deletions lib/api/src/Cardano/Wallet/Api/Http/Server/Error.hs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ instance IsServerError WalletException where
ExceptionSoftDerivationIndex e -> toServerError e
ExceptionHardenedDerivationIndex e -> toServerError e
ExceptionVoting e -> toServerError e
ExceptionInvalidTxOutInEra e -> toServerError e

instance IsServerError ErrNoSuchWallet where
toServerError = \case
Expand Down
2 changes: 1 addition & 1 deletion lib/api/src/Cardano/Wallet/Api/Http/Shelley/Server.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1000,7 +1000,7 @@ import qualified Internal.Cardano.Write.Tx.Balance as Write
( PartialTx (PartialTx)
)
import qualified Internal.Cardano.Write.Tx.Sign as Write
( TimelockKeyWitnessCounts (TimelockKeyWitnessCounts)
( TimelockKeyWitnessCounts (..)
, estimateMinWitnessRequiredPerInput
)
import qualified Network.Ntp as Ntp
Expand Down
29 changes: 28 additions & 1 deletion lib/balance-tx/lib/internal/Internal/Cardano/Write/Tx.hs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ module Internal.Cardano.Write.Tx
, TxOutInRecentEra (..)
, ErrInvalidTxOutInEra (..)
, unwrapTxOutInRecentEra
, wrapTxOutInRecentEra

, computeMinimumCoinForTxOut
, isBelowMinimumCoinForTxOut
Expand Down Expand Up @@ -140,6 +141,7 @@ module Internal.Cardano.Write.Tx
, Shelley.UTxO (..)
, utxoFromTxOutsInRecentEra
, unsafeUtxoFromTxOutsInRecentEra
, forceUTxOToEra

-- * Policy and asset identifiers
, type PolicyId
Expand Down Expand Up @@ -176,9 +178,11 @@ import Cardano.Ledger.Alonzo.UTxO
import Cardano.Ledger.Api
( coinTxOutL
, ppKeyDepositL
, upgradeTxOut
)
import Cardano.Ledger.Api.UTxO
( EraUTxO (ScriptsNeeded)
, UTxO (..)
)
import Cardano.Ledger.Babbage.TxBody
( BabbageTxOut (..)
Expand All @@ -188,6 +192,7 @@ import Cardano.Ledger.BaseTypes
, StrictMaybe (..)
, Version
, maybeToStrictMaybe
, strictMaybeToMaybe
)
import Cardano.Ledger.Coin
( Coin (..)
Expand Down Expand Up @@ -221,7 +226,8 @@ import Cardano.Ledger.Val
, modifyCoin
)
import Control.Arrow
( (>>>)
( second
, (>>>)
)
import Data.ByteString
( ByteString
Expand Down Expand Up @@ -591,6 +597,18 @@ data TxOutInRecentEra =
(Maybe (AlonzoScript LatestLedgerEra))
-- Same contents as 'TxOut LatestLedgerEra'.

wrapTxOutInRecentEra
:: forall era. IsRecentEra era
=> TxOut era
-> TxOutInRecentEra
wrapTxOutInRecentEra out = case recentEra @era of
RecentEraConway ->
let
BabbageTxOut addr v d s = out
in
TxOutInRecentEra addr v d (strictMaybeToMaybe s)
RecentEraBabbage -> wrapTxOutInRecentEra @ConwayEra $ upgradeTxOut out

data ErrInvalidTxOutInEra
= InlinePlutusV3ScriptNotSupportedInBabbage
deriving (Show, Eq)
Expand Down Expand Up @@ -716,6 +734,15 @@ unsafeUtxoFromTxOutsInRecentEra
unsafeUtxoFromTxOutsInRecentEra =
either (error . show) id . utxoFromTxOutsInRecentEra

forceUTxOToEra
:: forall era1 era2. (IsRecentEra era1, IsRecentEra era2)
=> UTxO era1
-> Either ErrInvalidTxOutInEra (UTxO era2)
forceUTxOToEra (UTxO utxo) =
utxoFromTxOutsInRecentEra
$ map (second wrapTxOutInRecentEra)
$ Map.toList utxo

--------------------------------------------------------------------------------
-- Tx
--------------------------------------------------------------------------------
Expand Down
16 changes: 13 additions & 3 deletions lib/network-layer/src/Cardano/Wallet/Network/Implementation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ import Data.Function
)
import Data.Functor
( ($>)
, (<&>)
)
import Data.Functor.Contravariant
( Contravariant (..)
Expand Down Expand Up @@ -518,7 +519,7 @@ withNodeNetworkLayerBase
, stakeDistribution =
_stakeDistribution queryRewardQ
, getUTxOByTxIn =
_getUTxOByTxIn queryRewardQ
_getUTxOByTxIn queryRewardQ readCurrentNodeEra
, getCachedRewardAccountBalance =
_getCachedRewardAccountBalance rewardsObserver
, fetchRewardAccountBalances =
Expand Down Expand Up @@ -661,8 +662,17 @@ withNodeNetworkLayerBase
return res
Nothing -> pure $ StakePoolsSummary 0 mempty mempty

_getUTxOByTxIn queue ins =
bracketQuery "getUTxOByTxIn" tr
_getUTxOByTxIn queue readCachedEra ins
| ins == mempty = readCachedEra <&> \case
AnyCardanoEra ByronEra -> InNonRecentEraByron
AnyCardanoEra ShelleyEra -> InNonRecentEraShelley
AnyCardanoEra AllegraEra -> InNonRecentEraAllegra
AnyCardanoEra MaryEra -> InNonRecentEraMary
AnyCardanoEra AlonzoEra -> InNonRecentEraAlonzo
AnyCardanoEra BabbageEra -> InRecentEraBabbage mempty
AnyCardanoEra ConwayEra -> InRecentEraConway mempty
| otherwise
= bracketQuery "getUTxOByTxIn" tr
$ queue `send` SomeLSQ (LSQ.getUTxOByTxIn ins)

_watchNodeTip readTip callback = do
Expand Down
43 changes: 39 additions & 4 deletions lib/wallet/src/Cardano/Wallet.hs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,8 @@ import Cardano.Crypto.Wallet
( toXPub
)
import Cardano.Ledger.Api
( bodyTxL
( EraTxBody (allInputsTxBodyF)
, bodyTxL
, feeTxBodyL
)
import Cardano.Mnemonic
Expand Down Expand Up @@ -720,6 +721,7 @@ import Data.Functor.Contravariant
)
import Data.Generics.Internal.VL.Lens
( Lens'
, over
, view
, (.~)
, (^.)
Expand Down Expand Up @@ -795,7 +797,8 @@ import GHC.TypeNats
( Nat
)
import Internal.Cardano.Write.Tx
( recentEra
( MaybeInRecentEra (..)
, recentEra
, toRecentEraGADT
)
import Internal.Cardano.Write.Tx.Balance
Expand Down Expand Up @@ -867,15 +870,18 @@ import qualified Data.Vector as V
import qualified Internal.Cardano.Write.Tx as Write
( AnyRecentEra
, CardanoApiEra
, ErrInvalidTxOutInEra
, FeePerByte
, IsRecentEra
, IsRecentEra (..)
, MaybeInRecentEra (..)
, PParams
, PParamsInAnyRecentEra (PParamsInAnyRecentEra)
, RecentEra (..)
, Tx
, UTxO (UTxO)
, cardanoEraFromRecentEra
, feeOfBytes
, forceUTxOToEra
, fromCardanoApiTx
, getFeePerByte
, stakeKeyDeposit
Expand Down Expand Up @@ -2155,6 +2161,9 @@ readNodeTipStateForTxWrite netLayer = do
-- workflow with Shelley- and Shared- wallet flavors.
--
-- Changes to the change state are not written to the DB.
--
-- Inputs of the partial transaction are looked up using a local state query to
-- the node.
balanceTx
:: forall s era.
( GenChange s
Expand All @@ -2175,6 +2184,13 @@ balanceTx wrk pp timeTranslation partialTx = do
Write.constructUTxOIndex $
Write.fromWalletUTxO utxo

-- Resolve inputs using LSQ. Useful for foreign reference inputs supplied by
-- the user when calling transactions-construct, or in transactions-balance.
let netLayer = wrk ^. networkLayer
let inputsToLookup = partialTx ^. #tx . bodyTxL . allInputsTxBodyF
lookedUpUTxO <- liftIO $
forceUTxOToEra =<< getUTxOByTxIn netLayer inputsToLookup

let utxoAssumptions = case walletFlavor @s of
ShelleyWallet -> AllKeyPaymentCredentials
SharedWallet -> AllScriptPaymentCredentialsFrom
Expand All @@ -2190,10 +2206,28 @@ balanceTx wrk pp timeTranslation partialTx = do
utxoIndex
(defaultChangeAddressGen argGenChange)
changeState
partialTx
(over #extraUTxO (<> lookedUpUTxO) partialTx)

return tx
where
-- Assumes the 'utxo' was queried from the node /after/ the 'era'. As
-- rolling back to a previous era should be impossible, we know 'IsRecentEra
-- era => IsRecentEra eraOfUTxO'.
forceUTxOToEra
:: Write.MaybeInRecentEra Write.UTxO
-> IO (Write.UTxO era)
forceUTxOToEra = \case
InRecentEraConway utxo -> hoist $ Write.forceUTxOToEra utxo
InRecentEraBabbage utxo -> hoist $ Write.forceUTxOToEra utxo
InNonRecentEraAlonzo -> impossibleRollback
InNonRecentEraMary -> impossibleRollback
InNonRecentEraAllegra -> impossibleRollback
InNonRecentEraShelley -> impossibleRollback
InNonRecentEraByron -> impossibleRollback
where
impossibleRollback = error "forceUTxOToEra: era should not roll back"
hoist = either (throwIO . ExceptionInvalidTxOutInEra) pure

argGenChange :: ArgGenChange s
argGenChange = case walletFlavor @s of
ShelleyWallet -> delegationAddressS @(NetworkOf s)
Expand Down Expand Up @@ -3850,6 +3884,7 @@ data WalletException
| ExceptionSignPayment ErrSignPayment
| forall era. Write.IsRecentEra era => ExceptionBalanceTx (ErrBalanceTx era)
| ExceptionWriteTxEra ErrWriteTxEra
| ExceptionInvalidTxOutInEra Write.ErrInvalidTxOutInEra
| ExceptionSubmitTransaction ErrSubmitTransaction
| ExceptionConstructTx ErrConstructTx
| ExceptionGetPolicyId ErrGetPolicyId
Expand Down

0 comments on commit ebe1412

Please sign in to comment.