diff --git a/src/main/java/org/qortal/block/BlockChain.java b/src/main/java/org/qortal/block/BlockChain.java index 44ad4a7fa..76815bdf8 100644 --- a/src/main/java/org/qortal/block/BlockChain.java +++ b/src/main/java/org/qortal/block/BlockChain.java @@ -70,7 +70,8 @@ public enum FeatureTrigger { shareBinFix, calcChainWeightTimestamp, transactionV5Timestamp, - transactionV6Timestamp; + transactionV6Timestamp, + disableReferenceTimestamp } // Custom transaction fees @@ -410,6 +411,10 @@ public long getTransactionV6Timestamp() { return this.featureTriggers.get(FeatureTrigger.transactionV6Timestamp.name()).longValue(); } + public long getDisableReferenceTimestamp() { + return this.featureTriggers.get(FeatureTrigger.disableReferenceTimestamp.name()).longValue(); + } + // More complex getters for aspects that change by height or timestamp public long getRewardAtHeight(int ourHeight) { diff --git a/src/main/java/org/qortal/transaction/ArbitraryTransaction.java b/src/main/java/org/qortal/transaction/ArbitraryTransaction.java index 8abebe5c7..ca5ce5171 100644 --- a/src/main/java/org/qortal/transaction/ArbitraryTransaction.java +++ b/src/main/java/org/qortal/transaction/ArbitraryTransaction.java @@ -6,6 +6,7 @@ import java.util.stream.Collectors; import org.qortal.account.Account; +import org.qortal.block.BlockChain; import org.qortal.controller.arbitrary.ArbitraryDataManager; import org.qortal.controller.arbitrary.ArbitraryDataStorageManager; import org.qortal.crypto.Crypto; @@ -19,6 +20,7 @@ import org.qortal.repository.Repository; import org.qortal.arbitrary.ArbitraryDataFile; import org.qortal.transform.TransformationException; +import org.qortal.transform.Transformer; import org.qortal.transform.transaction.ArbitraryTransactionTransformer; import org.qortal.transform.transaction.TransactionTransformer; import org.qortal.utils.ArbitraryTransactionUtils; @@ -86,6 +88,14 @@ public ValidationResult isFeeValid() throws DataException { @Override public boolean hasValidReference() throws DataException { // We shouldn't really get this far, but just in case: + + // Disable reference checking after feature trigger timestamp + if (this.arbitraryTransactionData.getTimestamp() >= BlockChain.getInstance().getDisableReferenceTimestamp()) { + // Allow any value as long as it is the correct length + return this.arbitraryTransactionData.getReference() != null && + this.arbitraryTransactionData.getReference().length == Transformer.SIGNATURE_LENGTH; + } + if (this.arbitraryTransactionData.getReference() == null) { return false; } diff --git a/src/main/java/org/qortal/transaction/AtTransaction.java b/src/main/java/org/qortal/transaction/AtTransaction.java index c570bb653..b07f006b9 100644 --- a/src/main/java/org/qortal/transaction/AtTransaction.java +++ b/src/main/java/org/qortal/transaction/AtTransaction.java @@ -5,6 +5,7 @@ import org.qortal.account.Account; import org.qortal.asset.Asset; +import org.qortal.block.BlockChain; import org.qortal.crypto.Crypto; import org.qortal.data.asset.AssetData; import org.qortal.data.transaction.ATTransactionData; @@ -12,6 +13,7 @@ import org.qortal.repository.DataException; import org.qortal.repository.Repository; import org.qortal.transform.TransformationException; +import org.qortal.transform.Transformer; import org.qortal.transform.transaction.AtTransactionTransformer; import org.qortal.utils.Amounts; @@ -75,6 +77,13 @@ public Account getRecipient() { @Override public boolean hasValidReference() throws DataException { + // Disable reference checking after feature trigger timestamp + if (this.atTransactionData.getTimestamp() >= BlockChain.getInstance().getDisableReferenceTimestamp()) { + // Allow any value as long as it is the correct length + return this.atTransactionData.getReference() != null && + this.atTransactionData.getReference().length == Transformer.SIGNATURE_LENGTH; + } + // Check reference is correct, using AT account, not transaction creator which is null account Account atAccount = getATAccount(); return Arrays.equals(atAccount.getLastReference(), atTransactionData.getReference()); diff --git a/src/main/java/org/qortal/transaction/MessageTransaction.java b/src/main/java/org/qortal/transaction/MessageTransaction.java index d02b6fdd2..a9d3a01cf 100644 --- a/src/main/java/org/qortal/transaction/MessageTransaction.java +++ b/src/main/java/org/qortal/transaction/MessageTransaction.java @@ -8,6 +8,7 @@ import org.qortal.account.PrivateKeyAccount; import org.qortal.account.PublicKeyAccount; import org.qortal.asset.Asset; +import org.qortal.block.BlockChain; import org.qortal.crypto.Crypto; import org.qortal.crypto.MemoryPoW; import org.qortal.data.PaymentData; @@ -20,6 +21,7 @@ import org.qortal.repository.GroupRepository; import org.qortal.repository.Repository; import org.qortal.transform.TransformationException; +import org.qortal.transform.Transformer; import org.qortal.transform.transaction.ChatTransactionTransformer; import org.qortal.transform.transaction.MessageTransactionTransformer; import org.qortal.transform.transaction.TransactionTransformer; @@ -163,6 +165,14 @@ public ValidationResult isFeeValid() throws DataException { @Override public boolean hasValidReference() throws DataException { // We shouldn't really get this far, but just in case: + + // Disable reference checking after feature trigger timestamp + if (this.messageTransactionData.getTimestamp() >= BlockChain.getInstance().getDisableReferenceTimestamp()) { + // Allow any value as long as it is the correct length + return this.messageTransactionData.getReference() != null && + this.messageTransactionData.getReference().length == Transformer.SIGNATURE_LENGTH; + } + if (this.messageTransactionData.getReference() == null) return false; diff --git a/src/main/java/org/qortal/transaction/Transaction.java b/src/main/java/org/qortal/transaction/Transaction.java index a1fd6baad..b56d48cff 100644 --- a/src/main/java/org/qortal/transaction/Transaction.java +++ b/src/main/java/org/qortal/transaction/Transaction.java @@ -31,6 +31,7 @@ import org.qortal.repository.Repository; import org.qortal.settings.Settings; import org.qortal.transform.TransformationException; +import org.qortal.transform.Transformer; import org.qortal.transform.transaction.TransactionTransformer; import org.qortal.utils.NTP; @@ -905,6 +906,13 @@ protected void onImportAsUnconfirmed() throws DataException { * @throws DataException */ public boolean hasValidReference() throws DataException { + // Disable reference checking after feature trigger timestamp + if (this.transactionData.getTimestamp() >= BlockChain.getInstance().getDisableReferenceTimestamp()) { + // Allow any value as long as it is the correct length + return this.transactionData.getReference() != null && + this.transactionData.getReference().length == Transformer.SIGNATURE_LENGTH; + } + Account creator = getCreator(); return Arrays.equals(transactionData.getReference(), creator.getLastReference()); diff --git a/src/main/resources/blockchain.json b/src/main/resources/blockchain.json index c8502d1b8..4cd45baa6 100644 --- a/src/main/resources/blockchain.json +++ b/src/main/resources/blockchain.json @@ -59,7 +59,8 @@ "shareBinFix": 399000, "calcChainWeightTimestamp": 1620579600000, "transactionV5Timestamp": 1642176000000, - "transactionV6Timestamp": 9999999999999 + "transactionV6Timestamp": 9999999999999, + "disableReferenceTimestamp": 9999999999999 }, "genesisInfo": { "version": 4, diff --git a/src/test/java/org/qortal/test/TransactionReferenceTests.java b/src/test/java/org/qortal/test/TransactionReferenceTests.java new file mode 100644 index 000000000..fdff8b599 --- /dev/null +++ b/src/test/java/org/qortal/test/TransactionReferenceTests.java @@ -0,0 +1,165 @@ +package org.qortal.test; + +import org.junit.Before; +import org.junit.Test; +import org.qortal.account.PrivateKeyAccount; +import org.qortal.data.transaction.PaymentTransactionData; +import org.qortal.data.transaction.TransactionData; +import org.qortal.repository.DataException; +import org.qortal.repository.Repository; +import org.qortal.repository.RepositoryManager; +import org.qortal.test.common.Common; +import org.qortal.test.common.TransactionUtils; +import org.qortal.test.common.transaction.TestTransaction; +import org.qortal.transaction.Transaction; + +import java.util.Random; + +import static org.junit.Assert.assertEquals; + +public class TransactionReferenceTests extends Common { + + @Before + public void beforeTest() throws DataException { + Common.useDefaultSettings(); + } + + @Test + public void testInvalidRandomReferenceBeforeFeatureTrigger() throws DataException { + Random random = new Random(); + + try (final Repository repository = RepositoryManager.getRepository()) { + PrivateKeyAccount alice = Common.getTestAccount(repository, "alice"); + + byte[] randomPrivateKey = new byte[32]; + random.nextBytes(randomPrivateKey); + PrivateKeyAccount recipient = new PrivateKeyAccount(repository, randomPrivateKey); + + // Create payment transaction data + TransactionData paymentTransactionData = new PaymentTransactionData(TestTransaction.generateBase(alice), recipient.getAddress(), 100000L); + + // Set random reference + byte[] randomReference = new byte[64]; + random.nextBytes(randomReference); + paymentTransactionData.setReference(randomReference); + + Transaction paymentTransaction = Transaction.fromData(repository, paymentTransactionData); + + // Transaction should be invalid due to random reference + Transaction.ValidationResult validationResult = paymentTransaction.isValidUnconfirmed(); + assertEquals(Transaction.ValidationResult.INVALID_REFERENCE, validationResult); + } + } + + @Test + public void testValidRandomReferenceAfterFeatureTrigger() throws DataException { + Common.useSettings("test-settings-v2-disable-reference.json"); + Random random = new Random(); + + try (final Repository repository = RepositoryManager.getRepository()) { + PrivateKeyAccount alice = Common.getTestAccount(repository, "alice"); + + byte[] randomPrivateKey = new byte[32]; + random.nextBytes(randomPrivateKey); + PrivateKeyAccount recipient = new PrivateKeyAccount(repository, randomPrivateKey); + + // Create payment transaction data + TransactionData paymentTransactionData = new PaymentTransactionData(TestTransaction.generateBase(alice), recipient.getAddress(), 100000L); + + // Set random reference + byte[] randomReference = new byte[64]; + random.nextBytes(randomReference); + paymentTransactionData.setReference(randomReference); + + Transaction paymentTransaction = Transaction.fromData(repository, paymentTransactionData); + + // Transaction should be valid, even with random reference, because reference checking is now disabled + Transaction.ValidationResult validationResult = paymentTransaction.isValidUnconfirmed(); + assertEquals(Transaction.ValidationResult.OK, validationResult); + TransactionUtils.signAndImportValid(repository, paymentTransactionData, alice); + } + } + + @Test + public void testNullReferenceAfterFeatureTrigger() throws DataException { + Common.useSettings("test-settings-v2-disable-reference.json"); + Random random = new Random(); + + try (final Repository repository = RepositoryManager.getRepository()) { + PrivateKeyAccount alice = Common.getTestAccount(repository, "alice"); + + byte[] randomPrivateKey = new byte[32]; + random.nextBytes(randomPrivateKey); + PrivateKeyAccount recipient = new PrivateKeyAccount(repository, randomPrivateKey); + + // Create payment transaction data + TransactionData paymentTransactionData = new PaymentTransactionData(TestTransaction.generateBase(alice), recipient.getAddress(), 100000L); + + // Set null reference + paymentTransactionData.setReference(null); + + Transaction paymentTransaction = Transaction.fromData(repository, paymentTransactionData); + + // Transaction should be invalid, as we require a non-null reference + Transaction.ValidationResult validationResult = paymentTransaction.isValidUnconfirmed(); + assertEquals(Transaction.ValidationResult.INVALID_REFERENCE, validationResult); + } + } + + @Test + public void testShortReferenceAfterFeatureTrigger() throws DataException { + Common.useSettings("test-settings-v2-disable-reference.json"); + Random random = new Random(); + + try (final Repository repository = RepositoryManager.getRepository()) { + PrivateKeyAccount alice = Common.getTestAccount(repository, "alice"); + + byte[] randomPrivateKey = new byte[32]; + random.nextBytes(randomPrivateKey); + PrivateKeyAccount recipient = new PrivateKeyAccount(repository, randomPrivateKey); + + // Create payment transaction data + TransactionData paymentTransactionData = new PaymentTransactionData(TestTransaction.generateBase(alice), recipient.getAddress(), 100000L); + + // Set a 1-byte reference + byte[] randomByte = new byte[63]; + random.nextBytes(randomByte); + paymentTransactionData.setReference(randomByte); + + Transaction paymentTransaction = Transaction.fromData(repository, paymentTransactionData); + + // Transaction should be invalid, as reference isn't long enough + Transaction.ValidationResult validationResult = paymentTransaction.isValidUnconfirmed(); + assertEquals(Transaction.ValidationResult.INVALID_REFERENCE, validationResult); + } + } + + @Test + public void testLongReferenceAfterFeatureTrigger() throws DataException { + Common.useSettings("test-settings-v2-disable-reference.json"); + Random random = new Random(); + + try (final Repository repository = RepositoryManager.getRepository()) { + PrivateKeyAccount alice = Common.getTestAccount(repository, "alice"); + + byte[] randomPrivateKey = new byte[32]; + random.nextBytes(randomPrivateKey); + PrivateKeyAccount recipient = new PrivateKeyAccount(repository, randomPrivateKey); + + // Create payment transaction data + TransactionData paymentTransactionData = new PaymentTransactionData(TestTransaction.generateBase(alice), recipient.getAddress(), 100000L); + + // Set a 1-byte reference + byte[] randomByte = new byte[65]; + random.nextBytes(randomByte); + paymentTransactionData.setReference(randomByte); + + Transaction paymentTransaction = Transaction.fromData(repository, paymentTransactionData); + + // Transaction should be invalid, as reference is too long + Transaction.ValidationResult validationResult = paymentTransaction.isValidUnconfirmed(); + assertEquals(Transaction.ValidationResult.INVALID_REFERENCE, validationResult); + } + } + +} diff --git a/src/test/resources/test-chain-v2-disable-reference.json b/src/test/resources/test-chain-v2-disable-reference.json new file mode 100644 index 000000000..f5bf63acb --- /dev/null +++ b/src/test/resources/test-chain-v2-disable-reference.json @@ -0,0 +1,84 @@ +{ + "isTestChain": true, + "blockTimestampMargin": 500, + "transactionExpiryPeriod": 86400000, + "maxBlockSize": 2097152, + "maxBytesPerUnitFee": 1024, + "unitFee": "0.1", + "nameRegistrationUnitFees": [ + { "timestamp": 1645372800000, "fee": "5" } + ], + "requireGroupForApproval": false, + "minAccountLevelToRewardShare": 5, + "maxRewardSharesPerMintingAccount": 20, + "founderEffectiveMintingLevel": 10, + "onlineAccountSignaturesMinLifetime": 3600000, + "onlineAccountSignaturesMaxLifetime": 86400000, + "rewardsByHeight": [ + { "height": 1, "reward": 100 }, + { "height": 11, "reward": 10 }, + { "height": 21, "reward": 1 } + ], + "sharesByLevel": [ + { "levels": [ 1, 2 ], "share": 0.05 }, + { "levels": [ 3, 4 ], "share": 0.10 }, + { "levels": [ 5, 6 ], "share": 0.15 }, + { "levels": [ 7, 8 ], "share": 0.20 }, + { "levels": [ 9, 10 ], "share": 0.25 } + ], + "qoraHoldersShare": 0.20, + "qoraPerQortReward": 250, + "blocksNeededByLevel": [ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 ], + "blockTimingsByHeight": [ + { "height": 1, "target": 60000, "deviation": 30000, "power": 0.2 } + ], + "ciyamAtSettings": { + "feePerStep": "0.0001", + "maxStepsPerRound": 500, + "stepsPerFunctionCall": 10, + "minutesPerBlock": 1 + }, + "featureTriggers": { + "messageHeight": 0, + "atHeight": 0, + "assetsTimestamp": 0, + "votingTimestamp": 0, + "arbitraryTimestamp": 0, + "powfixTimestamp": 0, + "qortalTimestamp": 0, + "newAssetPricingTimestamp": 0, + "groupApprovalTimestamp": 0, + "atFindNextTransactionFix": 0, + "newBlockSigHeight": 999999, + "shareBinFix": 999999, + "calcChainWeightTimestamp": 0, + "transactionV5Timestamp": 0, + "transactionV6Timestamp": 0, + "disableReferenceTimestamp": 0 + }, + "genesisInfo": { + "version": 4, + "timestamp": 0, + "transactions": [ + { "type": "ISSUE_ASSET", "assetName": "QORT", "description": "QORT native coin", "data": "", "quantity": 0, "isDivisible": true, "fee": 0 }, + { "type": "ISSUE_ASSET", "assetName": "Legacy-QORA", "description": "Representative legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true }, + { "type": "ISSUE_ASSET", "assetName": "QORT-from-QORA", "description": "QORT gained from holding legacy QORA", "quantity": 0, "isDivisible": true, "data": "{}", "isUnspendable": true }, + + { "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000" }, + { "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000" }, + { "type": "GENESIS", "recipient": "QaUpHNhT3Ygx6avRiKobuLdusppR5biXjL", "amount": "1000000" }, + { "type": "GENESIS", "recipient": "Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er", "amount": "1000000" }, + + { "type": "CREATE_GROUP", "creatorPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT100", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 }, + + { "type": "ISSUE_ASSET", "issuerPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "assetName": "TEST", "description": "test asset", "data": "", "quantity": "1000000", "isDivisible": true, "fee": 0 }, + { "type": "ISSUE_ASSET", "issuerPublicKey": "C6wuddsBV3HzRrXUtezE7P5MoRXp5m3mEDokRDGZB6ry", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": "1000000", "isDivisible": true, "fee": 0 }, + { "type": "ISSUE_ASSET", "issuerPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": "1000000", "isDivisible": true, "fee": 0 }, + + { "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 }, + { "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": "100" }, + + { "type": "ACCOUNT_LEVEL", "target": "Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er", "level": 5 } + ] + } +} diff --git a/src/test/resources/test-chain-v2-founder-rewards.json b/src/test/resources/test-chain-v2-founder-rewards.json index e8a22dfcd..36a3423d9 100644 --- a/src/test/resources/test-chain-v2-founder-rewards.json +++ b/src/test/resources/test-chain-v2-founder-rewards.json @@ -53,7 +53,8 @@ "shareBinFix": 999999, "calcChainWeightTimestamp": 0, "transactionV5Timestamp": 0, - "transactionV6Timestamp": 0 + "transactionV6Timestamp": 0, + "disableReferenceTimestamp": 9999999999999 }, "genesisInfo": { "version": 4, diff --git a/src/test/resources/test-chain-v2-leftover-reward.json b/src/test/resources/test-chain-v2-leftover-reward.json index eb6f56a9f..1ff9edea5 100644 --- a/src/test/resources/test-chain-v2-leftover-reward.json +++ b/src/test/resources/test-chain-v2-leftover-reward.json @@ -53,7 +53,8 @@ "shareBinFix": 999999, "calcChainWeightTimestamp": 0, "transactionV5Timestamp": 0, - "transactionV6Timestamp": 0 + "transactionV6Timestamp": 0, + "disableReferenceTimestamp": 9999999999999 }, "genesisInfo": { "version": 4, diff --git a/src/test/resources/test-chain-v2-minting.json b/src/test/resources/test-chain-v2-minting.json index d9893cb25..d2c522ea6 100644 --- a/src/test/resources/test-chain-v2-minting.json +++ b/src/test/resources/test-chain-v2-minting.json @@ -53,7 +53,8 @@ "shareBinFix": 999999, "calcChainWeightTimestamp": 0, "transactionV5Timestamp": 0, - "transactionV6Timestamp": 0 + "transactionV6Timestamp": 0, + "disableReferenceTimestamp": 9999999999999 }, "genesisInfo": { "version": 4, diff --git a/src/test/resources/test-chain-v2-qora-holder-extremes.json b/src/test/resources/test-chain-v2-qora-holder-extremes.json index 3fbb13758..73593ba50 100644 --- a/src/test/resources/test-chain-v2-qora-holder-extremes.json +++ b/src/test/resources/test-chain-v2-qora-holder-extremes.json @@ -53,7 +53,8 @@ "shareBinFix": 999999, "calcChainWeightTimestamp": 0, "transactionV5Timestamp": 0, - "transactionV6Timestamp": 0 + "transactionV6Timestamp": 0, + "disableReferenceTimestamp": 9999999999999 }, "genesisInfo": { "version": 4, diff --git a/src/test/resources/test-chain-v2-qora-holder.json b/src/test/resources/test-chain-v2-qora-holder.json index b14dc8b75..4bee8c939 100644 --- a/src/test/resources/test-chain-v2-qora-holder.json +++ b/src/test/resources/test-chain-v2-qora-holder.json @@ -53,7 +53,8 @@ "shareBinFix": 999999, "calcChainWeightTimestamp": 0, "transactionV5Timestamp": 0, - "transactionV6Timestamp": 0 + "transactionV6Timestamp": 0, + "disableReferenceTimestamp": 9999999999999 }, "genesisInfo": { "version": 4, diff --git a/src/test/resources/test-chain-v2-reward-levels.json b/src/test/resources/test-chain-v2-reward-levels.json index 932a8cda8..eba770610 100644 --- a/src/test/resources/test-chain-v2-reward-levels.json +++ b/src/test/resources/test-chain-v2-reward-levels.json @@ -53,7 +53,8 @@ "shareBinFix": 6, "calcChainWeightTimestamp": 0, "transactionV5Timestamp": 0, - "transactionV6Timestamp": 0 + "transactionV6Timestamp": 0, + "disableReferenceTimestamp": 9999999999999 }, "genesisInfo": { "version": 4, diff --git a/src/test/resources/test-chain-v2-reward-scaling.json b/src/test/resources/test-chain-v2-reward-scaling.json index 6244ea587..14772c600 100644 --- a/src/test/resources/test-chain-v2-reward-scaling.json +++ b/src/test/resources/test-chain-v2-reward-scaling.json @@ -53,7 +53,8 @@ "shareBinFix": 999999, "calcChainWeightTimestamp": 0, "transactionV5Timestamp": 0, - "transactionV6Timestamp": 0 + "transactionV6Timestamp": 0, + "disableReferenceTimestamp": 9999999999999 }, "genesisInfo": { "version": 4, diff --git a/src/test/resources/test-chain-v2.json b/src/test/resources/test-chain-v2.json index f308712df..f897e38d3 100644 --- a/src/test/resources/test-chain-v2.json +++ b/src/test/resources/test-chain-v2.json @@ -53,7 +53,8 @@ "shareBinFix": 999999, "calcChainWeightTimestamp": 0, "transactionV5Timestamp": 0, - "transactionV6Timestamp": 0 + "transactionV6Timestamp": 0, + "disableReferenceTimestamp": 9999999999999 }, "genesisInfo": { "version": 4, diff --git a/src/test/resources/test-settings-v2-disable-reference.json b/src/test/resources/test-settings-v2-disable-reference.json new file mode 100644 index 000000000..d9607c836 --- /dev/null +++ b/src/test/resources/test-settings-v2-disable-reference.json @@ -0,0 +1,11 @@ +{ + "repositoryPath": "testdb", + "restrictedApi": false, + "blockchainConfig": "src/test/resources/test-chain-v2-disable-reference.json", + "exportPath": "qortal-backup-test", + "bootstrap": false, + "wipeUnconfirmedOnStart": false, + "testNtpOffset": 0, + "minPeers": 0, + "pruneBlockLimit": 100 +}