Skip to content

Commit

Permalink
Support BigInteger for "required" in ScriptAtLeast and change slot fr…
Browse files Browse the repository at this point in the history
…om long to BigInteger (#462)

* #461 Support BigInteger for required in ScriptAtLeast and change slot no to BigInteger in other script types

Enhanced RequireTimeBefore, RequireTimeAfter, and ScriptAtLeast to handle BigInteger values, allowing support for larger numeric ranges. Updated deserialization and serialization methods accordingly.

* Remove public modifier

* Remove public modifiers to fix sonarcloud report
  • Loading branch information
satran004 authored Oct 16, 2024
1 parent e23a793 commit f3a244d
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigInteger;

/**
* This script class is for "RequireTimeAfter" expression
*/
Expand All @@ -16,9 +18,13 @@
public class RequireTimeAfter implements NativeScript {

private final ScriptType type = ScriptType.after;
private long slot;
private BigInteger slot;

public RequireTimeAfter(long slot) {
this.slot = BigInteger.valueOf(slot);
}

public RequireTimeAfter(BigInteger slot) {
this.slot = slot;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigInteger;

/**
* This script class is for "RequireTimeBefore" expression
*/
Expand All @@ -16,9 +18,13 @@
public class RequireTimeBefore implements NativeScript {

private final ScriptType type = ScriptType.before;
private long slot;
private BigInteger slot;

public RequireTimeBefore(long slot) {
this.slot = BigInteger.valueOf(slot);
}

public RequireTimeBefore(BigInteger slot) {
this.slot = slot;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package com.bloxbean.cardano.client.transaction.spec.script;

import co.nstant.in.cbor.model.Array;
import co.nstant.in.cbor.model.DataItem;
import co.nstant.in.cbor.model.UnsignedInteger;
import co.nstant.in.cbor.model.*;
import co.nstant.in.cbor.model.Number;
import com.bloxbean.cardano.client.exception.CborDeserializationException;
import com.bloxbean.cardano.client.exception.CborSerializationException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

Expand All @@ -21,10 +21,18 @@
public class ScriptAtLeast implements NativeScript {

private final ScriptType type = ScriptType.atLeast;
private int required;
private BigInteger required;
private final List<NativeScript> scripts = new ArrayList<>();

public ScriptAtLeast(int required) {
this.required = BigInteger.valueOf(required);
}

public ScriptAtLeast(long required) {
this.required = BigInteger.valueOf(required);
}

public ScriptAtLeast(BigInteger required) {
this.required = required;
}

Expand All @@ -33,12 +41,21 @@ public ScriptAtLeast addScript(NativeScript script) {
return this;
}

//script_n_of_k = (3, n: uint, [ * native_script ])
//Till Babbage: script_n_of_k = (3, n: uint, [ * native_script ])
//Conway: script_n_of_k = (3, int64, [* native_script])
@Override
public DataItem serializeAsDataItem() throws CborSerializationException {
Array array = new Array();
array.add(new UnsignedInteger(3));
array.add(new UnsignedInteger(required));

if (required == null)
required = BigInteger.ZERO;

if (required.signum() >= 0) {
array.add(new UnsignedInteger(required));
} else {
array.add(new NegativeInteger(required));
}

Array scriptsArray = new Array();
for (NativeScript script : scripts) {
Expand All @@ -50,7 +67,7 @@ public DataItem serializeAsDataItem() throws CborSerializationException {
}

public static ScriptAtLeast deserialize(Array array) throws CborDeserializationException {
int required = ((UnsignedInteger) (array.getDataItems().get(1))).getValue().intValue();
BigInteger required = ((Number) (array.getDataItems().get(1))).getValue();
ScriptAtLeast scriptAtLeast = new ScriptAtLeast(required);
Array scriptsDIArray = (Array) (array.getDataItems().get(2));
for (DataItem scriptDI : scriptsDIArray.getDataItems()) {
Expand All @@ -64,8 +81,8 @@ public static ScriptAtLeast deserialize(Array array) throws CborDeserializationE
}

public static ScriptAtLeast deserialize(JsonNode jsonNode) throws CborDeserializationException {
int required = jsonNode.get("required").asInt();
ScriptAtLeast scriptAtLeast = new ScriptAtLeast(required);
String required = jsonNode.get("required").asText();
ScriptAtLeast scriptAtLeast = new ScriptAtLeast(new BigInteger(required));

ArrayNode scriptsNode = (ArrayNode) jsonNode.get("scripts");
for (JsonNode scriptNode : scriptsNode) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
package com.bloxbean.cardano.client.transaction.spec.script;

import co.nstant.in.cbor.model.Array;
import com.bloxbean.cardano.client.common.cbor.CborSerializationUtil;
import com.bloxbean.cardano.client.crypto.KeyGenUtil;
import com.bloxbean.cardano.client.crypto.Keys;
import com.bloxbean.cardano.client.crypto.SecretKey;
import com.bloxbean.cardano.client.crypto.VerificationKey;
import com.bloxbean.cardano.client.exception.CborDeserializationException;
import com.bloxbean.cardano.client.exception.CborSerializationException;
import com.bloxbean.cardano.client.util.HexUtil;
import com.bloxbean.cardano.client.util.JsonUtil;
import com.bloxbean.cardano.client.util.Tuple;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.math.BigInteger;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.hamcrest.Matchers.*;
import static org.junit.jupiter.api.Assertions.*;

class ScriptTest {

ObjectMapper mapper = new ObjectMapper();

@Test
public void testGetPolicyId() throws CborSerializationException {
void testGetPolicyId() throws CborSerializationException {
ScriptPubkey scriptPubkey = new ScriptPubkey("ad7a7b87959173fc9eac9a85891cc93892f800dd45c0544128228884");
String policyId = scriptPubkey.getPolicyId();

Expand All @@ -35,7 +37,7 @@ public void testGetPolicyId() throws CborSerializationException {
}

@Test
public void testSciptAllPolicyId() throws CborSerializationException {
void testSciptAllPolicyId() throws CborSerializationException {
ScriptPubkey scriptPubkey1 = new ScriptPubkey("ad7a7b87959173fc9eac9a85891cc93892f800dd45c0544128228884");
ScriptPubkey scriptPubkey2 = new ScriptPubkey("ee7a7b87959173fc9eac9a85891cc93892f800dd45c0544128228884");
ScriptPubkey scriptPubkey3 = new ScriptPubkey("ff7a7b87959173fc9eac9a85891cc93892f800dd45c0544128228884");
Expand All @@ -54,7 +56,7 @@ public void testSciptAllPolicyId() throws CborSerializationException {
}

@Test
public void testSciptAnyPolicyId() throws CborSerializationException {
void testSciptAnyPolicyId() throws CborSerializationException {
ScriptPubkey scriptPubkey1 = new ScriptPubkey("ad7a7b87959173fc9eac9a85891cc93892f800dd45c0544128228884");
ScriptPubkey scriptPubkey2 = new ScriptPubkey("ef7a7b87959173fc9eac9a85891cc93892f800dd45c0544128228884");
ScriptPubkey scriptPubkey3 = new ScriptPubkey("ff7a7b87959173fc9eac9a85891cc93892f800dd45c0544128228884");
Expand All @@ -73,7 +75,7 @@ public void testSciptAnyPolicyId() throws CborSerializationException {
}

@Test
public void testSciptAtLeastPolicyId() throws CborSerializationException {
void testSciptAtLeastPolicyId() throws CborSerializationException {
ScriptPubkey scriptPubkey1 = new ScriptPubkey("2f3d4cf10d0471a1db9f2d2907de867968c27bca6272f062cd1c2413");
ScriptPubkey scriptPubkey2 = new ScriptPubkey("f856c0c5839bab22673747d53f1ae9eed84afafb085f086e8e988614");
ScriptPubkey scriptPubkey3 = new ScriptPubkey("b275b08c999097247f7c17e77007c7010cd19f20cc086ad99d398538");
Expand All @@ -91,7 +93,7 @@ public void testSciptAtLeastPolicyId() throws CborSerializationException {
}

@Test
public void testRequiredAfterPolicyId() throws CborSerializationException {
void testRequiredAfterPolicyId() throws CborSerializationException {
RequireTimeAfter requiredAfter = new RequireTimeAfter(1000);
ScriptPubkey scriptPubkey = new ScriptPubkey("966e394a544f242081e41d1965137b1bb412ac230d40ed5407821c37");

Expand All @@ -107,7 +109,7 @@ public void testRequiredAfterPolicyId() throws CborSerializationException {
}

@Test
public void testRequiredBeforePolicyId() throws CborSerializationException {
void testRequiredBeforePolicyId() throws CborSerializationException {
RequireTimeBefore requireTimeBefore = new RequireTimeBefore(2000);
ScriptPubkey scriptPubkey = new ScriptPubkey("966e394a544f242081e41d1965137b1bb412ac230d40ed5407821c37");

Expand All @@ -123,7 +125,7 @@ public void testRequiredBeforePolicyId() throws CborSerializationException {
}

@Test
public void testScriptAnyScriptPubRequiredBeforePolicyId() throws CborSerializationException {
void testScriptAnyScriptPubRequiredBeforePolicyId() throws CborSerializationException {

ScriptAny scriptAny = new ScriptAny()
.addScript(new ScriptPubkey("b275b08c999097247f7c17e77007c7010cd19f20cc086ad99d398538"))
Expand All @@ -139,7 +141,7 @@ public void testScriptAnyScriptPubRequiredBeforePolicyId() throws CborSerializat
}

@Test
public void testJsonSerDeser_whenScriptPubKey() throws JsonProcessingException, CborDeserializationException {
void testJsonSerDeser_whenScriptPubKey() throws JsonProcessingException, CborDeserializationException {
ScriptPubkey key = new ScriptPubkey("74cfebcf5e97474d7b89c862d7ee7cff22efbb032d4133a1b84cbdcd");

String jsonStr = mapper.writeValueAsString(key);
Expand All @@ -151,7 +153,7 @@ public void testJsonSerDeser_whenScriptPubKey() throws JsonProcessingException,
}

@Test
public void testJsonSerDeser_whenScriptPubKeyJackson() throws JsonProcessingException {
void testJsonSerDeser_whenScriptPubKeyJackson() throws JsonProcessingException {
ScriptPubkey scriptPubkey1 = new ScriptPubkey("74cfebcf5e97474d7b89c862d7ee7cff22efbb032d4133a1b84cbdcd");

String jsonStr = mapper.writeValueAsString(scriptPubkey1);
Expand All @@ -163,7 +165,7 @@ public void testJsonSerDeser_whenScriptPubKeyJackson() throws JsonProcessingExce
}

@Test
public void testJsonSerDeser_whenScriptAll() throws IOException, CborDeserializationException {
void testJsonSerDeser_whenScriptAll() throws IOException, CborDeserializationException {
ScriptPubkey key1 = new ScriptPubkey("74cfebcf5e97474d7b89c862d7ee7cff22efbb032d4133a1b84cbdcd");
ScriptPubkey key2 = new ScriptPubkey("710ee487dbbcdb59b5841a00d1029a56a407c722b3081c02470b516d");
ScriptPubkey key3 = new ScriptPubkey("beed26382ec96254a6714928c3c5bb8227abecbbb095cfeab9fb2dd1");
Expand All @@ -183,7 +185,7 @@ public void testJsonSerDeser_whenScriptAll() throws IOException, CborDeserializa
}

@Test
public void testJsonSerDeser_whenScriptAllJackson() throws IOException {
void testJsonSerDeser_whenScriptAllJackson() throws IOException {
ScriptPubkey key1 = new ScriptPubkey("74cfebcf5e97474d7b89c862d7ee7cff22efbb032d4133a1b84cbdcd");
ScriptPubkey key2 = new ScriptPubkey("710ee487dbbcdb59b5841a00d1029a56a407c722b3081c02470b516d");
ScriptPubkey key3 = new ScriptPubkey("beed26382ec96254a6714928c3c5bb8227abecbbb095cfeab9fb2dd1");
Expand All @@ -202,7 +204,7 @@ public void testJsonSerDeser_whenScriptAllJackson() throws IOException {
}

@Test
public void testJsonSerDeser_whenScriptAny() throws IOException, CborDeserializationException {
void testJsonSerDeser_whenScriptAny() throws IOException, CborDeserializationException {
ScriptPubkey key1 = new ScriptPubkey("74cfebcf5e97474d7b89c862d7ee7cff22efbb032d4133a1b84cbdcd");
ScriptPubkey key2 = new ScriptPubkey("710ee487dbbcdb59b5841a00d1029a56a407c722b3081c02470b516d");
ScriptPubkey key3 = new ScriptPubkey("beed26382ec96254a6714928c3c5bb8227abecbbb095cfeab9fb2dd1");
Expand All @@ -222,7 +224,7 @@ public void testJsonSerDeser_whenScriptAny() throws IOException, CborDeserializa
}

@Test
public void testJsonSerDeser_whenScriptAnyJackson() throws IOException {
void testJsonSerDeser_whenScriptAnyJackson() throws IOException {
ScriptPubkey key1 = new ScriptPubkey("74cfebcf5e97474d7b89c862d7ee7cff22efbb032d4133a1b84cbdcd");
ScriptPubkey key2 = new ScriptPubkey("710ee487dbbcdb59b5841a00d1029a56a407c722b3081c02470b516d");
ScriptPubkey key3 = new ScriptPubkey("beed26382ec96254a6714928c3c5bb8227abecbbb095cfeab9fb2dd1");
Expand All @@ -240,7 +242,7 @@ public void testJsonSerDeser_whenScriptAnyJackson() throws IOException {
}

@Test
public void testJsonSerDeser_whenScriptAtLeast() throws IOException, CborDeserializationException {
void testJsonSerDeser_whenScriptAtLeast() throws IOException, CborDeserializationException {
ScriptPubkey key1 = new ScriptPubkey("74cfebcf5e97474d7b89c862d7ee7cff22efbb032d4133a1b84cbdcd");
ScriptPubkey key2 = new ScriptPubkey("710ee487dbbcdb59b5841a00d1029a56a407c722b3081c02470b516d");
ScriptPubkey key3 = new ScriptPubkey("beed26382ec96254a6714928c3c5bb8227abecbbb095cfeab9fb2dd1");
Expand All @@ -260,7 +262,7 @@ public void testJsonSerDeser_whenScriptAtLeast() throws IOException, CborDeseria
}

@Test
public void testJsonSerDeser_whenScriptAtLeastJackson() throws IOException {
void testJsonSerDeser_whenScriptAtLeastJackson() throws IOException {
ScriptPubkey key1 = new ScriptPubkey("74cfebcf5e97474d7b89c862d7ee7cff22efbb032d4133a1b84cbdcd");
ScriptPubkey key2 = new ScriptPubkey("710ee487dbbcdb59b5841a00d1029a56a407c722b3081c02470b516d");
ScriptPubkey key3 = new ScriptPubkey("beed26382ec96254a6714928c3c5bb8227abecbbb095cfeab9fb2dd1");
Expand All @@ -279,7 +281,7 @@ public void testJsonSerDeser_whenScriptAtLeastJackson() throws IOException {
}

@Test
public void testJsonSerDeSer_whenRequireTimeBefore() throws JsonProcessingException, CborDeserializationException {
void testJsonSerDeSer_whenRequireTimeBefore() throws JsonProcessingException, CborDeserializationException {
RequireTimeBefore requireTimeBefore = new RequireTimeBefore(30003);

String jsonStr = mapper.writeValueAsString(requireTimeBefore);
Expand All @@ -292,7 +294,7 @@ public void testJsonSerDeSer_whenRequireTimeBefore() throws JsonProcessingExcept
}

@Test
public void testJsonSerDeSer_whenRequireTimeBeforeJackson() throws JsonProcessingException {
void testJsonSerDeSer_whenRequireTimeBeforeJackson() throws JsonProcessingException {
RequireTimeBefore requireTimeBefore1 = new RequireTimeBefore(30003);

String jsonStr = mapper.writeValueAsString(requireTimeBefore1);
Expand All @@ -304,7 +306,7 @@ public void testJsonSerDeSer_whenRequireTimeBeforeJackson() throws JsonProcessin
}

@Test
public void testJsonSerDeSer_whenRequireTimeAfter() throws JsonProcessingException, CborDeserializationException {
void testJsonSerDeSer_whenRequireTimeAfter() throws JsonProcessingException, CborDeserializationException {
RequireTimeAfter requireTimeAfter = new RequireTimeAfter(20003);

String jsonStr = mapper.writeValueAsString(requireTimeAfter);
Expand All @@ -317,7 +319,7 @@ public void testJsonSerDeSer_whenRequireTimeAfter() throws JsonProcessingExcepti
}

@Test
public void testJsonSerDeSer_whenRequireTimeAfterJackson() throws JsonProcessingException {
void testJsonSerDeSer_whenRequireTimeAfterJackson() throws JsonProcessingException {
RequireTimeAfter requireTimeAfter1 = new RequireTimeAfter(20003);

String jsonStr = mapper.writeValueAsString(requireTimeAfter1);
Expand All @@ -329,7 +331,7 @@ public void testJsonSerDeSer_whenRequireTimeAfterJackson() throws JsonProcessing
}

@Test
public void testGetScriptPubkey() throws CborSerializationException {
void testGetScriptPubkey() throws CborSerializationException {
String cborText = "582037abc7f86d3f53cbedd38835cd4dbcf0ff7d2bf5a5c12ec77c6851bf5295ae63";
VerificationKey vkey = KeyGenUtil.getPublicKeyFromPrivateKey(new SecretKey(cborText));

Expand All @@ -341,7 +343,7 @@ public void testGetScriptPubkey() throws CborSerializationException {
}

@Test
public void testKeysSerializationDeserialization() throws CborSerializationException, JsonProcessingException {
void testKeysSerializationDeserialization() throws CborSerializationException, JsonProcessingException {
Tuple<ScriptPubkey, Keys> tuple = ScriptPubkey.createWithNewKey();
Keys keys1 = tuple._2;

Expand All @@ -352,4 +354,35 @@ public void testKeysSerializationDeserialization() throws CborSerializationExcep

assertEquals(keys1,keys2);
}

@Test
void testScriptAtLeastWithNegativeRequires() throws Exception {
String cborHex = "820083031affffb5ff858202828200581c1c12f03c1ef2e935acc35ec2e6f96c650fd3bfba3e96550504d5336183031afff6b79a8182051a0005561382051a0003dd4683031a000491b58182041a0004dc05820180820180";
NativeScript scriptAtLeast = NativeScript.deserializeScriptRef(HexUtil.decodeHexString(cborHex));

var scriptHash = scriptAtLeast.getScriptHash();

var reSerHex = HexUtil.encodeHexString(scriptAtLeast.scriptRefBytes());

assertThat(reSerHex, is(cborHex));
assertNotNull(scriptHash);
assertThat(HexUtil.encodeHexString(scriptHash), is("f711cc44f1611e6784f13ca21a0863ed2923d065d4493ef24246ea46"));
}

@Test
void testScriptAtLeastWithMaxLongRequires() throws Exception {
ScriptAtLeast scriptAtLeast = new ScriptAtLeast(9223372036854775807L);
ScriptPubkey scriptPubkey = new ScriptPubkey("ad7a7b87959173fc9eac9a85891cc93892f800dd45c0544128228884");
scriptAtLeast.addScript(scriptPubkey);

var serHex = HexUtil.encodeHexString(scriptAtLeast.serialize());
//remove type byte from serHex. As first byte is type byte
String serializedBodyHex = serHex.substring(2);

var deScriptAtLeast = (ScriptAtLeast) NativeScript.deserialize((Array) CborSerializationUtil.deserialize(HexUtil.decodeHexString(serializedBodyHex)));
var deSerHex = HexUtil.encodeHexString(deScriptAtLeast.serialize());

assertThat(deSerHex, is(serHex));
assertThat(deScriptAtLeast.getRequired().compareTo(BigInteger.valueOf(9223372036854775807L)), is(0));
}
}

0 comments on commit f3a244d

Please sign in to comment.