diff --git a/cardano_clusterlib/structs.py b/cardano_clusterlib/structs.py index 71a399c..b92ce1d 100644 --- a/cardano_clusterlib/structs.py +++ b/cardano_clusterlib/structs.py @@ -248,6 +248,8 @@ class TxRawOutput: mint: OptionalMint = () # Minting data (Tx outputs, script, etc.) invalid_hereafter: tp.Optional[int] = None # Validity interval upper bound invalid_before: tp.Optional[int] = None # Validity interval lower bound + current_treasury_value: tp.Optional[int] = None # Current treasury value + treasury_donation: tp.Optional[int] = None # Amount of funds that will be donated to treasury withdrawals: OptionalTxOuts = () # All withdrawals (including those combined with scripts) change_address: str = "" # Address for change return_collateral_txouts: OptionalTxOuts = () # Tx outputs for returning collateral diff --git a/cardano_clusterlib/transaction_group.py b/cardano_clusterlib/transaction_group.py index 06ff90c..1573f38 100644 --- a/cardano_clusterlib/transaction_group.py +++ b/cardano_clusterlib/transaction_group.py @@ -167,6 +167,8 @@ def build_raw_tx_bare( # noqa: C901 script_votes: structs.OptionalScriptVotes = (), invalid_hereafter: tp.Optional[int] = None, invalid_before: tp.Optional[int] = None, + current_treasury_value: tp.Optional[int] = None, + treasury_donation: tp.Optional[int] = None, script_valid: bool = True, join_txouts: bool = True, ) -> structs.TxRawOutput: @@ -202,6 +204,8 @@ def build_raw_tx_bare( # noqa: C901 script_votes: An iterable of `ScriptVote`, specifying vote script data (optional). invalid_hereafter: A last block when the transaction is still valid (optional). invalid_before: A first block when the transaction is valid (optional). + current_treasury_value: The current treasury value (optional). + treasury_donation: A donation to the treasury to perform (optional). script_valid: A bool indicating that the script is valid (True by default). join_txouts: A bool indicating whether to aggregate transaction outputs by payment address (True by default). @@ -210,6 +214,12 @@ def build_raw_tx_bare( # noqa: C901 structs.TxRawOutput: A tuple with transaction output details. """ # pylint: disable=too-many-arguments,too-many-branches,too-many-locals,too-many-statements + if (treasury_donation is not None) != (current_treasury_value is not None): + msg = ( + "Both `treasury_donation` and `current_treasury_value` must be specified together." + ) + raise AssertionError(msg) + if tx_files.certificate_files and complex_certs: LOGGER.warning( "Mixing `tx_files.certificate_files` and `complex_certs`, " @@ -252,6 +262,11 @@ def build_raw_tx_bare( # noqa: C901 # `--ttl` and `--invalid-hereafter` are the same misc_args.extend(["--ttl", str(ttl)]) + if current_treasury_value is not None: + misc_args.extend(["--current-treasury-value", str(current_treasury_value)]) + if treasury_donation is not None: + misc_args.extend(["--treasury-donation", str(treasury_donation)]) + if not script_valid: misc_args.append("--script-invalid") @@ -340,6 +355,8 @@ def build_raw_tx_bare( # noqa: C901 mint=mint, invalid_hereafter=invalid_hereafter or ttl, invalid_before=invalid_before, + current_treasury_value=current_treasury_value, + treasury_donation=treasury_donation, withdrawals=withdrawals, return_collateral_txouts=return_collateral_txouts, total_collateral_amount=total_collateral_amount, @@ -378,6 +395,8 @@ def build_raw_tx( script_withdrawals: structs.OptionalScriptWithdrawals = (), script_votes: structs.OptionalScriptVotes = (), deposit: tp.Optional[int] = None, + current_treasury_value: tp.Optional[int] = None, + treasury_donation: tp.Optional[int] = None, invalid_hereafter: tp.Optional[int] = None, invalid_before: tp.Optional[int] = None, join_txouts: bool = True, @@ -416,6 +435,8 @@ def build_raw_tx( data (optional). script_votes: An iterable of `ScriptVote`, specifying vote script data (optional). deposit: A deposit amount needed by the transaction (optional). + current_treasury_value: The current treasury value (optional). + treasury_donation: A donation to the treasury to perform (optional). invalid_hereafter: A last block when the transaction is still valid (optional). invalid_before: A first block when the transaction is valid (optional). join_txouts: A bool indicating whether to aggregate transaction outputs @@ -446,6 +467,7 @@ def build_raw_tx( withdrawals=withdrawals, script_withdrawals=script_withdrawals, deposit=deposit, + treasury_donation=treasury_donation, ) if ( @@ -478,6 +500,8 @@ def build_raw_tx( script_votes=script_votes, invalid_hereafter=invalid_hereafter or ttl, invalid_before=invalid_before, + current_treasury_value=current_treasury_value, + treasury_donation=treasury_donation, join_txouts=join_txouts, ) @@ -556,6 +580,8 @@ def calculate_tx_fee( script_withdrawals: structs.OptionalScriptWithdrawals = (), script_votes: structs.OptionalScriptVotes = (), deposit: tp.Optional[int] = None, + current_treasury_value: tp.Optional[int] = None, + treasury_donation: tp.Optional[int] = None, invalid_hereafter: tp.Optional[int] = None, invalid_before: tp.Optional[int] = None, witness_count_add: int = 0, @@ -595,6 +621,8 @@ def calculate_tx_fee( data (optional). script_votes: An iterable of `ScriptVote`, specifying vote script data (optional). deposit: A deposit amount needed by the transaction (optional). + current_treasury_value: The current treasury value (optional). + treasury_donation: A donation to the treasury to perform (optional). invalid_hereafter: A last block when the transaction is still valid (optional). invalid_before: A first block when the transaction is valid (optional). witness_count_add: A number of witnesses to add - workaround to make the fee @@ -641,6 +669,8 @@ def calculate_tx_fee( invalid_hereafter=invalid_hereafter or ttl, invalid_before=invalid_before, deposit=deposit, + current_treasury_value=current_treasury_value, + treasury_donation=treasury_donation, join_txouts=join_txouts, destination_dir=destination_dir, ) @@ -768,6 +798,7 @@ def build_tx( # noqa: C901 script_withdrawals: structs.OptionalScriptWithdrawals = (), script_votes: structs.OptionalScriptVotes = (), deposit: tp.Optional[int] = None, + treasury_donation: tp.Optional[int] = None, invalid_hereafter: tp.Optional[int] = None, invalid_before: tp.Optional[int] = None, witness_override: tp.Optional[int] = None, @@ -810,6 +841,7 @@ def build_tx( # noqa: C901 data (optional). script_votes: An iterable of `ScriptVote`, specifying vote script data (optional). deposit: A deposit amount needed by the transaction (optional). + treasury_donation: A donation to the treasury to perform (optional). invalid_hereafter: A last block when the transaction is still valid (optional). invalid_before: A first block when the transaction is valid (optional). witness_override: An integer indicating real number of witnesses. Can be used to fix @@ -867,6 +899,7 @@ def build_tx( # noqa: C901 withdrawals=withdrawals, script_withdrawals=script_withdrawals, deposit=deposit, + treasury_donation=treasury_donation, lovelace_balanced=True, skip_asset_balancing=skip_asset_balancing, ) @@ -892,6 +925,9 @@ def build_tx( # noqa: C901 if invalid_hereafter is not None: misc_args.extend(["--invalid-hereafter", str(invalid_hereafter)]) + if treasury_donation is not None: + misc_args.extend(["--treasury-donation", str(treasury_donation)]) + if not script_valid: misc_args.append("--script-invalid") @@ -980,6 +1016,7 @@ def build_tx( # noqa: C901 mint=mint, invalid_hereafter=invalid_hereafter, invalid_before=invalid_before, + treasury_donation=treasury_donation, withdrawals=collected_data.withdrawals, change_address=change_address or src_address, return_collateral_txouts=return_collateral_txouts, @@ -1207,6 +1244,8 @@ def send_tx( script_withdrawals: structs.OptionalScriptWithdrawals = (), script_votes: structs.OptionalScriptVotes = (), deposit: tp.Optional[int] = None, + current_treasury_value: tp.Optional[int] = None, + treasury_donation: tp.Optional[int] = None, invalid_hereafter: tp.Optional[int] = None, invalid_before: tp.Optional[int] = None, witness_count_add: int = 0, @@ -1254,6 +1293,8 @@ def send_tx( data (optional). script_votes: An iterable of `ScriptVote`, specifying vote script data (optional). deposit: A deposit amount needed by the transaction (optional). + current_treasury_value: The current treasury value (optional). + treasury_donation: A donation to the treasury to perform (optional). invalid_hereafter: A last block when the transaction is still valid (optional). invalid_before: A first block when the transaction is valid (optional). witness_count_add: A number of witnesses to add - workaround to make the fee @@ -1298,6 +1339,8 @@ def send_tx( withdrawals=withdrawals, script_withdrawals=script_withdrawals, deposit=deposit, + current_treasury_value=current_treasury_value, + treasury_donation=treasury_donation, invalid_hereafter=invalid_hereafter or ttl, witness_count_add=witness_count_add, join_txouts=join_txouts, @@ -1328,6 +1371,8 @@ def send_tx( script_withdrawals=script_withdrawals, script_votes=script_votes, deposit=deposit, + current_treasury_value=current_treasury_value, + treasury_donation=treasury_donation, invalid_hereafter=invalid_hereafter or ttl, invalid_before=invalid_before, join_txouts=join_txouts, diff --git a/cardano_clusterlib/txtools.py b/cardano_clusterlib/txtools.py index a0548c2..2ff7e82 100644 --- a/cardano_clusterlib/txtools.py +++ b/cardano_clusterlib/txtools.py @@ -99,6 +99,7 @@ def _select_utxos( withdrawals: structs.OptionalTxOuts, min_change_value: int, deposit: int = 0, + treasury_donation: int = 0, ) -> tp.Set[str]: """Select UTxOs that can satisfy all outputs, deposits and fee. @@ -121,7 +122,7 @@ def _select_utxos( continue tx_fee = fee if fee > 1 else 1 - funds_needed = total_output_amount + tx_fee + deposit + funds_needed = total_output_amount + tx_fee + deposit + treasury_donation total_withdrawals_amount = functools.reduce(lambda x, y: x + y.amount, withdrawals, 0) # fee needs an input, even if withdrawal would cover all needed funds input_funds_needed = max(funds_needed - total_withdrawals_amount, tx_fee) @@ -150,6 +151,7 @@ def _balance_txouts( # noqa: C901 fee: int, withdrawals: structs.OptionalTxOuts, deposit: int = 0, + treasury_donation: int = 0, lovelace_balanced: bool = False, skip_asset_balancing: bool = False, ) -> tp.List[structs.TxOut]: @@ -190,7 +192,7 @@ def _balance_txouts( # noqa: C901 tx_fee = fee if fee > 0 else 0 total_withdrawals_amount = functools.reduce(lambda x, y: x + y.amount, withdrawals, 0) funds_available = total_input_amount + total_withdrawals_amount - funds_needed = total_output_amount + tx_fee + deposit + funds_needed = total_output_amount + tx_fee + deposit + treasury_donation change = funds_available - funds_needed if change < 0: LOGGER.error( @@ -492,6 +494,7 @@ def _get_tx_ins_outs( txouts: structs.OptionalTxOuts = (), fee: int = 0, deposit: tp.Optional[int] = None, + treasury_donation: tp.Optional[int] = None, withdrawals: structs.OptionalTxOuts = (), mint_txouts: structs.OptionalTxOuts = (), lovelace_balanced: bool = False, @@ -507,6 +510,7 @@ def _get_tx_ins_outs( txouts: A list (iterable) of `TxOuts`, specifying transaction outputs (optional). fee: A fee amount (optional). deposit: A deposit amount needed by the transaction (optional). + treasury_donation: A donation to the treasury to perform (optional). withdrawals: A list (iterable) of `TxOuts`, specifying reward withdrawals (optional). mint_txouts: A list (iterable) of `TxOuts`, specifying minted tokens (optional). lovelace_balanced: A bool indicating whether Lovelace ins/outs are balanced @@ -554,6 +558,8 @@ def _get_tx_ins_outs( else deposit ) + tx_treasury_donation = treasury_donation if treasury_donation is not None else 0 + if txins: # don't touch txins that were passed to the function txins_filtered = txins_all @@ -568,6 +574,7 @@ def _get_tx_ins_outs( withdrawals=withdrawals, min_change_value=clusterlib_obj._min_change_value, deposit=tx_deposit, + treasury_donation=tx_treasury_donation, ) txins_by_id: tp.Dict[str, tp.List[structs.UTXOData]] = _organize_utxos_by_id(txins_all) _txins_filtered = [utxo for uid, utxo in txins_by_id.items() if uid in selected_utxo_ids] @@ -595,6 +602,7 @@ def _get_tx_ins_outs( fee=fee, withdrawals=withdrawals, deposit=tx_deposit, + treasury_donation=tx_treasury_donation, lovelace_balanced=lovelace_balanced, skip_asset_balancing=skip_asset_balancing, ) @@ -616,6 +624,7 @@ def collect_data_for_build( withdrawals: structs.OptionalTxOuts = (), script_withdrawals: structs.OptionalScriptWithdrawals = (), deposit: tp.Optional[int] = None, + treasury_donation: tp.Optional[int] = None, lovelace_balanced: bool = False, skip_asset_balancing: bool = False, ) -> structs.DataForBuild: @@ -639,6 +648,7 @@ def collect_data_for_build( script_withdrawals: An iterable of `ScriptWithdrawal`, specifying withdrawal script data (optional). deposit: A deposit amount needed by the transaction (optional). + treasury_donation: A donation to the treasury to perform (optional). lovelace_balanced: A bool indicating whether Lovelace ins/outs are balanced (by `build` command). skip_asset_balancing: A bool indicating if assets balancing should be skipped @@ -688,6 +698,7 @@ def collect_data_for_build( txouts=txouts, fee=fee, deposit=deposit, + treasury_donation=treasury_donation, withdrawals=withdrawals_txouts, mint_txouts=mint_txouts, lovelace_balanced=lovelace_balanced,