diff --git a/CHANGELOG.md b/CHANGELOG.md index 636067bf4..84b00b442 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 12.1.0 + +- Added deserialization for the `ConfigureDelegation` payload +- Fixed incorrect deserialization of the `UpdateContract` payload parameter + ## 12.0.0 - Support for Protocol 10 diff --git a/concordium-android-sdk/pom.xml b/concordium-android-sdk/pom.xml index c07fa23ed..24351a1a9 100644 --- a/concordium-android-sdk/pom.xml +++ b/concordium-android-sdk/pom.xml @@ -5,7 +5,7 @@ com.concordium.sdk concordium-sdk-base - 12.0.0 + 12.1.0-alpha.1 concordium-android-sdk diff --git a/concordium-sdk/pom.xml b/concordium-sdk/pom.xml index 4568a23b3..e41d807ec 100644 --- a/concordium-sdk/pom.xml +++ b/concordium-sdk/pom.xml @@ -7,7 +7,7 @@ com.concordium.sdk concordium-sdk-base - 12.0.0 + 12.1.0-alpha.1 concordium-sdk diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/DelegationTarget.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/DelegationTarget.java index f3f90d8de..35477513b 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/DelegationTarget.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/transactionstatus/DelegationTarget.java @@ -1,8 +1,6 @@ package com.concordium.sdk.responses.transactionstatus; import com.concordium.sdk.responses.BakerId; -import com.concordium.sdk.transactions.TransactionType; -import com.concordium.sdk.types.UInt16; import com.concordium.sdk.types.UInt64; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.*; @@ -62,6 +60,18 @@ public byte[] getBytes() { throw new IllegalArgumentException("Illegal DelegationType. Must be either PASSIVE or BAKER"); } + public static DelegationTarget fromBytes(ByteBuffer source) { + val tag = source.get(); + switch (tag) { + case 0: + return newPassiveDelegationTarget(); + case 1: + return newBakerDelegationTarget(BakerId.from(UInt64.fromBytes(source).getValue())); + default: + throw new IllegalArgumentException("Unrecognized delegation target type"); + } + } + @ToString public enum DelegationType { /** diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/ConfigureDelegation.java b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/ConfigureDelegation.java index fd0373e16..78226ec22 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/ConfigureDelegation.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/ConfigureDelegation.java @@ -2,7 +2,10 @@ import com.concordium.sdk.responses.transactionstatus.DelegationTarget; import com.concordium.sdk.types.UInt16; -import lombok.*; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.val; import javax.annotation.Nullable; import java.nio.ByteBuffer; @@ -104,4 +107,17 @@ protected byte[] getPayloadBytes() { return buffer.array(); } + + public static ConfigureDelegation fromBytes(ByteBuffer source) { + int bitmap = UInt16.fromBytes(source).getValue(); + boolean hasCapital = (bitmap & 1) != 0; + boolean hasRestakeEarnings = (bitmap & (1 << 1)) != 0; + boolean hasDelegationTarget = (bitmap & (1 << 2)) != 0; + + return new ConfigureDelegation( + (hasCapital) ? CCDAmount.fromBytes(source) : null, + (hasRestakeEarnings) ? source.get() != 0 : null, + (hasDelegationTarget) ? DelegationTarget.fromBytes(source) : null + ); + } } diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/Parameter.java b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/Parameter.java index 98699b80c..8c9f7f7bc 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/Parameter.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/Parameter.java @@ -74,4 +74,11 @@ public byte[] getBytesForContractInvocation() { * @return converted {@link Parameter}. */ public static Parameter from(SchemaParameter param) {return from(param.toBytes());} + + public static Parameter fromBytes(ByteBuffer source) { + val length = UInt16.fromBytes(source); + val bytes = new byte[length.getValue()]; + source.get(bytes); + return new Parameter(bytes); + } } diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/Payload.java b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/Payload.java index c54818a2d..15fdd551f 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/Payload.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/Payload.java @@ -63,6 +63,8 @@ public static Payload fromBytes(ByteBuffer source) { return RegisterData.fromBytes(source); case TRANSFER_WITH_MEMO: return TransferWithMemo.fromBytes(source); + case CONFIGURE_DELEGATION: + return ConfigureDelegation.fromBytes(source); case TOKEN_UPDATE: return TokenUpdate.fromBytes(source); default: diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/UpdateContract.java b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/UpdateContract.java index 1cfc040dd..07266e455 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/transactions/UpdateContract.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/transactions/UpdateContract.java @@ -135,8 +135,7 @@ public static Payload fromBytes(ByteBuffer source) { val amount = CCDAmount.fromBytes(source); val contractAddress = ContractAddress.from(source); val receiveName = ReceiveName.from(source); - byte[] parameterBuffer = new byte[source.remaining()]; - source.get(parameterBuffer); - return UpdateContract.from(amount, contractAddress, receiveName, Parameter.from(parameterBuffer)); + val parameter = Parameter.fromBytes(source); + return UpdateContract.from(amount, contractAddress, receiveName, parameter); } } diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/transactions/ConfigureDelegationTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/transactions/ConfigureDelegationTest.java index f28e2691a..16cee27fb 100644 --- a/concordium-sdk/src/test/java/com/concordium/sdk/transactions/ConfigureDelegationTest.java +++ b/concordium-sdk/src/test/java/com/concordium/sdk/transactions/ConfigureDelegationTest.java @@ -9,6 +9,8 @@ import org.apache.commons.codec.binary.Hex; import org.junit.Test; +import java.nio.ByteBuffer; + import static org.junit.Assert.assertEquals; public class ConfigureDelegationTest { @@ -34,7 +36,7 @@ public void shouldConfigureDelegationTransaction() { assertEquals(212, transaction.getVersionedBytes().length); } - + @SneakyThrows @Test public void serializeConfigurePassivePoolNoRestake() { val payload = ConfigureDelegation @@ -43,9 +45,12 @@ public void serializeConfigurePassivePoolNoRestake() { .capital(CCDAmount.from(100)) .restakeEarnings(false) .build(); - assertEquals("1a00070000000005f5e1000000", Hex.encodeHexString(payload.getBytes())); + val expectedHex = "1a00070000000005f5e1000000"; + assertEquals(expectedHex, Hex.encodeHexString(payload.getBytes())); + assertEquals(payload, Payload.fromBytes(ByteBuffer.wrap(Hex.decodeHex(expectedHex)))); } + @SneakyThrows @Test public void serializeConfigurePassivePoolRestake() { val payload = ConfigureDelegation @@ -54,9 +59,12 @@ public void serializeConfigurePassivePoolRestake() { .capital(CCDAmount.from(100)) .restakeEarnings(true) .build(); - assertEquals("1a00070000000005f5e1000100", Hex.encodeHexString(payload.getBytes())); + val expectedHex = "1a00070000000005f5e1000100"; + assertEquals(expectedHex, Hex.encodeHexString(payload.getBytes())); + assertEquals(payload, Payload.fromBytes(ByteBuffer.wrap(Hex.decodeHex(expectedHex)))); } + @SneakyThrows @Test public void serializeConfigureBakerPoolNoRestake() { val payload = ConfigureDelegation @@ -65,9 +73,12 @@ public void serializeConfigureBakerPoolNoRestake() { .restakeEarnings(false) .capital(CCDAmount.from(100)) .build(); - assertEquals("1a00070000000005f5e100000100000000000004d2", Hex.encodeHexString(payload.getBytes())); + val expectedHex = "1a00070000000005f5e100000100000000000004d2"; + assertEquals(expectedHex, Hex.encodeHexString(payload.getBytes())); + assertEquals(payload, Payload.fromBytes(ByteBuffer.wrap(Hex.decodeHex(expectedHex)))); } + @SneakyThrows @Test public void serializeConfigureBakerPoolRestake() { val payload = ConfigureDelegation @@ -76,34 +87,44 @@ public void serializeConfigureBakerPoolRestake() { .capital(CCDAmount.from(100)) .restakeEarnings(true) .build(); - assertEquals("1a00070000000005f5e100010100000000000004d2", Hex.encodeHexString(payload.getBytes())); + val expectedHex = "1a00070000000005f5e100010100000000000004d2"; + assertEquals(expectedHex, Hex.encodeHexString(payload.getBytes())); + assertEquals(payload, Payload.fromBytes(ByteBuffer.wrap(Hex.decodeHex(expectedHex)))); } + @SneakyThrows @Test public void serializeDeregisterPayload() { val payload = ConfigureDelegation .builder() .capital(CCDAmount.from(0)) .build(); - assertEquals("1a00010000000000000000", Hex.encodeHexString(payload.getBytes())); + val expectedHex = "1a00010000000000000000"; + assertEquals(expectedHex, Hex.encodeHexString(payload.getBytes())); + assertEquals(payload, Payload.fromBytes(ByteBuffer.wrap(Hex.decodeHex(expectedHex)))); } + @SneakyThrows @Test public void serializeStopRestake() { val payload = ConfigureDelegation .builder() .restakeEarnings(false) .build(); - assertEquals("1a000200", Hex.encodeHexString(payload.getBytes())); + val expectedHex = "1a000200"; + assertEquals(expectedHex, Hex.encodeHexString(payload.getBytes())); + assertEquals(payload, Payload.fromBytes(ByteBuffer.wrap(Hex.decodeHex(expectedHex)))); } + @SneakyThrows @Test public void serializeEnableRestake() { val payload = ConfigureDelegation .builder() .restakeEarnings(true) .build(); - assertEquals("1a000201", Hex.encodeHexString(payload.getBytes())); + val expectedHex = "1a000201"; + assertEquals(expectedHex, Hex.encodeHexString(payload.getBytes())); + assertEquals(payload, Payload.fromBytes(ByteBuffer.wrap(Hex.decodeHex(expectedHex)))); } - } diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/transactions/TransactionSerializationTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/transactions/TransactionSerializationTest.java index a9f63df75..7fdea3a77 100644 --- a/concordium-sdk/src/test/java/com/concordium/sdk/transactions/TransactionSerializationTest.java +++ b/concordium-sdk/src/test/java/com/concordium/sdk/transactions/TransactionSerializationTest.java @@ -8,11 +8,9 @@ import com.concordium.sdk.types.AccountAddress; import com.concordium.sdk.types.ContractAddress; import com.concordium.sdk.types.Nonce; -import com.concordium.sdk.types.UInt16; import com.google.common.collect.Lists; import lombok.SneakyThrows; import org.apache.commons.codec.binary.Hex; -import org.bouncycastle.util.Arrays; import org.junit.Test; import java.nio.ByteBuffer; @@ -113,7 +111,7 @@ public void testDeserializeContractUpdate() { Cis2Transfer expectedParameters = new Cis2Transfer(TokenId.from(new byte[0]), TokenAmount.from(11078313), AccountAddress.from("49NGYqmPtbuCkXSQt7298mL6Xp52UpSR4U2jVzJjKW9P3b3whw"), AccountAddress.from("4sGtbuGKgakv5pKSMsy3CEQbW3sn2PbTzTVLZLA6zxX5bB3C5a"), null); byte[] expectedParams = updateContract.getParam().getBytes(); byte[] cis2TransferParams = SerializationUtils.serializeTransfers(Lists.newArrayList(expectedParameters)).getBytes(); - assertArrayEquals(expectedParams, Arrays.concatenate(UInt16.from(cis2TransferParams.length).getBytes(), cis2TransferParams)); + assertArrayEquals(expectedParams, cis2TransferParams); } diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/transactions/UpdateContractTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/transactions/UpdateContractTest.java index 514dfbea8..8fca9cb5a 100644 --- a/concordium-sdk/src/test/java/com/concordium/sdk/transactions/UpdateContractTest.java +++ b/concordium-sdk/src/test/java/com/concordium/sdk/transactions/UpdateContractTest.java @@ -10,6 +10,8 @@ import org.apache.commons.codec.binary.Hex; import org.junit.Test; +import java.nio.ByteBuffer; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -25,7 +27,7 @@ public void updateContractTest() { byte[] emptyArray = new byte[0]; UpdateContract updateContractPayload = UpdateContract.from(0, ContractAddress.from(81, 0), "CIS2-NFT", "mint", emptyArray); AccountTransaction tx = TransactionFactory - .newUpdateContract(updateContractPayload,UInt64.from(3000)) + .newUpdateContract(updateContractPayload, UInt64.from(3000)) .sender(AccountAddress.from("3JwD2Wm3nMbsowCwb1iGEpnt47UQgdrtnq2qT6opJc3z2AgCrc")) .nonce(Nonce.from(78910)) .expiry(Expiry.from(123456)) @@ -51,4 +53,25 @@ public void updateContractTest() { val blockItemHash = tx.getHash(); assertEquals("0a869928f2491d0652a708eac0231582e24c0cc036481f209862147856531d20", blockItemHash.asHex()); } + + @SneakyThrows + @Test + public void testUpdateContractPayloadSerialization() { + UpdateContract updateContractPayload = UpdateContract.from( + 1, + ContractAddress.from(81, 0), + "CIS2-NFT", + "mint", + new byte[]{1, 2, 3} + ); + val expectedHex = "02000000000000000100000000000000510000000000000000000d434953322d4e46542e6d696e740003010203"; + assertEquals( + expectedHex, + Hex.encodeHexString(updateContractPayload.getBytes()) + ); + assertEquals( + updateContractPayload, + Payload.fromBytes(ByteBuffer.wrap(Hex.decodeHex(expectedHex))) + ); + } } diff --git a/pom.xml b/pom.xml index 446962aaa..6909f722b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.concordium.sdk concordium-sdk-base - 12.0.0 + 12.1.0-alpha.1 pom https://github.com/Concordium/concordium-java-sdk