mirror of
https://github.com/Qortal/qortal.git
synced 2025-07-23 04:36:50 +00:00
Update various transaction types at a future unknown timestamp.
- PUBLICIZE transactions are no longer possible. - ARBITRARY transactions are now only possible using a fee. - MESSAGE transactions only confirm when they are being sent to an AT. Messages to regular addresses (or no recipient) will expire after 24 hours. - Difficulty for confirmed MESSAGE transactions increases from 14 to 16. - Difficulty for unconfirmed MESSAGE transactions decreases from 14 to 12.
This commit is contained in:
@@ -3,6 +3,8 @@ package org.qortal.test;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.qortal.crypto.MemoryPoW;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.test.common.Common;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@@ -39,13 +41,14 @@ public class MemoryPoWTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleComputes() {
|
||||
public void testMultipleComputes() throws DataException {
|
||||
Common.useDefaultSettings();
|
||||
Random random = new Random();
|
||||
|
||||
final int sampleSize = 20;
|
||||
final int sampleSize = 10;
|
||||
final long stddevDivisor = sampleSize * (sampleSize - 1);
|
||||
|
||||
for (int difficulty = 8; difficulty < 16; difficulty += 2) {
|
||||
for (int difficulty = 8; difficulty <= 16; difficulty++) {
|
||||
byte[] data = new byte[256];
|
||||
long[] times = new long[sampleSize];
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package org.qortal.test;
|
||||
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -14,12 +15,9 @@ import org.qortal.group.Group.ApprovalThreshold;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
import org.qortal.repository.RepositoryManager;
|
||||
import org.qortal.test.common.BlockUtils;
|
||||
import org.qortal.test.common.Common;
|
||||
import org.qortal.test.common.GroupUtils;
|
||||
import org.qortal.test.common.TestAccount;
|
||||
import org.qortal.test.common.TransactionUtils;
|
||||
import org.qortal.test.common.*;
|
||||
import org.qortal.test.common.transaction.TestTransaction;
|
||||
import org.qortal.transaction.DeployAtTransaction;
|
||||
import org.qortal.transaction.MessageTransaction;
|
||||
import org.qortal.transaction.Transaction;
|
||||
import org.qortal.transaction.Transaction.TransactionType;
|
||||
@@ -139,7 +137,7 @@ public class MessageTests extends Common {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withRecipentWithAmount() throws DataException {
|
||||
public void withRecipientWithAmount() throws DataException {
|
||||
testMessage(Group.NO_GROUP, recipient, 123L, Asset.QORT);
|
||||
}
|
||||
|
||||
@@ -153,6 +151,132 @@ public class MessageTests extends Common {
|
||||
testMessage(1, null, 0L, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void atRecipientNoFeeWithNonce() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
String atRecipient = deployAt();
|
||||
MessageTransaction transaction = testFeeNonce(repository, false, true, atRecipient, true);
|
||||
|
||||
// Transaction should be confirmable because it's to an AT, and therefore should be present in a block
|
||||
assertTrue(transaction.isConfirmable());
|
||||
TransactionUtils.signAndMint(repository, transaction.getTransactionData(), alice);
|
||||
assertTrue(isTransactionConfirmed(repository, transaction));
|
||||
assertEquals(16, transaction.getPoWDifficulty());
|
||||
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void regularRecipientNoFeeWithNonce() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
|
||||
MessageTransaction transaction = testFeeNonce(repository, false, true, recipient, true);
|
||||
|
||||
// Transaction shouldn't be confirmable because it's not to an AT, and therefore shouldn't be present in a block
|
||||
assertFalse(transaction.isConfirmable());
|
||||
TransactionUtils.signAndMint(repository, transaction.getTransactionData(), alice);
|
||||
assertFalse(isTransactionConfirmed(repository, transaction));
|
||||
assertEquals(12, transaction.getPoWDifficulty());
|
||||
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noRecipientNoFeeWithNonce() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
|
||||
MessageTransaction transaction = testFeeNonce(repository, false, true, null, true);
|
||||
|
||||
// Transaction shouldn't be confirmable because it's not to an AT, and therefore shouldn't be present in a block
|
||||
assertFalse(transaction.isConfirmable());
|
||||
TransactionUtils.signAndMint(repository, transaction.getTransactionData(), alice);
|
||||
assertFalse(isTransactionConfirmed(repository, transaction));
|
||||
assertEquals(12, transaction.getPoWDifficulty());
|
||||
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void atRecipientWithFeeNoNonce() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
String atRecipient = deployAt();
|
||||
MessageTransaction transaction = testFeeNonce(repository, true, false, atRecipient, true);
|
||||
|
||||
// Transaction should be confirmable because it's to an AT, and therefore should be present in a block
|
||||
assertTrue(transaction.isConfirmable());
|
||||
TransactionUtils.signAndMint(repository, transaction.getTransactionData(), alice);
|
||||
assertTrue(isTransactionConfirmed(repository, transaction));
|
||||
assertEquals(16, transaction.getPoWDifficulty());
|
||||
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void regularRecipientWithFeeNoNonce() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
|
||||
MessageTransaction transaction = testFeeNonce(repository, true, false, recipient, true);
|
||||
|
||||
// Transaction shouldn't be confirmable because it's not to an AT, and therefore shouldn't be present in a block
|
||||
assertFalse(transaction.isConfirmable());
|
||||
TransactionUtils.signAndMint(repository, transaction.getTransactionData(), alice);
|
||||
assertFalse(isTransactionConfirmed(repository, transaction));
|
||||
assertEquals(12, transaction.getPoWDifficulty());
|
||||
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void atRecipientNoFeeWithNonceLegacyDifficulty() throws DataException, IllegalAccessException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
|
||||
// Set mempowTransactionUpdatesTimestamp to a high value, so that it hasn't activated key
|
||||
FieldUtils.writeField(BlockChain.getInstance(), "mempowTransactionUpdatesTimestamp", Long.MAX_VALUE, true);
|
||||
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
String atRecipient = deployAt();
|
||||
MessageTransaction transaction = testFeeNonce(repository, false, true, atRecipient, true);
|
||||
|
||||
// Transaction should be confirmable because all MESSAGE transactions confirmed prior to the feature trigger
|
||||
assertTrue(transaction.isConfirmable());
|
||||
TransactionUtils.signAndMint(repository, transaction.getTransactionData(), alice);
|
||||
assertTrue(isTransactionConfirmed(repository, transaction));
|
||||
assertEquals(14, transaction.getPoWDifficulty()); // Legacy difficulty was 14 in all cases
|
||||
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void regularRecipientNoFeeWithNonceLegacyDifficulty() throws DataException, IllegalAccessException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
|
||||
// Set mempowTransactionUpdatesTimestamp to a high value, so that it hasn't activated key
|
||||
FieldUtils.writeField(BlockChain.getInstance(), "mempowTransactionUpdatesTimestamp", Long.MAX_VALUE, true);
|
||||
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
MessageTransaction transaction = testFeeNonce(repository, false, true, recipient, true);
|
||||
|
||||
// Transaction should be confirmable because all MESSAGE transactions confirmed prior to the feature trigger
|
||||
assertTrue(transaction.isConfirmable());
|
||||
TransactionUtils.signAndMint(repository, transaction.getTransactionData(), alice);
|
||||
assertTrue(isTransactionConfirmed(repository, transaction)); // All MESSAGE transactions would confirm before feature trigger
|
||||
assertEquals(14, transaction.getPoWDifficulty()); // Legacy difficulty was 14 in all cases
|
||||
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializationTests() throws DataException, TransformationException {
|
||||
// with recipient, with amount
|
||||
@@ -165,6 +289,24 @@ public class MessageTests extends Common {
|
||||
testSerialization(null, 0L, null);
|
||||
}
|
||||
|
||||
private String deployAt() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount deployer = Common.getTestAccount(repository, "alice");
|
||||
byte[] creationBytes = AtUtils.buildSimpleAT();
|
||||
long fundingAmount = 1_00000000L;
|
||||
DeployAtTransaction deployAtTransaction = AtUtils.doDeployAT(repository, deployer, creationBytes, fundingAmount);
|
||||
|
||||
String address = deployAtTransaction.getATAccount().getAddress();
|
||||
assertNotNull(address);
|
||||
return address;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isTransactionConfirmed(Repository repository, MessageTransaction transaction) throws DataException {
|
||||
TransactionData queriedTransactionData = repository.getTransactionRepository().fromSignature(transaction.getTransactionData().getSignature());
|
||||
return queriedTransactionData.getBlockHeight() != null && queriedTransactionData.getBlockHeight() > 0;
|
||||
}
|
||||
|
||||
private boolean isValid(int txGroupId, String recipient, long amount, Long assetId) throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
TestAccount alice = Common.getTestAccount(repository, "alice");
|
||||
@@ -195,41 +337,48 @@ public class MessageTests extends Common {
|
||||
return messageTransaction.hasValidReference();
|
||||
}
|
||||
|
||||
private void testFeeNonce(boolean withFee, boolean withNonce, boolean isValid) throws DataException {
|
||||
|
||||
private MessageTransaction testFeeNonce(boolean withFee, boolean withNonce, boolean isValid) throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
TestAccount alice = Common.getTestAccount(repository, "alice");
|
||||
|
||||
int txGroupId = 0;
|
||||
int nonce = 0;
|
||||
long amount = 0;
|
||||
long assetId = Asset.QORT;
|
||||
byte[] data = new byte[1];
|
||||
boolean isText = false;
|
||||
boolean isEncrypted = false;
|
||||
|
||||
MessageTransactionData transactionData = new MessageTransactionData(TestTransaction.generateBase(alice, txGroupId),
|
||||
version, nonce, recipient, amount, assetId, data, isText, isEncrypted);
|
||||
|
||||
MessageTransaction transaction = new MessageTransaction(repository, transactionData);
|
||||
|
||||
if (withFee)
|
||||
transactionData.setFee(transaction.calcRecommendedFee());
|
||||
else
|
||||
transactionData.setFee(0L);
|
||||
|
||||
if (withNonce) {
|
||||
transaction.computeNonce();
|
||||
} else {
|
||||
transactionData.setNonce(-1);
|
||||
}
|
||||
|
||||
transaction.sign(alice);
|
||||
|
||||
assertEquals(isValid, transaction.isSignatureValid());
|
||||
return testFeeNonce(repository, withFee, withNonce, recipient, isValid);
|
||||
}
|
||||
}
|
||||
|
||||
private void testMessage(int txGroupId, String recipient, long amount, Long assetId) throws DataException {
|
||||
private MessageTransaction testFeeNonce(Repository repository, boolean withFee, boolean withNonce, String recipient, boolean isValid) throws DataException {
|
||||
TestAccount alice = Common.getTestAccount(repository, "alice");
|
||||
|
||||
int txGroupId = 0;
|
||||
int nonce = 0;
|
||||
long amount = 0;
|
||||
long assetId = Asset.QORT;
|
||||
byte[] data = new byte[1];
|
||||
boolean isText = false;
|
||||
boolean isEncrypted = false;
|
||||
|
||||
MessageTransactionData transactionData = new MessageTransactionData(TestTransaction.generateBase(alice, txGroupId),
|
||||
version, nonce, recipient, amount, assetId, data, isText, isEncrypted);
|
||||
|
||||
MessageTransaction transaction = new MessageTransaction(repository, transactionData);
|
||||
|
||||
if (withFee)
|
||||
transactionData.setFee(transaction.calcRecommendedFee());
|
||||
else
|
||||
transactionData.setFee(0L);
|
||||
|
||||
if (withNonce) {
|
||||
transaction.computeNonce();
|
||||
} else {
|
||||
transactionData.setNonce(-1);
|
||||
}
|
||||
|
||||
transaction.sign(alice);
|
||||
|
||||
assertEquals(isValid, transaction.isSignatureValid());
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
private MessageTransaction testMessage(int txGroupId, String recipient, long amount, Long assetId) throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
TestAccount alice = Common.getTestAccount(repository, "alice");
|
||||
|
||||
@@ -244,6 +393,8 @@ public class MessageTests extends Common {
|
||||
TransactionUtils.signAndMint(repository, transactionData, alice);
|
||||
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
return new MessageTransaction(repository, transactionData);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -11,6 +11,7 @@ import org.qortal.arbitrary.ArbitraryDataReader;
|
||||
import org.qortal.arbitrary.exception.MissingDataException;
|
||||
import org.qortal.arbitrary.misc.Category;
|
||||
import org.qortal.arbitrary.misc.Service;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.controller.arbitrary.ArbitraryDataManager;
|
||||
import org.qortal.data.arbitrary.ArbitraryResourceMetadata;
|
||||
import org.qortal.data.transaction.ArbitraryTransactionData;
|
||||
@@ -24,6 +25,7 @@ import org.qortal.test.common.TransactionUtils;
|
||||
import org.qortal.test.common.transaction.TestTransaction;
|
||||
import org.qortal.transaction.RegisterNameTransaction;
|
||||
import org.qortal.utils.Base58;
|
||||
import org.qortal.utils.NTP;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
@@ -106,8 +108,9 @@ public class ArbitraryTransactionMetadataTests extends Common {
|
||||
|
||||
// Create PUT transaction
|
||||
Path path1 = ArbitraryUtils.generateRandomDataPath(dataLength);
|
||||
long fee = BlockChain.getInstance().getUnitFeeAtTimestamp(NTP.getTime());
|
||||
ArbitraryDataFile arbitraryDataFile = ArbitraryUtils.createAndMintTxn(repository, publicKey58, path1, name,
|
||||
identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize, 0L, true,
|
||||
identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize, fee, false,
|
||||
title, description, tags, category);
|
||||
|
||||
// Check the chunk count is correct
|
||||
@@ -157,8 +160,9 @@ public class ArbitraryTransactionMetadataTests extends Common {
|
||||
|
||||
// Create PUT transaction
|
||||
Path path1 = ArbitraryUtils.generateRandomDataPath(dataLength);
|
||||
long fee = BlockChain.getInstance().getUnitFeeAtTimestamp(NTP.getTime());
|
||||
ArbitraryDataFile arbitraryDataFile = ArbitraryUtils.createAndMintTxn(repository, publicKey58, path1, name,
|
||||
identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize, 0L, true,
|
||||
identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize, fee, false,
|
||||
title, description, tags, category);
|
||||
|
||||
// Check the chunk count is correct
|
||||
@@ -220,8 +224,9 @@ public class ArbitraryTransactionMetadataTests extends Common {
|
||||
|
||||
// Create PUT transaction
|
||||
Path path1 = ArbitraryUtils.generateRandomDataPath(dataLength);
|
||||
long fee = BlockChain.getInstance().getUnitFeeAtTimestamp(NTP.getTime());
|
||||
ArbitraryDataFile arbitraryDataFile = ArbitraryUtils.createAndMintTxn(repository, publicKey58, path1, name,
|
||||
identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize, 0L, true,
|
||||
identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize, fee, false,
|
||||
title, description, tags, category);
|
||||
|
||||
// Check the chunk count is correct
|
||||
@@ -272,8 +277,9 @@ public class ArbitraryTransactionMetadataTests extends Common {
|
||||
|
||||
// Create PUT transaction
|
||||
Path path1 = ArbitraryUtils.generateRandomDataPath(dataLength);
|
||||
long fee = BlockChain.getInstance().getUnitFeeAtTimestamp(NTP.getTime());
|
||||
ArbitraryDataFile arbitraryDataFile = ArbitraryUtils.createAndMintTxn(repository, publicKey58, path1, name,
|
||||
identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize, 0L, true,
|
||||
identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize, fee, false,
|
||||
title, description, tags, category);
|
||||
|
||||
// Check the chunk count is correct
|
||||
@@ -316,8 +322,9 @@ public class ArbitraryTransactionMetadataTests extends Common {
|
||||
|
||||
// Create PUT transaction
|
||||
Path path1 = ArbitraryUtils.generateRandomDataPath(dataLength);
|
||||
long fee = BlockChain.getInstance().getUnitFeeAtTimestamp(NTP.getTime());
|
||||
ArbitraryDataFile arbitraryDataFile = ArbitraryUtils.createAndMintTxn(repository, publicKey58, path1, name,
|
||||
identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize, 0L, true,
|
||||
identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize, fee, false,
|
||||
title, description, tags, category);
|
||||
|
||||
// Check the metadata is correct
|
||||
|
@@ -10,6 +10,7 @@ import org.qortal.arbitrary.ArbitraryDataTransactionBuilder;
|
||||
import org.qortal.arbitrary.exception.MissingDataException;
|
||||
import org.qortal.arbitrary.misc.Category;
|
||||
import org.qortal.arbitrary.misc.Service;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.controller.arbitrary.ArbitraryDataManager;
|
||||
import org.qortal.crypto.Crypto;
|
||||
import org.qortal.data.PaymentData;
|
||||
@@ -50,51 +51,6 @@ public class ArbitraryTransactionTests extends Common {
|
||||
Common.useDefaultSettings();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDifficultyTooLow() throws IllegalAccessException, DataException, IOException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
String publicKey58 = Base58.encode(alice.getPublicKey());
|
||||
String name = "TEST"; // Can be anything for this test
|
||||
String identifier = null; // Not used for this test
|
||||
Service service = Service.ARBITRARY_DATA;
|
||||
int chunkSize = 100;
|
||||
int dataLength = 900; // Actual data length will be longer due to encryption
|
||||
|
||||
// Register the name to Alice
|
||||
RegisterNameTransactionData registerNameTransactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), name, "");
|
||||
registerNameTransactionData.setFee(new RegisterNameTransaction(null, null).getUnitFee(registerNameTransactionData.getTimestamp()));
|
||||
TransactionUtils.signAndMint(repository, registerNameTransactionData, alice);
|
||||
|
||||
// Set difficulty to 1
|
||||
FieldUtils.writeField(ArbitraryDataManager.getInstance(), "powDifficulty", 1, true);
|
||||
|
||||
// Create PUT transaction
|
||||
Path path1 = ArbitraryUtils.generateRandomDataPath(dataLength);
|
||||
ArbitraryDataFile arbitraryDataFile = ArbitraryUtils.createAndMintTxn(repository, publicKey58, path1, name, identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize);
|
||||
|
||||
// Check that nonce validation succeeds
|
||||
byte[] signature = arbitraryDataFile.getSignature();
|
||||
TransactionData transactionData = repository.getTransactionRepository().fromSignature(signature);
|
||||
ArbitraryTransaction transaction = new ArbitraryTransaction(repository, transactionData);
|
||||
assertTrue(transaction.isSignatureValid());
|
||||
|
||||
// Increase difficulty to 15
|
||||
FieldUtils.writeField(ArbitraryDataManager.getInstance(), "powDifficulty", 15, true);
|
||||
|
||||
// Make sure the nonce validation fails
|
||||
// Note: there is a very tiny chance this could succeed due to being extremely lucky
|
||||
// and finding a high difficulty nonce in the first couple of cycles. It will be rare
|
||||
// enough that we shouldn't need to account for it.
|
||||
assertFalse(transaction.isSignatureValid());
|
||||
|
||||
// Reduce difficulty back to 1, to double check
|
||||
FieldUtils.writeField(ArbitraryDataManager.getInstance(), "powDifficulty", 1, true);
|
||||
assertTrue(transaction.isSignatureValid());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonceAndFee() throws IllegalAccessException, DataException, IOException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
@@ -497,8 +453,9 @@ public class ArbitraryTransactionTests extends Common {
|
||||
|
||||
// Create PUT transaction
|
||||
Path path1 = ArbitraryUtils.generateRandomDataPath(dataLength, true);
|
||||
long fee = BlockChain.getInstance().getUnitFeeAtTimestamp(NTP.getTime());
|
||||
ArbitraryDataFile arbitraryDataFile = ArbitraryUtils.createAndMintTxn(repository, publicKey58, path1, name,
|
||||
identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize, 0L, true,
|
||||
identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize, fee, false,
|
||||
null, null, null, null);
|
||||
|
||||
byte[] signature = arbitraryDataFile.getSignature();
|
||||
@@ -556,8 +513,9 @@ public class ArbitraryTransactionTests extends Common {
|
||||
|
||||
// Create PUT transaction
|
||||
Path path1 = ArbitraryUtils.generateRandomDataPath(dataLength, true);
|
||||
long fee = BlockChain.getInstance().getUnitFeeAtTimestamp(NTP.getTime());
|
||||
ArbitraryDataFile arbitraryDataFile = ArbitraryUtils.createAndMintTxn(repository, publicKey58, path1, name,
|
||||
identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize, 0L, true,
|
||||
identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize, fee, false,
|
||||
title, description, tags, category);
|
||||
|
||||
byte[] signature = arbitraryDataFile.getSignature();
|
||||
@@ -614,8 +572,9 @@ public class ArbitraryTransactionTests extends Common {
|
||||
|
||||
// Create PUT transaction
|
||||
Path path1 = ArbitraryUtils.generateRandomDataPath(dataLength, true);
|
||||
long fee = BlockChain.getInstance().getUnitFeeAtTimestamp(NTP.getTime());
|
||||
ArbitraryDataFile arbitraryDataFile = ArbitraryUtils.createAndMintTxn(repository, publicKey58, path1, name,
|
||||
identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize, 0L, true,
|
||||
identifier, ArbitraryTransactionData.Method.PUT, service, alice, chunkSize, fee, false,
|
||||
null, null, null, null);
|
||||
|
||||
byte[] signature = arbitraryDataFile.getSignature();
|
||||
|
@@ -5,10 +5,12 @@ import org.qortal.arbitrary.ArbitraryDataFile;
|
||||
import org.qortal.arbitrary.ArbitraryDataTransactionBuilder;
|
||||
import org.qortal.arbitrary.misc.Category;
|
||||
import org.qortal.arbitrary.misc.Service;
|
||||
import org.qortal.block.BlockChain;
|
||||
import org.qortal.data.transaction.ArbitraryTransactionData;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
import org.qortal.transaction.Transaction;
|
||||
import org.qortal.utils.NTP;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
@@ -20,16 +22,15 @@ import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class ArbitraryUtils {
|
||||
|
||||
public static ArbitraryDataFile createAndMintTxn(Repository repository, String publicKey58, Path path, String name, String identifier,
|
||||
ArbitraryTransactionData.Method method, Service service, PrivateKeyAccount account,
|
||||
int chunkSize) throws DataException {
|
||||
|
||||
long fee = BlockChain.getInstance().getUnitFeeAtTimestamp(NTP.getTime());
|
||||
return ArbitraryUtils.createAndMintTxn(repository, publicKey58, path, name, identifier, method, service,
|
||||
account, chunkSize, 0L, true, null, null, null, null);
|
||||
account, chunkSize, fee, false, null, null, null, null);
|
||||
}
|
||||
|
||||
public static ArbitraryDataFile createAndMintTxn(Repository repository, String publicKey58, Path path, String name, String identifier,
|
||||
@@ -47,7 +48,9 @@ public class ArbitraryUtils {
|
||||
}
|
||||
ArbitraryTransactionData transactionData = txnBuilder.getArbitraryTransactionData();
|
||||
Transaction.ValidationResult result = TransactionUtils.signAndImport(repository, transactionData, account);
|
||||
assertEquals(Transaction.ValidationResult.OK, result);
|
||||
if (result != Transaction.ValidationResult.OK) {
|
||||
throw new DataException(String.format("Arbitrary transaction invalid: %s", result.toString()));
|
||||
}
|
||||
BlockUtils.mintBlock(repository);
|
||||
|
||||
// We need a new ArbitraryDataFile instance because the files will have been moved to the signature's folder
|
||||
|
@@ -444,6 +444,7 @@ public class MiscTests extends Common {
|
||||
// Payment
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
PrivateKeyAccount bob = Common.getTestAccount(repository, "bob");
|
||||
PrivateKeyAccount chloe = Common.getTestAccount(repository, "chloe");
|
||||
|
||||
PaymentTransactionData transactionData = new PaymentTransactionData(TestTransaction.generateBase(alice), bob.getAddress(), 100000);
|
||||
transactionData.setFee(new PaymentTransaction(null, null).getUnitFee(transactionData.getTimestamp()));
|
||||
@@ -473,16 +474,16 @@ public class MiscTests extends Common {
|
||||
Transaction transaction = Transaction.fromData(repository, transactionData);
|
||||
transaction.sign(alice);
|
||||
ValidationResult result = transaction.importAsUnconfirmed();
|
||||
assertTrue("Transaction should be valid", ValidationResult.OK == result);
|
||||
assertEquals("Transaction should be valid", ValidationResult.OK, result);
|
||||
|
||||
// Now try fetching and setting fee manually
|
||||
transactionData = new PaymentTransactionData(TestTransaction.generateBase(alice), bob.getAddress(), 50000);
|
||||
transactionData = new PaymentTransactionData(TestTransaction.generateBase(alice), chloe.getAddress(), 50000);
|
||||
transactionData.setFee(new PaymentTransaction(null, null).getUnitFee(transactionData.getTimestamp()));
|
||||
assertEquals(300000000L, transactionData.getFee().longValue());
|
||||
transaction = Transaction.fromData(repository, transactionData);
|
||||
transaction.sign(alice);
|
||||
result = transaction.importAsUnconfirmed();
|
||||
assertTrue("Transaction should be valid", ValidationResult.OK == result);
|
||||
assertEquals("Transaction should be valid", ValidationResult.OK, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -18,6 +18,7 @@
|
||||
"onlineAccountSignaturesMinLifetime": 3600000,
|
||||
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||
"selfSponsorshipAlgoV1SnapshotTimestamp": 9999999999999,
|
||||
"mempowTransactionUpdatesTimestamp": 0,
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
|
@@ -22,6 +22,7 @@
|
||||
"onlineAccountSignaturesMinLifetime": 3600000,
|
||||
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||
"selfSponsorshipAlgoV1SnapshotTimestamp": 9999999999999,
|
||||
"mempowTransactionUpdatesTimestamp": 0,
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
|
@@ -23,6 +23,7 @@
|
||||
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||
"onlineAccountsModulusV2Timestamp": 9999999999999,
|
||||
"selfSponsorshipAlgoV1SnapshotTimestamp": 9999999999999,
|
||||
"mempowTransactionUpdatesTimestamp": 0,
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
|
@@ -23,6 +23,7 @@
|
||||
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||
"onlineAccountsModulusV2Timestamp": 9999999999999,
|
||||
"selfSponsorshipAlgoV1SnapshotTimestamp": 9999999999999,
|
||||
"mempowTransactionUpdatesTimestamp": 0,
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
|
@@ -23,6 +23,7 @@
|
||||
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||
"onlineAccountsModulusV2Timestamp": 9999999999999,
|
||||
"selfSponsorshipAlgoV1SnapshotTimestamp": 9999999999999,
|
||||
"mempowTransactionUpdatesTimestamp": 9999999999999,
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
|
@@ -23,6 +23,7 @@
|
||||
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||
"onlineAccountsModulusV2Timestamp": 9999999999999,
|
||||
"selfSponsorshipAlgoV1SnapshotTimestamp": 9999999999999,
|
||||
"mempowTransactionUpdatesTimestamp": 0,
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
|
@@ -23,6 +23,7 @@
|
||||
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||
"onlineAccountsModulusV2Timestamp": 9999999999999,
|
||||
"selfSponsorshipAlgoV1SnapshotTimestamp": 9999999999999,
|
||||
"mempowTransactionUpdatesTimestamp": 0,
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
|
@@ -23,6 +23,7 @@
|
||||
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||
"onlineAccountsModulusV2Timestamp": 9999999999999,
|
||||
"selfSponsorshipAlgoV1SnapshotTimestamp": 9999999999999,
|
||||
"mempowTransactionUpdatesTimestamp": 0,
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
|
@@ -23,6 +23,7 @@
|
||||
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||
"onlineAccountsModulusV2Timestamp": 9999999999999,
|
||||
"selfSponsorshipAlgoV1SnapshotTimestamp": 9999999999999,
|
||||
"mempowTransactionUpdatesTimestamp": 0,
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
|
@@ -23,6 +23,7 @@
|
||||
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||
"onlineAccountsModulusV2Timestamp": 9999999999999,
|
||||
"selfSponsorshipAlgoV1SnapshotTimestamp": 9999999999999,
|
||||
"mempowTransactionUpdatesTimestamp": 0,
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
|
@@ -22,6 +22,7 @@
|
||||
"onlineAccountSignaturesMinLifetime": 3600000,
|
||||
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||
"selfSponsorshipAlgoV1SnapshotTimestamp": 9999999999999,
|
||||
"mempowTransactionUpdatesTimestamp": 0,
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
|
@@ -23,6 +23,7 @@
|
||||
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||
"onlineAccountsModulusV2Timestamp": 9999999999999,
|
||||
"selfSponsorshipAlgoV1SnapshotTimestamp": 9999999999999,
|
||||
"mempowTransactionUpdatesTimestamp": 0,
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
|
@@ -24,6 +24,7 @@
|
||||
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||
"onlineAccountsModulusV2Timestamp": 9999999999999,
|
||||
"selfSponsorshipAlgoV1SnapshotTimestamp": 9999999999999,
|
||||
"mempowTransactionUpdatesTimestamp": 0,
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
|
Reference in New Issue
Block a user