Skip to content

Commit

Permalink
Merge pull request #254 from /issues/253
Browse files Browse the repository at this point in the history
Issues/253 - Refactor for defects in byte serialization and desieralization of AbstractCLTypeWithChildren
  • Loading branch information
cnorburn authored Mar 13, 2024
2 parents e642b36 + 6e588c0 commit c31faa7
Show file tree
Hide file tree
Showing 38 changed files with 419 additions and 170 deletions.
65 changes: 41 additions & 24 deletions src/main/java/com/casper/sdk/helper/CasperDeployHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,13 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class CasperDeployHelper {

public static DeployHeader buildDeployHeader(PublicKey fromPublicKey, String chainName,
Long gasPrice, Ttl ttl, Date date,
List<Digest> dependencies, byte[] bodyHash) {
public static DeployHeader buildDeployHeader(final PublicKey fromPublicKey,
final String chainName,
final Long gasPrice,
final Ttl ttl,
final Date date,
final List<Digest> dependencies,
final byte[] bodyHash) {
return DeployHeader
.builder()
.account(fromPublicKey)
Expand All @@ -54,28 +58,29 @@ public static DeployHeader buildDeployHeader(PublicKey fromPublicKey, String cha
.build();
}

public static HashAndSignature signDeployHeader(AbstractPrivateKey privateKey, DeployHeader deployHeader)
public static HashAndSignature signDeployHeader(final AbstractPrivateKey privateKey, final DeployHeader deployHeader)
throws GeneralSecurityException, NoSuchTypeException, ValueSerializationException {
SerializerBuffer serializerBuffer = new SerializerBuffer();

final SerializerBuffer serializerBuffer = new SerializerBuffer();
deployHeader.serialize(serializerBuffer, Target.BYTE);
byte[] headerHash = Blake2b.digest(serializerBuffer.toByteArray(), 32);
Signature signature = Signature.sign(privateKey, headerHash);
final byte[] headerHash = Blake2b.digest(serializerBuffer.toByteArray(), 32);
final Signature signature = Signature.sign(privateKey, headerHash);
return new HashAndSignature(headerHash, signature);
}

public static byte[] getDeployItemAndModuleBytesHash(ExecutableDeployItem deployItem, ModuleBytes moduleBytes)
public static byte[] getDeployItemAndModuleBytesHash(final ExecutableDeployItem deployItem, final ModuleBytes moduleBytes)
throws NoSuchTypeException, ValueSerializationException {
SerializerBuffer ser = new SerializerBuffer();
final SerializerBuffer ser = new SerializerBuffer();
moduleBytes.serialize(ser, Target.BYTE);
deployItem.serialize(ser, Target.BYTE);
return Blake2b.digest(ser.toByteArray(), 32);
}

public static ModuleBytes getPaymentModuleBytes(BigInteger paymentAmount) throws ValueSerializationException {
List<NamedArg<?>> paymentArgs = new LinkedList<>();
NamedArg<CLTypeU512> paymentArg = new NamedArg<>("amount",
new CLValueU512(paymentAmount));
public static ModuleBytes getPaymentModuleBytes(final BigInteger paymentAmount) throws ValueSerializationException {
final List<NamedArg<?>> paymentArgs = new LinkedList<>();
final NamedArg<CLTypeU512> paymentArg = new NamedArg<>(
"amount",
new CLValueU512(paymentAmount)
);
paymentArgs.add(paymentArg);
return ModuleBytes
.builder()
Expand All @@ -96,26 +101,38 @@ public static ModuleBytes getPaymentModuleBytes(BigInteger paymentAmount) throws
* ms (30 minutes))
* @param date deploy date
* @param dependencies list of digest dependencies
* @return
* @return the built deploy
* @throws NoSuchTypeException
* @throws GeneralSecurityException
* @throws ValueSerializationException
*/
public static Deploy buildDeploy(AbstractPrivateKey fromPrivateKey, String chainName,
ExecutableDeployItem session, ModuleBytes payment,
Long gasPrice, Ttl ttl, Date date, List<Digest> dependencies)
public static Deploy buildDeploy(final AbstractPrivateKey fromPrivateKey,
final String chainName,
final ExecutableDeployItem session,
final ModuleBytes payment,
final Long gasPrice,
final Ttl ttl,
final Date date,
final List<Digest> dependencies)
throws NoSuchTypeException, GeneralSecurityException, ValueSerializationException {

byte[] sessionAnPaymentHash = getDeployItemAndModuleBytesHash(session, payment);
final byte[] sessionAnPaymentHash = getDeployItemAndModuleBytesHash(session, payment);

PublicKey fromPublicKey = PublicKey.fromAbstractPublicKey(fromPrivateKey.derivePublicKey());
final PublicKey fromPublicKey = PublicKey.fromAbstractPublicKey(fromPrivateKey.derivePublicKey());

DeployHeader deployHeader = buildDeployHeader(fromPublicKey, chainName, gasPrice, ttl,
date, dependencies, sessionAnPaymentHash);
final DeployHeader deployHeader = buildDeployHeader(
fromPublicKey,
chainName,
gasPrice,
ttl,
date,
dependencies,
sessionAnPaymentHash
);

HashAndSignature hashAndSignature = signDeployHeader(fromPrivateKey, deployHeader);
final HashAndSignature hashAndSignature = signDeployHeader(fromPrivateKey, deployHeader);

List<Approval> approvals = new LinkedList<>();
final List<Approval> approvals = new LinkedList<>();
approvals.add(Approval.builder()
.signer(PublicKey.fromAbstractPublicKey(fromPrivateKey.derivePublicKey()))
.signature(hashAndSignature.getSignature())
Expand Down
27 changes: 16 additions & 11 deletions src/main/java/com/casper/sdk/model/clvalue/AbstractCLValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.casper.sdk.exception.NoSuchTypeException;
import com.casper.sdk.jackson.resolver.CLValueResolver;
import com.casper.sdk.model.clvalue.cltype.AbstractCLType;
import com.casper.sdk.model.clvalue.cltype.AbstractCLTypeWithChildren;
import com.casper.sdk.model.clvalue.cltype.CLTypeData;
import com.casper.sdk.model.clvalue.serde.CasperDeserializableObject;
import com.casper.sdk.model.clvalue.serde.CasperSerializableObject;
Expand Down Expand Up @@ -58,15 +59,27 @@ public void setValue(final T value) throws ValueSerializationException {
final int length = deser.readI32();
final byte[] bytes = deser.readByteArray(length);
final byte clType = deser.readU8();

try {
final AbstractCLValue<?, ?> clValue = CLTypeData.getTypeBySerializationTag(clType).getClazz().getDeclaredConstructor().newInstance();
CLTypeData clTypeData = CLTypeData.getTypeBySerializationTag(clType);
final AbstractCLValue<?, ?> clValue = clTypeData.getClazz().getDeclaredConstructor().newInstance();
if (clValue instanceof AbstractCLValueWithChildren) {
// We have only obtained the parent type from the buffer now we need to read the child types
((AbstractCLTypeWithChildren) clValue.getClType()).deserializeChildTypes(deser);
}

clValue.deserializeCustom(new DeserializerBuffer(Hex.encode(bytes)));
return clValue;
} catch (Exception e) {
throw new ValueDeserializationException("Error while instantiating CLValue", e);
}
}

@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}

@SneakyThrows({ValueSerializationException.class, NoSuchTypeException.class})
@JsonGetter(value = "bytes")
@ExcludeFromJacocoGeneratedReport
Expand All @@ -84,10 +97,7 @@ protected String getJsonBytes() {
@ExcludeFromJacocoGeneratedReport
protected void setJsonBytes(final String bytes) {
this.bytes = bytes;

final DeserializerBuffer deser = new DeserializerBuffer(this.bytes);

this.deserialize(deser);
this.deserialize(new DeserializerBuffer(this.bytes));
}

@JsonIgnore
Expand Down Expand Up @@ -124,7 +134,7 @@ public void serialize(final SerializerBuffer ser, final Target target) throws Va
serializeValue(ser);

if (Target.BYTE.equals(target)) {
this.encodeType(ser);
getClType().serialize(ser);
}
}

Expand All @@ -140,9 +150,4 @@ public void deserialize(final DeserializerBuffer deserializerBuffer) throws Valu
throw new ValueDeserializationException("Error deserializing value", e);
}
}

protected void encodeType(final SerializerBuffer ser) throws NoSuchTypeException {
final byte typeTag = (getClType().getClTypeData().getSerializationTag());
ser.writeU8(typeTag);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package com.casper.sdk.model.clvalue;

import com.casper.sdk.annotation.ExcludeFromJacocoGeneratedReport;
import com.casper.sdk.exception.NoSuchTypeException;
import com.casper.sdk.model.clvalue.cltype.AbstractCLTypeWithChildren;
import com.casper.sdk.model.clvalue.cltype.CLTypeData;
import com.fasterxml.jackson.annotation.JsonSetter;
import dev.oak3.sbs4j.DeserializerBuffer;
import dev.oak3.sbs4j.SerializerBuffer;
import dev.oak3.sbs4j.exception.ValueDeserializationException;
import lombok.EqualsAndHashCode;
import lombok.SneakyThrows;
Expand All @@ -32,8 +29,7 @@ public abstract class AbstractCLValueWithChildren<T, P extends AbstractCLTypeWit
@SneakyThrows({ValueDeserializationException.class})
protected void childTypesSet() {
if (!getBytes().isEmpty()) {
DeserializerBuffer deser = new DeserializerBuffer(this.getBytes());
this.deserialize(deser);
this.deserialize(new DeserializerBuffer(this.getBytes()));
}
}

Expand All @@ -50,36 +46,7 @@ protected void setJsonBytes(String bytes) {
this.setBytes(bytes);

if (!getClType().getChildTypes().isEmpty() && getClType().isDeserializable()) {
DeserializerBuffer deser = new DeserializerBuffer(this.getBytes());
this.deserialize(deser);
}
}

protected void encodeType(final SerializerBuffer ser) throws NoSuchTypeException {
super.encodeType(ser);
encodeChildTypes(ser);
}

protected abstract void encodeChildTypes(final SerializerBuffer ser) throws NoSuchTypeException;

/**
* Encodes the bytes of the child type, if the child value is not present but the type is known from the parent type
* info, the childDataType is used to encode the bytes of the child rather than the child value.
*
* @param ser the serializer buffer
* @param child the child value whose type is to be encoded
* @param childDataType the data type of the child
* @throws NoSuchTypeException if the child type is not found
*/
protected void encodeChildType(final SerializerBuffer ser,
final AbstractCLValue<?, ?> child,
final CLTypeData childDataType) throws NoSuchTypeException {
if (child instanceof AbstractCLValueWithChildren) {
child.encodeType(ser);
} else {
// If there are no AbstractCLValueWithChildren as children we just need a simple tag
byte element0TypeTag = childDataType.getSerializationTag();
ser.writeU8(element0TypeTag);
this.deserialize(new DeserializerBuffer(this.getBytes()));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.casper.sdk.model.clvalue;

import com.casper.sdk.annotation.ExcludeFromJacocoGeneratedReport;
import com.casper.sdk.exception.NoSuchTypeException;
import com.casper.sdk.model.clvalue.cltype.CLTypeByteArray;
import com.fasterxml.jackson.annotation.JsonProperty;
import dev.oak3.sbs4j.DeserializerBuffer;
Expand Down Expand Up @@ -42,12 +41,6 @@ protected void serializeValue(final SerializerBuffer ser) throws ValueSerializat
this.setBytes(Hex.toHexString(getValue()));
}

@Override
protected void encodeType(final SerializerBuffer ser) throws NoSuchTypeException {
super.encodeType(ser);
ser.writeI32(this.getClType().getLength());
}

@Override
public void deserializeCustom(final DeserializerBuffer deser) throws Exception {
this.setValue(deser.readByteArray(this.getClType().getLength()));
Expand Down
6 changes: 0 additions & 6 deletions src/main/java/com/casper/sdk/model/clvalue/CLValueList.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.casper.sdk.model.clvalue;

import com.casper.sdk.exception.NoSuchTypeException;
import com.casper.sdk.model.clvalue.cltype.AbstractCLTypeWithChildren;
import com.casper.sdk.model.clvalue.cltype.CLTypeData;
import com.casper.sdk.model.clvalue.cltype.CLTypeList;
Expand Down Expand Up @@ -67,11 +66,6 @@ protected void serializeValue(final SerializerBuffer ser) throws ValueSerializat
this.setBytes(Hex.toHexString(bytes));
}

@Override
protected void encodeChildTypes(final SerializerBuffer ser) throws NoSuchTypeException {
final byte val = (getClType().getListType().getClTypeData().getSerializationTag());
ser.writeU8(val);
}

@Override
public void deserializeCustom(final DeserializerBuffer deser) throws Exception {
Expand Down
37 changes: 23 additions & 14 deletions src/main/java/com/casper/sdk/model/clvalue/CLValueMap.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.casper.sdk.model.clvalue;

import com.casper.sdk.exception.NoSuchTypeException;
import com.casper.sdk.model.clvalue.cltype.AbstractCLTypeWithChildren;
import com.casper.sdk.model.clvalue.cltype.CLTypeData;
import com.casper.sdk.model.clvalue.cltype.CLTypeMap;
Expand Down Expand Up @@ -70,18 +69,13 @@ protected void serializeValue(final SerializerBuffer ser) throws ValueSerializat
this.setBytes(Hex.toHexString(bytes));
}

@Override
protected void encodeChildTypes(final SerializerBuffer ser) throws NoSuchTypeException {

final byte keyTypeTag = (getClType().getKeyValueTypes().getKeyType().getClTypeData().getSerializationTag());
ser.writeU8(keyTypeTag);

final byte valueTypeTag = (getClType().getKeyValueTypes().getValueType().getClTypeData().getSerializationTag());
ser.writeU8(valueTypeTag);
}

@Override
public void deserializeCustom(final DeserializerBuffer deser) throws Exception {
if (this.clType.getChildTypes().isEmpty()) {
this.clType.deserializeChildTypes(deser);
}

final CLTypeData keyType = clType.getKeyValueTypes().getKeyType().getClTypeData();
final CLTypeData valType = clType.getKeyValueTypes().getValueType().getClTypeData();

Expand Down Expand Up @@ -116,6 +110,7 @@ public void deserializeCustom(final DeserializerBuffer deser) throws Exception {
setValue(map);
}


@Override
@JsonIgnore
protected void setChildTypes(final Map<? extends AbstractCLValue<?, ?>, ? extends AbstractCLValue<?, ?>> value) {
Expand All @@ -127,9 +122,14 @@ protected void setChildTypes(final Map<? extends AbstractCLValue<?, ?>, ? extend
}
}

// This needed to be customized to ensure equality is being checked correctly.
// The java Map equals method tries to get the "other" map entry's value by using "this" key object,
// which then fails to find the object since they are "different" and returns always null.
/**
* This needed to be customized to ensure equality is being checked correctly.
* The java Map equals method tries to get the "other" map entry's value by using "this" key object,
* which then fails to find the object since they are "different" and returns always null.
*
* @param o the object to compare
* @return true if the objects are equal, false otherwise
*/
@Override
public boolean equals(final Object o) {
if (o == this) return true;
Expand Down Expand Up @@ -180,6 +180,15 @@ public int hashCode() {

@Override
public String toString() {
return getValue() != null ? getValue().keySet().stream().map(key -> key.getValue().toString() + "=" + key.getValue().toString()).collect(Collectors.joining(", ")) : null;
if (getValue() == null) {
return null;
} else {
return getValue()
.entrySet()
.stream()
.map(entry ->
entry.getKey().toString() + "=" + entry.getValue().toString()).collect(Collectors.joining(", ")
);
}
}
}
9 changes: 0 additions & 9 deletions src/main/java/com/casper/sdk/model/clvalue/CLValueOption.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.casper.sdk.model.clvalue;

import com.casper.sdk.exception.NoSuchTypeException;
import com.casper.sdk.model.clvalue.cltype.*;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter;
Expand Down Expand Up @@ -92,14 +91,6 @@ public void deserializeCustom(final DeserializerBuffer deser) throws Exception {
setValue(Optional.of(child));
}

@Override
protected void encodeChildTypes(final SerializerBuffer ser) throws NoSuchTypeException {
final Optional<AbstractCLValue<?, ?>> child = getValue();
if (child.isPresent()) {
encodeChildType(ser, child.get(), this.getClType().getOptionType().getClTypeData());
}
}

@Override
protected void setChildTypes(final Optional<AbstractCLValue<?, ?>> value) {
if (value.isPresent()) {
Expand Down
6 changes: 0 additions & 6 deletions src/main/java/com/casper/sdk/model/clvalue/CLValueTuple1.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.casper.sdk.model.clvalue;

import com.casper.sdk.exception.NoSuchTypeException;
import com.casper.sdk.model.clvalue.cltype.AbstractCLTypeWithChildren;
import com.casper.sdk.model.clvalue.cltype.CLTypeData;
import com.casper.sdk.model.clvalue.cltype.CLTypeTuple1;
Expand Down Expand Up @@ -56,11 +55,6 @@ protected void serializeValue(final SerializerBuffer ser) throws ValueSerializat
this.setBytes(Hex.toHexString(bytes));
}

@Override
protected void encodeChildTypes(final SerializerBuffer ser) throws NoSuchTypeException {
encodeChildType(ser, this.getValue().getValue0(), getClType().getChildClTypeData(0));
}

@Override
public void deserializeCustom(final DeserializerBuffer deser) throws Exception {
CLTypeData childTypeData1 = clType.getChildClTypeData(0);
Expand Down
Loading

0 comments on commit c31faa7

Please sign in to comment.