Skip to content

Commit 2de335e

Browse files
authored
Spend utxo with script in the output (#462)
* [bugfix] spend utxo with script in the output * unit tests
1 parent a9442be commit 2de335e

File tree

3 files changed

+97
-7
lines changed

3 files changed

+97
-7
lines changed

integration-test/test/test_plutus.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,45 @@ def test_plutus_v2_ref_script(self):
330330

331331
self.assert_output(taker_address, take_output)
332332

333+
@retry(tries=TEST_RETRIES, backoff=1.3, delay=2, jitter=(0, 10))
334+
@pytest.mark.post_alonzo
335+
def test_plutus_v2_spend_ref_script(self):
336+
# ----------- Create a reference script ---------------
337+
with open("./plutus_scripts/fortytwoV2.plutus", "r") as f:
338+
script_hex = f.read()
339+
forty_two_script = PlutusV2Script(cbor2.loads(bytes.fromhex(script_hex)))
340+
341+
giver_address = Address(self.payment_vkey.hash(), network=self.NETWORK)
342+
343+
builder = TransactionBuilder(self.chain_context)
344+
builder.add_input_address(giver_address)
345+
builder.add_output(
346+
TransactionOutput(giver_address, 50000000, script=forty_two_script)
347+
)
348+
349+
signed_tx = builder.build_and_sign([self.payment_skey], giver_address)
350+
351+
print("############### Transaction created ###############")
352+
print(signed_tx)
353+
print(signed_tx.to_cbor_hex())
354+
print("############### Submitting transaction ###############")
355+
self.chain_context.submit_tx(signed_tx)
356+
time.sleep(6)
357+
358+
# ----------- Spend script utxo ---------------
359+
utxo_to_spend = UTxO(
360+
TransactionInput(signed_tx.id, 0), signed_tx.transaction_body.outputs[0]
361+
)
362+
363+
builder = TransactionBuilder(self.chain_context)
364+
builder.add_input(utxo_to_spend)
365+
signed_tx = builder.build_and_sign([self.payment_skey], giver_address)
366+
print("############### Transaction created ###############")
367+
print(signed_tx)
368+
print(signed_tx.to_cbor_hex())
369+
print("############### Submitting transaction ###############")
370+
self.chain_context.submit_tx(signed_tx)
371+
333372
@retry(tries=TEST_RETRIES, backoff=1.3, delay=2, jitter=(0, 10))
334373
@pytest.mark.post_alonzo
335374
def test_transaction_chaining(self):

pycardano/txbuilder.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ def add_input(self, utxo: UTxO) -> TransactionBuilder:
218218
TransactionBuilder: Current transaction builder.
219219
"""
220220
self.inputs.append(utxo)
221+
if utxo.output.script:
222+
self._reference_scripts.append(utxo.output.script)
221223
return self
222224

223225
def _consolidate_redeemer(self, redeemer):
@@ -1403,7 +1405,11 @@ def build(
14031405

14041406
for address in self.input_addresses:
14051407
for utxo in self.context.utxos(address):
1406-
if utxo not in seen_utxos and utxo not in self.excluded_inputs:
1408+
if (
1409+
utxo not in seen_utxos
1410+
and utxo not in self.excluded_inputs
1411+
and utxo.output.script is None
1412+
):
14071413
additional_utxo_pool.append(utxo)
14081414
additional_amount += utxo.output.amount
14091415
seen_utxos.add(utxo)

test/pycardano/test_txbuilder.py

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2041,12 +2041,6 @@ def test_build_witness_set_mixed_scripts(chain_context):
20412041
assert witness_set.plutus_v2_script is None
20422042
assert witness_set.plutus_v3_script is None
20432043

2044-
# Test with remove_dup_script=False
2045-
witness_set = builder.build_witness_set(remove_dup_script=False)
2046-
assert len(witness_set.plutus_v1_script) == 2
2047-
assert len(witness_set.plutus_v2_script) == 1
2048-
assert len(witness_set.plutus_v3_script) == 1
2049-
20502044

20512045
def test_add_script_input_post_chang(chain_context):
20522046
tx_builder = TransactionBuilder(chain_context)
@@ -2421,3 +2415,54 @@ def test_token_transfer_with_change(chain_context):
24212415
change_output.amount.multi_asset[token_policy_id][token_name]
24222416
== 1876083 - 382
24232417
)
2418+
2419+
2420+
def test_spend_utxo_with_script(chain_context):
2421+
"""Test that UTxOs with scripts are added as reference scripts when added directly."""
2422+
utxo = UTxO(
2423+
TransactionInput.from_primitive(
2424+
[
2425+
"a6cbe6cadecd3f89b60e08e68e5e6c7d72d730aaa1ad21431590f7e6643438ef",
2426+
0,
2427+
]
2428+
),
2429+
TransactionOutput(
2430+
Address.from_primitive(
2431+
"addr_test1vrm9x2zsux7va6w892g38tvchnzahvcd9tykqf3ygnmwtaqyfg52x"
2432+
),
2433+
Value(10000000),
2434+
script=PlutusV2Script(b"dummy test script"),
2435+
),
2436+
)
2437+
2438+
tx_builder = TransactionBuilder(chain_context)
2439+
tx_builder.add_input(utxo)
2440+
assert len(tx_builder._reference_scripts) == 1
2441+
2442+
2443+
def test_skip_utxo_with_script(chain_context):
2444+
"""Test that UTxOs with scripts are skipped when selecting UTxOs by address."""
2445+
addr = Address.from_primitive(
2446+
"addr_test1vrm9x2zsux7va6w892g38tvchnzahvcd9tykqf3ygnmwtaqyfg52x"
2447+
)
2448+
2449+
utxo = UTxO(
2450+
TransactionInput.from_primitive(
2451+
[
2452+
"a6cbe6cadecd3f89b60e08e68e5e6c7d72d730aaa1ad21431590f7e6643438ef",
2453+
0,
2454+
]
2455+
),
2456+
TransactionOutput(
2457+
addr,
2458+
Value(10000000),
2459+
script=PlutusV2Script(b"dummy test script"),
2460+
),
2461+
)
2462+
2463+
with patch.object(chain_context, "utxos") as mock_utxos:
2464+
mock_utxos.return_value = [utxo]
2465+
tx_builder = TransactionBuilder(chain_context)
2466+
tx_builder.add_input_address(addr)
2467+
with pytest.raises(UTxOSelectionException):
2468+
tx_builder.build()

0 commit comments

Comments
 (0)