Skip to content

Commit

Permalink
feat: #378 Initial implementation to support PlutusV3 (#382)
Browse files Browse the repository at this point in the history
* feat: #378 Initial implementation to support  PlutusV3

* chore: #378 Cost model sorting logic updated for int keys

* fix: Add redeemer only if there is no redeemer for the policy id

* feat: #402 Add Tx Evaluator implementation to return constant cost

* chore: Update PlutusV3 cost

* feat: Add fee calculation for reference script

* feat: Add withReferenceScripts() to QuickTx Builder

* feat: Take protocol param as parameter to Tx api

* refactor: Int setter for index

* feat: Script related methods added for registerDRep, unregisterDRep, createProposal, vote, vote delegation

* feat: Added plutus v3

* feat: ScriptSupplier interface

* fix: Added reference script to fix fee calculation

* chore: New overloaded methods

* chore: GovTx script transactions unit tests

* chore: cleanup
  • Loading branch information
satran004 authored Jul 1, 2024
1 parent 2d80494 commit d5b023d
Show file tree
Hide file tree
Showing 36 changed files with 2,482 additions and 140 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.bloxbean.cardano.client.spec;

public enum EraSerializationConfig {
INSTANCE();

private boolean useConwayEraFormat = false;

EraSerializationConfig() {
}

public boolean useConwayEraFormat() {
return useConwayEraFormat;
}

public void setUseConwayEraFormat(boolean useConwayEraFormat) {
this.useConwayEraFormat = useConwayEraFormat;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.bloxbean.cardano.client.api;

import com.bloxbean.cardano.client.plutus.spec.PlutusScript;

/**
* Implement this interface to provide PlutusScript
*/
@FunctionalInterface
public interface ScriptSupplier {
PlutusScript getScript(String scriptHash);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.bloxbean.cardano.client.api.impl;

import com.bloxbean.cardano.client.api.TransactionEvaluator;
import com.bloxbean.cardano.client.api.exception.ApiException;
import com.bloxbean.cardano.client.api.model.EvaluationResult;
import com.bloxbean.cardano.client.api.model.Result;
import com.bloxbean.cardano.client.api.model.Utxo;
import com.bloxbean.cardano.client.exception.CborDeserializationException;
import com.bloxbean.cardano.client.plutus.spec.ExUnits;
import com.bloxbean.cardano.client.transaction.spec.Transaction;
import com.bloxbean.cardano.client.util.JsonUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
* A static implementation of {@link TransactionEvaluator} which returns a static list of {@link EvaluationResult}
*/
public class StaticTransactionEvaluator implements TransactionEvaluator {
private List<ExUnits> exUnits;

/**
* Constructor
* @param exUnits List of {@link ExUnits} to be returned as evaluation result. The number of ExUnits should match the
* number of redeemers in the transaction in the order they appear in the transaction
*/
public StaticTransactionEvaluator(List<ExUnits> exUnits) {
this.exUnits = exUnits;
}

@Override
public Result<List<EvaluationResult>> evaluateTx(byte[] cbor, Set<Utxo> inputUtxos) throws ApiException {
var evaluationResults = getEvaluationResults(cbor);
return Result.success(JsonUtil.getPrettyJson(evaluationResults)).withValue(evaluationResults);
}

@Override
public Result<List<EvaluationResult>> evaluateTx(byte[] cbor) throws ApiException {
var evaluationResults = getEvaluationResults(cbor);
return Result.success(JsonUtil.getPrettyJson(evaluationResults)).withValue(evaluationResults);
}

@Override
public Result<List<EvaluationResult>> evaluateTx(Transaction transaction, Set<Utxo> inputUtxos) throws ApiException {
var evaluationResults = getEvaluationResults(transaction);
return Result.success(JsonUtil.getPrettyJson(evaluationResults)).withValue(evaluationResults);
}

private List<EvaluationResult> getEvaluationResults(byte[] txCbor) {
Transaction transaction = null;
try {
transaction = Transaction.deserialize(txCbor);
} catch (CborDeserializationException e) {
throw new IllegalArgumentException("Invalid transaction cbor. Cost cannot be returned");
}
return getEvaluationResults(transaction);
}

private List<EvaluationResult> getEvaluationResults(Transaction transaction) {
if (transaction.getWitnessSet().getRedeemers() == null)
throw new IllegalArgumentException("Transaction doesn't have redeemers. Cost cannot be returned");

if (transaction.getWitnessSet().getRedeemers().size() != exUnits.size())
throw new IllegalArgumentException("Number of redeemers in the transaction doesn't match the number of exUnits provided");

List<EvaluationResult> evaluationResults = new ArrayList<>();
for (int i = 0; i < transaction.getWitnessSet().getRedeemers().size(); i++) {
var redeemer = transaction.getWitnessSet().getRedeemers().get(i);
var evaluationResult = new EvaluationResult();
evaluationResult.setExUnits(exUnits.get(i));
evaluationResult.setIndex(redeemer.getIndex().intValue());
evaluationResult.setRedeemerTag(redeemer.getTag());

evaluationResults.add(evaluationResult);
}

return evaluationResults;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.Comparator;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;

public class CostModelUtil {

Expand Down Expand Up @@ -359,8 +360,245 @@ public class CostModelUtil {
10
};

public static final long[] plutusV3Costs = new long[]{
205665,
812,
1,
1,
1000,
571,
0,
1,
1000,
24177,
4,
1,
1000,
32,
117366,
10475,
4,
23000,
100,
23000,
100,
23000,
100,
23000,
100,
23000,
100,
23000,
100,
100,
100,
23000,
100,
19537,
32,
175354,
32,
46417,
4,
221973,
511,
0,
1,
89141,
32,
497525,
14068,
4,
2,
196500,
453240,
220,
0,
1,
1,
1000,
28662,
4,
2,
245000,
216773,
62,
1,
1060367,
12586,
1,
208512,
421,
1,
187000,
1000,
52998,
1,
80436,
32,
43249,
32,
1000,
32,
80556,
1,
57667,
4,
1000,
10,
197145,
156,
1,
197145,
156,
1,
204924,
473,
1,
208896,
511,
1,
52467,
32,
64832,
32,
65493,
32,
22558,
32,
16563,
32,
76511,
32,
196500,
453240,
220,
0,
1,
1,
69522,
11687,
0,
1,
60091,
32,
196500,
453240,
220,
0,
1,
1,
196500,
453240,
220,
0,
1,
1,
1159724,
392670,
0,
2,
806990,
30482,
4,
1927926,
82523,
4,
265318,
0,
4,
0,
85931,
32,
205665,
812,
1,
1,
41182,
32,
212342,
32,
31220,
32,
32696,
32,
43357,
32,
32247,
32,
38314,
32,
35190005,
10,
57996947,
18975,
10,
39121781,
32260,
10,
23000,
100,
23000,
100,
832808,
18,
3209094,
6,
331451,
1,
65990684,
23097,
18,
114242,
18,
94393407,
87060,
18,
16420089,
18,
2145798,
36,
3795345,
12,
889023,
1,
204237282,
23271,
36,
129165,
36,
189977790,
85902,
36,
33012864,
36,
388443360,
1,
401885761,
72,
2331379,
72,
1927926,
82523,
4,
117366,
10475,
4,
1292075,
24469,
74,
0,
1,
936157,
49601,
237,
0,
1
};

public final static CostModel PlutusV1CostModel = new CostModel(Language.PLUTUS_V1, plutusV1Costs);
public final static CostModel PlutusV2CostModel = new CostModel(Language.PLUTUS_V2, plutusV2Costs);
public final static CostModel PlutusV3CostModel = new CostModel(Language.PLUTUS_V3, plutusV3Costs);

/**
* Get language view encoding for costmodels
Expand Down Expand Up @@ -388,6 +626,8 @@ public static Optional<CostModel> getCostModelFromProtocolParams(ProtocolParams
languageKey = "PlutusV1";
} else if (language == Language.PLUTUS_V2) {
languageKey = "PlutusV2";
} else if (language == Language.PLUTUS_V3) {
languageKey = "PlutusV3";
}

if (protocolParams.getCostModels() == null)
Expand All @@ -398,8 +638,17 @@ public static Optional<CostModel> getCostModelFromProtocolParams(ProtocolParams
if (costModelMap == null)
return Optional.empty();

long[] costModel = costModelMap.entrySet().stream()
.sorted(Comparator.comparing(Map.Entry::getKey))
boolean sortByAsIntegerKey = costModelMap.containsKey("0") && costModelMap.containsKey("1");
Stream<Map.Entry<String, Long>> sortedStream;
if (sortByAsIntegerKey) {
sortedStream = costModelMap.entrySet().stream()
.sorted(Map.Entry.comparingByKey(Comparator.comparing(Integer::valueOf)));
} else {
sortedStream = costModelMap.entrySet().stream()
.sorted(Map.Entry.comparingByKey());
}

long[] costModel = sortedStream
.map(e -> e.getValue())
.mapToLong(x -> x)
.toArray();
Expand Down
Loading

0 comments on commit d5b023d

Please sign in to comment.