forked from Qortal/qortal
More tests and fixes resulting from such
Settings class reworked to allow easier testing Fix to Payment.orphan() where fee was being incorrectly subtracted instead of added Added AssetRepository.fromAssetName(String): AssetData Fixed deleting assets from HSQLDB repository due to broken column name in SQL. Fixed saving IssueAssetTransactions in HSQLDB repository due to missing column binding. More TransactionTests!
This commit is contained in:
parent
2bfb0227ae
commit
7536ab37fa
@ -36,6 +36,11 @@ public class IssueAssetTransactionData extends TransactionData {
|
||||
this(null, issuerPublicKey, owner, assetName, description, quantity, isDivisible, fee, timestamp, reference, signature);
|
||||
}
|
||||
|
||||
public IssueAssetTransactionData(byte[] issuerPublicKey, String owner, String assetName, String description, long quantity, boolean isDivisible,
|
||||
BigDecimal fee, long timestamp, byte[] reference) {
|
||||
this(null, issuerPublicKey, owner, assetName, description, quantity, isDivisible, fee, timestamp, reference, null);
|
||||
}
|
||||
|
||||
// Getters/Setters
|
||||
|
||||
public Long getAssetId() {
|
||||
|
@ -155,9 +155,9 @@ public class Block {
|
||||
* @return 1, 2 or 3
|
||||
*/
|
||||
public int getNextBlockVersion() {
|
||||
if (this.blockData.getHeight() < BlockChain.AT_BLOCK_HEIGHT_RELEASE)
|
||||
if (this.blockData.getHeight() < BlockChain.getATReleaseHeight())
|
||||
return 1;
|
||||
else if (this.blockData.getTimestamp() < BlockChain.POWFIX_RELEASE_TIMESTAMP)
|
||||
else if (this.blockData.getTimestamp() < BlockChain.getPowFixReleaseTimestamp())
|
||||
return 2;
|
||||
else
|
||||
return 3;
|
||||
|
@ -10,6 +10,7 @@ import repository.BlockRepository;
|
||||
import repository.DataException;
|
||||
import repository.Repository;
|
||||
import repository.RepositoryManager;
|
||||
import settings.Settings;
|
||||
|
||||
/**
|
||||
* Class representing the blockchain as a whole.
|
||||
@ -31,11 +32,11 @@ public class BlockChain {
|
||||
public static final long BLOCK_TIMESTAMP_MARGIN = 500L;
|
||||
|
||||
// Various release timestamps / block heights
|
||||
public static final int MESSAGE_RELEASE_HEIGHT = 99000;
|
||||
public static final int AT_BLOCK_HEIGHT_RELEASE = 99000;
|
||||
public static final long POWFIX_RELEASE_TIMESTAMP = 1456426800000L; // Block Version 3 // 2016-02-25T19:00:00+00:00
|
||||
public static final long ASSETS_RELEASE_TIMESTAMP = 0L; // From Qora epoch
|
||||
public static final long VOTING_RELEASE_TIMESTAMP = 1403715600000L; // 2014-06-25T17:00:00+00:00
|
||||
private static final int MESSAGE_RELEASE_HEIGHT = 99000;
|
||||
private static final int AT_RELEASE_HEIGHT = 99000;
|
||||
private static final long POWFIX_RELEASE_TIMESTAMP = 1456426800000L; // Block Version 3 // 2016-02-25T19:00:00+00:00
|
||||
private static final long ASSETS_RELEASE_TIMESTAMP = 0L; // From Qora epoch
|
||||
private static final long VOTING_RELEASE_TIMESTAMP = 1403715600000L; // 2014-06-25T17:00:00+00:00
|
||||
|
||||
/**
|
||||
* Some sort start-up/initialization/checking method.
|
||||
@ -96,4 +97,39 @@ public class BlockChain {
|
||||
return balance;
|
||||
}
|
||||
|
||||
public static int getMessageReleaseHeight() {
|
||||
if (Settings.getInstance().isTestNet())
|
||||
return 0;
|
||||
|
||||
return MESSAGE_RELEASE_HEIGHT;
|
||||
}
|
||||
|
||||
public static int getATReleaseHeight() {
|
||||
if (Settings.getInstance().isTestNet())
|
||||
return 0;
|
||||
|
||||
return AT_RELEASE_HEIGHT;
|
||||
}
|
||||
|
||||
public static long getPowFixReleaseTimestamp() {
|
||||
if (Settings.getInstance().isTestNet())
|
||||
return 0;
|
||||
|
||||
return POWFIX_RELEASE_TIMESTAMP;
|
||||
}
|
||||
|
||||
public static long getAssetsReleaseTimestamp() {
|
||||
if (Settings.getInstance().isTestNet())
|
||||
return 0;
|
||||
|
||||
return ASSETS_RELEASE_TIMESTAMP;
|
||||
}
|
||||
|
||||
public static long getVotingReleaseTimestamp() {
|
||||
if (Settings.getInstance().isTestNet())
|
||||
return 0;
|
||||
|
||||
return VOTING_RELEASE_TIMESTAMP;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ public class Payment {
|
||||
Account sender = new PublicKeyAccount(this.repository, senderPublicKey);
|
||||
|
||||
// Update sender's balance due to fee
|
||||
sender.setConfirmedBalance(Asset.QORA, sender.getConfirmedBalance(Asset.QORA).subtract(fee));
|
||||
sender.setConfirmedBalance(Asset.QORA, sender.getConfirmedBalance(Asset.QORA).add(fee));
|
||||
|
||||
// Update sender's reference
|
||||
sender.setLastReference(reference);
|
||||
|
@ -115,7 +115,7 @@ public class CreateOrderTransaction extends Transaction {
|
||||
|
||||
// Check creator has enough funds for fee in QORA
|
||||
// NOTE: in Gen1 pre-POWFIX-RELEASE transactions didn't have this check
|
||||
if (createOrderTransactionData.getTimestamp() >= BlockChain.POWFIX_RELEASE_TIMESTAMP
|
||||
if (createOrderTransactionData.getTimestamp() >= BlockChain.getPowFixReleaseTimestamp()
|
||||
&& creator.getConfirmedBalance(Asset.QORA).compareTo(createOrderTransactionData.getFee()) == -1)
|
||||
return ValidationResult.NO_BALANCE;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ public class CreatePollTransaction extends Transaction {
|
||||
public ValidationResult isValid() throws DataException {
|
||||
// Are CreatePollTransactions even allowed at this point?
|
||||
// XXX In gen1 this used NTP.getTime() but surely the transaction's timestamp should be used?
|
||||
if (this.createPollTransactionData.getTimestamp() < BlockChain.VOTING_RELEASE_TIMESTAMP)
|
||||
if (this.createPollTransactionData.getTimestamp() < BlockChain.getVotingReleaseTimestamp())
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
// Check owner address is valid
|
||||
|
@ -79,7 +79,7 @@ public class IssueAssetTransaction extends Transaction {
|
||||
public ValidationResult isValid() throws DataException {
|
||||
// Are IssueAssetTransactions even allowed at this point?
|
||||
// XXX In gen1 this used NTP.getTime() but surely the transaction's timestamp should be used?
|
||||
if (this.issueAssetTransactionData.getTimestamp() < BlockChain.ASSETS_RELEASE_TIMESTAMP)
|
||||
if (this.issueAssetTransactionData.getTimestamp() < BlockChain.getAssetsReleaseTimestamp())
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
// Check owner address is valid
|
||||
|
@ -90,7 +90,7 @@ public class MessageTransaction extends Transaction {
|
||||
if (messageTransactionData.getVersion() != MessageTransaction.getVersionByTimestamp(messageTransactionData.getTimestamp()))
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
if (this.repository.getBlockRepository().getBlockchainHeight() < BlockChain.MESSAGE_RELEASE_HEIGHT)
|
||||
if (this.repository.getBlockRepository().getBlockchainHeight() < BlockChain.getMessageReleaseHeight())
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
// Check data length
|
||||
|
@ -90,7 +90,7 @@ public class MultiPaymentTransaction extends Transaction {
|
||||
List<PaymentData> payments = multiPaymentTransactionData.getPayments();
|
||||
|
||||
// Are MultiPaymentTransactions even allowed at this point?
|
||||
if (NTP.getTime() < BlockChain.ASSETS_RELEASE_TIMESTAMP)
|
||||
if (NTP.getTime() < BlockChain.getAssetsReleaseTimestamp())
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
// Check number of payments
|
||||
@ -105,7 +105,7 @@ public class MultiPaymentTransaction extends Transaction {
|
||||
|
||||
// Check sender has enough funds for fee
|
||||
// NOTE: in Gen1 pre-POWFIX-RELEASE transactions didn't have this check
|
||||
if (multiPaymentTransactionData.getTimestamp() >= BlockChain.POWFIX_RELEASE_TIMESTAMP
|
||||
if (multiPaymentTransactionData.getTimestamp() >= BlockChain.getPowFixReleaseTimestamp()
|
||||
&& sender.getConfirmedBalance(Asset.QORA).compareTo(multiPaymentTransactionData.getFee()) == -1)
|
||||
return ValidationResult.NO_BALANCE;
|
||||
|
||||
|
@ -206,7 +206,7 @@ public abstract class Transaction {
|
||||
* @return transaction version number, likely 1 or 3
|
||||
*/
|
||||
public static int getVersionByTimestamp(long timestamp) {
|
||||
if (timestamp < BlockChain.POWFIX_RELEASE_TIMESTAMP) {
|
||||
if (timestamp < BlockChain.getPowFixReleaseTimestamp()) {
|
||||
return 1;
|
||||
} else {
|
||||
return 3;
|
||||
|
@ -85,7 +85,7 @@ public class TransferAssetTransaction extends Transaction {
|
||||
TransferAssetTransactionData transferAssetTransactionData = (TransferAssetTransactionData) this.transactionData;
|
||||
|
||||
// Are IssueAssetTransactions even allowed at this point?
|
||||
if (NTP.getTime() < BlockChain.ASSETS_RELEASE_TIMESTAMP)
|
||||
if (NTP.getTime() < BlockChain.getAssetsReleaseTimestamp())
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
// Check reference is correct
|
||||
|
@ -68,7 +68,7 @@ public class VoteOnPollTransaction extends Transaction {
|
||||
public ValidationResult isValid() throws DataException {
|
||||
// Are VoteOnPollTransactions even allowed at this point?
|
||||
// XXX In gen1 this used NTP.getTime() but surely the transaction's timestamp should be used?
|
||||
if (this.voteOnPollTransactionData.getTimestamp() < BlockChain.VOTING_RELEASE_TIMESTAMP)
|
||||
if (this.voteOnPollTransactionData.getTimestamp() < BlockChain.getVotingReleaseTimestamp())
|
||||
return ValidationResult.NOT_YET_RELEASED;
|
||||
|
||||
// Check name size bounds
|
||||
|
@ -9,6 +9,8 @@ public interface AssetRepository {
|
||||
|
||||
public AssetData fromAssetId(long assetId) throws DataException;
|
||||
|
||||
public AssetData fromAssetName(String assetName) throws DataException;
|
||||
|
||||
public boolean assetExists(long assetId) throws DataException;
|
||||
|
||||
public boolean assetExists(String assetName) throws DataException;
|
||||
|
@ -39,6 +39,26 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
}
|
||||
}
|
||||
|
||||
public AssetData fromAssetName(String assetName) throws DataException {
|
||||
try {
|
||||
ResultSet resultSet = this.repository
|
||||
.checkedExecute("SELECT owner, asset_id, description, quantity, is_divisible, reference FROM Assets WHERE asset_name = ?", assetName);
|
||||
if (resultSet == null)
|
||||
return null;
|
||||
|
||||
String owner = resultSet.getString(1);
|
||||
long assetId = resultSet.getLong(2);
|
||||
String description = resultSet.getString(3);
|
||||
long quantity = resultSet.getLong(4);
|
||||
boolean isDivisible = resultSet.getBoolean(5);
|
||||
byte[] reference = resultSet.getBytes(6);
|
||||
|
||||
return new AssetData(assetId, owner, assetName, description, quantity, isDivisible, reference);
|
||||
} catch (SQLException e) {
|
||||
throw new DataException("Unable to fetch asset from repository", e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean assetExists(long assetId) throws DataException {
|
||||
try {
|
||||
return this.repository.exists("Assets", "asset_id = ?", assetId);
|
||||
@ -73,7 +93,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
|
||||
public void delete(long assetId) throws DataException {
|
||||
try {
|
||||
this.repository.delete("Assets", "assetId = ?", assetId);
|
||||
this.repository.delete("Assets", "asset_id = ?", assetId);
|
||||
} catch (SQLException e) {
|
||||
throw new DataException("Unable to delete asset from repository", e);
|
||||
}
|
||||
|
@ -46,9 +46,9 @@ public class HSQLDBIssueAssetTransactionRepository extends HSQLDBTransactionRepo
|
||||
HSQLDBSaver saveHelper = new HSQLDBSaver("IssueAssetTransactions");
|
||||
|
||||
saveHelper.bind("signature", issueAssetTransactionData.getSignature()).bind("issuer", issueAssetTransactionData.getIssuerPublicKey())
|
||||
.bind("asset_name", issueAssetTransactionData.getAssetName()).bind("description", issueAssetTransactionData.getDescription())
|
||||
.bind("quantity", issueAssetTransactionData.getQuantity()).bind("is_divisible", issueAssetTransactionData.getIsDivisible())
|
||||
.bind("asset_id", issueAssetTransactionData.getAssetId());
|
||||
.bind("owner", issueAssetTransactionData.getOwner()).bind("asset_name", issueAssetTransactionData.getAssetName())
|
||||
.bind("description", issueAssetTransactionData.getDescription()).bind("quantity", issueAssetTransactionData.getQuantity())
|
||||
.bind("is_divisible", issueAssetTransactionData.getIsDivisible()).bind("asset_id", issueAssetTransactionData.getAssetId());
|
||||
|
||||
try {
|
||||
saveHelper.execute(this.repository);
|
||||
|
@ -1,38 +1,118 @@
|
||||
package settings;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import qora.block.GenesisBlock;
|
||||
|
||||
public class Settings {
|
||||
|
||||
private static Settings instance;
|
||||
|
||||
// Properties
|
||||
private long genesisTimestamp = -1;
|
||||
private static Settings instance;
|
||||
private long genesisTimestamp = GenesisBlock.GENESIS_TIMESTAMP;
|
||||
private int maxBytePerFee = 1024;
|
||||
|
||||
// Constants
|
||||
private static final String SETTINGS_FILENAME = "settings.json";
|
||||
|
||||
// Constructors
|
||||
|
||||
private Settings() {
|
||||
}
|
||||
|
||||
private Settings(String filename) {
|
||||
// Read from file
|
||||
String path = "";
|
||||
|
||||
try {
|
||||
do {
|
||||
File file = new File(path + filename);
|
||||
|
||||
if (!file.exists()) {
|
||||
// log lack of settings file
|
||||
break;
|
||||
}
|
||||
|
||||
List<String> lines = Files.readLines(file, Charsets.UTF_8);
|
||||
|
||||
// Concatenate lines for JSON parsing
|
||||
String jsonString = "";
|
||||
for (String line : lines) {
|
||||
// Escape single backslashes in "userpath" entries, typically Windows-style paths
|
||||
if (line.contains("userpath"))
|
||||
line.replace("\\", "\\\\");
|
||||
|
||||
jsonString += line;
|
||||
}
|
||||
|
||||
JSONObject settingsJSON = (JSONObject) JSONValue.parse(jsonString);
|
||||
|
||||
String userpath = (String) settingsJSON.get("userpath");
|
||||
if (userpath != null) {
|
||||
path = userpath;
|
||||
|
||||
// Add trailing directory separator if needed
|
||||
if (!path.endsWith(File.separator))
|
||||
path += File.separator;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
process(settingsJSON);
|
||||
break;
|
||||
} while (true);
|
||||
} catch (IOException | ClassCastException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Other methods
|
||||
|
||||
public static Settings getInstance() {
|
||||
if (instance == null)
|
||||
instance = new Settings();
|
||||
instance = new Settings(SETTINGS_FILENAME);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static void test(JSONObject settingsJSON) {
|
||||
// Discard previous settings
|
||||
if (instance != null)
|
||||
instance = null;
|
||||
|
||||
instance = new Settings();
|
||||
getInstance().process(settingsJSON);
|
||||
}
|
||||
|
||||
private void process(JSONObject json) {
|
||||
if (json.containsKey("testnetstamp")) {
|
||||
if (json.get("testnetstamp").toString().equals("now") || ((Long) json.get("testnetstamp")).longValue() == 0) {
|
||||
this.genesisTimestamp = System.currentTimeMillis();
|
||||
} else {
|
||||
this.genesisTimestamp = ((Long) json.get("testnetstamp")).longValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isTestNet() {
|
||||
return this.genesisTimestamp != GenesisBlock.GENESIS_TIMESTAMP;
|
||||
}
|
||||
|
||||
// Getters / setters
|
||||
|
||||
public int getMaxBytePerFee() {
|
||||
return 1024;
|
||||
return this.maxBytePerFee;
|
||||
}
|
||||
|
||||
public long getGenesisTimestamp() {
|
||||
if (this.genesisTimestamp != -1)
|
||||
return this.genesisTimestamp;
|
||||
|
||||
return GenesisBlock.GENESIS_TIMESTAMP;
|
||||
}
|
||||
|
||||
public void setGenesisTimestamp(long timestamp) {
|
||||
this.genesisTimestamp = timestamp;
|
||||
}
|
||||
|
||||
public void unsetGenesisTimestamp() {
|
||||
this.genesisTimestamp = -1;
|
||||
return this.genesisTimestamp;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -15,15 +16,18 @@ import com.google.common.hash.HashCode;
|
||||
|
||||
import data.account.AccountBalanceData;
|
||||
import data.account.AccountData;
|
||||
import data.assets.AssetData;
|
||||
import data.block.BlockData;
|
||||
import data.naming.NameData;
|
||||
import data.transaction.BuyNameTransactionData;
|
||||
import data.transaction.CancelSellNameTransactionData;
|
||||
import data.transaction.CreatePollTransactionData;
|
||||
import data.transaction.IssueAssetTransactionData;
|
||||
import data.transaction.MessageTransactionData;
|
||||
import data.transaction.PaymentTransactionData;
|
||||
import data.transaction.RegisterNameTransactionData;
|
||||
import data.transaction.SellNameTransactionData;
|
||||
import data.transaction.TransferAssetTransactionData;
|
||||
import data.transaction.UpdateNameTransactionData;
|
||||
import data.transaction.VoteOnPollTransactionData;
|
||||
import data.voting.PollData;
|
||||
@ -38,15 +42,18 @@ import qora.block.BlockChain;
|
||||
import qora.transaction.BuyNameTransaction;
|
||||
import qora.transaction.CancelSellNameTransaction;
|
||||
import qora.transaction.CreatePollTransaction;
|
||||
import qora.transaction.IssueAssetTransaction;
|
||||
import qora.transaction.MessageTransaction;
|
||||
import qora.transaction.PaymentTransaction;
|
||||
import qora.transaction.RegisterNameTransaction;
|
||||
import qora.transaction.SellNameTransaction;
|
||||
import qora.transaction.Transaction;
|
||||
import qora.transaction.Transaction.ValidationResult;
|
||||
import qora.transaction.TransferAssetTransaction;
|
||||
import qora.transaction.UpdateNameTransaction;
|
||||
import qora.transaction.VoteOnPollTransaction;
|
||||
import repository.AccountRepository;
|
||||
import repository.AssetRepository;
|
||||
import repository.DataException;
|
||||
import repository.Repository;
|
||||
import repository.RepositoryFactory;
|
||||
@ -63,8 +70,8 @@ public class TransactionTests {
|
||||
private static final byte[] senderSeed = HashCode.fromString("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef").asBytes();
|
||||
private static final byte[] recipientSeed = HashCode.fromString("fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210").asBytes();
|
||||
|
||||
private static final BigDecimal generatorBalance = BigDecimal.valueOf(1_000_000_000L);
|
||||
private static final BigDecimal senderBalance = BigDecimal.valueOf(1_000_000L);
|
||||
private static final BigDecimal initialGeneratorBalance = BigDecimal.valueOf(1_000_000_000L);
|
||||
private static final BigDecimal initialSenderBalance = BigDecimal.valueOf(1_000_000L);
|
||||
|
||||
private Repository repository;
|
||||
private AccountRepository accountRepository;
|
||||
@ -73,6 +80,7 @@ public class TransactionTests {
|
||||
private PrivateKeyAccount generator;
|
||||
private byte[] reference;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void createTestAccounts(Long genesisTimestamp) throws DataException {
|
||||
RepositoryFactory repositoryFactory = new HSQLDBRepositoryFactory(connectionUrl);
|
||||
RepositoryManager.setRepositoryFactory(repositoryFactory);
|
||||
@ -82,10 +90,11 @@ public class TransactionTests {
|
||||
}
|
||||
|
||||
// [Un]set genesis timestamp as required by test
|
||||
JSONObject settingsJSON = new JSONObject();
|
||||
if (genesisTimestamp != null)
|
||||
Settings.getInstance().setGenesisTimestamp(genesisTimestamp);
|
||||
else
|
||||
Settings.getInstance().unsetGenesisTimestamp();
|
||||
settingsJSON.put("testnetstamp", genesisTimestamp);
|
||||
|
||||
Settings.test(settingsJSON);
|
||||
|
||||
// This needs to be called outside of acquiring our own repository or it will deadlock
|
||||
BlockChain.validate();
|
||||
@ -101,7 +110,7 @@ public class TransactionTests {
|
||||
// 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));
|
||||
accountRepository.save(new AccountBalanceData(generator.getAddress(), Asset.QORA, initialGeneratorBalance));
|
||||
|
||||
// Create test sender account
|
||||
sender = new PrivateKeyAccount(repository, senderSeed);
|
||||
@ -111,7 +120,7 @@ public class TransactionTests {
|
||||
accountRepository.save(new AccountData(sender.getAddress(), reference));
|
||||
|
||||
// Mock balance
|
||||
accountRepository.save(new AccountBalanceData(sender.getAddress(), Asset.QORA, senderBalance));
|
||||
accountRepository.save(new AccountBalanceData(sender.getAddress(), Asset.QORA, initialSenderBalance));
|
||||
|
||||
repository.saveChanges();
|
||||
}
|
||||
@ -163,12 +172,12 @@ public class TransactionTests {
|
||||
repository.saveChanges();
|
||||
|
||||
// Check sender's balance
|
||||
BigDecimal expectedBalance = senderBalance.subtract(amount).subtract(fee);
|
||||
BigDecimal expectedBalance = initialSenderBalance.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);
|
||||
expectedBalance = initialGeneratorBalance.add(fee);
|
||||
actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||
|
||||
@ -176,6 +185,22 @@ public class TransactionTests {
|
||||
expectedBalance = amount;
|
||||
actualBalance = accountRepository.getBalance(recipient.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Recipient's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||
|
||||
// Check recipient's reference
|
||||
byte[] recipientsReference = recipient.getLastReference();
|
||||
assertTrue("Recipient's new reference incorrect", Arrays.equals(paymentTransaction.getTransactionData().getSignature(), recipientsReference));
|
||||
|
||||
// Orphan block
|
||||
block.orphan();
|
||||
repository.saveChanges();
|
||||
|
||||
// Check sender's balance
|
||||
actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Sender's reverted balance incorrect", initialSenderBalance.compareTo(actualBalance) == 0);
|
||||
|
||||
// Check generator's balance
|
||||
actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Generator's new balance incorrect", initialGeneratorBalance.compareTo(actualBalance) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -208,12 +233,12 @@ public class TransactionTests {
|
||||
repository.saveChanges();
|
||||
|
||||
// Check sender's balance
|
||||
BigDecimal expectedBalance = senderBalance.subtract(fee);
|
||||
BigDecimal expectedBalance = initialSenderBalance.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);
|
||||
expectedBalance = initialGeneratorBalance.add(fee);
|
||||
actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||
|
||||
@ -445,7 +470,7 @@ public class TransactionTests {
|
||||
@Test
|
||||
public void testCreatePollTransaction() throws DataException {
|
||||
// This test requires GenesisBlock's timestamp is set to something after BlockChain.VOTING_RELEASE_TIMESTAMP
|
||||
createTestAccounts(BlockChain.VOTING_RELEASE_TIMESTAMP + 1_000L);
|
||||
createTestAccounts(BlockChain.getVotingReleaseTimestamp() + 1_000L);
|
||||
|
||||
// Make a new create poll transaction
|
||||
String pollName = "test poll";
|
||||
@ -479,12 +504,12 @@ public class TransactionTests {
|
||||
repository.saveChanges();
|
||||
|
||||
// Check sender's balance
|
||||
BigDecimal expectedBalance = senderBalance.subtract(fee);
|
||||
BigDecimal expectedBalance = initialSenderBalance.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);
|
||||
expectedBalance = initialGeneratorBalance.add(fee);
|
||||
actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||
|
||||
@ -575,12 +600,174 @@ public class TransactionTests {
|
||||
|
||||
@Test
|
||||
public void testIssueAssetTransaction() throws DataException {
|
||||
// TODO
|
||||
createTestAccounts(null);
|
||||
|
||||
// Create new asset
|
||||
String assetName = "test asset";
|
||||
String description = "test asset description";
|
||||
long quantity = 1_000_000L;
|
||||
boolean isDivisible = false;
|
||||
BigDecimal fee = BigDecimal.ONE;
|
||||
long timestamp = parentBlockData.getTimestamp() + 1_000;
|
||||
|
||||
IssueAssetTransactionData issueAssetTransactionData = new IssueAssetTransactionData(sender.getPublicKey(), sender.getAddress(), assetName, description,
|
||||
quantity, isDivisible, fee, timestamp, reference);
|
||||
|
||||
Transaction issueAssetTransaction = new IssueAssetTransaction(repository, issueAssetTransactionData);
|
||||
issueAssetTransaction.calcSignature(sender);
|
||||
assertTrue(issueAssetTransaction.isSignatureValid());
|
||||
assertEquals(ValidationResult.OK, issueAssetTransaction.isValid());
|
||||
|
||||
// Forge new block with payment transaction
|
||||
Block block = new Block(repository, parentBlockData, generator, null, null);
|
||||
block.addTransaction(issueAssetTransactionData);
|
||||
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 = initialSenderBalance.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 = initialGeneratorBalance.add(fee);
|
||||
actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||
|
||||
// Check we now have an assetId
|
||||
Long assetId = issueAssetTransactionData.getAssetId();
|
||||
assertNotNull(assetId);
|
||||
// Should NOT collide with Asset.QORA
|
||||
assertFalse(assetId == Asset.QORA);
|
||||
|
||||
// Check asset now exists
|
||||
AssetRepository assetRepo = this.repository.getAssetRepository();
|
||||
assertTrue(assetRepo.assetExists(assetId));
|
||||
assertTrue(assetRepo.assetExists(assetName));
|
||||
// Check asset data
|
||||
AssetData assetData = assetRepo.fromAssetId(assetId);
|
||||
assertNotNull(assetData);
|
||||
assertEquals(assetName, assetData.getName());
|
||||
assertEquals(description, assetData.getDescription());
|
||||
|
||||
// Orphan block
|
||||
block.orphan();
|
||||
repository.saveChanges();
|
||||
|
||||
// Check sender's balance
|
||||
actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Sender's reverted balance incorrect", initialSenderBalance.compareTo(actualBalance) == 0);
|
||||
|
||||
// Check generator's balance
|
||||
actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Generator's reverted balance incorrect", initialGeneratorBalance.compareTo(actualBalance) == 0);
|
||||
|
||||
// Check asset no longer exists
|
||||
assertFalse(assetRepo.assetExists(assetId));
|
||||
assertFalse(assetRepo.assetExists(assetName));
|
||||
assetData = assetRepo.fromAssetId(assetId);
|
||||
assertNull(assetData);
|
||||
|
||||
// Re-process block for use by other tests
|
||||
block.process();
|
||||
repository.saveChanges();
|
||||
|
||||
// Update variables for use by other tests
|
||||
reference = sender.getLastReference();
|
||||
parentBlockData = block.getBlockData();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransferAssetTransaction() throws DataException {
|
||||
// TODO
|
||||
// Issue asset using another test
|
||||
testIssueAssetTransaction();
|
||||
|
||||
String assetName = "test asset";
|
||||
AssetRepository assetRepo = this.repository.getAssetRepository();
|
||||
AssetData originalAssetData = assetRepo.fromAssetName(assetName);
|
||||
long assetId = originalAssetData.getAssetId();
|
||||
BigDecimal originalSenderBalance = sender.getConfirmedBalance(Asset.QORA);
|
||||
BigDecimal originalGeneratorBalance = generator.getConfirmedBalance(Asset.QORA);
|
||||
|
||||
// Transfer asset to new recipient
|
||||
Account recipient = new PublicKeyAccount(repository, recipientSeed);
|
||||
BigDecimal amount = BigDecimal.valueOf(1_000L).setScale(8);
|
||||
BigDecimal fee = BigDecimal.ONE;
|
||||
long timestamp = parentBlockData.getTimestamp() + 1_000;
|
||||
|
||||
TransferAssetTransactionData transferAssetTransactionData = new TransferAssetTransactionData(sender.getPublicKey(), recipient.getAddress(), amount,
|
||||
assetId, fee, timestamp, reference);
|
||||
|
||||
Transaction transferAssetTransaction = new TransferAssetTransaction(repository, transferAssetTransactionData);
|
||||
transferAssetTransaction.calcSignature(sender);
|
||||
assertTrue(transferAssetTransaction.isSignatureValid());
|
||||
assertEquals(ValidationResult.OK, transferAssetTransaction.isValid());
|
||||
|
||||
// Forge new block with payment transaction
|
||||
Block block = new Block(repository, parentBlockData, generator, null, null);
|
||||
block.addTransaction(transferAssetTransactionData);
|
||||
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 = originalSenderBalance.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 = originalGeneratorBalance.add(fee);
|
||||
actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||
|
||||
// Check asset balances
|
||||
BigDecimal actualSenderAssetBalance = sender.getConfirmedBalance(assetId);
|
||||
assertNotNull(actualSenderAssetBalance);
|
||||
BigDecimal expectedSenderAssetBalance = BigDecimal.valueOf(originalAssetData.getQuantity()).setScale(8).subtract(amount);
|
||||
assertEquals(expectedSenderAssetBalance, actualSenderAssetBalance);
|
||||
|
||||
BigDecimal actualRecipientAssetBalance = recipient.getConfirmedBalance(assetId);
|
||||
assertNotNull(actualRecipientAssetBalance);
|
||||
assertEquals(amount, actualRecipientAssetBalance);
|
||||
|
||||
// Orphan block
|
||||
block.orphan();
|
||||
repository.saveChanges();
|
||||
|
||||
// Check sender's balance
|
||||
actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Sender's reverted balance incorrect", originalSenderBalance.compareTo(actualBalance) == 0);
|
||||
|
||||
// Check generator's balance
|
||||
actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Generator's reverted balance incorrect", originalGeneratorBalance.compareTo(actualBalance) == 0);
|
||||
|
||||
// Check asset balances
|
||||
actualSenderAssetBalance = sender.getConfirmedBalance(assetId);
|
||||
assertNotNull(actualSenderAssetBalance);
|
||||
expectedSenderAssetBalance = BigDecimal.valueOf(originalAssetData.getQuantity()).setScale(8);
|
||||
assertEquals(expectedSenderAssetBalance, actualSenderAssetBalance);
|
||||
|
||||
actualRecipientAssetBalance = recipient.getConfirmedBalance(assetId);
|
||||
if (actualRecipientAssetBalance != null)
|
||||
assertEquals(BigDecimal.ZERO.setScale(8), actualRecipientAssetBalance);
|
||||
|
||||
// Re-process block for use by other tests
|
||||
block.process();
|
||||
repository.saveChanges();
|
||||
|
||||
// Update variables for use by other tests
|
||||
reference = sender.getLastReference();
|
||||
parentBlockData = block.getBlockData();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -600,7 +787,7 @@ public class TransactionTests {
|
||||
|
||||
@Test
|
||||
public void testMessageTransaction() throws DataException, UnsupportedEncodingException {
|
||||
createTestAccounts(null);
|
||||
createTestAccounts(1431861220336L); // timestamp taken from main blockchain block 99000
|
||||
|
||||
// Make a new message transaction
|
||||
Account recipient = new PublicKeyAccount(repository, recipientSeed);
|
||||
@ -632,12 +819,12 @@ public class TransactionTests {
|
||||
repository.saveChanges();
|
||||
|
||||
// Check sender's balance
|
||||
BigDecimal expectedBalance = senderBalance.subtract(amount).subtract(fee);
|
||||
BigDecimal expectedBalance = initialSenderBalance.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);
|
||||
expectedBalance = initialGeneratorBalance.add(fee);
|
||||
actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance();
|
||||
assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user