Skip to content

Commit 87fb538

Browse files
henryyuanheng-wangYuanheng WangYuanheng Wangdependabot[bot]
authored
Support utxo query with kupo for Vasil (#121)
* incorporate split change logic * incorporate split change logic * incorporate split change logic * minor modification to change combine logic * minor modification to change combine logic * minor modification to change combine logic * integrate diff changes * integrate diff changes and remove unused functions * add change split test case. Modify txbuilder logic in handeling splits. * Bump pytest from 7.0.1 to 7.1.1 Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.0.1 to 7.1.1. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](pytest-dev/pytest@7.0.1...7.1.1) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> * replace max fee with more accurately estimated fees * replace max fee with more precise fee estimation * remove max fee import * modify format to be consistent with code base * supports utxo queries using kupo * support utxo query with Kupo * reformat * query utxo with Kupo when kupo url is provided * remove the hardcoded genesis utxo in test_all file * Create usage guides for Plutus and fix hyperlinks * create separate section for datum/redeemer serialiation * add -f flag to try to clean up the build if it exists * Create usage guides for Plutus and fix hyperlinks * create separate section for datum/redeemer serialiation * add -f flag to try to clean up the build if it exists * hdwallet implementation and unit test * modify poetry * modify poetry file * modify poetry lock * made changes to hdwallet and incorporated into bip32 * remove commented code block * support utxo query with kupo * move test_bip32 * update utxo query with kupo * update plutus guide with vasil Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Yuanheng Wang <[email protected]> Co-authored-by: Yuanheng Wang <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1 parent a2c3a8e commit 87fb538

File tree

5 files changed

+101
-6
lines changed

5 files changed

+101
-6
lines changed

docs/source/guides/plutus.rst

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,71 @@ Taker/Unlocker provides collateral. Collateral has been introduced in Alonzo tra
161161

162162
The funds locked in script address is successfully retrieved to the taker address.
163163

164+
-------------
165+
Vasil Upgrade
166+
-------------
167+
As part of the Basho phase of Cardano roadmap, the Vasil upgrade brings new capabilities on Plutus, namely reference inputs, inline datums, reference scripts, collateral output and Plutus V2 primitives.
168+
169+
- **Reference inputs** (`CIP-31 <https://cips.cardano.org/cips/cip31/>`_): This upgrade enables data sharing on-chain. Previously, datums were carried in transaction outputs; they stored and provided access to information on the blockchain. However, to access information in this datum, one had to spend the output that the datum was attached to. This required the re-creation of a spent output. The addition of reference inputs now allows developers to look at the datum without extra steps. This facilitates access to information stored on the blockchain without the need for spending and re-creating UTXOs. This can be useful for oracles and other use cases where state need to be inspected.
170+
171+
- **Inline datums** (`CIP-32 <https://cips.cardano.org/cips/cip32/>`_): Transaction datums were previously attached to outputs as hashes. With the implementation of inline datums, developers can now create scripts and attach datums directly to outputs instead of using their hashes. This simplifies how datums are used – a user can see the actual datum rather than supply it to match the given hash.
172+
173+
- **Reference scripts** (`CIP-33 <https://cips.cardano.org/cips/cip33/>`_): In Alonzo, when spending an output locked within a Plutus script, one had to include the script in the spending transaction. This increased the size of the script and caused certain delays in its processing. The reference scripts upgrade allows developers to reference a script without including it in each transaction. This significantly reduces transaction size, improves throughput, and reduces script execution costs (since the script only needs to be paid for once).
174+
175+
- **Explicit collateral output** (`CIP-40 <https://cips.cardano.org/cips/cip40/>`_): Transactions that call Plutus smart contracts are required to put up collateral to cover the potential cost of smart contract execution failure. If contract execution fails during phase 2 validation, all the funds stored in the chose UTXO for the collateral will be lost. After Vasil, user can specify a change address for the script collateral. If the script fails phase-2 validation, only the collateral amount will be taken, and the remaining funds will be sent to the change address.
176+
177+
- **Plutus V2 scripts**: The Vasil upgrade includes a new cost model that's lower than before, and developers will be able to see redeemers for all inputs rather than just the one being passed to the currently executing script.
178+
179+
Using the same FortyTwo example, now in Vasil, we show how reference scripts can be used. Reference script exists at a particular transaction output, and it can be used to witness UTxO at the corresponding script address::
180+
181+
>>> builder = TransactionBuilder(context)
182+
>>> builder.add_input_address(giver_address)
183+
>>> datum = 42
184+
>>> # Include scripts in the script address
185+
>>> builder.add_output(
186+
>>> TransactionOutput(script_address, 50000000, script=forty_two_script)
187+
>>> )
188+
189+
With reference script, actual script doesn't need to be included in the transaction anymore in order to spend UTxO sitting at script address::
190+
191+
>>> utxo_to_spend = None
192+
>>> # Spend the utxo that has datum/datum hash but no script
193+
>>> for utxo in chain_context.utxos(str(script_address)):
194+
>>> if not utxo.output.script and (
195+
>>> utxo.output.datum_hash == datum_hash(datum)
196+
>>> or utxo.output.datum == datum
197+
>>> ):
198+
>>> utxo_to_spend = utxo
199+
>>> break
200+
201+
>>> builder = TransactionBuilder(context)
202+
>>> builder.add_script_input(utxo_to_spend, datum=datum, redeemer=redeemer)
203+
>>> take_output = TransactionOutput(taker_address, 25123456)
204+
>>> builder.add_output(take_output)
205+
>>> signed_tx = builder.build_and_sign([extended_payment_skey], taker_address)
206+
207+
Again, with the same example, we show that you can send funds to script address with inline datums directly::
208+
209+
>>> builder = TransactionBuilder(context)
210+
>>> builder.add_input_address(giver_address)
211+
>>> datum = 42
212+
>>> builder.add_output(
213+
>>> TransactionOutput(script_address, 50000000, datum=datum, script=forty_two_script)
214+
>>> )
215+
216+
With inline datum, we no longer have to include a datum within our transaction for our plutus spending scripts. Instead we can specify the transaction output where our datum exists to be used in conjunction with our Plutus spending script. This reduces the overall size of our transaction::
217+
218+
>>> utxo_to_spend = None
219+
>>> # Speed the utxo that has both inline script and inline datum
220+
>>> for utxo in chain_context.utxos(str(script_address)):
221+
>>> if utxo.output.datum and utxo.output.script:
222+
>>> utxo_to_spend = utxo
223+
>>> break
224+
225+
>>> builder = TransactionBuilder(context)
226+
>>> builder.add_script_input(utxo_to_spend, redeemer=redeemer)
227+
>>> take_output = TransactionOutput(taker_address, 25123456)
228+
>>> builder.add_output(take_output)
229+
>>> signed_tx = builder.build_and_sign([extended_payment_skey], taker_address)
230+
231+

integration-test/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ services:
7373
max-file: "10"
7474

7575
kupo:
76-
image: cardanosolutions/kupo
76+
image: cardanosolutions/kupo:v2.1.0
7777
environment:
7878
NETWORK: "${NETWORK:-local}"
7979

integration-test/test/base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ class TestBase:
2121

2222
OGMIOS_WS = "ws://localhost:1337"
2323

24-
KUPO_URL = "http://localhost:1442/v1/matches"
24+
KUPO_URL = "http://localhost:1442"
2525

26-
chain_context = OgmiosChainContext(OGMIOS_WS, Network.TESTNET)
26+
chain_context = OgmiosChainContext(OGMIOS_WS, Network.TESTNET, kupo_url=KUPO_URL)
2727

2828
check_chain_context(chain_context)
2929

integration-test/test/test_plutus.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ def test_plutus_v2_ref_script(self):
293293
for utxo in self.chain_context.utxos(str(script_address)):
294294
if not utxo.output.script and (
295295
utxo.output.datum_hash == datum_hash(datum)
296-
or utxo.output.datum == datum
296+
or datum_hash(utxo.output.datum) == datum_hash(datum)
297297
):
298298
utxo_to_spend = utxo
299299
break

pycardano/backend/ogmios.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,8 @@ def _utxos_kupo(self, address: str) -> List[UTxO]:
254254
"kupo_url object attribute has not been assigned properly."
255255
)
256256

257-
address_url = self._kupo_url + "/" + address
258-
results = requests.get(address_url).json()
257+
kupo_utxo_url = self._kupo_url + "/matches/" + address
258+
results = requests.get(kupo_utxo_url).json()
259259

260260
utxos = []
261261

@@ -272,17 +272,42 @@ def _utxos_kupo(self, address: str) -> List[UTxO]:
272272

273273
lovelace_amount = result["value"]["coins"]
274274

275+
script = None
276+
script_hash = result.get("script_hash", None)
277+
if script_hash:
278+
kupo_script_url = self._kupo_url + "/scripts/" + script_hash
279+
script = requests.get(kupo_script_url).json()
280+
if script["language"] == "plutus:v2":
281+
script = PlutusV2Script(
282+
cbor2.loads(bytes.fromhex(script["script"]))
283+
)
284+
elif script["language"] == "plutus:v1":
285+
script = PlutusV1Script(
286+
cbor2.loads(bytes.fromhex(script["script"]))
287+
)
288+
else:
289+
raise ValueError("Unknown plutus script type")
290+
291+
datum = None
275292
datum_hash = (
276293
DatumHash.from_primitive(result["datum_hash"])
277294
if result["datum_hash"]
278295
else None
279296
)
297+
if datum_hash:
298+
kupo_datum_url = self._kupo_url + "/datums/" + result["datum_hash"]
299+
datum_result = requests.get(kupo_datum_url).json()
300+
if datum_result and datum_result["datum"] != datum_hash:
301+
datum = RawCBOR(bytes.fromhex(datum_result["datum"]))
302+
datum_hash = None
280303

281304
if not result["value"]["assets"]:
282305
tx_out = TransactionOutput(
283306
Address.from_primitive(address),
284307
amount=lovelace_amount,
285308
datum_hash=datum_hash,
309+
datum=datum,
310+
script=script,
286311
)
287312
else:
288313
multi_assets = MultiAsset()
@@ -299,6 +324,8 @@ def _utxos_kupo(self, address: str) -> List[UTxO]:
299324
Address.from_primitive(address),
300325
amount=Value(lovelace_amount, multi_assets),
301326
datum_hash=datum_hash,
327+
datum=datum,
328+
script=script,
302329
)
303330
utxos.append(UTxO(tx_in, tx_out))
304331
else:

0 commit comments

Comments
 (0)