Skip to content

Commit

Permalink
Merge #3502
Browse files Browse the repository at this point in the history
3502: Make sure payment template is available during coin selection and fee estimation is using it for multisig r=paweljakubas a=paweljakubas

<!--
Detail in a few bullet points the work accomplished in this PR.

Before you submit, don't forget to:

* Make sure the GitHub PR fields are correct:
   ✓ Set a good Title for your PR.
   ✓ Assign yourself to the PR.
   ✓ Assign one or more reviewer(s).
   ✓ Link to a Jira issue, and/or other GitHub issues or PRs.
   ✓ In the PR description delete any empty sections
     and all text commented in <!--, so that this text does not appear
     in merge commit messages.

* Don't waste reviewers' time:
   ✓ If it's a draft, select the Create Draft PR option.
   ✓ Self-review your changes to make sure nothing unexpected slipped through.

* Try to make your intent clear:
   ✓ Write a good Description that explains what this PR is meant to do.
   ✓ Jira will detect and link to this PR once created, but you can also
     link this PR in the description of the corresponding Jira ticket.
   ✓ Highlight what Testing you have done.
   ✓ Acknowledge any changes required to the Documentation.
-->


- [x] Added script template of native script to tx skeleton and update tx size estimation basing on ledger's cddl

### Comments

Minting/delegation/validity for multisig is going to be addressed in coming PRs. At this point single/multiple output multisig txs along with metadata support should work. 

<!-- Additional comments, links, or screenshots to attach, if any. -->

### Issue Number
adp-2221
<!-- Reference the Jira/GitHub issue that this PR relates to, and which requirements it tackles.
  Note: Jira issues of the form ADP- will be auto-linked. -->


Co-authored-by: Pawel Jakubas <[email protected]>
Co-authored-by: Piotr Stachyra <[email protected]>
  • Loading branch information
3 people authored Oct 11, 2022
2 parents f4b1566 + eb9b589 commit 9c122c9
Show file tree
Hide file tree
Showing 6 changed files with 245 additions and 88 deletions.
31 changes: 17 additions & 14 deletions lib/wallet/src/Cardano/Wallet/Api/Server.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2638,23 +2638,26 @@ constructSharedTransaction
when (hereafter < before || isThereNegativeTime) $
liftHandler $ throwE ErrConstructTxWrongValidityBounds

let txCtx = defaultTransactionCtx
{ txWithdrawal = NoWithdrawal
, txMetadata = md
, txValidityInterval = (Just before, hereafter)
, txDelegationAction = Nothing
}

let transform s sel =
( W.assignChangeAddresses genChange sel s
& uncurry (W.selectionToUnsignedTx (txWithdrawal txCtx))
, sel
, selectionDelta TokenBundle.getCoin sel
)

withWorkerCtx ctx wid liftE liftE $ \wrk -> do
(cp, _, _) <- liftHandler $ withExceptT ErrConstructTxNoSuchWallet $
W.readWallet @_ @s @k wrk wid

let txCtx = defaultTransactionCtx
{ txWithdrawal = NoWithdrawal
, txMetadata = md
, txValidityInterval = (Just before, hereafter)
, txDelegationAction = Nothing
, txPaymentCredentialScriptTemplate =
Just (Shared.paymentTemplate $ getState cp)
}

let transform s sel =
( W.assignChangeAddresses genChange sel s
& uncurry (W.selectionToUnsignedTx (txWithdrawal txCtx))
, sel
, selectionDelta TokenBundle.getCoin sel
)

case Shared.ready (getState cp) of
Shared.Pending ->
liftHandler $ throwE ErrConstructTxSharedWalletPending
Expand Down
1 change: 0 additions & 1 deletion lib/wallet/src/Cardano/Wallet/Shelley/Launch/Cluster.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2509,4 +2509,3 @@ instance HasSeverityAnnotation ClusterLog where

bracketTracer' :: Tracer IO ClusterLog -> Text -> IO a -> IO a
bracketTracer' tr name = bracketTracer (contramap (MsgBracket name) tr)

64 changes: 45 additions & 19 deletions lib/wallet/src/Cardano/Wallet/Shelley/Transaction.hs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ import Prelude
import Cardano.Address.Derivation
( XPrv, toXPub )
import Cardano.Address.Script
( KeyHash, Script (..), foldScript )
( Cosigner, KeyHash, Script (..), ScriptTemplate (..), foldScript )
import Cardano.Api
( AnyCardanoEra (..)
, ByronEra
Expand Down Expand Up @@ -1551,7 +1551,8 @@ data TxSkeleton = TxSkeleton
, txInputCount :: !Int
, txOutputs :: ![TxOut]
, txChange :: ![Set AssetId]
, txScripts :: [Script KeyHash]
, txPaymentTemplate :: !(Maybe (Script Cosigner))
, txMintOrBurnScripts :: [Script KeyHash]
, txAssetsToMintOrBurn :: Set AssetId
-- ^ The set of assets to mint or burn.
, txScriptExecutionCost :: !Coin
Expand All @@ -1571,7 +1572,8 @@ emptyTxSkeleton txWitnessTag = TxSkeleton
, txInputCount = 0
, txOutputs = []
, txChange = []
, txScripts = []
, txPaymentTemplate = Nothing
, txMintOrBurnScripts = []
, txAssetsToMintOrBurn = Set.empty
, txScriptExecutionCost = Coin 0
}
Expand All @@ -1594,7 +1596,10 @@ mkTxSkeleton witness context skeleton = TxSkeleton
, txInputCount = view #skeletonInputCount skeleton
, txOutputs = view #skeletonOutputs skeleton
, txChange = view #skeletonChange skeleton
, txScripts = (<>)
, txPaymentTemplate =
template <$>
view #txPaymentCredentialScriptTemplate context
, txMintOrBurnScripts = (<>)
(Map.elems (snd $ view #txAssetsToMint context))
(Map.elems (snd $ view #txAssetsToBurn context))
, txAssetsToMintOrBurn = (<>)
Expand Down Expand Up @@ -1805,7 +1810,8 @@ estimateTxSize era skeleton =
, txInputCount
, txOutputs
, txChange
, txScripts
, txPaymentTemplate
, txMintOrBurnScripts
, txAssetsToMintOrBurn
} = skeleton

Expand All @@ -1819,10 +1825,13 @@ estimateTxSize era skeleton =
= if txRewardWithdrawal > Coin 0 then 1 else 0

-- Total number of signatures the scripts require
numberOf_MintingWitnesses
= sumVia scriptRequiredKeySigs txMintOrBurnScripts

numberOf_ScriptVkeyWitnesses
= sumVia scriptRequiredKeySigs txScripts
= maybe 0 scriptRequiredKeySigs txPaymentTemplate

scriptRequiredKeySigs :: Num num => Script KeyHash -> num
scriptRequiredKeySigs :: Num num => Script object -> num
scriptRequiredKeySigs = \case
RequireSignatureOf _ ->
1
Expand All @@ -1843,10 +1852,16 @@ estimateTxSize era skeleton =
= case txWitnessTag of
TxWitnessByronUTxO{} -> 0
TxWitnessShelleyUTxO ->
numberOf_Inputs
+ numberOf_Withdrawals
+ numberOf_CertificateSignatures
+ numberOf_ScriptVkeyWitnesses
if numberOf_ScriptVkeyWitnesses == 0 then
numberOf_Inputs
+ numberOf_Withdrawals
+ numberOf_CertificateSignatures
+ numberOf_MintingWitnesses
else
(numberOf_Inputs * numberOf_ScriptVkeyWitnesses)
+ numberOf_Withdrawals
+ numberOf_CertificateSignatures
+ numberOf_MintingWitnesses

numberOf_BootstrapWitnesses
= case txWitnessTag of
Expand Down Expand Up @@ -2122,15 +2137,31 @@ estimateTxSize era skeleton =
= sizeOf_Hash28
+ sizeOf_LargeUInt

-- [* native_script ]
sizeOf_NativeScripts []
= 0
sizeOf_NativeScripts ss
= sizeOf_Array
+ sizeOf_SmallUInt
+ sumVia sizeOf_NativeScript ss

determinePaymentTemplateSize [] scriptCosigner
= sizeOf_Array
+ sizeOf_SmallUInt
+ numberOf_Inputs * (sizeOf_NativeScript scriptCosigner)
determinePaymentTemplateSize _ scriptCosigner
= numberOf_Inputs * (sizeOf_NativeScript scriptCosigner)

-- transaction_witness_set =
-- { ?0 => [* vkeywitness ]
-- , ?1 => [* multisig_script ]
-- , ?1 => [* native_script ]
-- , ?2 => [* bootstrap_witness ]
-- }
sizeOf_WitnessSet
= sizeOf_SmallMap
+ sizeOf_VKeyWitnesses
+ sizeOf_NativeScripts txScripts
+ sizeOf_NativeScripts txMintOrBurnScripts
+ maybe 0 (determinePaymentTemplateSize txMintOrBurnScripts) txPaymentTemplate
+ sizeOf_BootstrapWitnesses
where
-- ?0 => [* vkeywitness ]
Expand All @@ -2140,12 +2171,6 @@ estimateTxSize era skeleton =
+ sizeOf_VKeyWitness * numberOf_VkeyWitnesses

-- ?1 => [* native_script ]
sizeOf_NativeScripts []
= 0
sizeOf_NativeScripts ss
= sizeOf_Array
+ sizeOf_SmallUInt
+ sumVia sizeOf_NativeScript ss

-- ?2 => [* bootstrap_witness ]
sizeOf_BootstrapWitnesses
Expand Down Expand Up @@ -2191,6 +2216,7 @@ estimateTxSize era skeleton =
-- ; Timelock validity intervals are half-open intervals [a, b).
-- ; This field specifies the right (excluded) endpoint b.
-- ]
sizeOf_NativeScript :: Script object -> Integer
sizeOf_NativeScript = \case
RequireSignatureOf _ ->
sizeOf_SmallUInt + sizeOf_Hash28
Expand Down
5 changes: 4 additions & 1 deletion lib/wallet/src/Cardano/Wallet/Transaction.hs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ import Prelude
import Cardano.Address.Derivation
( XPrv, XPub )
import Cardano.Address.Script
( KeyHash, Script )
( KeyHash, Script, ScriptTemplate )
import Cardano.Api
( AnyCardanoEra )
import Cardano.Api.Extra
Expand Down Expand Up @@ -409,6 +409,8 @@ data TransactionCtx = TransactionCtx
-- ^ The assets to mint.
, txAssetsToBurn :: (TokenMap, Map AssetId (Script KeyHash))
-- ^ The assets to burn.
, txPaymentCredentialScriptTemplate :: Maybe ScriptTemplate
-- ^ Script template regulating payment credentials
, txNativeScriptInputs :: Map TxIn (Script KeyHash)
-- ^ A map of script hashes related to inputs. Only for multisig wallets
, txCollateralRequirement :: SelectionCollateralRequirement
Expand Down Expand Up @@ -442,6 +444,7 @@ defaultTransactionCtx = TransactionCtx
, txPlutusScriptExecutionCost = Coin 0
, txAssetsToMint = (TokenMap.empty, Map.empty)
, txAssetsToBurn = (TokenMap.empty, Map.empty)
, txPaymentCredentialScriptTemplate = Nothing
, txNativeScriptInputs = Map.empty
, txCollateralRequirement = SelectionCollateralNotRequired
, txFeePadding = Coin 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1155,7 +1155,7 @@ feeCalculationSpec era = describe "fee calculations" $ do
it "scripts incur fees" $ property $ \scripts ->
let
costWith =
minFeeSkeleton $ emptyTxSkeleton { txScripts = scripts }
minFeeSkeleton $ emptyTxSkeleton { txMintOrBurnScripts = scripts }
costWithout =
minFeeSkeleton emptyTxSkeleton

Expand Down Expand Up @@ -1214,7 +1214,7 @@ feeCalculationSpec era = describe "fee calculations" $ do
F.foldMap (Sum . BS.length . serializeScript ) scripts

sizeWith =
estimateTxSize' $ emptyTxSkeleton { txScripts = scripts }
estimateTxSize' $ emptyTxSkeleton { txMintOrBurnScripts = scripts }
sizeWithout =
estimateTxSize' emptyTxSkeleton

Expand Down Expand Up @@ -1319,7 +1319,7 @@ feeCalculationSpec era = describe "fee calculations" $ do
it "scripts incur fees" $ property $ \scripts ->
let
costWith =
minFeeSkeleton $ emptyTxSkeleton { txScripts = scripts }
minFeeSkeleton $ emptyTxSkeleton { txMintOrBurnScripts = scripts }
costWithout =
minFeeSkeleton emptyTxSkeleton

Expand Down Expand Up @@ -1378,7 +1378,7 @@ feeCalculationSpec era = describe "fee calculations" $ do
F.foldMap (Sum . BS.length . serializeScript ) scripts

sizeWith =
estimateTxSize' $ emptyTxSkeleton { txScripts = scripts }
estimateTxSize' $ emptyTxSkeleton { txMintOrBurnScripts = scripts }
sizeWithout =
estimateTxSize' emptyTxSkeleton

Expand Down
Loading

0 comments on commit 9c122c9

Please sign in to comment.