From 9384a50879765c2b0813d28f3fefbe0fa77eff9c Mon Sep 17 00:00:00 2001 From: CalDescent Date: Tue, 13 Jul 2021 22:18:21 +0100 Subject: [PATCH] Derive PoW difficulty from the file size. Exact values TBC. --- .../transaction/ArbitraryTransaction.java | 18 ++++- .../arbitrary/ArbitraryTransactionTests.java | 65 +++++++++++++++++++ 2 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 src/test/java/org/qortal/test/arbitrary/ArbitraryTransactionTests.java diff --git a/src/main/java/org/qortal/transaction/ArbitraryTransaction.java b/src/main/java/org/qortal/transaction/ArbitraryTransaction.java index c4b595bf..6ee8d5ff 100644 --- a/src/main/java/org/qortal/transaction/ArbitraryTransaction.java +++ b/src/main/java/org/qortal/transaction/ArbitraryTransaction.java @@ -1,5 +1,6 @@ package org.qortal.transaction; +import java.math.BigInteger; import java.util.List; import java.util.stream.Collectors; @@ -28,7 +29,9 @@ public class ArbitraryTransaction extends Transaction { public static final int MAX_CHUNK_HASHES_LENGTH = 8000; public static final int HASH_LENGTH = TransactionTransformer.SHA256_LENGTH; public static final int POW_BUFFER_SIZE = 8 * 1024 * 1024; // bytes - public static final int POW_DIFFICULTY = 10; // leading zero bits + public static final int POW_MIN_DIFFICULTY = 12; // leading zero bits + public static final int POW_MAX_DIFFICULTY = 19; // leading zero bits + public static final long MAX_FILE_SIZE = DataFile.MAX_FILE_SIZE; // Constructors @@ -65,7 +68,7 @@ public class ArbitraryTransaction extends Transaction { // Clear nonce from transactionBytes ArbitraryTransactionTransformer.clearNonce(transactionBytes); - int difficulty = POW_DIFFICULTY; + int difficulty = difficultyForFileSize(arbitraryTransactionData.getSize()); // Calculate nonce this.arbitraryTransactionData.setNonce(MemoryPoW.compute2(transactionBytes, POW_BUFFER_SIZE, difficulty)); @@ -155,7 +158,7 @@ public class ArbitraryTransaction extends Transaction { // Clear nonce from transactionBytes ArbitraryTransactionTransformer.clearNonce(transactionBytes); - int difficulty = POW_DIFFICULTY; + int difficulty = difficultyForFileSize(arbitraryTransactionData.getSize()); // Check nonce return MemoryPoW.verify2(transactionBytes, POW_BUFFER_SIZE, difficulty, nonce); @@ -213,4 +216,13 @@ public class ArbitraryTransaction extends Transaction { return null; } + // Helper methods + + public int difficultyForFileSize(long size) { + final BigInteger powRange = BigInteger.valueOf(POW_MAX_DIFFICULTY - POW_MIN_DIFFICULTY); + final BigInteger multiplier = BigInteger.valueOf(100); + final BigInteger percentage = BigInteger.valueOf(size).multiply(multiplier).divide(BigInteger.valueOf(MAX_FILE_SIZE)); + return POW_MIN_DIFFICULTY + powRange.multiply(percentage).divide(multiplier).intValue(); + } + } diff --git a/src/test/java/org/qortal/test/arbitrary/ArbitraryTransactionTests.java b/src/test/java/org/qortal/test/arbitrary/ArbitraryTransactionTests.java new file mode 100644 index 00000000..39204167 --- /dev/null +++ b/src/test/java/org/qortal/test/arbitrary/ArbitraryTransactionTests.java @@ -0,0 +1,65 @@ +package org.qortal.test.arbitrary; + +import org.junit.Before; +import org.junit.Test; + +import org.qortal.data.PaymentData; +import org.qortal.data.transaction.ArbitraryTransactionData; +import org.qortal.repository.DataException; +import org.qortal.repository.Repository; +import org.qortal.repository.RepositoryManager; +import org.qortal.test.common.*; +import org.qortal.test.common.transaction.TestTransaction; +import org.qortal.transaction.ArbitraryTransaction; +import org.qortal.transaction.Transaction; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.*; + +public class ArbitraryTransactionTests extends Common { + + private static final int version = 4; + private static final String recipient = Common.getTestAccount(null, "bob").getAddress(); + + + @Before + public void beforeTest() throws DataException { + Common.useDefaultSettings(); + } + + @Test + public void testDifficultyCalculation() throws DataException { + + try (final Repository repository = RepositoryManager.getRepository()) { + + TestAccount alice = Common.getTestAccount(repository, "alice"); + ArbitraryTransactionData.DataType dataType = ArbitraryTransactionData.DataType.DATA_HASH; + List payments = new ArrayList<>(); + + ArbitraryTransactionData transactionData = new ArbitraryTransactionData(TestTransaction.generateBase(alice), + 5, ArbitraryTransaction.SERVICE_ARBITRARY_DATA, 0, 0, null, dataType, null, payments); + + ArbitraryTransaction transaction = (ArbitraryTransaction) Transaction.fromData(repository, transactionData); + assertEquals(12, transaction.difficultyForFileSize(1)); + assertEquals(12, transaction.difficultyForFileSize(5123456)); + assertEquals(12, transaction.difficultyForFileSize(74 * 1024 * 1024)); + assertEquals(13, transaction.difficultyForFileSize(75 * 1024 * 1024)); + assertEquals(13, transaction.difficultyForFileSize(144 * 1024 * 1024)); + assertEquals(14, transaction.difficultyForFileSize(145 * 1024 * 1024)); + assertEquals(14, transaction.difficultyForFileSize(214 * 1024 * 1024)); + assertEquals(15, transaction.difficultyForFileSize(215 * 1024 * 1024)); + assertEquals(15, transaction.difficultyForFileSize(289 * 1024 * 1024)); + assertEquals(16, transaction.difficultyForFileSize(290 * 1024 * 1024)); + assertEquals(16, transaction.difficultyForFileSize(359 * 1024 * 1024)); + assertEquals(17, transaction.difficultyForFileSize(360 * 1024 * 1024)); + assertEquals(17, transaction.difficultyForFileSize(429 * 1024 * 1024)); + assertEquals(18, transaction.difficultyForFileSize(430 * 1024 * 1024)); + assertEquals(18, transaction.difficultyForFileSize(499 * 1024 * 1024)); + assertEquals(19, transaction.difficultyForFileSize(500 * 1024 * 1024)); + + } + } + +}