mirror of
https://github.com/Qortal/qortal.git
synced 2025-07-23 04:36:50 +00:00
Work on Polls
Added CreatePollTransactionData constructor that doesn't need signature (for creating new transactions). Added missing "published" timestamp support to PollData and Poll. Removed extraneous timestamp test from Block.isValid. Corrected inconsistent column names in poll-related tables in HSQLDBDatabaseUpdates. HSQLDBRepository.checkedExecute(PreparedStatement) now takes extra Object... params so that values can be bound to placeholders. Code moved from checkedExecute(String, Object...). This fixes an issue with exists(String, String, Object...) where placeholders weren't having any values bound to them. (Also removed "ORDER BY NULL" clause which isn't supported by HSQLDB). HSQLDBVotingRepository method stubs fleshed out with real code. TransactionTests rejigged but more work needed to test various transactions before/after their feature release. e.g. testing create poll transactions before & after they supposedly went live. Could do with a GenesisBlock constructor that takes a timestamp for testing purposes? CreatePollTransactionTransformer now skips serializing a null signature, in the same way PaymentTransactionTransformer does, to aid getBytesLessSignature(). This will probably need to be rolled out to all other transaction types.
This commit is contained in:
@@ -3,8 +3,12 @@ package test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -13,13 +17,17 @@ import com.google.common.hash.HashCode;
|
||||
import data.account.AccountBalanceData;
|
||||
import data.account.AccountData;
|
||||
import data.block.BlockData;
|
||||
import data.transaction.CreatePollTransactionData;
|
||||
import data.transaction.PaymentTransactionData;
|
||||
import data.voting.PollData;
|
||||
import data.voting.PollOptionData;
|
||||
import qora.account.Account;
|
||||
import qora.account.PrivateKeyAccount;
|
||||
import qora.account.PublicKeyAccount;
|
||||
import qora.assets.Asset;
|
||||
import qora.block.Block;
|
||||
import qora.block.BlockChain;
|
||||
import qora.transaction.CreatePollTransaction;
|
||||
import qora.transaction.PaymentTransaction;
|
||||
import qora.transaction.Transaction;
|
||||
import qora.transaction.Transaction.ValidationResult;
|
||||
@@ -39,19 +47,21 @@ public class TransactionTests {
|
||||
private static final byte[] senderSeed = HashCode.fromString("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef").asBytes();
|
||||
private static final byte[] recipientSeed = HashCode.fromString("fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210").asBytes();
|
||||
|
||||
@BeforeClass
|
||||
public static void setRepository() throws DataException {
|
||||
private static final BigDecimal generatorBalance = BigDecimal.valueOf(1_000_000_000L);
|
||||
private static final BigDecimal senderBalance = BigDecimal.valueOf(1_000_000L);
|
||||
|
||||
private Repository repository;
|
||||
private AccountRepository accountRepository;
|
||||
private BlockData genesisBlockData;
|
||||
private PrivateKeyAccount sender;
|
||||
private PrivateKeyAccount generator;
|
||||
private byte[] reference;
|
||||
|
||||
@Before
|
||||
public void createTestAccounts() throws DataException {
|
||||
RepositoryFactory repositoryFactory = new HSQLDBRepositoryFactory(connectionUrl);
|
||||
RepositoryManager.setRepositoryFactory(repositoryFactory);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void closeRepository() throws DataException {
|
||||
RepositoryManager.closeRepositoryFactory();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPaymentTransactions() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
assertEquals("Blockchain should be empty for this test", 0, repository.getBlockRepository().getBlockchainHeight());
|
||||
}
|
||||
@@ -59,70 +69,127 @@ public class TransactionTests {
|
||||
// This needs to be called outside of acquiring our own repository or it will deadlock
|
||||
BlockChain.validate();
|
||||
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
// Grab genesis block
|
||||
BlockData genesisBlockData = repository.getBlockRepository().fromHeight(1);
|
||||
// Grab repository for further use, including during test itself
|
||||
repository = RepositoryManager.getRepository();
|
||||
|
||||
AccountRepository accountRepository = repository.getAccountRepository();
|
||||
// Grab genesis block
|
||||
genesisBlockData = repository.getBlockRepository().fromHeight(1);
|
||||
|
||||
// Create test generator account
|
||||
BigDecimal generatorBalance = BigDecimal.valueOf(1_000_000_000L);
|
||||
PrivateKeyAccount generator = new PrivateKeyAccount(repository, generatorSeed);
|
||||
accountRepository.save(new AccountData(generator.getAddress(), generatorSeed));
|
||||
accountRepository.save(new AccountBalanceData(generator.getAddress(), Asset.QORA, generatorBalance));
|
||||
accountRepository = repository.getAccountRepository();
|
||||
|
||||
// Create test sender account
|
||||
PrivateKeyAccount sender = new PrivateKeyAccount(repository, senderSeed);
|
||||
// Create test generator account
|
||||
generator = new PrivateKeyAccount(repository, generatorSeed);
|
||||
accountRepository.save(new AccountData(generator.getAddress(), generatorSeed));
|
||||
accountRepository.save(new AccountBalanceData(generator.getAddress(), Asset.QORA, generatorBalance));
|
||||
|
||||
// Mock account
|
||||
byte[] reference = senderSeed;
|
||||
accountRepository.save(new AccountData(sender.getAddress(), reference));
|
||||
// Create test sender account
|
||||
sender = new PrivateKeyAccount(repository, senderSeed);
|
||||
|
||||
// Mock balance
|
||||
BigDecimal initialBalance = BigDecimal.valueOf(1_000_000L);
|
||||
accountRepository.save(new AccountBalanceData(sender.getAddress(), Asset.QORA, initialBalance));
|
||||
// Mock account
|
||||
reference = senderSeed;
|
||||
accountRepository.save(new AccountData(sender.getAddress(), reference));
|
||||
|
||||
repository.saveChanges();
|
||||
// Mock balance
|
||||
accountRepository.save(new AccountBalanceData(sender.getAddress(), Asset.QORA, senderBalance));
|
||||
|
||||
// Make a new payment transaction
|
||||
Account recipient = new PublicKeyAccount(repository, recipientSeed);
|
||||
BigDecimal amount = BigDecimal.valueOf(1_000L);
|
||||
BigDecimal fee = BigDecimal.ONE;
|
||||
long timestamp = genesisBlockData.getTimestamp() + 1_000;
|
||||
PaymentTransactionData paymentTransactionData = new PaymentTransactionData(sender.getPublicKey(), recipient.getAddress(), amount, fee, timestamp,
|
||||
reference);
|
||||
repository.saveChanges();
|
||||
}
|
||||
|
||||
Transaction paymentTransaction = new PaymentTransaction(repository, paymentTransactionData);
|
||||
paymentTransaction.calcSignature(sender);
|
||||
assertTrue(paymentTransaction.isSignatureValid());
|
||||
assertEquals(ValidationResult.OK, paymentTransaction.isValid());
|
||||
@After
|
||||
public void closeRepository() throws DataException {
|
||||
RepositoryManager.closeRepositoryFactory();
|
||||
}
|
||||
|
||||
// Forge new block with payment transaction
|
||||
Block block = new Block(repository, genesisBlockData, generator, null, null);
|
||||
block.addTransaction(paymentTransactionData);
|
||||
block.sign();
|
||||
@Test
|
||||
public void testPaymentTransaction() throws DataException {
|
||||
// Make a new payment transaction
|
||||
Account recipient = new PublicKeyAccount(repository, recipientSeed);
|
||||
BigDecimal amount = BigDecimal.valueOf(1_000L);
|
||||
BigDecimal fee = BigDecimal.ONE;
|
||||
long timestamp = genesisBlockData.getTimestamp() + 1_000;
|
||||
PaymentTransactionData paymentTransactionData = new PaymentTransactionData(sender.getPublicKey(), recipient.getAddress(), amount, fee, timestamp,
|
||||
reference);
|
||||
|
||||
assertTrue("Block signatures invalid", block.isSignatureValid());
|
||||
assertEquals("Block is invalid", Block.ValidationResult.OK, block.isValid());
|
||||
Transaction paymentTransaction = new PaymentTransaction(repository, paymentTransactionData);
|
||||
paymentTransaction.calcSignature(sender);
|
||||
assertTrue(paymentTransaction.isSignatureValid());
|
||||
assertEquals(ValidationResult.OK, paymentTransaction.isValid());
|
||||
|
||||
block.process();
|
||||
repository.saveChanges();
|
||||
// Forge new block with payment transaction
|
||||
Block block = new Block(repository, genesisBlockData, generator, null, null);
|
||||
block.addTransaction(paymentTransactionData);
|
||||
block.sign();
|
||||
|
||||
// Check sender's balance
|
||||
BigDecimal expectedBalance = initialBalance.subtract(amount).subtract(fee);
|
||||
BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Sender's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||
assertTrue("Block signatures invalid", block.isSignatureValid());
|
||||
assertEquals("Block is invalid", Block.ValidationResult.OK, block.isValid());
|
||||
|
||||
// Fee should be in generator's balance
|
||||
expectedBalance = generatorBalance.add(fee);
|
||||
actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||
block.process();
|
||||
repository.saveChanges();
|
||||
|
||||
// Amount should be in recipient's balance
|
||||
expectedBalance = amount;
|
||||
actualBalance = accountRepository.getBalance(recipient.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Recipient's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||
}
|
||||
// Check sender's balance
|
||||
BigDecimal expectedBalance = senderBalance.subtract(amount).subtract(fee);
|
||||
BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Sender's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||
|
||||
// Fee should be in generator's balance
|
||||
expectedBalance = generatorBalance.add(fee);
|
||||
actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||
|
||||
// Amount should be in recipient's balance
|
||||
expectedBalance = amount;
|
||||
actualBalance = accountRepository.getBalance(recipient.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Recipient's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatePollTransaction() throws DataException {
|
||||
// XXX This test fails unless GenesisBlock's timestamp is set to something after BlockChain.VOTING_RELEASE_TIMESTAMP so we need better testing setup
|
||||
|
||||
// Make a new create poll transaction
|
||||
String pollName = "test poll";
|
||||
String description = "test poll description";
|
||||
|
||||
List<PollOptionData> pollOptions = new ArrayList<PollOptionData>();
|
||||
pollOptions.add(new PollOptionData("abort"));
|
||||
pollOptions.add(new PollOptionData("retry"));
|
||||
pollOptions.add(new PollOptionData("fail"));
|
||||
|
||||
Account recipient = new PublicKeyAccount(repository, recipientSeed);
|
||||
BigDecimal fee = BigDecimal.ONE;
|
||||
long timestamp = genesisBlockData.getTimestamp() + 1_000;
|
||||
CreatePollTransactionData createPollTransactionData = new CreatePollTransactionData(sender.getPublicKey(), recipient.getAddress(), pollName,
|
||||
description, pollOptions, fee, timestamp, reference);
|
||||
|
||||
Transaction createPollTransaction = new CreatePollTransaction(repository, createPollTransactionData);
|
||||
createPollTransaction.calcSignature(sender);
|
||||
assertTrue(createPollTransaction.isSignatureValid());
|
||||
assertEquals(ValidationResult.OK, createPollTransaction.isValid());
|
||||
|
||||
// Forge new block with payment transaction
|
||||
Block block = new Block(repository, genesisBlockData, generator, null, null);
|
||||
block.addTransaction(createPollTransactionData);
|
||||
block.sign();
|
||||
|
||||
assertTrue("Block signatures invalid", block.isSignatureValid());
|
||||
assertEquals("Block is invalid", Block.ValidationResult.OK, block.isValid());
|
||||
|
||||
block.process();
|
||||
repository.saveChanges();
|
||||
|
||||
// Check sender's balance
|
||||
BigDecimal expectedBalance = senderBalance.subtract(fee);
|
||||
BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Sender's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||
|
||||
// Fee should be in generator's balance
|
||||
expectedBalance = generatorBalance.add(fee);
|
||||
actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||
|
||||
// Check poll was created
|
||||
PollData actualPollData = this.repository.getVotingRepository().fromPollName(pollName);
|
||||
assertNotNull(actualPollData);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user