Skip to content

Commit 514da26

Browse files
committed
chore: Ignore resolving reference scripts if reference scripts are added through withReferenceSctip() and V3 tests
1 parent ffb88f3 commit 514da26

File tree

2 files changed

+267
-36
lines changed

2 files changed

+267
-36
lines changed
Lines changed: 248 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,23 @@
11
package com.bloxbean.cardano.client.quicktx;
22

33
import com.bloxbean.cardano.client.address.AddressProvider;
4-
import com.bloxbean.cardano.client.api.TransactionEvaluator;
54
import com.bloxbean.cardano.client.api.exception.ApiException;
65
import com.bloxbean.cardano.client.api.model.Amount;
7-
import com.bloxbean.cardano.client.api.model.EvaluationResult;
86
import com.bloxbean.cardano.client.api.model.Result;
97
import com.bloxbean.cardano.client.api.model.Utxo;
108
import com.bloxbean.cardano.client.backend.model.TxContentRedeemers;
119
import com.bloxbean.cardano.client.common.model.Networks;
1210
import com.bloxbean.cardano.client.function.helper.ScriptUtxoFinders;
1311
import com.bloxbean.cardano.client.function.helper.SignerProviders;
14-
import com.bloxbean.cardano.client.plutus.spec.BigIntPlutusData;
15-
import com.bloxbean.cardano.client.plutus.spec.ExUnits;
16-
import com.bloxbean.cardano.client.plutus.spec.PlutusV3Script;
17-
import com.bloxbean.cardano.client.plutus.spec.RedeemerTag;
12+
import com.bloxbean.cardano.client.plutus.spec.*;
13+
import com.bloxbean.cardano.client.spec.EraSerializationConfig;
1814
import com.bloxbean.cardano.client.util.JsonUtil;
1915
import org.junit.jupiter.api.Test;
2016

2117
import java.math.BigInteger;
2218
import java.util.List;
2319
import java.util.Optional;
2420
import java.util.Random;
25-
import java.util.Set;
2621

2722
import static org.assertj.core.api.Assertions.assertThat;
2823
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -33,15 +28,15 @@ public class ScriptTxV3IT extends TestDataBaseIT {
3328
void alwaysTrueScript() throws ApiException {
3429
PlutusV3Script plutusScript = PlutusV3Script.builder()
3530
.type("PlutusScriptV3")
36-
.cborHex("49480100002221200101")
31+
.cborHex("46450101002499")
3732
.build();
3833

3934
String scriptAddress = AddressProvider.getEntAddress(plutusScript, Networks.testnet()).toBech32();
4035
BigInteger scriptAmt = new BigInteger("2479280");
4136

4237
Random rand = new Random();
4338
long randInt = System.currentTimeMillis();
44-
BigIntPlutusData plutusData = new BigIntPlutusData(BigInteger.valueOf(randInt)); //any random number
39+
BigIntPlutusData plutusData = new BigIntPlutusData(BigInteger.valueOf(randInt)); //any random number
4540

4641
Tx tx = new Tx();
4742
tx.payToContract(scriptAddress, Amount.lovelace(scriptAmt), plutusData)
@@ -55,7 +50,7 @@ void alwaysTrueScript() throws ApiException {
5550
System.out.println(result.getResponse());
5651
checkIfUtxoAvailable(result.getValue(), scriptAddress);
5752

58-
Optional<Utxo> optionalUtxo = ScriptUtxoFinders.findFirstByInlineDatum(utxoSupplier, scriptAddress, plutusData);
53+
Optional<Utxo> optionalUtxo = ScriptUtxoFinders.findFirstByInlineDatum(utxoSupplier, scriptAddress, plutusData);
5954
ScriptTx scriptTx = new ScriptTx()
6055
.collectFrom(optionalUtxo.get(), plutusData)
6156
.payToAddress(receiver1, Amount.lovelace(scriptAmt))
@@ -66,22 +61,6 @@ void alwaysTrueScript() throws ApiException {
6661
.feePayer(sender2Addr)
6762
.withSigner(SignerProviders.signerFrom(sender2))
6863
.withRequiredSigners(sender2.getBaseAddress())
69-
// .withTxEvaluator(!backendType.equals(BLOCKFROST)?
70-
// new AikenTransactionEvaluator(utxoSupplier, protocolParamsSupplier): null)
71-
.withTxEvaluator(new TransactionEvaluator() {
72-
@Override
73-
public Result<List<EvaluationResult>> evaluateTx(byte[] cbor, Set<Utxo> inputUtxos) throws ApiException {
74-
EvaluationResult evaluationResult = new EvaluationResult();
75-
evaluationResult.setRedeemerTag(RedeemerTag.Spend);
76-
evaluationResult.setIndex(0);
77-
evaluationResult.setExUnits(ExUnits.builder()
78-
.mem(BigInteger.valueOf(42061))
79-
.steps(BigInteger.valueOf(14890343))
80-
.build()
81-
);
82-
return Result.success("success").withValue(List.of(evaluationResult));
83-
}
84-
})
8564
.withVerifier(txn -> {
8665
System.out.println(JsonUtil.getPrettyJson(txn));
8766
assertThat(txn.getBody().getRequiredSigners()).hasSize(1);
@@ -99,10 +78,253 @@ public Result<List<EvaluationResult>> evaluateTx(byte[] cbor, Set<Utxo> inputUtx
9978
List<TxContentRedeemers> redeemers = getBackendService().getTransactionService()
10079
.getTransactionRedeemers(result1.getValue()).getValue();
10180

81+
try {
82+
Thread.sleep(1000);
83+
} catch (InterruptedException e) {
84+
throw new RuntimeException(e);
85+
}
10286
long gottenValue = getBackendService().getScriptService()
10387
.getScriptDatum(redeemers.get(0).getRedeemerDataHash())
10488
.getValue().getJsonValue().get("int").asLong();
10589
assertThat(gottenValue).isEqualTo(randInt);
10690
}
10791

92+
@Test
93+
void referenceInputUtxo_guessSumScript() throws ApiException, InterruptedException {
94+
EraSerializationConfig.INSTANCE.useConwayEraFormat();
95+
//Sum Script
96+
PlutusV3Script sumScript =
97+
PlutusV3Script.builder()
98+
.cborHex("46450101002499")
99+
.build();
100+
String sumScriptAddr = AddressProvider.getEntAddress(sumScript, Networks.testnet()).toBech32();
101+
Amount sumScriptAmt = Amount.ada(4.0);
102+
PlutusData sumScriptDatum = new BigIntPlutusData(BigInteger.valueOf(8)); //redeemer should be 36
103+
PlutusData sumScriptRedeemer = new BigIntPlutusData(BigInteger.valueOf(36));
104+
105+
//Create a reference input and send lock amount at script address
106+
Tx createRefInputTx = new Tx();
107+
createRefInputTx.payToAddress(receiver1, List.of(Amount.ada(1.0)), sumScript)
108+
.payToContract(sumScriptAddr, sumScriptAmt, sumScriptDatum)
109+
.from(sender1Addr);
110+
111+
QuickTxBuilder quickTxBuilder = new QuickTxBuilder(backendService);
112+
Result<String> result = quickTxBuilder.compose(createRefInputTx)
113+
.feePayer(sender1Addr)
114+
.withSigner(SignerProviders.signerFrom(sender1))
115+
.completeAndWait(System.out::println);
116+
System.out.println("Tx Response: " + result.getResponse());
117+
assertTrue(result.isSuccessful());
118+
119+
//Required as backend service returns outdated utxo
120+
if (result.isSuccessful()) {
121+
checkIfUtxoAvailable(result.getValue(), sender1Addr);
122+
}
123+
124+
Utxo refUtxo = Utxo.builder()
125+
.txHash(result.getValue())
126+
.outputIndex(0)
127+
.build();
128+
129+
//Pay to script
130+
Tx scriptPayTx = new Tx();
131+
scriptPayTx.payToContract(sumScriptAddr, sumScriptAmt, sumScriptDatum)
132+
.from(sender1Addr);
133+
result = quickTxBuilder.compose(scriptPayTx)
134+
.withSigner(SignerProviders.signerFrom(sender1))
135+
.completeAndWait(System.out::println);
136+
//Required as backend service returns outdated utxo
137+
if (result.isSuccessful()) {
138+
checkIfUtxoAvailable(result.getValue(), sender1Addr);
139+
}
140+
141+
//Find the utxo for the script address
142+
Optional<Utxo> sumUtxo = ScriptUtxoFinders.findFirstByInlineDatum(utxoSupplier, sumScriptAddr, sumScriptDatum);
143+
ScriptTx scriptTx = new ScriptTx()
144+
.collectFrom(sumUtxo.get(), sumScriptRedeemer)
145+
.readFrom(refUtxo)
146+
.payToAddress(receiver1, List.of(sumScriptAmt))
147+
.withChangeAddress(sumScriptAddr, sumScriptDatum);
148+
149+
Result<String> result1 = quickTxBuilder.compose(scriptTx)
150+
.feePayer(sender1Addr)
151+
.withSigner(SignerProviders.signerFrom(sender1))
152+
// .withTxEvaluator(!backendType.equals(BLOCKFROST)?
153+
// new AikenTransactionEvaluator(utxoSupplier, protocolParamsSupplier, scriptHash -> sumScript): null)
154+
.completeAndWait(System.out::println);
155+
156+
System.out.println(result1.getResponse());
157+
assertTrue(result1.isSuccessful());
158+
159+
checkIfUtxoAvailable(result1.getValue(), sender1Addr);
160+
}
161+
162+
163+
@Test
164+
void referenceInputUtxo_guessSumScript_withRefScriptsCall() throws ApiException, InterruptedException {
165+
166+
EraSerializationConfig.INSTANCE.setUseConwayEraFormat(true);
167+
//Sum Script
168+
PlutusV3Script sumScript =
169+
PlutusV3Script.builder()
170+
.cborHex("46450101002499")
171+
.build();
172+
String sumScriptAddr = AddressProvider.getEntAddress(sumScript, Networks.testnet()).toBech32();
173+
Amount sumScriptAmt = Amount.ada(4.0);
174+
PlutusData sumScriptDatum = new BigIntPlutusData(BigInteger.valueOf(8)); //redeemer should be 36
175+
PlutusData sumScriptRedeemer = new BigIntPlutusData(BigInteger.valueOf(36));
176+
177+
//Create a reference input and send lock amount at script address
178+
Tx createRefInputTx = new Tx();
179+
createRefInputTx.payToAddress(receiver1, List.of(Amount.ada(1.0)), sumScript)
180+
.payToContract(sumScriptAddr, sumScriptAmt, sumScriptDatum)
181+
.from(sender1Addr);
182+
183+
QuickTxBuilder quickTxBuilder = new QuickTxBuilder(backendService);
184+
Result<String> result = quickTxBuilder.compose(createRefInputTx)
185+
.feePayer(sender1Addr)
186+
.withSigner(SignerProviders.signerFrom(sender1))
187+
.completeAndWait(System.out::println);
188+
System.out.println("Tx Response: " + result.getResponse());
189+
assertTrue(result.isSuccessful());
190+
191+
//Required as backend service returns outdated utxo
192+
if (result.isSuccessful()) {
193+
checkIfUtxoAvailable(result.getValue(), sender1Addr);
194+
}
195+
196+
Utxo refUtxo = Utxo.builder()
197+
.txHash(result.getValue())
198+
.outputIndex(0)
199+
.build();
200+
201+
//Pay to script
202+
Tx scriptPayTx = new Tx();
203+
scriptPayTx.payToContract(sumScriptAddr, sumScriptAmt, sumScriptDatum)
204+
.from(sender1Addr);
205+
result = quickTxBuilder.compose(scriptPayTx)
206+
.withSigner(SignerProviders.signerFrom(sender1))
207+
.completeAndWait(System.out::println);
208+
//Required as backend service returns outdated utxo
209+
if (result.isSuccessful()) {
210+
checkIfUtxoAvailable(result.getValue(), sender1Addr);
211+
}
212+
213+
//Find the utxo for the script address
214+
Optional<Utxo> sumUtxo = ScriptUtxoFinders.findFirstByInlineDatum(utxoSupplier, sumScriptAddr, sumScriptDatum);
215+
ScriptTx scriptTx = new ScriptTx()
216+
.collectFrom(sumUtxo.get(), sumScriptRedeemer)
217+
.readFrom(refUtxo)
218+
.payToAddress(receiver1, List.of(sumScriptAmt))
219+
.withChangeAddress(sumScriptAddr, sumScriptDatum);
220+
221+
Result<String> result1 = quickTxBuilder.compose(scriptTx)
222+
.feePayer(sender1Addr)
223+
.withSigner(SignerProviders.signerFrom(sender1))
224+
.withReferenceScripts(sumScript)
225+
// .withTxEvaluator(!backendType.equals(BLOCKFROST)?
226+
// new AikenTransactionEvaluator(utxoSupplier, protocolParamsSupplier, scriptHash -> sumScript): null)
227+
.completeAndWait(System.out::println);
228+
229+
System.out.println(result1.getResponse());
230+
assertTrue(result1.isSuccessful());
231+
232+
checkIfUtxoAvailable(result1.getValue(), sender1Addr);
233+
}
234+
235+
@Test
236+
void plutusV2AndPlutusV3() throws ApiException, InterruptedException {
237+
238+
EraSerializationConfig.INSTANCE.setUseConwayEraFormat(true);
239+
//Sum Script
240+
PlutusV3Script sumScript =
241+
PlutusV3Script.builder()
242+
.cborHex("46450101002499")
243+
.build();
244+
String sumScriptAddr = AddressProvider.getEntAddress(sumScript, Networks.testnet()).toBech32();
245+
Amount sumScriptAmt = Amount.ada(4.0);
246+
PlutusData sumScriptDatum = new BigIntPlutusData(BigInteger.valueOf(8)); //redeemer should be 36
247+
PlutusData sumScriptRedeemer = new BigIntPlutusData(BigInteger.valueOf(36));
248+
249+
//Create a reference input and send lock amount at script address
250+
Tx createRefInputTx = new Tx();
251+
createRefInputTx.payToAddress(receiver1, List.of(Amount.ada(1.0)), sumScript)
252+
.payToContract(sumScriptAddr, sumScriptAmt, sumScriptDatum)
253+
.from(sender1Addr);
254+
255+
QuickTxBuilder quickTxBuilder = new QuickTxBuilder(backendService);
256+
Result<String> result = quickTxBuilder.compose(createRefInputTx)
257+
.feePayer(sender1Addr)
258+
.withSigner(SignerProviders.signerFrom(sender1))
259+
.completeAndWait(System.out::println);
260+
System.out.println("Tx Response: " + result.getResponse());
261+
assertTrue(result.isSuccessful());
262+
263+
//Required as backend service returns outdated utxo
264+
if (result.isSuccessful()) {
265+
checkIfUtxoAvailable(result.getValue(), sender1Addr);
266+
}
267+
268+
Utxo refUtxo = Utxo.builder()
269+
.txHash(result.getValue())
270+
.outputIndex(0)
271+
.build();
272+
273+
//Pay to script
274+
Tx scriptPayTx = new Tx();
275+
scriptPayTx.payToContract(sumScriptAddr, sumScriptAmt, sumScriptDatum)
276+
.from(sender1Addr);
277+
result = quickTxBuilder.compose(scriptPayTx)
278+
.withSigner(SignerProviders.signerFrom(sender1))
279+
.completeAndWait(System.out::println);
280+
//Required as backend service returns outdated utxo
281+
if (result.isSuccessful()) {
282+
checkIfUtxoAvailable(result.getValue(), sender1Addr);
283+
}
284+
285+
PlutusV2Script alwaysSuccessScript = PlutusV2Script.builder()
286+
.type("PlutusScriptV2")
287+
.cborHex("49480100002221200101")
288+
.build();
289+
290+
String alwaysSuccessV2ScriptAddress = AddressProvider.getEntAddress(alwaysSuccessScript, Networks.testnet()).toBech32();
291+
BigInteger scriptAmt = new BigInteger("2479280");
292+
293+
Random rand = new Random();
294+
int randInt = rand.nextInt();
295+
BigIntPlutusData plutusData = new BigIntPlutusData(BigInteger.valueOf(randInt)); //any random number
296+
297+
Tx tx = new Tx();
298+
tx.payToContract(alwaysSuccessV2ScriptAddress, Amount.lovelace(scriptAmt), plutusData)
299+
.from(sender2Addr);
300+
301+
Result<String> result1 = quickTxBuilder.compose(tx)
302+
.withSigner(SignerProviders.signerFrom(sender2))
303+
.completeAndWait(System.out::println);
304+
305+
System.out.println(result1.getResponse());
306+
checkIfUtxoAvailable(result1.getValue(), alwaysSuccessV2ScriptAddress);
307+
308+
//Find the utxo for the script address
309+
Optional<Utxo> sumUtxo = ScriptUtxoFinders.findFirstByInlineDatum(utxoSupplier, sumScriptAddr, sumScriptDatum);
310+
Optional<Utxo> alwaysSuccessUtxo = ScriptUtxoFinders.findFirstByInlineDatum(utxoSupplier, alwaysSuccessV2ScriptAddress, plutusData);
311+
ScriptTx scriptTx = new ScriptTx()
312+
.collectFrom(sumUtxo.get(), sumScriptRedeemer)
313+
.collectFrom(alwaysSuccessUtxo.get(), PlutusData.unit())
314+
.readFrom(refUtxo)
315+
.payToAddress(receiver1, List.of(sumScriptAmt))
316+
.attachSpendingValidator(alwaysSuccessScript)
317+
.withChangeAddress(sumScriptAddr, sumScriptDatum);
318+
319+
Result<String> result2 = quickTxBuilder.compose(scriptTx)
320+
.feePayer(sender1Addr)
321+
.withSigner(SignerProviders.signerFrom(sender1))
322+
.withReferenceScripts(sumScript)
323+
.completeAndWait(System.out::println);
324+
325+
System.out.println(result2.getResponse());
326+
assertTrue(result2.isSuccessful());
327+
328+
checkIfUtxoAvailable(result2.getValue(), sender1Addr);
329+
}
108330
}

quicktx/src/main/java/com/bloxbean/cardano/client/quicktx/QuickTxBuilder.java

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.bloxbean.cardano.client.function.TxSigner;
1818
import com.bloxbean.cardano.client.function.exception.TxBuildException;
1919
import com.bloxbean.cardano.client.function.helper.CollateralBuilders;
20+
import com.bloxbean.cardano.client.function.helper.ReferenceScriptResolver;
2021
import com.bloxbean.cardano.client.function.helper.ScriptCostEvaluators;
2122
import com.bloxbean.cardano.client.function.helper.ScriptBalanceTxProviders;
2223
import com.bloxbean.cardano.client.plutus.spec.PlutusScript;
@@ -99,16 +100,20 @@ public QuickTxBuilder(UtxoSupplier utxoSupplier,
99100
}
100101

101102
/**
102-
* Create QuickTxBuilder with backend service
103+
* Create QuickTxBuilder from BackendService
103104
*
104-
* @param backendService backend service
105+
* @param backendService
105106
*/
106107
public QuickTxBuilder(BackendService backendService) {
107-
this(new DefaultUtxoSupplier(backendService.getUtxoService()),
108-
new DefaultProtocolParamsSupplier(backendService.getEpochService()),
109-
new DefaultScriptSupplier(backendService.getScriptService()),
110-
new DefaultTransactionProcessor(backendService.getTransactionService())
111-
);
108+
this.utxoSupplier = new DefaultUtxoSupplier(backendService.getUtxoService());
109+
this.protocolParamsSupplier = new DefaultProtocolParamsSupplier(backendService.getEpochService());
110+
this.transactionProcessor = new DefaultTransactionProcessor(backendService.getTransactionService());
111+
112+
try {
113+
this.backendScriptSupplier = new DefaultScriptSupplier(backendService.getScriptService());
114+
} catch (UnsupportedOperationException e) {
115+
//Not supported
116+
}
112117
}
113118

114119
/**
@@ -285,10 +290,9 @@ public Transaction build() {
285290
txBuilder = txBuilder.andThen(addRequiredSignersBuilder());
286291
}
287292

293+
//set reference scripts if set
288294
if (referenceScripts != null && !referenceScripts.isEmpty()) {
289-
txBuilder = txBuilder.andThen((context, transaction) -> {
290-
referenceScripts.forEach(script -> context.addRefScripts(script));
291-
});
295+
referenceScripts.forEach(script -> txBuilderContext.addRefScripts(script));
292296
}
293297

294298
if (preBalanceTrasformer != null)
@@ -314,6 +318,11 @@ public Transaction build() {
314318
}
315319

316320
if (containsScriptTx) {
321+
//Resolve any reference scripts if any
322+
if (referenceScripts == null || referenceScripts.isEmpty()) { //Resolve only if not set explicitly
323+
txBuilder = txBuilder.andThen(ReferenceScriptResolver.resolveReferenceScript());
324+
}
325+
317326
txBuilder = txBuilder.andThen(((context, transaction) -> {
318327
boolean negativeAmt = transaction.getBody().getOutputs()
319328
.stream()

0 commit comments

Comments
 (0)