From 6fe8589aa23410a4eed3a7e54c42317680b31827 Mon Sep 17 00:00:00 2001 From: Anton Wiedermann Date: Fri, 26 Jul 2019 00:12:30 +0200 Subject: [PATCH 1/2] issue #101 - deadline implementation changed internal deadline implementation to work on both android and SE - DeadlineRaw is new implementation - using directly milliseconds to represent deadline - fixed couple comments - sdk implementation now uses raw deadline - e2e tests now use the raw deadline implementation --- src/e2e/java/io/proximax/sdk/E2EBaseTest.java | 5 +- .../sdk/infrastructure/TransactionHttp.java | 6 +-- .../infrastructure/TransactionMapping.java | 28 +++++------ .../listener/StatusChannelMessage.java | 4 +- .../sdk/model/transaction/Deadline.java | 4 +- .../sdk/model/transaction/DeadlineBP.java | 8 +--- .../sdk/model/transaction/DeadlineRaw.java | 48 +++++++++++++++++++ 7 files changed, 72 insertions(+), 31 deletions(-) create mode 100644 src/main/java/io/proximax/sdk/model/transaction/DeadlineRaw.java diff --git a/src/e2e/java/io/proximax/sdk/E2EBaseTest.java b/src/e2e/java/io/proximax/sdk/E2EBaseTest.java index 02c854c6..411e9961 100644 --- a/src/e2e/java/io/proximax/sdk/E2EBaseTest.java +++ b/src/e2e/java/io/proximax/sdk/E2EBaseTest.java @@ -21,7 +21,6 @@ import java.io.IOException; import java.math.BigInteger; import java.net.URL; -import java.time.temporal.ChronoUnit; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; @@ -39,7 +38,7 @@ import io.proximax.sdk.model.account.Address; import io.proximax.sdk.model.mosaic.Mosaic; import io.proximax.sdk.model.mosaic.NetworkCurrencyMosaic; -import io.proximax.sdk.model.transaction.Deadline; +import io.proximax.sdk.model.transaction.DeadlineRaw; import io.proximax.sdk.model.transaction.PlainMessage; import io.proximax.sdk.model.transaction.SignedTransaction; import io.proximax.sdk.model.transaction.TransactionDeadline; @@ -116,7 +115,7 @@ void cleanup() { * @return deadline */ protected TransactionDeadline getDeadline() { - return new Deadline(5, ChronoUnit.MINUTES); + return DeadlineRaw.startNow(BigInteger.valueOf(5*60*1000l)); } diff --git a/src/main/java/io/proximax/sdk/infrastructure/TransactionHttp.java b/src/main/java/io/proximax/sdk/infrastructure/TransactionHttp.java index b1b88298..31a93a14 100644 --- a/src/main/java/io/proximax/sdk/infrastructure/TransactionHttp.java +++ b/src/main/java/io/proximax/sdk/infrastructure/TransactionHttp.java @@ -32,7 +32,7 @@ import io.proximax.sdk.TransactionRepository; import io.proximax.sdk.gen.model.TransactionStatusDTO; import io.proximax.sdk.model.transaction.CosignatureSignedTransaction; -import io.proximax.sdk.model.transaction.DeadlineBP; +import io.proximax.sdk.model.transaction.DeadlineRaw; import io.proximax.sdk.model.transaction.SignedTransaction; import io.proximax.sdk.model.transaction.Transaction; import io.proximax.sdk.model.transaction.TransactionAnnounceResponse; @@ -91,7 +91,7 @@ public Observable getTransactionStatus(String transactionHash .map(transactionStatusDTO -> new TransactionStatus(transactionStatusDTO.getGroup(), transactionStatusDTO.getStatus(), transactionStatusDTO.getHash(), - new DeadlineBP(toBigInt(transactionStatusDTO.getDeadline())), + new DeadlineRaw(toBigInt(transactionStatusDTO.getDeadline())), toBigInt(transactionStatusDTO.getHeight()))); } @@ -107,7 +107,7 @@ public Observable> getTransactionStatuses(List t .map(transactionStatusDTO -> new TransactionStatus(transactionStatusDTO.getGroup(), transactionStatusDTO.getStatus(), transactionStatusDTO.getHash(), - new DeadlineBP(toBigInt(transactionStatusDTO.getDeadline())), + new DeadlineRaw(toBigInt(transactionStatusDTO.getDeadline())), toBigInt(transactionStatusDTO.getHeight()))) .toList() .toObservable(); diff --git a/src/main/java/io/proximax/sdk/infrastructure/TransactionMapping.java b/src/main/java/io/proximax/sdk/infrastructure/TransactionMapping.java index d16f1bf5..e402cbdd 100644 --- a/src/main/java/io/proximax/sdk/infrastructure/TransactionMapping.java +++ b/src/main/java/io/proximax/sdk/infrastructure/TransactionMapping.java @@ -205,7 +205,7 @@ public TransferTransaction apply(JsonObject input) { // retrieve transaction data from transaction field JsonObject transaction = input.getAsJsonObject("transaction"); // deadline - DeadlineBP deadline = new DeadlineBP(extractBigInteger(transaction.getAsJsonArray("deadline"))); + TransactionDeadline deadline = new DeadlineRaw(extractBigInteger(transaction.getAsJsonArray("deadline"))); // mosaics List mosaics; if (transaction.getAsJsonArray("mosaics") != null) { @@ -259,7 +259,7 @@ public ModifyMetadataTransaction apply(JsonObject input) { // retrieve transaction data from transaction field JsonObject transaction = input.getAsJsonObject("transaction"); // deadline - DeadlineBP deadline = new DeadlineBP(extractBigInteger(transaction.getAsJsonArray("deadline"))); + TransactionDeadline deadline = new DeadlineRaw(extractBigInteger(transaction.getAsJsonArray("deadline"))); // version JsonElement version = transaction.get("version"); // transaction type @@ -328,7 +328,7 @@ public ModifyAccountPropertyTransaction apply(JsonObject input) { // retrieve transaction data from transaction field JsonObject transaction = input.getAsJsonObject("transaction"); // deadline - DeadlineBP deadline = new DeadlineBP(extractBigInteger(transaction.getAsJsonArray("deadline"))); + TransactionDeadline deadline = new DeadlineRaw(extractBigInteger(transaction.getAsJsonArray("deadline"))); // version JsonElement version = transaction.get("version"); // transaction type @@ -435,7 +435,7 @@ public RegisterNamespaceTransaction apply(JsonObject input) { TransactionInfo transactionInfo = this.createTransactionInfo(input.getAsJsonObject("meta")); JsonObject transaction = input.getAsJsonObject("transaction"); // retrieve fields - DeadlineBP deadline = new DeadlineBP(extractBigInteger(transaction.getAsJsonArray("deadline"))); + TransactionDeadline deadline = new DeadlineRaw(extractBigInteger(transaction.getAsJsonArray("deadline"))); NamespaceType namespaceType = NamespaceType.rawValueOf(transaction.get("namespaceType").getAsInt()); NamespaceId namespaceId = new NamespaceId(extractBigInteger(transaction.getAsJsonArray("namespaceId"))); Optional namespaceDuration = namespaceType == NamespaceType.RootNamespace ? Optional.of(extractBigInteger(transaction.getAsJsonArray("duration"))) : Optional.empty(); @@ -470,7 +470,7 @@ public MosaicDefinitionTransaction apply(JsonObject input) { TransactionInfo transactionInfo = this.createTransactionInfo(input.getAsJsonObject("meta")); JsonObject transaction = input.getAsJsonObject("transaction"); // load data fields - DeadlineBP deadline = new DeadlineBP(extractBigInteger(transaction.getAsJsonArray("deadline"))); + TransactionDeadline deadline = new DeadlineRaw(extractBigInteger(transaction.getAsJsonArray("deadline"))); // construct properties JsonElement version = transaction.get("version"); // return instance of mosaic definition transaction @@ -542,7 +542,7 @@ public AliasTransaction apply(JsonObject input) { TransactionInfo transactionInfo = this.createTransactionInfo(input.getAsJsonObject("meta")); JsonObject transaction = input.getAsJsonObject("transaction"); // load data fields - DeadlineBP deadline = new DeadlineBP(extractBigInteger(transaction.getAsJsonArray("deadline"))); + TransactionDeadline deadline = new DeadlineRaw(extractBigInteger(transaction.getAsJsonArray("deadline"))); JsonElement version = transaction.get("version"); // return instance of mosaic alias definition transaction return new AliasTransaction( @@ -585,7 +585,7 @@ public AliasTransaction apply(JsonObject input) { TransactionInfo transactionInfo = this.createTransactionInfo(input.getAsJsonObject("meta")); JsonObject transaction = input.getAsJsonObject("transaction"); // load data fields - DeadlineBP deadline = new DeadlineBP(extractBigInteger(transaction.getAsJsonArray("deadline"))); + TransactionDeadline deadline = new DeadlineRaw(extractBigInteger(transaction.getAsJsonArray("deadline"))); JsonElement version = transaction.get("version"); // return instance of mosaic alias definition transaction return new AliasTransaction( @@ -612,7 +612,7 @@ public MosaicSupplyChangeTransaction apply(JsonObject input) { TransactionInfo transactionInfo = this.createTransactionInfo(input.getAsJsonObject("meta")); JsonObject transaction = input.getAsJsonObject("transaction"); - DeadlineBP deadline = new DeadlineBP(extractBigInteger(transaction.getAsJsonArray("deadline"))); + TransactionDeadline deadline = new DeadlineRaw(extractBigInteger(transaction.getAsJsonArray("deadline"))); return new MosaicSupplyChangeTransaction( extractNetworkType(transaction.get("version")), @@ -636,7 +636,7 @@ public ModifyMultisigAccountTransaction apply(JsonObject input) { TransactionInfo transactionInfo = this.createTransactionInfo(input.getAsJsonObject("meta")); JsonObject transaction = input.getAsJsonObject("transaction"); - DeadlineBP deadline = new DeadlineBP(extractBigInteger(transaction.getAsJsonArray("deadline"))); + TransactionDeadline deadline = new DeadlineRaw(extractBigInteger(transaction.getAsJsonArray("deadline"))); NetworkType networkType = extractNetworkType(transaction.get("version")); List modifications = transaction.has("modifications") ? stream(transaction.getAsJsonArray("modifications")) @@ -671,7 +671,7 @@ public ModifyContractTransaction apply(JsonObject input) { TransactionInfo transactionInfo = this.createTransactionInfo(input.getAsJsonObject("meta")); JsonObject transaction = input.getAsJsonObject("transaction"); - DeadlineBP deadline = new DeadlineBP(extractBigInteger(transaction.getAsJsonArray("deadline"))); + TransactionDeadline deadline = new DeadlineRaw(extractBigInteger(transaction.getAsJsonArray("deadline"))); NetworkType networkType = extractNetworkType(transaction.get("version")); return new ModifyContractTransaction( @@ -722,7 +722,7 @@ public AggregateTransaction apply(JsonObject input) { TransactionInfo transactionInfo = this.createTransactionInfo(input.getAsJsonObject("meta")); JsonObject transaction = input.getAsJsonObject("transaction"); - DeadlineBP deadline = new DeadlineBP(extractBigInteger(transaction.getAsJsonArray("deadline"))); + TransactionDeadline deadline = new DeadlineRaw(extractBigInteger(transaction.getAsJsonArray("deadline"))); NetworkType networkType = extractNetworkType(transaction.get("version")); List transactions = new ArrayList<>(); @@ -787,7 +787,7 @@ public LockFundsTransaction apply(JsonObject input) { TransactionInfo transactionInfo = this.createTransactionInfo(input.getAsJsonObject("meta")); JsonObject transaction = input.getAsJsonObject("transaction"); - DeadlineBP deadline = new DeadlineBP(extractBigInteger(transaction.getAsJsonArray("deadline"))); + TransactionDeadline deadline = new DeadlineRaw(extractBigInteger(transaction.getAsJsonArray("deadline"))); NetworkType networkType = extractNetworkType(transaction.get("version")); Mosaic mosaic; if (transaction.has("mosaicId")) { @@ -817,7 +817,7 @@ public SecretLockTransaction apply(JsonObject input) { TransactionInfo transactionInfo = this.createTransactionInfo(input.getAsJsonObject("meta")); JsonObject transaction = input.getAsJsonObject("transaction"); - DeadlineBP deadline = new DeadlineBP(extractBigInteger(transaction.getAsJsonArray("deadline"))); + TransactionDeadline deadline = new DeadlineRaw(extractBigInteger(transaction.getAsJsonArray("deadline"))); NetworkType networkType = extractNetworkType(transaction.get("version")); Mosaic mosaic; if (transaction.has("mosaicId")) { @@ -849,7 +849,7 @@ public SecretProofTransaction apply(JsonObject input) { TransactionInfo transactionInfo = this.createTransactionInfo(input.getAsJsonObject("meta")); JsonObject transaction = input.getAsJsonObject("transaction"); - DeadlineBP deadline = new DeadlineBP(extractBigInteger(transaction.getAsJsonArray("deadline"))); + TransactionDeadline deadline = new DeadlineRaw(extractBigInteger(transaction.getAsJsonArray("deadline"))); NetworkType networkType = extractNetworkType(transaction.get("version")); return new SecretProofTransaction( diff --git a/src/main/java/io/proximax/sdk/infrastructure/listener/StatusChannelMessage.java b/src/main/java/io/proximax/sdk/infrastructure/listener/StatusChannelMessage.java index eacb6bfe..6fa3d1e6 100644 --- a/src/main/java/io/proximax/sdk/infrastructure/listener/StatusChannelMessage.java +++ b/src/main/java/io/proximax/sdk/infrastructure/listener/StatusChannelMessage.java @@ -8,7 +8,7 @@ import com.google.gson.JsonObject; import io.proximax.sdk.model.account.Address; -import io.proximax.sdk.model.transaction.DeadlineBP; +import io.proximax.sdk.model.transaction.DeadlineRaw; import io.proximax.sdk.model.transaction.TransactionStatusError; import io.reactivex.Observable; import io.reactivex.subjects.Subject; @@ -38,7 +38,7 @@ private static TransactionStatusError getMessageObject(JsonObject message) { return new TransactionStatusError( message.get("hash").getAsString(), message.get("status").getAsString(), - new DeadlineBP(extractBigInteger(message.getAsJsonArray("deadline")))); + new DeadlineRaw(extractBigInteger(message.getAsJsonArray("deadline")))); } diff --git a/src/main/java/io/proximax/sdk/model/transaction/Deadline.java b/src/main/java/io/proximax/sdk/model/transaction/Deadline.java index 79bfc005..64fb38bb 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/Deadline.java +++ b/src/main/java/io/proximax/sdk/model/transaction/Deadline.java @@ -21,10 +21,8 @@ import java.time.temporal.ChronoUnit; /** - * The deadline of the transaction. The deadline is given as the number of seconds elapsed since the creation of the + * The deadline of the transaction. The deadline is given as the number of milliseconds elapsed since the creation of the * nemesis block. If a transaction does not get included in a block before the deadline is reached, it is deleted. - * - * @since 1.0 */ public class Deadline implements TransactionDeadline { diff --git a/src/main/java/io/proximax/sdk/model/transaction/DeadlineBP.java b/src/main/java/io/proximax/sdk/model/transaction/DeadlineBP.java index df39dbd3..830f6d90 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/DeadlineBP.java +++ b/src/main/java/io/proximax/sdk/model/transaction/DeadlineBP.java @@ -48,7 +48,7 @@ public DeadlineBP(int units, ChronoUnit chronoUnit) { /** * Constructor * - * @param input Deadline in BigInteger format + * @param input milliseconds since epoch */ public DeadlineBP(BigInteger input) { instant = Instant.ofEpochMilli(input.longValue() + NETWORK_EPOCH_START_MILLIS); @@ -65,11 +65,7 @@ public static DeadlineBP create(int units, ChronoUnit chronoUnit) { return new DeadlineBP(units, chronoUnit); } - /** - * Returns number of seconds elapsed since the creation of the nemesis block. - * - * @return long - */ + @Override public long getInstant() { return instant.toEpochMilli() - DeadlineBP.NETWORK_EPOCH.toEpochMilli(); } diff --git a/src/main/java/io/proximax/sdk/model/transaction/DeadlineRaw.java b/src/main/java/io/proximax/sdk/model/transaction/DeadlineRaw.java new file mode 100644 index 00000000..ba079fed --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/DeadlineRaw.java @@ -0,0 +1,48 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction; + +import java.math.BigInteger; +import java.util.Date; + +/** + * Raw deadline implementation working directly with milliseconds. Consider using {@link Deadline} or {@link DeadlineBP} + */ +public class DeadlineRaw implements TransactionDeadline { + + /** milliseconds since epoch */ + private final long deadline; + + /** + * @param deadline in milliseconds since epoch + */ + public DeadlineRaw(BigInteger deadline) { + this.deadline = deadline.longValue(); + } + + /** + * create new deadline instance specifying duration since current time + * + * @param duration duration after current time + * @return deadline representing specified time + */ + public static TransactionDeadline startNow(BigInteger duration) { + return new DeadlineRaw(BigInteger + .valueOf(System.currentTimeMillis() - TransactionDeadline.NETWORK_EPOCH_START_MILLIS).add(duration)); + } + + @Override + public long getInstant() { + return deadline; + } + + @Override + public String toString() { + return "DeadlineRaw [deadline=" + new Date(deadline + TransactionDeadline.NETWORK_EPOCH_START_MILLIS) + "]"; + } + + +} From 4f6e259121a76846cc55a2471fc99d571d0bba65 Mon Sep 17 00:00:00 2001 From: Anton Wiedermann Date: Tue, 30 Jul 2019 09:21:27 +0200 Subject: [PATCH 2/2] adding missing test for DeadlineRaw implementation --- .../model/transaction/DeadlineRawTest.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/test/java/io/proximax/sdk/model/transaction/DeadlineRawTest.java diff --git a/src/test/java/io/proximax/sdk/model/transaction/DeadlineRawTest.java b/src/test/java/io/proximax/sdk/model/transaction/DeadlineRawTest.java new file mode 100644 index 00000000..15c81622 --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/DeadlineRawTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.math.BigInteger; +import java.time.temporal.ChronoUnit; + +import org.junit.jupiter.api.Test; + +/** + * {@link DeadlineRaw} tests + */ +class DeadlineRawTest { + private static final long HOUR_MILLIS = 3_600_000l; + private static final long ACCEPTABLE_THRESHOLD = 500l; + @Test + void constructor() { + DeadlineRaw rawDeadline = new DeadlineRaw(BigInteger.valueOf(HOUR_MILLIS)); + assertEquals(HOUR_MILLIS, rawDeadline.getInstant()); + } + + @Test + void startNow() { + Deadline deadline = new Deadline(1, ChronoUnit.HOURS); + TransactionDeadline rawDeadline = DeadlineRaw.startNow(BigInteger.valueOf(HOUR_MILLIS)); + long diff = Math.abs(deadline.getInstant() - rawDeadline.getInstant()); + assertTrue(diff < ACCEPTABLE_THRESHOLD); + } + + @Test + void compareWithDeadline() { + Deadline deadline = new Deadline(BigInteger.valueOf(HOUR_MILLIS)); + DeadlineRaw rawDeadline = new DeadlineRaw(BigInteger.valueOf(HOUR_MILLIS)); + + long diff = Math.abs(deadline.getInstant() - rawDeadline.getInstant()); + assertTrue(diff < ACCEPTABLE_THRESHOLD, "difference was "+diff); + } + + @Test + void toStringPasses() { + DeadlineRaw rawDeadline = new DeadlineRaw(BigInteger.valueOf(HOUR_MILLIS)); + assertTrue(rawDeadline.toString().startsWith("DeadlineRaw")); + } +}