Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues/200 - Issues with nested Any in events #242

Merged
merged 9 commits into from
Feb 14, 2024
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ out/
.vscode/*
!.vscode/tasks.json
!.vscode/launch.json
/assets/
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ public abstract class AbstractCLValueWithChildren<T, P extends AbstractCLTypeWit
*/
@SneakyThrows({ValueDeserializationException.class})
protected void childTypesSet() {
if (getBytes().length() > 0) {
if (!getBytes().isEmpty()) {
DeserializerBuffer deser = new DeserializerBuffer(this.getBytes());

this.deserialize(deser);
}
}
Expand All @@ -47,9 +46,8 @@ protected void childTypesSet() {
protected void setJsonBytes(String bytes) {
this.setBytes(bytes);

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

this.deserialize(deser);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,12 @@ public abstract class AbstractCLType {
public CLTypeData getClTypeData() throws NoSuchTypeException {
return CLTypeData.getTypeByName(getTypeName());
}

/**
* Indicates if the CLType contains any type child type in which case the bytes cannot be deserialized from bytes
* as the 'Any' type does not provide a length for its bytes. This information is obtained from the JSON metadata.
*
* @return true if a child, or child's child contains an 'Any' type.
*/
public abstract boolean isDeserializable();
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,10 @@ protected AbstractCLTypeBasic(String typeName) {
String.format("%s is an invalid type for %s", getClass().getSimpleName(), typeName));
}
}

@Override
public boolean isDeserializable() {
// Basic type can always be serialized
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,9 @@ public class CLTypeByteArray extends AbstractCLType {
@Setter
@JsonProperty(AbstractCLType.BYTE_ARRAY)
private int length;

@Override
public boolean isDeserializable() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ protected void setJsonValue(AbstractCLType clType) {

@JsonIgnore
public AbstractCLType getListType() {
if (getChildTypes().size() > 0) {
if (!getChildTypes().isEmpty()) {
return getChildTypes().get(0);
}

Expand All @@ -50,4 +50,16 @@ public void setListType(AbstractCLType listType) {
getChildTypes().clear();
getChildTypes().add(listType);
}

@Override
public boolean isDeserializable() {

return getChildTypes().stream().allMatch(childType -> {
if (childType instanceof CLTypeAny) {
meywood marked this conversation as resolved.
Show resolved Hide resolved
return false;
} else {
return childType.isDeserializable();
}
});
}
}
19 changes: 19 additions & 0 deletions src/main/java/com/casper/sdk/model/clvalue/cltype/CLTypeMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,25 @@ public void setKeyValueTypes(CLTypeMapEntryType keyValueTypes) {

private CLTypeMapEntryType keyValueTypes;

@Override
public boolean isDeserializable() {

if (getKeyValueTypes().keyType instanceof CLTypeAny || getKeyValueTypes().valueType instanceof CLTypeAny) {
// The map contains an 'Any' type therefore cannot be deserialized
return false;
} else if (getKeyValueTypes().valueType instanceof AbstractCLTypeWithChildren) {
return getChildTypes().stream().allMatch(childType -> {
meywood marked this conversation as resolved.
Show resolved Hide resolved
if (childType instanceof CLTypeAny) {
return false;
} else {
return childType.isDeserializable();
}
});
} else {
return getKeyValueTypes().keyType.isDeserializable() || getKeyValueTypes().valueType.isDeserializable();
}
}

/**
* Support class for {@link AbstractCLType#MAP} entry types
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ protected void setJsonClType(AbstractCLType clType) {

@JsonIgnore
public AbstractCLType getOptionType() {
if (getChildTypes().size() > 0) {
if (!getChildTypes().isEmpty()) {
return getChildTypes().get(0);
}

Expand All @@ -52,4 +52,9 @@ public void setOptionType(AbstractCLType listType) {
getChildTypes().clear();
getChildTypes().add(listType);
}

@Override
public boolean isDeserializable() {
return getOptionType().isDeserializable() || getChildTypes().stream().allMatch(AbstractCLType::isDeserializable);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
@EqualsAndHashCode(callSuper = false, of = {"typeName", "okErrTypes"})
public class CLTypeResult extends AbstractCLType {

private final String typeName = RESULT;

@Setter
@JsonProperty(RESULT)
private CLTypeResultOkErrTypes okErrTypes;

/**
* Support class for {@link AbstractCLType#RESULT} ok/err types
*
Expand Down Expand Up @@ -71,9 +77,8 @@ protected Object getJsonValue() {
}
}

private final String typeName = RESULT;

@Setter
@JsonProperty(RESULT)
private CLTypeResultOkErrTypes okErrTypes;
@Override
public boolean isDeserializable() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,9 @@ protected void setChildTypeObjects(List<Object> childTypeObjects)
protected List<Object> getChildTypeObjects() {
return super.getChildTypeObjects();
}

@Override
public boolean isDeserializable() {
return getChildTypes().stream().allMatch(AbstractCLType::isDeserializable);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,9 @@ protected void setChildTypeObjects(List<Object> childTypeObjects)
protected List<Object> getChildTypeObjects() {
return super.getChildTypeObjects();
}

@Override
public boolean isDeserializable() {
return getChildTypes().stream().allMatch(AbstractCLType::isDeserializable);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,9 @@ protected void setChildTypeObjects(List<Object> childTypeObjects)
protected List<Object> getChildTypeObjects() {
return super.getChildTypeObjects();
}

@Override
public boolean isDeserializable() {
return getChildTypes().stream().allMatch(AbstractCLType::isDeserializable);
}
}
129 changes: 129 additions & 0 deletions src/test/java/com/casper/sdk/model/clvalue/NestedAnyTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package com.casper.sdk.model.clvalue;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;

/**
* Test that a AbstractCLValueWithChildren provides a byte array string for undeserializable types (e.g. Any)
*
* @author [email protected]
*/
public class NestedAnyTest {

@Test
void readStepEventWithMapContainingAnyValue() throws Exception {

// This is a hex string that represents a map with a key of PublicKey and a value of Any
final String hexBytes = "04000000010000000000000005000000010d23984fefcce099679a24496f1d3072a540b95d321f8ba951" +
"df0cfe2c0691e5070280c6a47e8d030201000000013372bd275423a2191f3fc11e1bee0419fcb4890319873f455bb462e02b" +
"199457070280c6a47e8d03011213e00a3bd748278b38a00a4787a7143f28a9d564126566716a53daa9499852070380c6a47e" +
"8d03030100000001e45436d1609bd5c5ce13e8320a140421cf40a21089df1a08f7c58bcd06b6c9e4070380c6a47e8d030180" +
"b99ded1d271c61a26d1b18c289ab33fc64355fa90cda4ae18f91786aa6ba4b070580c6a47e8d030501000000018973a4ffc1" +
"7abab43f90bd229ef8a310236dd364ba0416d31612091d8cc17933070580c6a47e8d0301959d01aa68197e8cb91aa06bcc92" +
"0f8d4a245dff60ea726bb89255349107a565070180c6a47e8d03010100000001a1cce6ea8db0d11d95b83671cc69f726b36a" +
"afb46dbf808c608dbcd5d237b11c070180c6a47e8d0301fcf1392c59c7d89190bfcd1b00902cc0801700eab98034aa4e5681" +
"6d338f6c25070480c6a47e8d030401000000016997c57f973cd02df90941b7ace79d2b49e173f5f14a343cbf69a7a7ff8be3" +
"b5070480c6a47e8d03020000000000000005000000010d23984fefcce099679a24496f1d3072a540b95d321f8ba951df0cfe" +
"2c0691e5070280c6a47e8d030201000000013372bd275423a2191f3fc11e1bee0419fcb4890319873f455bb462e02b199457" +
"070280c6a47e8d03011213e00a3bd748278b38a00a4787a7143f28a9d564126566716a53daa9499852070380c6a47e8d0303" +
"0100000001e45436d1609bd5c5ce13e8320a140421cf40a21089df1a08f7c58bcd06b6c9e4070380c6a47e8d030180b99ded" +
"1d271c61a26d1b18c289ab33fc64355fa90cda4ae18f91786aa6ba4b070580c6a47e8d030501000000018973a4ffc17abab4" +
"3f90bd229ef8a310236dd364ba0416d31612091d8cc17933070580c6a47e8d0301959d01aa68197e8cb91aa06bcc920f8d4a" +
"245dff60ea726bb89255349107a565070180c6a47e8d03010100000001a1cce6ea8db0d11d95b83671cc69f726b36aafb46d" +
"bf808c608dbcd5d237b11c070180c6a47e8d0301fcf1392c59c7d89190bfcd1b00902cc0801700eab98034aa4e56816d338f" +
"6c25070480c6a47e8d030401000000016997c57f973cd02df90941b7ace79d2b49e173f5f14a343cbf69a7a7ff8be3b50704" +
"80c6a47e8d03030000000000000005000000010d23984fefcce099679a24496f1d3072a540b95d321f8ba951df0cfe2c0691" +
"e5070280c6a47e8d030201000000013372bd275423a2191f3fc11e1bee0419fcb4890319873f455bb462e02b199457070280" +
"c6a47e8d03011213e00a3bd748278b38a00a4787a7143f28a9d564126566716a53daa9499852070380c6a47e8d0303010000" +
"0001e45436d1609bd5c5ce13e8320a140421cf40a21089df1a08f7c58bcd06b6c9e4070380c6a47e8d030180b99ded1d271c" +
"61a26d1b18c289ab33fc64355fa90cda4ae18f91786aa6ba4b070580c6a47e8d030501000000018973a4ffc17abab43f90bd" +
"229ef8a310236dd364ba0416d31612091d8cc17933070580c6a47e8d0301959d01aa68197e8cb91aa06bcc920f8d4a245dff" +
"60ea726bb89255349107a565070180c6a47e8d03010100000001a1cce6ea8db0d11d95b83671cc69f726b36aafb46dbf808c" +
"608dbcd5d237b11c070180c6a47e8d0301fcf1392c59c7d89190bfcd1b00902cc0801700eab98034aa4e56816d338f6c2507" +
"0480c6a47e8d030401000000016997c57f973cd02df90941b7ace79d2b49e173f5f14a343cbf69a7a7ff8be3b5070480c6a4" +
"7e8d03040000000000000005000000010d23984fefcce099679a24496f1d3072a540b95d321f8ba951df0cfe2c0691e50702" +
"80c6a47e8d030201000000013372bd275423a2191f3fc11e1bee0419fcb4890319873f455bb462e02b199457070280c6a47e" +
"8d03011213e00a3bd748278b38a00a4787a7143f28a9d564126566716a53daa9499852070380c6a47e8d03030100000001e4" +
"5436d1609bd5c5ce13e8320a140421cf40a21089df1a08f7c58bcd06b6c9e4070380c6a47e8d030180b99ded1d271c61a26d" +
"1b18c289ab33fc64355fa90cda4ae18f91786aa6ba4b070580c6a47e8d030501000000018973a4ffc17abab43f90bd229ef8" +
"a310236dd364ba0416d31612091d8cc17933070580c6a47e8d0301959d01aa68197e8cb91aa06bcc920f8d4a245dff60ea72" +
"6bb89255349107a565070180c6a47e8d03010100000001a1cce6ea8db0d11d95b83671cc69f726b36aafb46dbf808c608dbc" +
"d5d237b11c070180c6a47e8d0301fcf1392c59c7d89190bfcd1b00902cc0801700eab98034aa4e56816d338f6c25070480c6" +
"a47e8d030401000000016997c57f973cd02df90941b7ace79d2b49e173f5f14a343cbf69a7a7ff8be3b5070480c6a47e8d03";

final String json = " {\n" +
" \"cl_type\": {\n" +
" \"Map\": {\n" +
" \"key\": \"PublicKey\",\n" +
" \"value\": \"Any\"\n" +
" }\n" +
" },\n" +
" \"bytes\": \"" + hexBytes + "\",\n" +
" \"parsed\": null\n" +
"}";

final CLValueMap clValueMap = (CLValueMap) new ObjectMapper().readValue(json, AbstractCLValue.class);

assertThat(clValueMap, is(notNullValue()));
assertThat(clValueMap.getClType().isDeserializable(), is(false));
assertThat(clValueMap.getBytes(), is(hexBytes));
}

@Test
public void nestedEmptyMapiWithoutAny() throws Exception {

final String json = " {\n" +
" \"cl_type\": {\n" +
" \"Map\": {\n" +
" \"key\": \"PublicKey\",\n" +
" \"value\": \"U256\"\n" +
" }\n" +
" },\n" +
" \"bytes\": \"00000000\",\n" +
" \"parsed\": null\n" +
"}";

final CLValueMap clValueMap = (CLValueMap) new ObjectMapper().readValue(json, AbstractCLValue.class);
assertThat(clValueMap, is(notNullValue()));
assertThat(clValueMap.getClType().isDeserializable(), is(true));
assertThat(clValueMap.getBytes(), is("00000000"));
}

@Test
void nestedListWithAny() throws Exception {

final String json = " {\n" +
" \"cl_type\": {\n" +
" \"List\": \"Any\"\n" +
" },\n" +
" \"bytes\": \"00000000\",\n" +
" \"parsed\": null\n" +
"}";

final CLValueList clValueList = (CLValueList) new ObjectMapper().readValue(json, AbstractCLValue.class);
assertThat(clValueList, is(notNullValue()));
assertThat(clValueList.getClType().isDeserializable(), is(false));
assertThat(clValueList.getBytes(), is("00000000"));
}

@Test
void nestedListWithoutAny() throws Exception {

final String json = " {\n" +
" \"cl_type\": {\n" +
" \"List\": \"U256\"\n" +
" },\n" +
" \"bytes\": \"00000000\",\n" +
" \"parsed\": null\n" +
"}";

final CLValueList clValueList = (CLValueList) new ObjectMapper().readValue(json, AbstractCLValue.class);
assertThat(clValueList, is(notNullValue()));
assertThat(clValueList.getClType().isDeserializable(), is(true));
assertThat(clValueList.getBytes(), is("00000000"));
}
}
5 changes: 5 additions & 0 deletions src/test/resources/event-samples/step-with-any-event.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
data:{"Step":{"era_id":0,"execution_effect":{"operations":[],"transforms":[{"key":"uref-cadd90e11751095414f0f48b7e428d4fc735c3a62f5a2dcd100db0314a7b5059-000","transform":{"WriteCLValue":{"cl_type":{"Map":{"key":"PublicKey","value":"Any"}}},"bytes":"010d23984fefcce099679a24496f1d3072a540b95d321f8ba951df0cfe2c0691e0070180c6a47e8d0301fcf1392c59c7d89190bfcd1b00902cc0801700eab98034aa4e56816d338f6c25070480c6a47e8d030401000000016997c57f973cd02df90941b7ace79d2b49e173f5f14a343cbf69a7a7ff8be3b5070480c6a47e8d0301483aba14ddd179941f24251dcb13e2fd017aeb58a5b184e215363482a107878c080180c6a47e8d0301fcf1392c59c7d89190bfcd1b00902cc0801700eab98034aa4e56816d338f6c25070480c6a47e8d030401000000016997c57f973cd02df90941b7ace79d2b49e173f5f14a343cbf69a7a7ff8be3b5070480c6a47e8d03"}}]}}}
id:0


{"era_id":0,"execution_effect":{"operations":[],"transforms":[{"key":"uref-cadd90e11751095414f0f48b7e428d4fc735c3a62f5a2dcd100db0314a7b5059-000","transform":"cl_type":{"Map":{"key":"PublicKey","value":"Any"}}},"bytes":"010d23984fefcce099679a24496f1d3072a540b95d321f8ba951df0cfe2c0691e0070180c6a47e8d0301fcf1392c59c7d89190bfcd1b00902cc0801700eab98034aa4e56816d338f6c25070480c6a47e8d030401000000016997c57f973cd02df90941b7ace79d2b49e173f5f14a343cbf69a7a7ff8be3b5070480c6a47e8d0301483aba14ddd179941f24251dcb13e2fd017aeb58a5b184e215363482a107878c080180c6a47e8d0301fcf1392c59c7d89190bfcd1b00902cc0801700eab98034aa4e56816d338f6c25070480c6a47e8d030401000000016997c57f973cd02df90941b7ace79d2b49e173f5f14a343cbf69a7a7ff8be3b5070480c6a47e8d03"}}]}
Loading