Skip to content

Commit

Permalink
fix: Handle serialization and deserialization of bigint as ByteString
Browse files Browse the repository at this point in the history
  • Loading branch information
satran004 committed May 22, 2024
1 parent 7a2be09 commit 993f480
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package com.bloxbean.cardano.client.plutus.spec;

import co.nstant.in.cbor.model.DataItem;
import co.nstant.in.cbor.model.NegativeInteger;
import co.nstant.in.cbor.model.*;
import co.nstant.in.cbor.model.Number;
import co.nstant.in.cbor.model.UnsignedInteger;
import com.bloxbean.cardano.client.exception.CborDeserializationException;
import com.bloxbean.cardano.client.exception.CborSerializationException;
import com.bloxbean.cardano.client.plutus.spec.serializers.BigIntDataJsonDeserializer;
import com.bloxbean.cardano.client.plutus.spec.serializers.BigIntDataJsonSerializer;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.*;
Expand All @@ -24,6 +23,14 @@
public class BigIntPlutusData implements PlutusData {
private BigInteger value;

@JsonIgnore
@Getter(AccessLevel.NONE)
private boolean encodeAsByteString;

public BigIntPlutusData(BigInteger value) {
this.value = value;
}

public static BigIntPlutusData deserialize(Number numberDI) throws CborDeserializationException {
if (numberDI == null)
return null;
Expand All @@ -47,13 +54,30 @@ public static BigIntPlutusData of(BigInteger b) {
public DataItem serialize() throws CborSerializationException {
DataItem di = null;
if (value != null) {
if (value.compareTo(BigInteger.ZERO) == 0 || value.compareTo(BigInteger.ZERO) == 1) {
di = new UnsignedInteger(value);
if (encodeAsByteString) {
if (value.compareTo(BigInteger.ZERO) == 0 || value.compareTo(BigInteger.ZERO) == 1) {
byte[] bytes = value.toByteArray();
di = new ByteString(bytes);
di.setTag(new Tag(BIG_UINT_TAG));
} else {
byte[] bytes = value.negate().toByteArray();
di = new ByteString(bytes);
di.setTag(new Tag(BIG_NINT_TAG));
}
} else {
di = new NegativeInteger(value);
if (value.compareTo(BigInteger.ZERO) == 0 || value.compareTo(BigInteger.ZERO) == 1) {
di = new UnsignedInteger(value);
} else {
di = new NegativeInteger(value);
}
}
}

return di;
}

public BigIntPlutusData encodeAsByteString(boolean flag) {
this.encodeAsByteString = flag;
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.NonNull;

import java.math.BigInteger;

public interface PlutusData {
int BIG_UINT_TAG = 2;
int BIG_NINT_TAG = 3;

// plutus_data = ; New
// constr<plutus_data>
Expand Down Expand Up @@ -41,7 +45,21 @@ static PlutusData deserialize(DataItem dataItem) throws CborDeserializationExcep
if (dataItem instanceof Number) {
return BigIntPlutusData.deserialize((Number) dataItem);
} else if (dataItem instanceof ByteString) {
return BytesPlutusData.deserialize((ByteString) dataItem);
var tag = dataItem.getTag();
if (tag != null) {
switch ((int)tag.getValue()) {
case BIG_UINT_TAG:
return BigIntPlutusData.of(new BigInteger(1, ((ByteString) dataItem).getBytes()))
.encodeAsByteString(true);
case BIG_NINT_TAG:
return BigIntPlutusData.of(new BigInteger(1, ((ByteString) dataItem).getBytes()).negate())
.encodeAsByteString(true);
default:
return BytesPlutusData.deserialize((ByteString) dataItem);
}
} else {
return BytesPlutusData.deserialize((ByteString) dataItem);
}
} else if (dataItem instanceof UnicodeString) {
return BytesPlutusData.deserialize(((UnicodeString) dataItem));
} else if (dataItem instanceof Array) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,59 @@ void unitPlutusDataSerialization() {
assertThat(((ConstrPlutusData)plutusData).getData().getPlutusDataList()).hasSize(0);
}

@Test
void bigIntAsByteString() throws Exception {
String datumCbor = "d8798b581c217a7bf7a6494a0165ae2cb77aabeadb865d33d5be5f9f57b9b0e8f6581c276ba8bb7fe700d0d21b7da11edeb650729efe0b1595af0e643e31844b4e656f6e50756e6b3033311a3b9aca005563687447785a454339663038514d504b6970773073d87980d87980c2410040c241005820dee0b6f2b41b1a75244ec7b83c77c45d5cda5ad4ff3a4964340bb6089d5256e5";
byte[] datumBytes = HexUtil.decodeHexString(datumCbor);

var constrPlutusData = ConstrPlutusData.deserialize(CborSerializationUtil.deserialize(datumBytes));

assertThat(constrPlutusData.getDatumHash()).isEqualTo("d350694acac39f6951f3e4ce2344d321d0cb1b3fa398759a72250b3f0732e16f");

assertThat(constrPlutusData.getData().getPlutusDataList().get(7)).isInstanceOf(BigIntPlutusData.class);
assertThat(constrPlutusData.getData().getPlutusDataList().get(8)).isInstanceOf(BytesPlutusData.class);
assertThat(constrPlutusData.getData().getPlutusDataList().get(9)).isInstanceOf(BigIntPlutusData.class);
assertThat(constrPlutusData.getData().getPlutusDataList().get(10)).isInstanceOf(BytesPlutusData.class);
}

@Test
void bigIntAsByteString_withNegativeValues() throws Exception {
var constrData = ConstrPlutusData.builder()
.alternative(0)
.data(ListPlutusData.builder()
.plutusDataList(Arrays.asList(
BigIntPlutusData.of(new BigInteger("-100100000000200000900000004000000"))
.encodeAsByteString(true),
BigIntPlutusData.of(new BigInteger("20010000000020000090000000000"))
.encodeAsByteString(true),
BigIntPlutusData.of(BigInteger.valueOf(Long.MAX_VALUE))
.encodeAsByteString(true),
BigIntPlutusData.of(BigInteger.valueOf(Long.MAX_VALUE).negate())
.encodeAsByteString(true),
BigIntPlutusData.of(BigInteger.valueOf(Integer.MAX_VALUE))
.encodeAsByteString(true),
BigIntPlutusData.of(BigInteger.valueOf(6700))
))
.build())
.build();

var serializedBytes = constrData.serializeToBytes();

var deserConstriData = ConstrPlutusData.deserialize(CborSerializationUtil.deserialize(serializedBytes));

assertThat(deserConstriData.getData().getPlutusDataList().get(0)).isInstanceOf(BigIntPlutusData.class);
assertThat(((BigIntPlutusData)deserConstriData.getData().getPlutusDataList().get(0)).getValue()).isEqualTo(new BigInteger("-100100000000200000900000004000000"));
assertThat(deserConstriData.getData().getPlutusDataList().get(1)).isInstanceOf(BigIntPlutusData.class);
assertThat(((BigIntPlutusData)deserConstriData.getData().getPlutusDataList().get(1)).getValue()).isEqualTo(new BigInteger("20010000000020000090000000000"));
assertThat(deserConstriData.getData().getPlutusDataList().get(2)).isInstanceOf(BigIntPlutusData.class);
assertThat(((BigIntPlutusData)deserConstriData.getData().getPlutusDataList().get(2)).getValue()).isEqualTo(BigInteger.valueOf(Long.MAX_VALUE));
assertThat(deserConstriData.getData().getPlutusDataList().get(3)).isInstanceOf(BigIntPlutusData.class);
assertThat(((BigIntPlutusData)deserConstriData.getData().getPlutusDataList().get(3)).getValue()).isEqualTo(BigInteger.valueOf(Long.MAX_VALUE).negate());
assertThat(deserConstriData.getData().getPlutusDataList().get(4)).isInstanceOf(BigIntPlutusData.class);
assertThat(((BigIntPlutusData)deserConstriData.getData().getPlutusDataList().get(4)).getValue()).isEqualTo(BigInteger.valueOf(Integer.MAX_VALUE));
assertThat(deserConstriData.getData().getPlutusDataList().get(5)).isInstanceOf(BigIntPlutusData.class);
assertThat(((BigIntPlutusData)deserConstriData.getData().getPlutusDataList().get(5)).getValue()).isEqualTo(BigInteger.valueOf(6700));

}

}

0 comments on commit 993f480

Please sign in to comment.