From 54d49e0f1da44e817b83f57be7a6f2e23a8565f6 Mon Sep 17 00:00:00 2001 From: catbref Date: Tue, 8 Oct 2019 14:58:00 +0100 Subject: [PATCH] More work on block rewards in relation to account level/legacy qora held. Rename Asset.QORA to Asset.QORT so we can also have Asset.LEGACY_QORA as another hard-coded asset. Add "is unspendable" aspect to assets where only the asset owner can transfer/pay asset to other people. Asset trading is barred regardless, as is use of asset for ATs. Added "initial level" to account data in preparation for accounts levelling up from generating blocks. Added distribution/removal of block reward based on legacy-QORA held. Removed "previous level" from ACCOUNT_LEVEL transactions as they're only ever valid in genesis block and so previous level is never needed. --- src/main/java/org/qora/account/Account.java | 7 ++ .../qora/api/resource/AddressesResource.java | 2 +- .../org/qora/api/resource/AssetsResource.java | 4 +- src/main/java/org/qora/asset/Asset.java | 8 +- src/main/java/org/qora/at/AT.java | 2 +- src/main/java/org/qora/at/QoraATAPI.java | 2 +- src/main/java/org/qora/block/Block.java | 46 +++++++++-- src/main/java/org/qora/block/BlockChain.java | 10 +++ .../java/org/qora/block/GenesisBlock.java | 2 +- .../org/qora/data/account/AccountData.java | 14 +++- .../java/org/qora/data/asset/AssetData.java | 12 ++- .../transaction/GenesisTransactionData.java | 2 +- .../IssueAssetTransactionData.java | 14 +++- .../transaction/MessageTransactionData.java | 2 +- src/main/java/org/qora/naming/Name.java | 8 +- src/main/java/org/qora/payment/Payment.java | 18 +++-- .../qora/repository/AccountRepository.java | 7 ++ .../hsqldb/HSQLDBAccountRepository.java | 25 +++++- .../hsqldb/HSQLDBAssetRepository.java | 32 ++++---- .../hsqldb/HSQLDBDatabaseUpdates.java | 9 ++- ...HSQLDBIssueAssetTransactionRepository.java | 11 +-- .../transaction/AccountFlagsTransaction.java | 2 +- .../transaction/AccountLevelTransaction.java | 24 ++---- .../transaction/AddGroupAdminTransaction.java | 2 +- .../transaction/ArbitraryTransaction.java | 2 +- .../org/qora/transaction/AtTransaction.java | 8 +- .../qora/transaction/BuyNameTransaction.java | 2 +- .../CancelAssetOrderTransaction.java | 2 +- .../CancelGroupBanTransaction.java | 2 +- .../CancelGroupInviteTransaction.java | 2 +- .../CancelSellNameTransaction.java | 2 +- .../CreateAssetOrderTransaction.java | 10 ++- .../transaction/CreateGroupTransaction.java | 2 +- .../transaction/CreatePollTransaction.java | 2 +- .../qora/transaction/DeployAtTransaction.java | 16 ++-- .../transaction/EnableForgingTransaction.java | 2 +- .../qora/transaction/GenesisTransaction.java | 2 +- .../transaction/GroupApprovalTransaction.java | 2 +- .../qora/transaction/GroupBanTransaction.java | 2 +- .../transaction/GroupInviteTransaction.java | 2 +- .../transaction/GroupKickTransaction.java | 2 +- .../transaction/IssueAssetTransaction.java | 2 +- .../transaction/JoinGroupTransaction.java | 2 +- .../transaction/LeaveGroupTransaction.java | 2 +- .../qora/transaction/MessageTransaction.java | 2 +- .../transaction/MultiPaymentTransaction.java | 4 +- .../qora/transaction/PaymentTransaction.java | 2 +- .../transaction/ProxyForgingTransaction.java | 2 +- .../transaction/RegisterNameTransaction.java | 2 +- .../RemoveGroupAdminTransaction.java | 2 +- .../qora/transaction/SellNameTransaction.java | 2 +- .../qora/transaction/SetGroupTransaction.java | 2 +- .../org/qora/transaction/Transaction.java | 5 +- .../transaction/TransferAssetTransaction.java | 2 +- .../transaction/UpdateAssetTransaction.java | 2 +- .../transaction/UpdateGroupTransaction.java | 2 +- .../transaction/UpdateNameTransaction.java | 2 +- .../transaction/VoteOnPollTransaction.java | 2 +- .../DeployAtTransactionTransformer.java | 2 +- .../GenesisTransactionTransformer.java | 2 +- .../IssueAssetTransactionTransformer.java | 47 +++++------ .../MessageTransactionTransformer.java | 2 +- .../java/org/qora/test/RepositoryTests.java | 4 +- .../java/org/qora/test/TransactionTests.java | 79 ++++++++++--------- .../java/org/qora/test/common/AssetUtils.java | 2 +- .../transaction/ArbitraryTestTransaction.java | 2 +- .../common/transaction/AtTestTransaction.java | 2 +- .../CreateAssetOrderTestTransaction.java | 2 +- .../transaction/DeployAtTestTransaction.java | 2 +- .../IssueAssetTestTransaction.java | 3 +- .../transaction/MessageTestTransaction.java | 2 +- .../MultiPaymentTestTransaction.java | 2 +- .../TransferAssetTestTransaction.java | 2 +- .../org/qora/test/forging/RewardTests.java | 18 ++--- .../qora/test/group/GroupApprovalTests.java | 12 +-- 75 files changed, 339 insertions(+), 212 deletions(-) diff --git a/src/main/java/org/qora/account/Account.java b/src/main/java/org/qora/account/Account.java index 28e8b2b1..17c0cf37 100644 --- a/src/main/java/org/qora/account/Account.java +++ b/src/main/java/org/qora/account/Account.java @@ -233,4 +233,11 @@ public class Account { this.repository.getAccountRepository().setLevel(accountData); } + public void setInitialLevel(int level) throws DataException { + AccountData accountData = this.buildAccountData(); + accountData.setLevel(level); + accountData.setInitialLevel(level); + this.repository.getAccountRepository().setInitialLevel(accountData); + } + } diff --git a/src/main/java/org/qora/api/resource/AddressesResource.java b/src/main/java/org/qora/api/resource/AddressesResource.java index 92eb4f0b..d3783501 100644 --- a/src/main/java/org/qora/api/resource/AddressesResource.java +++ b/src/main/java/org/qora/api/resource/AddressesResource.java @@ -207,7 +207,7 @@ public class AddressesResource { try (final Repository repository = RepositoryManager.getRepository()) { Account account = new Account(repository, address); - return account.getConfirmedBalance(Asset.QORA); + return account.getConfirmedBalance(Asset.QORT); } catch (ApiException e) { throw e; } catch (DataException e) { diff --git a/src/main/java/org/qora/api/resource/AssetsResource.java b/src/main/java/org/qora/api/resource/AssetsResource.java index 6e698493..6b3577bf 100644 --- a/src/main/java/org/qora/api/resource/AssetsResource.java +++ b/src/main/java/org/qora/api/resource/AssetsResource.java @@ -318,14 +318,14 @@ public class AssetsResource { ) @QueryParam("reverse") Boolean reverse) { try (final Repository repository = RepositoryManager.getRepository()) { if (assetIds.isEmpty()) - assetIds = Collections.singletonList(Asset.QORA); + assetIds = Collections.singletonList(Asset.QORT); else for (long assetId : assetIds) if (!repository.getAssetRepository().assetExists(assetId)) throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ASSET_ID); if (otherAssetIds.isEmpty()) - otherAssetIds = Collections.singletonList(Asset.QORA); + otherAssetIds = Collections.singletonList(Asset.QORT); else for (long assetId : otherAssetIds) if (!repository.getAssetRepository().assetExists(assetId)) diff --git a/src/main/java/org/qora/asset/Asset.java b/src/main/java/org/qora/asset/Asset.java index cae5fe01..5afbd122 100644 --- a/src/main/java/org/qora/asset/Asset.java +++ b/src/main/java/org/qora/asset/Asset.java @@ -10,9 +10,12 @@ import org.qora.repository.Repository; public class Asset { /** - * QORA coins are just another asset but with fixed assetId of zero. + * QORT coins are just another asset but with fixed assetId of zero. */ - public static final long QORA = 0L; + public static final long QORT = 0L; + + /** Hard-coded asset representing legacy QORA held in old QORA1 blockchain. */ + public static final long LEGACY_QORA = 1L; // Other useful constants @@ -41,6 +44,7 @@ public class Asset { this.assetData = new AssetData(issueAssetTransactionData.getOwner(), issueAssetTransactionData.getAssetName(), issueAssetTransactionData.getDescription(), issueAssetTransactionData.getQuantity(), issueAssetTransactionData.getIsDivisible(), issueAssetTransactionData.getData(), + issueAssetTransactionData.getIsUnspendable(), issueAssetTransactionData.getTxGroupId(), issueAssetTransactionData.getSignature()); } diff --git a/src/main/java/org/qora/at/AT.java b/src/main/java/org/qora/at/AT.java index e8ec2425..2051f215 100644 --- a/src/main/java/org/qora/at/AT.java +++ b/src/main/java/org/qora/at/AT.java @@ -97,7 +97,7 @@ public class AT { boolean isFrozen = false; Long frozenBalance = null; - this.atData = new ATData(atAddress, creatorPublicKey, creation, version, Asset.QORA, codeBytes, isSleeping, sleepUntilHeight, isFinished, + this.atData = new ATData(atAddress, creatorPublicKey, creation, version, Asset.QORT, codeBytes, isSleeping, sleepUntilHeight, isFinished, hadFatalError, isFrozen, frozenBalance); this.atStateData = new ATStateData(atAddress, height, creation, null, null, BigDecimal.ZERO.setScale(8)); diff --git a/src/main/java/org/qora/at/QoraATAPI.java b/src/main/java/org/qora/at/QoraATAPI.java index f0cdd69f..dd923083 100644 --- a/src/main/java/org/qora/at/QoraATAPI.java +++ b/src/main/java/org/qora/at/QoraATAPI.java @@ -254,7 +254,7 @@ public class QoraATAPI extends API { try { Account atAccount = this.getATAccount(); - return atAccount.getConfirmedBalance(Asset.QORA).unscaledValue().longValue(); + return atAccount.getConfirmedBalance(Asset.QORT).unscaledValue().longValue(); } catch (DataException e) { throw new RuntimeException("AT API unable to fetch AT's current balance?", e); } diff --git a/src/main/java/org/qora/block/Block.java b/src/main/java/org/qora/block/Block.java index 852818b9..0e01bb2d 100644 --- a/src/main/java/org/qora/block/Block.java +++ b/src/main/java/org/qora/block/Block.java @@ -26,6 +26,7 @@ import org.qora.block.BlockChain.BlockTimingByHeight; import org.qora.block.BlockChain.ShareByLevel; import org.qora.controller.Controller; import org.qora.crypto.Crypto; +import org.qora.data.account.AccountBalanceData; import org.qora.data.account.ProxyForgerData; import org.qora.data.at.ATData; import org.qora.data.at.ATStateData; @@ -1193,7 +1194,7 @@ public class Block { Account atAccount = new Account(this.repository, atState.getATAddress()); // Subtract AT-generated fees from AT accounts - atAccount.setConfirmedBalance(Asset.QORA, atAccount.getConfirmedBalance(Asset.QORA).subtract(atState.getFees())); + atAccount.setConfirmedBalance(Asset.QORT, atAccount.getConfirmedBalance(Asset.QORT).subtract(atState.getFees())); atRepository.save(atState); } @@ -1341,7 +1342,7 @@ public class Block { Account atAccount = new Account(this.repository, atState.getATAddress()); // Return AT-generated fees to AT accounts - atAccount.setConfirmedBalance(Asset.QORA, atAccount.getConfirmedBalance(Asset.QORA).add(atState.getFees())); + atAccount.setConfirmedBalance(Asset.QORT, atAccount.getConfirmedBalance(Asset.QORT).add(atState.getFees())); } // Delete ATStateData for this height @@ -1359,6 +1360,7 @@ public class Block { final boolean isFounder; final int level; final int shareBin; + final BigDecimal qoraAmount; final Account recipientAccount; AccountInfo(Repository repository, int accountIndex, List sharesByLevel) throws DataException { @@ -1367,6 +1369,12 @@ public class Block { this.forgerAccount = new PublicKeyAccount(repository, this.proxyForgerData.getForgerPublicKey()); this.recipientAccount = new Account(repository, this.proxyForgerData.getRecipient()); + AccountBalanceData qoraBalanceData = repository.getAccountRepository().getBalance(this.forgerAccount.getAddress(), Asset.LEGACY_QORA); + if (qoraBalanceData != null && qoraBalanceData.getBalance() != null && qoraBalanceData.getBalance().compareTo(BigDecimal.ZERO) > 0) + this.qoraAmount = qoraBalanceData.getBalance(); + else + this.qoraAmount = null; + if (this.forgerAccount.isFounder()) { this.isFounder = true; this.level = 0; @@ -1395,17 +1403,17 @@ public class Block { if (forgerAccount.getAddress().equals(recipientAccount.getAddress())) { // forger & recipient the same - simpler case LOGGER.trace(() -> String.format("Forger/recipient account %s share: %s", forgerAccount.getAddress(), accountAmount.toPlainString())); - forgerAccount.setConfirmedBalance(Asset.QORA, forgerAccount.getConfirmedBalance(Asset.QORA).add(accountAmount)); + forgerAccount.setConfirmedBalance(Asset.QORT, forgerAccount.getConfirmedBalance(Asset.QORT).add(accountAmount)); } else { // forger & recipient different - extra work needed BigDecimal recipientAmount = accountAmount.multiply(this.proxyForgerData.getShare()).divide(ONE_HUNDRED, RoundingMode.DOWN); BigDecimal forgerAmount = accountAmount.subtract(recipientAmount); LOGGER.trace(() -> String.format("Forger account %s share: %s", forgerAccount.getAddress(), forgerAmount.toPlainString())); - forgerAccount.setConfirmedBalance(Asset.QORA, forgerAccount.getConfirmedBalance(Asset.QORA).add(forgerAmount)); + forgerAccount.setConfirmedBalance(Asset.QORT, forgerAccount.getConfirmedBalance(Asset.QORT).add(forgerAmount)); LOGGER.trace(() -> String.format("Recipient account %s share: %s", recipientAccount.getAddress(), recipientAmount.toPlainString())); - recipientAccount.setConfirmedBalance(Asset.QORA, recipientAccount.getConfirmedBalance(Asset.QORA).add(recipientAmount)); + recipientAccount.setConfirmedBalance(Asset.QORT, recipientAccount.getConfirmedBalance(Asset.QORT).add(recipientAmount)); } } } @@ -1445,6 +1453,34 @@ public class Block { } } + // Distribute share across legacy QORA holders + BigDecimal qoraHoldersAmount = BlockChain.getInstance().getQoraHoldersShare().multiply(totalAmount).setScale(8, RoundingMode.DOWN); + LOGGER.trace(() -> String.format("Legacy QORA holders share of %s: %s", totalAmount.toPlainString(), qoraHoldersAmount.toPlainString())); + + List qoraHolderAccounts = new ArrayList<>(); + BigDecimal totalQoraHeld = BigDecimal.ZERO; + for (int i = 0; i < expandedAccounts.size(); ++i) { + AccountInfo accountInfo = expandedAccounts.get(i); + if (accountInfo.qoraAmount == null) + continue; + + qoraHolderAccounts.add(accountInfo); + totalQoraHeld = totalQoraHeld.add(accountInfo.qoraAmount); + } + + final BigDecimal finalTotalQoraHeld = totalQoraHeld; + LOGGER.trace(() -> String.format("Total legacy QORA held: %s", finalTotalQoraHeld.toPlainString())); + + for (int h = 0; h < qoraHolderAccounts.size(); ++h) { + AccountInfo accountInfo = qoraHolderAccounts.get(h); + final BigDecimal holderAmount = qoraHoldersAmount.multiply(totalQoraHeld).divide(accountInfo.qoraAmount, RoundingMode.DOWN); + LOGGER.trace(() -> String.format("Forger account %s has %s / %s QORA so share: %s", + accountInfo.forgerAccount.getAddress(), accountInfo.qoraAmount, finalTotalQoraHeld, holderAmount.toPlainString())); + + accountInfo.distribute(holderAmount); + sharedAmount = sharedAmount.add(holderAmount); + } + // Spread remainder across founder accounts BigDecimal foundersAmount = totalAmount.subtract(sharedAmount); LOGGER.debug(String.format("Shared %s of %s, remaining %s to founders", sharedAmount.toPlainString(), totalAmount.toPlainString(), foundersAmount.toPlainString())); diff --git a/src/main/java/org/qora/block/BlockChain.java b/src/main/java/org/qora/block/BlockChain.java index 1d744be2..3faa3dff 100644 --- a/src/main/java/org/qora/block/BlockChain.java +++ b/src/main/java/org/qora/block/BlockChain.java @@ -106,6 +106,9 @@ public class BlockChain { } List sharesByLevel; + /** Share of block reward/fees to legacy QORA coin holders */ + BigDecimal qoraHoldersShare; + /** Block times by block height */ public static class BlockTimingByHeight { public int height; @@ -284,6 +287,10 @@ public class BlockChain { return this.sharesByLevel; } + public BigDecimal getQoraHoldersShare() { + return this.qoraHoldersShare; + } + public List getForgingTiers() { return this.forgingTiers; } @@ -368,6 +375,9 @@ public class BlockChain { if (this.sharesByLevel == null) Settings.throwValidationError("No \"sharesByLevel\" entry found in blockchain config"); + if (this.qoraHoldersShare == null) + Settings.throwValidationError("No \"qoraHoldersShare\" entry found in blockchain config"); + if (this.blockTimingsByHeight == null) Settings.throwValidationError("No \"blockTimingsByHeight\" entry found in blockchain config"); diff --git a/src/main/java/org/qora/block/GenesisBlock.java b/src/main/java/org/qora/block/GenesisBlock.java index 7a9c723a..770d8eba 100644 --- a/src/main/java/org/qora/block/GenesisBlock.java +++ b/src/main/java/org/qora/block/GenesisBlock.java @@ -118,7 +118,7 @@ public class GenesisBlock extends Block { IssueAssetTransactionData issueAssetTransactionData = (IssueAssetTransactionData) transactionData; return new AssetData(issueAssetTransactionData.getOwner(), issueAssetTransactionData.getAssetName(), issueAssetTransactionData.getDescription(), - issueAssetTransactionData.getQuantity(), issueAssetTransactionData.getIsDivisible(), "", Group.NO_GROUP, issueAssetTransactionData.getReference()); + issueAssetTransactionData.getQuantity(), issueAssetTransactionData.getIsDivisible(), "", false, Group.NO_GROUP, issueAssetTransactionData.getReference()); }).collect(Collectors.toList()); } diff --git a/src/main/java/org/qora/data/account/AccountData.java b/src/main/java/org/qora/data/account/AccountData.java index 2d21806f..fd3d89d8 100644 --- a/src/main/java/org/qora/data/account/AccountData.java +++ b/src/main/java/org/qora/data/account/AccountData.java @@ -16,6 +16,7 @@ public class AccountData { protected int defaultGroupId; protected int flags; protected String forgingEnabler; + protected int initialLevel; protected int level; // Constructors @@ -24,18 +25,19 @@ public class AccountData { protected AccountData() { } - public AccountData(String address, byte[] reference, byte[] publicKey, int defaultGroupId, int flags, String forgingEnabler, int level) { + public AccountData(String address, byte[] reference, byte[] publicKey, int defaultGroupId, int flags, String forgingEnabler, int initialLevel, int level) { this.address = address; this.reference = reference; this.publicKey = publicKey; this.defaultGroupId = defaultGroupId; this.flags = flags; this.forgingEnabler = forgingEnabler; + this.initialLevel = initialLevel; this.level = level; } public AccountData(String address) { - this(address, null, null, Group.NO_GROUP, 0, null, 0); + this(address, null, null, Group.NO_GROUP, 0, null, 0, 0); } // Getters/Setters @@ -84,6 +86,14 @@ public class AccountData { this.forgingEnabler = forgingEnabler; } + public int getInitialLevel() { + return this.initialLevel; + } + + public void setInitialLevel(int level) { + this.initialLevel = level; + } + public int getLevel() { return this.level; } diff --git a/src/main/java/org/qora/data/asset/AssetData.java b/src/main/java/org/qora/data/asset/AssetData.java index 341d8243..f38859da 100644 --- a/src/main/java/org/qora/data/asset/AssetData.java +++ b/src/main/java/org/qora/data/asset/AssetData.java @@ -18,6 +18,7 @@ public class AssetData { private long quantity; private boolean isDivisible; private String data; + private boolean isUnspendable; private int creationGroupId; // No need to expose this via API @XmlTransient @@ -31,7 +32,7 @@ public class AssetData { } // NOTE: key is Long, not long, because it can be null if asset ID/key not yet assigned. - public AssetData(Long assetId, String owner, String name, String description, long quantity, boolean isDivisible, String data, int creationGroupId, byte[] reference) { + public AssetData(Long assetId, String owner, String name, String description, long quantity, boolean isDivisible, String data, boolean isUnspendable, int creationGroupId, byte[] reference) { this.assetId = assetId; this.owner = owner; this.name = name; @@ -39,13 +40,14 @@ public class AssetData { this.quantity = quantity; this.isDivisible = isDivisible; this.data = data; + this.isUnspendable = isUnspendable; this.creationGroupId = creationGroupId; this.reference = reference; } // New asset with unassigned assetId - public AssetData(String owner, String name, String description, long quantity, boolean isDivisible, String data, int creationGroupId, byte[] reference) { - this(null, owner, name, description, quantity, isDivisible, data, creationGroupId, reference); + public AssetData(String owner, String name, String description, long quantity, boolean isDivisible, String data, boolean isUnspendable, int creationGroupId, byte[] reference) { + this(null, owner, name, description, quantity, isDivisible, data, isUnspendable, creationGroupId, reference); } // Getters/Setters @@ -94,6 +96,10 @@ public class AssetData { this.data = data; } + public boolean getIsUnspendable() { + return this.isUnspendable; + } + public int getCreationGroupId() { return this.creationGroupId; } diff --git a/src/main/java/org/qora/data/transaction/GenesisTransactionData.java b/src/main/java/org/qora/data/transaction/GenesisTransactionData.java index f938f572..83302b5e 100644 --- a/src/main/java/org/qora/data/transaction/GenesisTransactionData.java +++ b/src/main/java/org/qora/data/transaction/GenesisTransactionData.java @@ -47,7 +47,7 @@ public class GenesisTransactionData extends TransactionData { /** From repository (V1, where asset locked to QORA) */ public GenesisTransactionData(BaseTransactionData baseTransactionData, String recipient, BigDecimal amount) { - this(baseTransactionData, recipient, amount, Asset.QORA); + this(baseTransactionData, recipient, amount, Asset.QORT); } // Getters/Setters diff --git a/src/main/java/org/qora/data/transaction/IssueAssetTransactionData.java b/src/main/java/org/qora/data/transaction/IssueAssetTransactionData.java index 37bf80ba..1f6c0d94 100644 --- a/src/main/java/org/qora/data/transaction/IssueAssetTransactionData.java +++ b/src/main/java/org/qora/data/transaction/IssueAssetTransactionData.java @@ -37,6 +37,8 @@ public class IssueAssetTransactionData extends TransactionData { private boolean isDivisible; @Schema(description = "non-human-readable asset-related data, typically JSON", example = "{\"logo\": \"data:image/jpeg;base64,/9j/4AAQSkZJRgA==\"}") private String data; + @Schema(description = "whether non-owner holders of asset are barred from using asset", example = "false") + private boolean isUnspendable; // Constructors @@ -59,7 +61,7 @@ public class IssueAssetTransactionData extends TransactionData { /** From repository */ public IssueAssetTransactionData(BaseTransactionData baseTransactionData, - Long assetId, String owner, String assetName, String description, long quantity, boolean isDivisible, String data) { + Long assetId, String owner, String assetName, String description, long quantity, boolean isDivisible, String data, boolean isUnspendable) { super(TransactionType.ISSUE_ASSET, baseTransactionData); this.assetId = assetId; @@ -70,11 +72,13 @@ public class IssueAssetTransactionData extends TransactionData { this.quantity = quantity; this.isDivisible = isDivisible; this.data = data; + this.isUnspendable = isUnspendable; } /** From network/API */ - public IssueAssetTransactionData(BaseTransactionData baseTransactionData, String owner, String assetName, String description, long quantity, boolean isDivisible, String data) { - this(baseTransactionData, null, owner, assetName, description, quantity, isDivisible, data); + public IssueAssetTransactionData(BaseTransactionData baseTransactionData, String owner, String assetName, String description, + long quantity, boolean isDivisible, String data, boolean isUnspendable) { + this(baseTransactionData, null, owner, assetName, description, quantity, isDivisible, data, isUnspendable); } // Getters/Setters @@ -119,4 +123,8 @@ public class IssueAssetTransactionData extends TransactionData { return this.data; } + public boolean getIsUnspendable() { + return this.isUnspendable; + } + } diff --git a/src/main/java/org/qora/data/transaction/MessageTransactionData.java b/src/main/java/org/qora/data/transaction/MessageTransactionData.java index 1a00fbfa..db5f3e08 100644 --- a/src/main/java/org/qora/data/transaction/MessageTransactionData.java +++ b/src/main/java/org/qora/data/transaction/MessageTransactionData.java @@ -48,7 +48,7 @@ public class MessageTransactionData extends TransactionData { if (assetId != null) this.assetId = assetId; else - this.assetId = Asset.QORA; + this.assetId = Asset.QORT; this.amount = amount; this.data = data; diff --git a/src/main/java/org/qora/naming/Name.java b/src/main/java/org/qora/naming/Name.java index 5ffbf01a..2741258c 100644 --- a/src/main/java/org/qora/naming/Name.java +++ b/src/main/java/org/qora/naming/Name.java @@ -158,13 +158,13 @@ public class Name { // Update seller's balance Account seller = new Account(this.repository, this.nameData.getOwner()); - seller.setConfirmedBalance(Asset.QORA, seller.getConfirmedBalance(Asset.QORA).add(buyNameTransactionData.getAmount())); + seller.setConfirmedBalance(Asset.QORT, seller.getConfirmedBalance(Asset.QORT).add(buyNameTransactionData.getAmount())); // Set new owner Account buyer = new PublicKeyAccount(this.repository, buyNameTransactionData.getBuyerPublicKey()); this.nameData.setOwner(buyer.getAddress()); // Update buyer's balance - buyer.setConfirmedBalance(Asset.QORA, buyer.getConfirmedBalance(Asset.QORA).subtract(buyNameTransactionData.getAmount())); + buyer.setConfirmedBalance(Asset.QORT, buyer.getConfirmedBalance(Asset.QORT).subtract(buyNameTransactionData.getAmount())); // Update reference in transaction data buyNameTransactionData.setNameReference(this.nameData.getReference()); @@ -189,14 +189,14 @@ public class Name { // Revert buyer's balance Account buyer = new PublicKeyAccount(this.repository, buyNameTransactionData.getBuyerPublicKey()); - buyer.setConfirmedBalance(Asset.QORA, buyer.getConfirmedBalance(Asset.QORA).add(buyNameTransactionData.getAmount())); + buyer.setConfirmedBalance(Asset.QORT, buyer.getConfirmedBalance(Asset.QORT).add(buyNameTransactionData.getAmount())); // Previous Name's owner and/or data taken from referenced transaction this.revert(); // Revert seller's balance Account seller = new Account(this.repository, this.nameData.getOwner()); - seller.setConfirmedBalance(Asset.QORA, seller.getConfirmedBalance(Asset.QORA).subtract(buyNameTransactionData.getAmount())); + seller.setConfirmedBalance(Asset.QORT, seller.getConfirmedBalance(Asset.QORT).subtract(buyNameTransactionData.getAmount())); // Save reverted name data this.repository.getNameRepository().save(this.nameData); diff --git a/src/main/java/org/qora/payment/Payment.java b/src/main/java/org/qora/payment/Payment.java index ee40dfa2..5c506e4e 100644 --- a/src/main/java/org/qora/payment/Payment.java +++ b/src/main/java/org/qora/payment/Payment.java @@ -47,7 +47,10 @@ public class Payment { // Total up payment amounts by assetId Map amountsByAssetId = new HashMap(); // Add transaction fee to start with - amountsByAssetId.put(Asset.QORA, fee); + amountsByAssetId.put(Asset.QORT, fee); + + // Grab sender info + Account sender = new PublicKeyAccount(this.repository, senderPublicKey); // Check payments, and calculate amount total by assetId for (PaymentData paymentData : payments) { @@ -82,6 +85,10 @@ public class Payment { if (assetData == null) return ValidationResult.ASSET_DOES_NOT_EXIST; + // Do not allow non-owner asset holders to use asset + if (assetData.getIsUnspendable() && !assetData.getOwner().equals(sender.getAddress())) + return ValidationResult.ASSET_NOT_SPENDABLE; + // If we're sending to an AT then assetId must match AT's assetId if (atData != null && atData.getAssetId() != paymentData.getAssetId()) return ValidationResult.ASSET_DOES_NOT_MATCH_AT; @@ -95,7 +102,6 @@ public class Payment { } // Check sender has enough of each asset - Account sender = new PublicKeyAccount(this.repository, senderPublicKey); for (Entry pair : amountsByAssetId.entrySet()) if (sender.getConfirmedBalance(pair.getKey()).compareTo(pair.getValue()) < 0) return ValidationResult.NO_BALANCE; @@ -177,7 +183,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.QORT, sender.getConfirmedBalance(Asset.QORT).subtract(fee)); // Update sender's reference sender.setLastReference(signature); @@ -189,7 +195,7 @@ public class Payment { long assetId = paymentData.getAssetId(); // For QORA amounts only: if recipient has no reference yet, then this is their starting reference - if ((alwaysInitializeRecipientReference || assetId == Asset.QORA) && recipient.getLastReference() == null) + if ((alwaysInitializeRecipientReference || assetId == Asset.QORT) && recipient.getLastReference() == null) recipient.setLastReference(signature); } } @@ -230,7 +236,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).add(fee)); + sender.setConfirmedBalance(Asset.QORT, sender.getConfirmedBalance(Asset.QORT).add(fee)); // Update sender's reference sender.setLastReference(reference); @@ -244,7 +250,7 @@ public class Payment { * For QORA amounts only: If recipient's last reference is this transaction's signature, then they can't have made any transactions of their own * (which would have changed their last reference) thus this is their first reference so remove it. */ - if ((alwaysUninitializeRecipientReference || assetId == Asset.QORA) && Arrays.equals(recipient.getLastReference(), signature)) + if ((alwaysUninitializeRecipientReference || assetId == Asset.QORT) && Arrays.equals(recipient.getLastReference(), signature)) recipient.setLastReference(null); } } diff --git a/src/main/java/org/qora/repository/AccountRepository.java b/src/main/java/org/qora/repository/AccountRepository.java index 01937b5a..730b5b03 100644 --- a/src/main/java/org/qora/repository/AccountRepository.java +++ b/src/main/java/org/qora/repository/AccountRepository.java @@ -67,6 +67,13 @@ public interface AccountRepository { */ public void setLevel(AccountData accountData) throws DataException; + /** + * Saves account's initial & current level, and public key if present, in repository. + *

+ * Note: ignores other fields like last reference, default groupID. + */ + public void setInitialLevel(AccountData accountData) throws DataException; + /** * Saves account's forging enabler, and public key if present, in repository. *

diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBAccountRepository.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBAccountRepository.java index a2dc6237..c748541d 100644 --- a/src/main/java/org/qora/repository/hsqldb/HSQLDBAccountRepository.java +++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBAccountRepository.java @@ -26,7 +26,7 @@ public class HSQLDBAccountRepository implements AccountRepository { @Override public AccountData getAccount(String address) throws DataException { - String sql = "SELECT reference, public_key, default_group_id, flags, forging_enabler, level FROM Accounts WHERE account = ?"; + String sql = "SELECT reference, public_key, default_group_id, flags, forging_enabler, initial_level, level FROM Accounts WHERE account = ?"; try (ResultSet resultSet = this.repository.checkedExecute(sql, address)) { if (resultSet == null) @@ -37,9 +37,10 @@ public class HSQLDBAccountRepository implements AccountRepository { int defaultGroupId = resultSet.getInt(3); int flags = resultSet.getInt(4); String forgingEnabler = resultSet.getString(5); - int level = resultSet.getInt(6); + int initialLevel = resultSet.getInt(6); + int level = resultSet.getInt(7); - return new AccountData(address, reference, publicKey, defaultGroupId, flags, forgingEnabler, level); + return new AccountData(address, reference, publicKey, defaultGroupId, flags, forgingEnabler, initialLevel, level); } catch (SQLException e) { throw new DataException("Unable to fetch account info from repository", e); } @@ -216,6 +217,24 @@ public class HSQLDBAccountRepository implements AccountRepository { } } + @Override + public void setInitialLevel(AccountData accountData) throws DataException { + HSQLDBSaver saveHelper = new HSQLDBSaver("Accounts"); + + saveHelper.bind("account", accountData.getAddress()).bind("level", accountData.getLevel()) + .bind("initial_level", accountData.getInitialLevel()); + + byte[] publicKey = accountData.getPublicKey(); + if (publicKey != null) + saveHelper.bind("public_key", publicKey); + + try { + saveHelper.execute(this.repository); + } catch (SQLException e) { + throw new DataException("Unable to save account's initial level into repository", e); + } + } + @Override public void setForgingEnabler(AccountData accountData) throws DataException { HSQLDBSaver saveHelper = new HSQLDBSaver("Accounts"); diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBAssetRepository.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBAssetRepository.java index aa011587..d48d6a91 100644 --- a/src/main/java/org/qora/repository/hsqldb/HSQLDBAssetRepository.java +++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBAssetRepository.java @@ -28,7 +28,7 @@ public class HSQLDBAssetRepository implements AssetRepository { @Override public AssetData fromAssetId(long assetId) throws DataException { - String sql = "SELECT owner, asset_name, description, quantity, is_divisible, data, creation_group_id, reference FROM Assets WHERE asset_id = ?"; + String sql = "SELECT owner, asset_name, description, quantity, is_divisible, data, is_unspendable, creation_group_id, reference FROM Assets WHERE asset_id = ?"; try (ResultSet resultSet = this.repository.checkedExecute(sql, assetId)) { if (resultSet == null) @@ -40,11 +40,12 @@ public class HSQLDBAssetRepository implements AssetRepository { long quantity = resultSet.getLong(4); boolean isDivisible = resultSet.getBoolean(5); String data = resultSet.getString(6); - int creationGroupId = resultSet.getInt(7); - byte[] reference = resultSet.getBytes(8); + boolean isUnspendable = resultSet.getBoolean(7); + int creationGroupId = resultSet.getInt(8); + byte[] reference = resultSet.getBytes(9); - return new AssetData(assetId, owner, assetName, description, quantity, isDivisible, data, creationGroupId, - reference); + return new AssetData(assetId, owner, assetName, description, quantity, isDivisible, data, isUnspendable, + creationGroupId, reference); } catch (SQLException e) { throw new DataException("Unable to fetch asset from repository", e); } @@ -52,7 +53,7 @@ public class HSQLDBAssetRepository implements AssetRepository { @Override public AssetData fromAssetName(String assetName) throws DataException { - String sql = "SELECT owner, asset_id, description, quantity, is_divisible, data, creation_group_id, reference FROM Assets WHERE asset_name = ?"; + String sql = "SELECT owner, asset_id, description, quantity, is_divisible, data, is_unspendable, creation_group_id, reference FROM Assets WHERE asset_name = ?"; try (ResultSet resultSet = this.repository.checkedExecute(sql, assetName)) { if (resultSet == null) @@ -64,11 +65,12 @@ public class HSQLDBAssetRepository implements AssetRepository { long quantity = resultSet.getLong(4); boolean isDivisible = resultSet.getBoolean(5); String data = resultSet.getString(6); - int creationGroupId = resultSet.getInt(7); - byte[] reference = resultSet.getBytes(8); + boolean isUnspendable = resultSet.getBoolean(7); + int creationGroupId = resultSet.getInt(8); + byte[] reference = resultSet.getBytes(9); - return new AssetData(assetId, owner, assetName, description, quantity, isDivisible, data, creationGroupId, - reference); + return new AssetData(assetId, owner, assetName, description, quantity, isDivisible, data, isUnspendable, + creationGroupId, reference); } catch (SQLException e) { throw new DataException("Unable to fetch asset from repository", e); } @@ -95,7 +97,8 @@ public class HSQLDBAssetRepository implements AssetRepository { @Override public List getAllAssets(Integer limit, Integer offset, Boolean reverse) throws DataException { StringBuilder sql = new StringBuilder(256); - sql.append("SELECT asset_id, owner, asset_name, description, quantity, is_divisible, data, creation_group_id, reference FROM Assets ORDER BY asset_id"); + sql.append("SELECT asset_id, owner, asset_name, description, quantity, is_divisible, data, is_unspendable, creation_group_id, reference " + + "FROM Assets ORDER BY asset_id"); if (reverse != null && reverse) sql.append(" DESC"); @@ -115,11 +118,12 @@ public class HSQLDBAssetRepository implements AssetRepository { long quantity = resultSet.getLong(5); boolean isDivisible = resultSet.getBoolean(6); String data = resultSet.getString(7); + boolean isUnspendable = resultSet.getBoolean(7); int creationGroupId = resultSet.getInt(8); byte[] reference = resultSet.getBytes(9); assets.add(new AssetData(assetId, owner, assetName, description, quantity, isDivisible, data, - creationGroupId, reference)); + isUnspendable,creationGroupId, reference)); } while (resultSet.next()); return assets; @@ -159,8 +163,8 @@ public class HSQLDBAssetRepository implements AssetRepository { saveHelper.bind("asset_id", assetData.getAssetId()).bind("owner", assetData.getOwner()) .bind("asset_name", assetData.getName()).bind("description", assetData.getDescription()) .bind("quantity", assetData.getQuantity()).bind("is_divisible", assetData.getIsDivisible()) - .bind("data", assetData.getData()).bind("creation_group_id", assetData.getCreationGroupId()) - .bind("reference", assetData.getReference()); + .bind("data", assetData.getData()).bind("is_unspendable", assetData.getIsUnspendable()) + .bind("creation_group_id", assetData.getCreationGroupId()).bind("reference", assetData.getReference()); try { saveHelper.execute(this.repository); diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBDatabaseUpdates.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBDatabaseUpdates.java index 698b241a..61ba018c 100644 --- a/src/main/java/org/qora/repository/hsqldb/HSQLDBDatabaseUpdates.java +++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBDatabaseUpdates.java @@ -778,10 +778,11 @@ public class HSQLDBDatabaseUpdates { case 54: // Account 'level' + stmt.execute("ALTER TABLE Accounts ADD COLUMN initial_level TINYINT NOT NULL DEFAULT 0"); stmt.execute("ALTER TABLE Accounts ADD COLUMN level TINYINT NOT NULL DEFAULT 0"); // Corresponding transaction to set level stmt.execute("CREATE TABLE AccountLevelTransactions (signature Signature, creator QoraPublicKey NOT NULL, target QoraAddress NOT NULL, level INT NOT NULL, " - + "previous_level INT, PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)"); + + "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)"); break; case 55: @@ -792,6 +793,12 @@ public class HSQLDBDatabaseUpdates { stmt.execute("ALTER TABLE Blocks ADD COLUMN online_accounts_signatures BLOB"); break; + case 56: + // Modify assets to support "unspendable" flag so we can implement the representative legacy QORA asset. + stmt.execute("ALTER TABLE Assets ADD COLUMN is_unspendable BOOLEAN NOT NULL DEFAULT FALSE BEFORE creation_group_id"); + stmt.execute("ALTER TABLE IssueAssetTransactions ADD COLUMN is_unspendable BOOLEAN NOT NULL DEFAULT FALSE BEFORE asset_id"); + break; + default: // nothing to do return false; diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java index e1a29003..00647708 100644 --- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java +++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java @@ -17,7 +17,7 @@ public class HSQLDBIssueAssetTransactionRepository extends HSQLDBTransactionRepo } TransactionData fromBase(BaseTransactionData baseTransactionData) throws DataException { - String sql = "SELECT owner, asset_name, description, quantity, is_divisible, data, asset_id FROM IssueAssetTransactions WHERE signature = ?"; + String sql = "SELECT owner, asset_name, description, quantity, is_divisible, data, is_unspendable, asset_id FROM IssueAssetTransactions WHERE signature = ?"; try (ResultSet resultSet = this.repository.checkedExecute(sql, baseTransactionData.getSignature())) { if (resultSet == null) @@ -29,14 +29,15 @@ public class HSQLDBIssueAssetTransactionRepository extends HSQLDBTransactionRepo long quantity = resultSet.getLong(4); boolean isDivisible = resultSet.getBoolean(5); String data = resultSet.getString(6); + boolean isUnspendable = resultSet.getBoolean(7); // Special null-checking for asset ID - Long assetId = resultSet.getLong(7); + Long assetId = resultSet.getLong(8); if (assetId == 0 && resultSet.wasNull()) assetId = null; return new IssueAssetTransactionData(baseTransactionData, assetId, owner, assetName, description, quantity, isDivisible, - data); + data, isUnspendable); } catch (SQLException e) { throw new DataException("Unable to fetch issue asset transaction from repository", e); } @@ -51,8 +52,8 @@ public class HSQLDBIssueAssetTransactionRepository extends HSQLDBTransactionRepo saveHelper.bind("signature", issueAssetTransactionData.getSignature()).bind("issuer", issueAssetTransactionData.getIssuerPublicKey()) .bind("owner", issueAssetTransactionData.getOwner()).bind("asset_name", issueAssetTransactionData.getAssetName()) .bind("description", issueAssetTransactionData.getDescription()).bind("quantity", issueAssetTransactionData.getQuantity()) - .bind("is_divisible", issueAssetTransactionData.getIsDivisible()) - .bind("data", issueAssetTransactionData.getData()).bind("asset_id", issueAssetTransactionData.getAssetId()); + .bind("is_divisible", issueAssetTransactionData.getIsDivisible()).bind("data", issueAssetTransactionData.getData()) + .bind("is_unspendable", issueAssetTransactionData.getIsUnspendable()).bind("asset_id", issueAssetTransactionData.getAssetId()); try { saveHelper.execute(this.repository); diff --git a/src/main/java/org/qora/transaction/AccountFlagsTransaction.java b/src/main/java/org/qora/transaction/AccountFlagsTransaction.java index 9ecbfe3e..ad537ba3 100644 --- a/src/main/java/org/qora/transaction/AccountFlagsTransaction.java +++ b/src/main/java/org/qora/transaction/AccountFlagsTransaction.java @@ -77,7 +77,7 @@ public class AccountFlagsTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check creator has enough funds - if (creator.getConfirmedBalance(Asset.QORA).compareTo(accountFlagsTransactionData.getFee()) < 0) + if (creator.getConfirmedBalance(Asset.QORT).compareTo(accountFlagsTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/AccountLevelTransaction.java b/src/main/java/org/qora/transaction/AccountLevelTransaction.java index 51534a77..018a339f 100644 --- a/src/main/java/org/qora/transaction/AccountLevelTransaction.java +++ b/src/main/java/org/qora/transaction/AccountLevelTransaction.java @@ -77,7 +77,7 @@ public class AccountLevelTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check creator has enough funds - if (creator.getConfirmedBalance(Asset.QORA).compareTo(accountLevelTransactionData.getFee()) < 0) + if (creator.getConfirmedBalance(Asset.QORT).compareTo(accountLevelTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; @@ -86,15 +86,12 @@ public class AccountLevelTransaction extends Transaction { @Override public void process() throws DataException { Account target = getTarget(); - Integer previousLevel = target.getLevel(); - accountLevelTransactionData.setPreviousLevel(previousLevel); - - // Save this transaction with target account's previous level value + // Save this transaction this.repository.getTransactionRepository().save(accountLevelTransactionData); - // Set account's new level - target.setLevel(this.accountLevelTransactionData.getLevel()); + // Set account's initial level + target.setInitialLevel(this.accountLevelTransactionData.getLevel()); } @Override @@ -102,17 +99,8 @@ public class AccountLevelTransaction extends Transaction { // Revert Account target = getTarget(); - Integer previousLevel = accountLevelTransactionData.getPreviousLevel(); - - // If previousLevel are null then account didn't exist before this transaction - if (previousLevel == null) - this.repository.getAccountRepository().delete(target.getAddress()); - else - target.setLevel(previousLevel); - - // Remove previous level from transaction itself - accountLevelTransactionData.setPreviousLevel(null); - this.repository.getTransactionRepository().save(accountLevelTransactionData); + // This is only ever a genesis block transaction so simply delete account + this.repository.getAccountRepository().delete(target.getAddress()); } } diff --git a/src/main/java/org/qora/transaction/AddGroupAdminTransaction.java b/src/main/java/org/qora/transaction/AddGroupAdminTransaction.java index 568a35b6..2cae7648 100644 --- a/src/main/java/org/qora/transaction/AddGroupAdminTransaction.java +++ b/src/main/java/org/qora/transaction/AddGroupAdminTransaction.java @@ -102,7 +102,7 @@ public class AddGroupAdminTransaction extends Transaction { return ValidationResult.ALREADY_GROUP_ADMIN; // Check group owner has enough funds - if (owner.getConfirmedBalance(Asset.QORA).compareTo(addGroupAdminTransactionData.getFee()) < 0) + if (owner.getConfirmedBalance(Asset.QORT).compareTo(addGroupAdminTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/ArbitraryTransaction.java b/src/main/java/org/qora/transaction/ArbitraryTransaction.java index 573d9b38..0108e514 100644 --- a/src/main/java/org/qora/transaction/ArbitraryTransaction.java +++ b/src/main/java/org/qora/transaction/ArbitraryTransaction.java @@ -71,7 +71,7 @@ public class ArbitraryTransaction extends Transaction { if (arbitraryTransactionData.getVersion() != 1) for (PaymentData paymentData : arbitraryTransactionData.getPayments()) // We're only interested in QORA - if (paymentData.getAssetId() == Asset.QORA) { + if (paymentData.getAssetId() == Asset.QORT) { if (address.equals(paymentData.getRecipient())) amount = amount.add(paymentData.getAmount()); else if (address.equals(senderAddress)) diff --git a/src/main/java/org/qora/transaction/AtTransaction.java b/src/main/java/org/qora/transaction/AtTransaction.java index 25f79054..f90bd299 100644 --- a/src/main/java/org/qora/transaction/AtTransaction.java +++ b/src/main/java/org/qora/transaction/AtTransaction.java @@ -84,12 +84,12 @@ public class AtTransaction extends Transaction { if (address.equals(atAddress)) { amount = amount.subtract(this.atTransactionData.getFee()); - if (this.atTransactionData.getAmount() != null && this.atTransactionData.getAssetId() == Asset.QORA) + if (this.atTransactionData.getAmount() != null && this.atTransactionData.getAssetId() == Asset.QORT) amount = amount.subtract(this.atTransactionData.getAmount()); } if (address.equals(this.atTransactionData.getRecipient()) && this.atTransactionData.getAmount() != null - && this.atTransactionData.getAssetId() == Asset.QORA) + && this.atTransactionData.getAssetId() == Asset.QORT) amount = amount.add(this.atTransactionData.getAmount()); return amount; @@ -183,7 +183,7 @@ public class AtTransaction extends Transaction { long assetId = this.atTransactionData.getAssetId(); // For QORA amounts only: if recipient has no reference yet, then this is their starting reference - if (assetId == Asset.QORA && recipient.getLastReference() == null) + if (assetId == Asset.QORT && recipient.getLastReference() == null) // In Qora1 last reference was set to 64-bytes of zero // In Qora2 we use AT-Transction's signature, which makes more sense recipient.setLastReference(this.atTransactionData.getSignature()); @@ -220,7 +220,7 @@ public class AtTransaction extends Transaction { * For QORA amounts only: If recipient's last reference is this transaction's signature, then they can't have made any transactions of their own * (which would have changed their last reference) thus this is their first reference so remove it. */ - if (assetId == Asset.QORA && Arrays.equals(recipient.getLastReference(), this.atTransactionData.getSignature())) + if (assetId == Asset.QORT && Arrays.equals(recipient.getLastReference(), this.atTransactionData.getSignature())) recipient.setLastReference(null); } } diff --git a/src/main/java/org/qora/transaction/BuyNameTransaction.java b/src/main/java/org/qora/transaction/BuyNameTransaction.java index 07a87f05..e2642c01 100644 --- a/src/main/java/org/qora/transaction/BuyNameTransaction.java +++ b/src/main/java/org/qora/transaction/BuyNameTransaction.java @@ -110,7 +110,7 @@ public class BuyNameTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check issuer has enough funds - if (buyer.getConfirmedBalance(Asset.QORA).compareTo(buyNameTransactionData.getFee()) < 0) + if (buyer.getConfirmedBalance(Asset.QORT).compareTo(buyNameTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/CancelAssetOrderTransaction.java b/src/main/java/org/qora/transaction/CancelAssetOrderTransaction.java index 66b1cf26..0b456f95 100644 --- a/src/main/java/org/qora/transaction/CancelAssetOrderTransaction.java +++ b/src/main/java/org/qora/transaction/CancelAssetOrderTransaction.java @@ -89,7 +89,7 @@ public class CancelAssetOrderTransaction extends Transaction { return ValidationResult.INVALID_ORDER_CREATOR; // Check creator has enough QORA for fee - if (creator.getConfirmedBalance(Asset.QORA).compareTo(cancelOrderTransactionData.getFee()) < 0) + if (creator.getConfirmedBalance(Asset.QORT).compareTo(cancelOrderTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/CancelGroupBanTransaction.java b/src/main/java/org/qora/transaction/CancelGroupBanTransaction.java index 164f7f78..7be7f157 100644 --- a/src/main/java/org/qora/transaction/CancelGroupBanTransaction.java +++ b/src/main/java/org/qora/transaction/CancelGroupBanTransaction.java @@ -100,7 +100,7 @@ public class CancelGroupBanTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check creator has enough funds - if (admin.getConfirmedBalance(Asset.QORA).compareTo(groupUnbanTransactionData.getFee()) < 0) + if (admin.getConfirmedBalance(Asset.QORT).compareTo(groupUnbanTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/CancelGroupInviteTransaction.java b/src/main/java/org/qora/transaction/CancelGroupInviteTransaction.java index 94ab0a55..d8f85085 100644 --- a/src/main/java/org/qora/transaction/CancelGroupInviteTransaction.java +++ b/src/main/java/org/qora/transaction/CancelGroupInviteTransaction.java @@ -100,7 +100,7 @@ public class CancelGroupInviteTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check creator has enough funds - if (admin.getConfirmedBalance(Asset.QORA).compareTo(cancelGroupInviteTransactionData.getFee()) < 0) + if (admin.getConfirmedBalance(Asset.QORT).compareTo(cancelGroupInviteTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/CancelSellNameTransaction.java b/src/main/java/org/qora/transaction/CancelSellNameTransaction.java index 88756295..ab18a3b3 100644 --- a/src/main/java/org/qora/transaction/CancelSellNameTransaction.java +++ b/src/main/java/org/qora/transaction/CancelSellNameTransaction.java @@ -96,7 +96,7 @@ public class CancelSellNameTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check issuer has enough funds - if (owner.getConfirmedBalance(Asset.QORA).compareTo(cancelSellNameTransactionData.getFee()) < 0) + if (owner.getConfirmedBalance(Asset.QORT).compareTo(cancelSellNameTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/CreateAssetOrderTransaction.java b/src/main/java/org/qora/transaction/CreateAssetOrderTransaction.java index a61018dd..308492a6 100644 --- a/src/main/java/org/qora/transaction/CreateAssetOrderTransaction.java +++ b/src/main/java/org/qora/transaction/CreateAssetOrderTransaction.java @@ -101,6 +101,10 @@ public class CreateAssetOrderTransaction extends Transaction { if (wantAssetData == null) return ValidationResult.ASSET_DOES_NOT_EXIST; + // Unspendable assets are not tradable + if (haveAssetData.getIsUnspendable() || wantAssetData.getIsUnspendable()) + return ValidationResult.ASSET_NOT_SPENDABLE; + Account creator = getCreator(); boolean isNewPricing = createOrderTransactionData.getTimestamp() >= BlockChain.getInstance().getNewAssetPricingTimestamp(); @@ -153,9 +157,9 @@ public class CreateAssetOrderTransaction extends Transaction { // Check order creator has enough asset balance AFTER removing fee, in case asset is QORA // If asset is QORA then we need to check amount + fee in one go - if (haveAssetId == Asset.QORA) { + if (haveAssetId == Asset.QORT) { // Check creator has enough funds for amount + fee in QORA - if (creator.getConfirmedBalance(Asset.QORA).compareTo(committedCost.add(createOrderTransactionData.getFee())) < 0) + if (creator.getConfirmedBalance(Asset.QORT).compareTo(committedCost.add(createOrderTransactionData.getFee())) < 0) return ValidationResult.NO_BALANCE; } else { // Check creator has enough funds for amount in whatever asset @@ -165,7 +169,7 @@ public class CreateAssetOrderTransaction 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.getInstance().getPowFixReleaseTimestamp() - && creator.getConfirmedBalance(Asset.QORA).compareTo(createOrderTransactionData.getFee()) < 0) + && creator.getConfirmedBalance(Asset.QORT).compareTo(createOrderTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; } diff --git a/src/main/java/org/qora/transaction/CreateGroupTransaction.java b/src/main/java/org/qora/transaction/CreateGroupTransaction.java index f1701798..85baa05c 100644 --- a/src/main/java/org/qora/transaction/CreateGroupTransaction.java +++ b/src/main/java/org/qora/transaction/CreateGroupTransaction.java @@ -98,7 +98,7 @@ public class CreateGroupTransaction extends Transaction { Account creator = getCreator(); // Check creator has enough funds - if (creator.getConfirmedBalance(Asset.QORA).compareTo(createGroupTransactionData.getFee()) < 0) + if (creator.getConfirmedBalance(Asset.QORT).compareTo(createGroupTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/CreatePollTransaction.java b/src/main/java/org/qora/transaction/CreatePollTransaction.java index c3e96072..d8cb8c46 100644 --- a/src/main/java/org/qora/transaction/CreatePollTransaction.java +++ b/src/main/java/org/qora/transaction/CreatePollTransaction.java @@ -133,7 +133,7 @@ public class CreatePollTransaction extends Transaction { Account creator = getCreator(); // Check issuer has enough funds - if (creator.getConfirmedBalance(Asset.QORA).compareTo(createPollTransactionData.getFee()) < 0) + if (creator.getConfirmedBalance(Asset.QORT).compareTo(createPollTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/DeployAtTransaction.java b/src/main/java/org/qora/transaction/DeployAtTransaction.java index 767d07d2..75aa3947 100644 --- a/src/main/java/org/qora/transaction/DeployAtTransaction.java +++ b/src/main/java/org/qora/transaction/DeployAtTransaction.java @@ -162,6 +162,10 @@ public class DeployAtTransaction extends Transaction { if (assetData == null) return ValidationResult.ASSET_DOES_NOT_EXIST; + // Unspendable assets are not valid + if (assetData.getIsUnspendable()) + return ValidationResult.ASSET_NOT_SPENDABLE; + // Check asset amount is integer if asset is not divisible if (!assetData.getIsDivisible() && deployATTransactionData.getAmount().stripTrailingZeros().scale() > 0) return ValidationResult.INVALID_AMOUNT; @@ -173,14 +177,14 @@ public class DeployAtTransaction extends Transaction { Account creator = getCreator(); // Check creator has enough funds - if (assetId == Asset.QORA) { + if (assetId == Asset.QORT) { // Simple case: amount and fee both in Qora BigDecimal minimumBalance = deployATTransactionData.getFee().add(deployATTransactionData.getAmount()); - if (creator.getConfirmedBalance(Asset.QORA).compareTo(minimumBalance) < 0) + if (creator.getConfirmedBalance(Asset.QORT).compareTo(minimumBalance) < 0) return ValidationResult.NO_BALANCE; } else { - if (creator.getConfirmedBalance(Asset.QORA).compareTo(deployATTransactionData.getFee()) < 0) + if (creator.getConfirmedBalance(Asset.QORT).compareTo(deployATTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; if (creator.getConfirmedBalance(assetId).compareTo(deployATTransactionData.getAmount()) < 0) @@ -209,14 +213,14 @@ public class DeployAtTransaction extends Transaction { long assetId = deployATTransactionData.getAssetId(); // Check creator has enough funds - if (assetId == Asset.QORA) { + if (assetId == Asset.QORT) { // Simple case: amount and fee both in Qora BigDecimal minimumBalance = deployATTransactionData.getFee().add(deployATTransactionData.getAmount()); - if (creator.getConfirmedBalance(Asset.QORA).compareTo(minimumBalance) < 0) + if (creator.getConfirmedBalance(Asset.QORT).compareTo(minimumBalance) < 0) return ValidationResult.NO_BALANCE; } else { - if (creator.getConfirmedBalance(Asset.QORA).compareTo(deployATTransactionData.getFee()) < 0) + if (creator.getConfirmedBalance(Asset.QORT).compareTo(deployATTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; if (creator.getConfirmedBalance(assetId).compareTo(deployATTransactionData.getAmount()) < 0) diff --git a/src/main/java/org/qora/transaction/EnableForgingTransaction.java b/src/main/java/org/qora/transaction/EnableForgingTransaction.java index dbed9c92..f0f96f9a 100644 --- a/src/main/java/org/qora/transaction/EnableForgingTransaction.java +++ b/src/main/java/org/qora/transaction/EnableForgingTransaction.java @@ -121,7 +121,7 @@ public class EnableForgingTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check creator has enough funds - if (creator.getConfirmedBalance(Asset.QORA).compareTo(enableForgingTransactionData.getFee()) < 0) + if (creator.getConfirmedBalance(Asset.QORT).compareTo(enableForgingTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/GenesisTransaction.java b/src/main/java/org/qora/transaction/GenesisTransaction.java index 00b6e05c..53d40fc0 100644 --- a/src/main/java/org/qora/transaction/GenesisTransaction.java +++ b/src/main/java/org/qora/transaction/GenesisTransaction.java @@ -139,7 +139,7 @@ public class GenesisTransaction extends Transaction { Account recipient = new Account(repository, genesisTransactionData.getRecipient()); // Update recipient's balance - recipient.setConfirmedBalance(Asset.QORA, genesisTransactionData.getAmount()); + recipient.setConfirmedBalance(Asset.QORT, genesisTransactionData.getAmount()); } @Override diff --git a/src/main/java/org/qora/transaction/GroupApprovalTransaction.java b/src/main/java/org/qora/transaction/GroupApprovalTransaction.java index 59ef97a9..15035d09 100644 --- a/src/main/java/org/qora/transaction/GroupApprovalTransaction.java +++ b/src/main/java/org/qora/transaction/GroupApprovalTransaction.java @@ -87,7 +87,7 @@ public class GroupApprovalTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check creator has enough funds - if (admin.getConfirmedBalance(Asset.QORA).compareTo(groupApprovalTransactionData.getFee()) < 0) + if (admin.getConfirmedBalance(Asset.QORT).compareTo(groupApprovalTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/GroupBanTransaction.java b/src/main/java/org/qora/transaction/GroupBanTransaction.java index 8516e4a5..ae5d3ed5 100644 --- a/src/main/java/org/qora/transaction/GroupBanTransaction.java +++ b/src/main/java/org/qora/transaction/GroupBanTransaction.java @@ -101,7 +101,7 @@ public class GroupBanTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check admin has enough funds - if (admin.getConfirmedBalance(Asset.QORA).compareTo(groupBanTransactionData.getFee()) < 0) + if (admin.getConfirmedBalance(Asset.QORT).compareTo(groupBanTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/GroupInviteTransaction.java b/src/main/java/org/qora/transaction/GroupInviteTransaction.java index 03d6a647..54e5855b 100644 --- a/src/main/java/org/qora/transaction/GroupInviteTransaction.java +++ b/src/main/java/org/qora/transaction/GroupInviteTransaction.java @@ -107,7 +107,7 @@ public class GroupInviteTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check creator has enough funds - if (admin.getConfirmedBalance(Asset.QORA).compareTo(groupInviteTransactionData.getFee()) < 0) + if (admin.getConfirmedBalance(Asset.QORT).compareTo(groupInviteTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/GroupKickTransaction.java b/src/main/java/org/qora/transaction/GroupKickTransaction.java index 7f10d8e8..d953e214 100644 --- a/src/main/java/org/qora/transaction/GroupKickTransaction.java +++ b/src/main/java/org/qora/transaction/GroupKickTransaction.java @@ -107,7 +107,7 @@ public class GroupKickTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check creator has enough funds - if (admin.getConfirmedBalance(Asset.QORA).compareTo(groupKickTransactionData.getFee()) < 0) + if (admin.getConfirmedBalance(Asset.QORT).compareTo(groupKickTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/IssueAssetTransaction.java b/src/main/java/org/qora/transaction/IssueAssetTransaction.java index 969dba7c..f94ba68c 100644 --- a/src/main/java/org/qora/transaction/IssueAssetTransaction.java +++ b/src/main/java/org/qora/transaction/IssueAssetTransaction.java @@ -120,7 +120,7 @@ public class IssueAssetTransaction extends Transaction { Account issuer = getIssuer(); // Check issuer has enough funds - if (issuer.getConfirmedBalance(Asset.QORA).compareTo(issueAssetTransactionData.getFee()) < 0) + if (issuer.getConfirmedBalance(Asset.QORT).compareTo(issueAssetTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/JoinGroupTransaction.java b/src/main/java/org/qora/transaction/JoinGroupTransaction.java index de883a95..74a39052 100644 --- a/src/main/java/org/qora/transaction/JoinGroupTransaction.java +++ b/src/main/java/org/qora/transaction/JoinGroupTransaction.java @@ -87,7 +87,7 @@ public class JoinGroupTransaction extends Transaction { if (joinGroupTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0) return ValidationResult.NEGATIVE_FEE; // Check creator has enough funds - if (joiner.getConfirmedBalance(Asset.QORA).compareTo(joinGroupTransactionData.getFee()) < 0) + if (joiner.getConfirmedBalance(Asset.QORT).compareTo(joinGroupTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/LeaveGroupTransaction.java b/src/main/java/org/qora/transaction/LeaveGroupTransaction.java index 5f7a9292..9ee97d6c 100644 --- a/src/main/java/org/qora/transaction/LeaveGroupTransaction.java +++ b/src/main/java/org/qora/transaction/LeaveGroupTransaction.java @@ -86,7 +86,7 @@ public class LeaveGroupTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check creator has enough funds - if (leaver.getConfirmedBalance(Asset.QORA).compareTo(leaveGroupTransactionData.getFee()) < 0) + if (leaver.getConfirmedBalance(Asset.QORT).compareTo(leaveGroupTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/MessageTransaction.java b/src/main/java/org/qora/transaction/MessageTransaction.java index 7dc0b982..73639f80 100644 --- a/src/main/java/org/qora/transaction/MessageTransaction.java +++ b/src/main/java/org/qora/transaction/MessageTransaction.java @@ -61,7 +61,7 @@ public class MessageTransaction extends Transaction { amount = amount.subtract(this.transactionData.getFee()); // We're only interested in QORA - if (messageTransactionData.getAssetId() == Asset.QORA) { + if (messageTransactionData.getAssetId() == Asset.QORT) { if (address.equals(messageTransactionData.getRecipient())) amount = amount.add(messageTransactionData.getAmount()); else if (address.equals(senderAddress)) diff --git a/src/main/java/org/qora/transaction/MultiPaymentTransaction.java b/src/main/java/org/qora/transaction/MultiPaymentTransaction.java index 702c4fbf..c5e5aed6 100644 --- a/src/main/java/org/qora/transaction/MultiPaymentTransaction.java +++ b/src/main/java/org/qora/transaction/MultiPaymentTransaction.java @@ -68,7 +68,7 @@ public class MultiPaymentTransaction extends Transaction { // We're only interested in QORA for (PaymentData paymentData : multiPaymentTransactionData.getPayments()) - if (paymentData.getAssetId() == Asset.QORA) { + if (paymentData.getAssetId() == Asset.QORT) { if (address.equals(paymentData.getRecipient())) amount = amount.add(paymentData.getAmount()); else if (address.equals(senderAddress)) @@ -104,7 +104,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.getInstance().getPowFixReleaseTimestamp() - && sender.getConfirmedBalance(Asset.QORA).compareTo(multiPaymentTransactionData.getFee()) < 0) + && sender.getConfirmedBalance(Asset.QORT).compareTo(multiPaymentTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return new Payment(this.repository).isValid(multiPaymentTransactionData.getSenderPublicKey(), payments, multiPaymentTransactionData.getFee()); diff --git a/src/main/java/org/qora/transaction/PaymentTransaction.java b/src/main/java/org/qora/transaction/PaymentTransaction.java index a0c37b64..273c7790 100644 --- a/src/main/java/org/qora/transaction/PaymentTransaction.java +++ b/src/main/java/org/qora/transaction/PaymentTransaction.java @@ -71,7 +71,7 @@ public class PaymentTransaction extends Transaction { // Processing private PaymentData getPaymentData() { - return new PaymentData(paymentTransactionData.getRecipient(), Asset.QORA, paymentTransactionData.getAmount()); + return new PaymentData(paymentTransactionData.getRecipient(), Asset.QORT, paymentTransactionData.getAmount()); } @Override diff --git a/src/main/java/org/qora/transaction/ProxyForgingTransaction.java b/src/main/java/org/qora/transaction/ProxyForgingTransaction.java index 09b6c357..f11fe5ab 100644 --- a/src/main/java/org/qora/transaction/ProxyForgingTransaction.java +++ b/src/main/java/org/qora/transaction/ProxyForgingTransaction.java @@ -120,7 +120,7 @@ public class ProxyForgingTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check creator has enough funds - if (creator.getConfirmedBalance(Asset.QORA).compareTo(proxyForgingTransactionData.getFee()) < 0) + if (creator.getConfirmedBalance(Asset.QORT).compareTo(proxyForgingTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/RegisterNameTransaction.java b/src/main/java/org/qora/transaction/RegisterNameTransaction.java index ca4c3748..3defabfd 100644 --- a/src/main/java/org/qora/transaction/RegisterNameTransaction.java +++ b/src/main/java/org/qora/transaction/RegisterNameTransaction.java @@ -100,7 +100,7 @@ public class RegisterNameTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check issuer has enough funds - if (registrant.getConfirmedBalance(Asset.QORA).compareTo(registerNameTransactionData.getFee()) < 0) + if (registrant.getConfirmedBalance(Asset.QORT).compareTo(registerNameTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/RemoveGroupAdminTransaction.java b/src/main/java/org/qora/transaction/RemoveGroupAdminTransaction.java index 971806f8..d5b1d117 100644 --- a/src/main/java/org/qora/transaction/RemoveGroupAdminTransaction.java +++ b/src/main/java/org/qora/transaction/RemoveGroupAdminTransaction.java @@ -100,7 +100,7 @@ public class RemoveGroupAdminTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check creator has enough funds - if (owner.getConfirmedBalance(Asset.QORA).compareTo(removeGroupAdminTransactionData.getFee()) < 0) + if (owner.getConfirmedBalance(Asset.QORT).compareTo(removeGroupAdminTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/SellNameTransaction.java b/src/main/java/org/qora/transaction/SellNameTransaction.java index 1302b3e9..de5cca4d 100644 --- a/src/main/java/org/qora/transaction/SellNameTransaction.java +++ b/src/main/java/org/qora/transaction/SellNameTransaction.java @@ -107,7 +107,7 @@ public class SellNameTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check issuer has enough funds - if (owner.getConfirmedBalance(Asset.QORA).compareTo(sellNameTransactionData.getFee()) < 0) + if (owner.getConfirmedBalance(Asset.QORT).compareTo(sellNameTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/SetGroupTransaction.java b/src/main/java/org/qora/transaction/SetGroupTransaction.java index 70d7845a..65d9e4da 100644 --- a/src/main/java/org/qora/transaction/SetGroupTransaction.java +++ b/src/main/java/org/qora/transaction/SetGroupTransaction.java @@ -74,7 +74,7 @@ public class SetGroupTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check creator has enough funds - if (creator.getConfirmedBalance(Asset.QORA).compareTo(setGroupTransactionData.getFee()) < 0) + if (creator.getConfirmedBalance(Asset.QORT).compareTo(setGroupTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/Transaction.java b/src/main/java/org/qora/transaction/Transaction.java index be713b95..2ed1e146 100644 --- a/src/main/java/org/qora/transaction/Transaction.java +++ b/src/main/java/org/qora/transaction/Transaction.java @@ -239,6 +239,7 @@ public abstract class Transaction { NO_BLOCKCHAIN_LOCK(86), ORDER_ALREADY_CLOSED(87), CLOCK_NOT_SYNCED(88), + ASSET_NOT_SPENDABLE(89), NOT_YET_RELEASED(1000); public final int value; @@ -946,7 +947,7 @@ public abstract class Transaction { Account creator = getCreator(); // Update transaction creator's balance - creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).subtract(transactionData.getFee())); + creator.setConfirmedBalance(Asset.QORT, creator.getConfirmedBalance(Asset.QORT).subtract(transactionData.getFee())); // Update transaction creator's reference creator.setLastReference(transactionData.getSignature()); @@ -970,7 +971,7 @@ public abstract class Transaction { Account creator = getCreator(); // Update transaction creator's balance - creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).add(transactionData.getFee())); + creator.setConfirmedBalance(Asset.QORT, creator.getConfirmedBalance(Asset.QORT).add(transactionData.getFee())); // Update transaction creator's reference creator.setLastReference(transactionData.getReference()); diff --git a/src/main/java/org/qora/transaction/TransferAssetTransaction.java b/src/main/java/org/qora/transaction/TransferAssetTransaction.java index c352b36c..8f0b06a9 100644 --- a/src/main/java/org/qora/transaction/TransferAssetTransaction.java +++ b/src/main/java/org/qora/transaction/TransferAssetTransaction.java @@ -58,7 +58,7 @@ public class TransferAssetTransaction extends Transaction { amount = amount.subtract(this.transactionData.getFee()); // We're only interested in QORA amounts - if (transferAssetTransactionData.getAssetId() == Asset.QORA) { + if (transferAssetTransactionData.getAssetId() == Asset.QORT) { if (address.equals(transferAssetTransactionData.getRecipient())) amount = amount.add(transferAssetTransactionData.getAmount()); else if (address.equals(senderAddress)) diff --git a/src/main/java/org/qora/transaction/UpdateAssetTransaction.java b/src/main/java/org/qora/transaction/UpdateAssetTransaction.java index f08c70ab..03f3d79a 100644 --- a/src/main/java/org/qora/transaction/UpdateAssetTransaction.java +++ b/src/main/java/org/qora/transaction/UpdateAssetTransaction.java @@ -110,7 +110,7 @@ public class UpdateAssetTransaction extends Transaction { Account currentOwner = getOwner(); // Check current owner has enough funds - if (currentOwner.getConfirmedBalance(Asset.QORA).compareTo(updateAssetTransactionData.getFee()) < 0) + if (currentOwner.getConfirmedBalance(Asset.QORT).compareTo(updateAssetTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/UpdateGroupTransaction.java b/src/main/java/org/qora/transaction/UpdateGroupTransaction.java index ede37bcc..528f820a 100644 --- a/src/main/java/org/qora/transaction/UpdateGroupTransaction.java +++ b/src/main/java/org/qora/transaction/UpdateGroupTransaction.java @@ -105,7 +105,7 @@ public class UpdateGroupTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check creator has enough funds - if (owner.getConfirmedBalance(Asset.QORA).compareTo(updateGroupTransactionData.getFee()) < 0) + if (owner.getConfirmedBalance(Asset.QORT).compareTo(updateGroupTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/UpdateNameTransaction.java b/src/main/java/org/qora/transaction/UpdateNameTransaction.java index eba2c0f1..d3f2bfd4 100644 --- a/src/main/java/org/qora/transaction/UpdateNameTransaction.java +++ b/src/main/java/org/qora/transaction/UpdateNameTransaction.java @@ -110,7 +110,7 @@ public class UpdateNameTransaction extends Transaction { return ValidationResult.NEGATIVE_FEE; // Check issuer has enough funds - if (owner.getConfirmedBalance(Asset.QORA).compareTo(updateNameTransactionData.getFee()) < 0) + if (owner.getConfirmedBalance(Asset.QORT).compareTo(updateNameTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transaction/VoteOnPollTransaction.java b/src/main/java/org/qora/transaction/VoteOnPollTransaction.java index 67553b00..0b38bd61 100644 --- a/src/main/java/org/qora/transaction/VoteOnPollTransaction.java +++ b/src/main/java/org/qora/transaction/VoteOnPollTransaction.java @@ -110,7 +110,7 @@ public class VoteOnPollTransaction extends Transaction { Account voter = getVoter(); // Check voter has enough funds - if (voter.getConfirmedBalance(Asset.QORA).compareTo(voteOnPollTransactionData.getFee()) < 0) + if (voter.getConfirmedBalance(Asset.QORT).compareTo(voteOnPollTransactionData.getFee()) < 0) return ValidationResult.NO_BALANCE; return ValidationResult.OK; diff --git a/src/main/java/org/qora/transform/transaction/DeployAtTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/DeployAtTransactionTransformer.java index b4640cb4..8f1a79d4 100644 --- a/src/main/java/org/qora/transform/transaction/DeployAtTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/DeployAtTransactionTransformer.java @@ -87,7 +87,7 @@ public class DeployAtTransactionTransformer extends TransactionTransformer { BigDecimal amount = Serialization.deserializeBigDecimal(byteBuffer); - long assetId = Asset.QORA; + long assetId = Asset.QORT; if (version >= 4) assetId = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/GenesisTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/GenesisTransactionTransformer.java index dfc9577d..3514eda5 100644 --- a/src/main/java/org/qora/transform/transaction/GenesisTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/GenesisTransactionTransformer.java @@ -47,7 +47,7 @@ public class GenesisTransactionTransformer extends TransactionTransformer { BigDecimal amount = Serialization.deserializeBigDecimal(byteBuffer); - long assetId = Asset.QORA; + long assetId = Asset.QORT; if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp()) assetId = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/IssueAssetTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/IssueAssetTransactionTransformer.java index 7c0454f9..d02e1904 100644 --- a/src/main/java/org/qora/transform/transaction/IssueAssetTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/IssueAssetTransactionTransformer.java @@ -28,6 +28,7 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer { private static final int IS_DIVISIBLE_LENGTH = BOOLEAN_LENGTH; private static final int ASSET_REFERENCE_LENGTH = REFERENCE_LENGTH; private static final int DATA_SIZE_LENGTH = INT_LENGTH; + private static final int IS_UNSPENDABLE_LENGTH = BOOLEAN_LENGTH; private static final int EXTRAS_LENGTH = OWNER_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + QUANTITY_LENGTH + IS_DIVISIBLE_LENGTH; @@ -50,6 +51,7 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer { layout.add("can asset quantities be fractional?", TransformationType.BOOLEAN); layout.add("asset data length", TransformationType.INT); layout.add("asset data", TransformationType.STRING); + layout.add("are non-owner holders barred from using asset?", TransformationType.BOOLEAN); layout.add("fee", TransformationType.AMOUNT); layout.add("signature", TransformationType.SIGNATURE); } @@ -76,16 +78,18 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer { boolean isDivisible = byteBuffer.get() != 0; - // in v2, assets have "data" field + byte[] assetReference = new byte[ASSET_REFERENCE_LENGTH]; String data = ""; - if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp()) - data = Serialization.deserializeSizedString(byteBuffer, Asset.MAX_DATA_SIZE); + boolean isUnspendable = false; - byte[] assetReference = new byte[ASSET_REFERENCE_LENGTH]; - // In v1, IssueAssetTransaction uses Asset.parse which also deserializes - // reference. - if (timestamp < BlockChain.getInstance().getQoraV2Timestamp()) + if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp()) { + // in v2, assets have additional fields + data = Serialization.deserializeSizedString(byteBuffer, Asset.MAX_DATA_SIZE); + isUnspendable = byteBuffer.get() != 0; + } else { + // In v1, IssueAssetTransaction uses Asset.parse which also deserializes reference. byteBuffer.get(assetReference); + } BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer); @@ -94,7 +98,7 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer { BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, issuerPublicKey, fee, signature); - return new IssueAssetTransactionData(baseTransactionData, owner, assetName, description, quantity, isDivisible, data); + return new IssueAssetTransactionData(baseTransactionData, owner, assetName, description, quantity, isDivisible, data, isUnspendable); } public static int getDataLength(TransactionData transactionData) throws TransformationException { @@ -104,14 +108,13 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer { + Utf8.encodedLength(issueAssetTransactionData.getAssetName()) + Utf8.encodedLength(issueAssetTransactionData.getDescription()); - // In v2, assets have "data" field - if (transactionData.getTimestamp() >= BlockChain.getInstance().getQoraV2Timestamp()) - dataLength += DATA_SIZE_LENGTH + Utf8.encodedLength(issueAssetTransactionData.getData()); - - // In v1, IssueAssetTransaction uses Asset.toBytes which also serializes - // reference. - if (transactionData.getTimestamp() < BlockChain.getInstance().getQoraV2Timestamp()) + if (transactionData.getTimestamp() >= BlockChain.getInstance().getQoraV2Timestamp()) { + // In v2, assets have additional fields. + dataLength += DATA_SIZE_LENGTH + Utf8.encodedLength(issueAssetTransactionData.getData()) + IS_UNSPENDABLE_LENGTH; + } else { + // In v1, IssueAssetTransaction uses Asset.toBytes which also serializes reference. dataLength += ASSET_REFERENCE_LENGTH; + } return dataLength; } @@ -133,14 +136,14 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer { bytes.write(Longs.toByteArray(issueAssetTransactionData.getQuantity())); bytes.write((byte) (issueAssetTransactionData.getIsDivisible() ? 1 : 0)); - // In v2, assets have "data" - if (transactionData.getTimestamp() >= BlockChain.getInstance().getQoraV2Timestamp()) + // In v2, assets have additional fields. + if (transactionData.getTimestamp() >= BlockChain.getInstance().getQoraV2Timestamp()) { Serialization.serializeSizedString(bytes, issueAssetTransactionData.getData()); - - // In v1, IssueAssetTransaction uses Asset.toBytes which also - // serializes Asset's reference which is the IssueAssetTransaction's - // signature - if (transactionData.getTimestamp() < BlockChain.getInstance().getQoraV2Timestamp()) { + bytes.write((byte) (issueAssetTransactionData.getIsUnspendable() ? 1 : 0)); + } else { + // In v1, IssueAssetTransaction uses Asset.toBytes which also + // serializes Asset's reference which is the IssueAssetTransaction's + // signature byte[] assetReference = issueAssetTransactionData.getSignature(); if (assetReference != null) bytes.write(assetReference); diff --git a/src/main/java/org/qora/transform/transaction/MessageTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/MessageTransactionTransformer.java index a195c210..cd3a0694 100644 --- a/src/main/java/org/qora/transform/transaction/MessageTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/MessageTransactionTransformer.java @@ -68,7 +68,7 @@ public class MessageTransactionTransformer extends TransactionTransformer { long assetId; if (version == 1) - assetId = Asset.QORA; + assetId = Asset.QORT; else assetId = byteBuffer.getLong(); diff --git a/src/test/java/org/qora/test/RepositoryTests.java b/src/test/java/org/qora/test/RepositoryTests.java index 42653d9a..f700b337 100644 --- a/src/test/java/org/qora/test/RepositoryTests.java +++ b/src/test/java/org/qora/test/RepositoryTests.java @@ -78,14 +78,14 @@ public class RepositoryTests extends Common { try (final Repository repository2 = RepositoryManager.getRepository()) { // Update account in 2 Account account2 = Common.getTestAccount(repository2, "alice"); - account2.setConfirmedBalance(Asset.QORA, BigDecimal.valueOf(1234L)); + account2.setConfirmedBalance(Asset.QORT, BigDecimal.valueOf(1234L)); repository2.saveChanges(); } repository1.discardChanges(); // Update account in 1 - account1.setConfirmedBalance(Asset.QORA, BigDecimal.valueOf(5678L)); + account1.setConfirmedBalance(Asset.QORT, BigDecimal.valueOf(5678L)); repository1.saveChanges(); } } diff --git a/src/test/java/org/qora/test/TransactionTests.java b/src/test/java/org/qora/test/TransactionTests.java index f80ecf44..cdc6d61f 100644 --- a/src/test/java/org/qora/test/TransactionTests.java +++ b/src/test/java/org/qora/test/TransactionTests.java @@ -105,18 +105,18 @@ public class TransactionTests extends Common { // Create test generator account generator = new PrivateKeyAccount(repository, generatorSeed); - accountRepository.setLastReference(new AccountData(generator.getAddress(), generatorSeed, generator.getPublicKey(), Group.NO_GROUP, 0, null, 0)); - accountRepository.save(new AccountBalanceData(generator.getAddress(), Asset.QORA, initialGeneratorBalance)); + accountRepository.setLastReference(new AccountData(generator.getAddress(), generatorSeed, generator.getPublicKey(), Group.NO_GROUP, 0, null, 0, 0)); + accountRepository.save(new AccountBalanceData(generator.getAddress(), Asset.QORT, initialGeneratorBalance)); // Create test sender account sender = new PrivateKeyAccount(repository, senderSeed); // Mock account reference = senderSeed; - accountRepository.setLastReference(new AccountData(sender.getAddress(), reference, sender.getPublicKey(), Group.NO_GROUP, 0, null, 0)); + accountRepository.setLastReference(new AccountData(sender.getAddress(), reference, sender.getPublicKey(), Group.NO_GROUP, 0, null, 0, 0)); // Mock balance - accountRepository.save(new AccountBalanceData(sender.getAddress(), Asset.QORA, initialSenderBalance)); + accountRepository.save(new AccountBalanceData(sender.getAddress(), Asset.QORT, initialSenderBalance)); repository.saveChanges(); } @@ -170,17 +170,17 @@ public class TransactionTests extends Common { // Check sender's balance BigDecimal expectedBalance = initialSenderBalance.subtract(amount).subtract(fee); - BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance(); + BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORT).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(); + actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORT).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(); + actualBalance = accountRepository.getBalance(recipient.getAddress(), Asset.QORT).getBalance(); assertTrue("Recipient's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0); // Check recipient's reference @@ -192,11 +192,11 @@ public class TransactionTests extends Common { repository.saveChanges(); // Check sender's balance - actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance(); + actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORT).getBalance(); assertTrue("Sender's reverted balance incorrect", initialSenderBalance.compareTo(actualBalance) == 0); // Check generator's balance - actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance(); + actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORT).getBalance(); assertTrue("Generator's new balance incorrect", initialGeneratorBalance.compareTo(actualBalance) == 0); } @@ -230,12 +230,12 @@ public class TransactionTests extends Common { // Check sender's balance BigDecimal expectedBalance = initialSenderBalance.subtract(fee); - BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance(); + BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORT).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(); + actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORT).getBalance(); assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0); // Check name was registered @@ -494,12 +494,12 @@ public class TransactionTests extends Common { // Check sender's balance BigDecimal expectedBalance = initialSenderBalance.subtract(fee); - BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance(); + BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORT).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(); + actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORT).getBalance(); assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0); // Check poll was created @@ -598,9 +598,10 @@ public class TransactionTests extends Common { BigDecimal fee = BigDecimal.ONE; long timestamp = parentBlockData.getTimestamp() + 1_000; String data = (timestamp >= BlockChain.getInstance().getQoraV2Timestamp()) ? "{}" : null; + boolean isUnspendable = false; BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, sender.getPublicKey(), fee, null); - IssueAssetTransactionData issueAssetTransactionData = new IssueAssetTransactionData(baseTransactionData, sender.getAddress(), assetName, description, quantity, isDivisible, data); + IssueAssetTransactionData issueAssetTransactionData = new IssueAssetTransactionData(baseTransactionData, sender.getAddress(), assetName, description, quantity, isDivisible, data, isUnspendable); Transaction issueAssetTransaction = new IssueAssetTransaction(repository, issueAssetTransactionData); issueAssetTransaction.sign(sender); @@ -618,19 +619,19 @@ public class TransactionTests extends Common { // Check sender's balance BigDecimal expectedBalance = initialSenderBalance.subtract(fee); - BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance(); + BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORT).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(); + actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORT).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); + assertFalse(assetId == Asset.QORT); // Check asset now exists AssetRepository assetRepo = this.repository.getAssetRepository(); @@ -647,11 +648,11 @@ public class TransactionTests extends Common { repository.saveChanges(); // Check sender's balance - actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance(); + actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORT).getBalance(); assertTrue("Sender's reverted balance incorrect", initialSenderBalance.compareTo(actualBalance) == 0); // Check generator's balance - actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance(); + actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORT).getBalance(); assertTrue("Generator's reverted balance incorrect", initialGeneratorBalance.compareTo(actualBalance) == 0); // Check asset no longer exists @@ -678,8 +679,8 @@ public class TransactionTests extends Common { 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); + BigDecimal originalSenderBalance = sender.getConfirmedBalance(Asset.QORT); + BigDecimal originalGeneratorBalance = generator.getConfirmedBalance(Asset.QORT); // Transfer asset to new recipient Account recipient = new PublicKeyAccount(repository, recipientSeed); @@ -706,12 +707,12 @@ public class TransactionTests extends Common { // Check sender's balance BigDecimal expectedBalance = originalSenderBalance.subtract(fee); - BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance(); + BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORT).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(); + actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORT).getBalance(); assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0); // Check asset balances @@ -729,11 +730,11 @@ public class TransactionTests extends Common { repository.saveChanges(); // Check sender's balance - actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance(); + actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORT).getBalance(); assertTrue("Sender's reverted balance incorrect", originalSenderBalance.compareTo(actualBalance) == 0); // Check generator's balance - actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance(); + actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORT).getBalance(); assertTrue("Generator's reverted balance incorrect", originalGeneratorBalance.compareTo(actualBalance) == 0); // Check asset balances @@ -781,7 +782,7 @@ public class TransactionTests extends Common { parentBlockData = block.getBlockData(); // Order: buyer has 10 QORA and wants to buy "test asset" at a price of 50 "test asset" per QORA. - long haveAssetId = Asset.QORA; + long haveAssetId = Asset.QORT; BigDecimal amount = BigDecimal.valueOf(10).setScale(8); long wantAssetId = assetId; BigDecimal price = BigDecimal.valueOf(50).setScale(8); @@ -852,7 +853,7 @@ public class TransactionTests extends Common { PrivateKeyAccount buyer = new PrivateKeyAccount(repository, recipientSeed); // Fetch orders - long haveAssetId = Asset.QORA; + long haveAssetId = Asset.QORT; long wantAssetId = assetId; List orders = assetRepo.getOpenOrders(haveAssetId, wantAssetId); @@ -917,7 +918,7 @@ public class TransactionTests extends Common { PrivateKeyAccount buyer = new PrivateKeyAccount(repository, recipientSeed); // Fetch orders - long originalHaveAssetId = Asset.QORA; + long originalHaveAssetId = Asset.QORT; long originalWantAssetId = assetId; List orders = assetRepo.getOpenOrders(originalHaveAssetId, originalWantAssetId); @@ -937,7 +938,7 @@ public class TransactionTests extends Common { // This order should be a partial match for original order, and at a better price than asked long haveAssetId = assetId; BigDecimal amount = BigDecimal.valueOf(40).setScale(8); - long wantAssetId = Asset.QORA; + long wantAssetId = Asset.QORT; BigDecimal price = BigDecimal.ONE.setScale(8).divide(BigDecimal.valueOf(60).setScale(8), RoundingMode.DOWN); BigDecimal fee = BigDecimal.ONE; long timestamp = parentBlockData.getTimestamp() + 1_000; @@ -1041,7 +1042,7 @@ public class TransactionTests extends Common { byte[] seed = recipientSeed.clone(); seed[0] += i; Account recipient = new PublicKeyAccount(repository, seed); - long assetId = Asset.QORA; + long assetId = Asset.QORT; BigDecimal amount = BigDecimal.valueOf(1_000L + i).setScale(8); expectedSenderBalance = expectedSenderBalance.subtract(amount); @@ -1069,12 +1070,12 @@ public class TransactionTests extends Common { repository.saveChanges(); // Check sender's balance - BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance(); + BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORT).getBalance(); assertTrue("Sender's new balance incorrect", expectedSenderBalance.compareTo(actualBalance) == 0); // Fee should be in generator's balance BigDecimal expectedBalance = initialGeneratorBalance.add(fee); - actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance(); + actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORT).getBalance(); assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0); // Check recipients @@ -1087,7 +1088,7 @@ public class TransactionTests extends Common { // Amount should be in recipient's balance expectedBalance = paymentData.getAmount(); - actualBalance = accountRepository.getBalance(recipient.getAddress(), Asset.QORA).getBalance(); + actualBalance = accountRepository.getBalance(recipient.getAddress(), Asset.QORT).getBalance(); assertTrue("Recipient's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0); } @@ -1097,11 +1098,11 @@ public class TransactionTests extends Common { repository.saveChanges(); // Check sender's balance - actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance(); + actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORT).getBalance(); assertTrue("Sender's reverted balance incorrect", initialSenderBalance.compareTo(actualBalance) == 0); // Check generator's balance - actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORA).getBalance(); + actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORT).getBalance(); assertTrue("Generator's new balance incorrect", initialGeneratorBalance.compareTo(actualBalance) == 0); } @@ -1121,7 +1122,7 @@ public class TransactionTests extends Common { BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, sender.getPublicKey(), fee, null); MessageTransactionData messageTransactionData = new MessageTransactionData(baseTransactionData, version, - recipient.getAddress(), Asset.QORA, amount, data, isText, isEncrypted); + recipient.getAddress(), Asset.QORT, amount, data, isText, isEncrypted); Transaction messageTransaction = new MessageTransaction(repository, messageTransactionData); messageTransaction.sign(sender); @@ -1139,17 +1140,17 @@ public class TransactionTests extends Common { // Check sender's balance BigDecimal expectedBalance = initialSenderBalance.subtract(amount).subtract(fee); - BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORA).getBalance(); + BigDecimal actualBalance = accountRepository.getBalance(sender.getAddress(), Asset.QORT).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(); + actualBalance = accountRepository.getBalance(generator.getAddress(), Asset.QORT).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(); + actualBalance = accountRepository.getBalance(recipient.getAddress(), Asset.QORT).getBalance(); assertTrue("Recipient's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0); } diff --git a/src/test/java/org/qora/test/common/AssetUtils.java b/src/test/java/org/qora/test/common/AssetUtils.java index dabaf68f..fc40afa9 100644 --- a/src/test/java/org/qora/test/common/AssetUtils.java +++ b/src/test/java/org/qora/test/common/AssetUtils.java @@ -39,7 +39,7 @@ public class AssetUtils { long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1; BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, AssetUtils.txGroupId, reference, account.getPublicKey(), AssetUtils.fee, null); - TransactionData transactionData = new IssueAssetTransactionData(baseTransactionData, account.getAddress(), assetName, "desc", quantity, isDivisible, "{}"); + TransactionData transactionData = new IssueAssetTransactionData(baseTransactionData, account.getAddress(), assetName, "desc", quantity, isDivisible, "{}", false); TransactionUtils.signAndForge(repository, transactionData, account); diff --git a/src/test/java/org/qora/test/common/transaction/ArbitraryTestTransaction.java b/src/test/java/org/qora/test/common/transaction/ArbitraryTestTransaction.java index abb37648..3ada2849 100644 --- a/src/test/java/org/qora/test/common/transaction/ArbitraryTestTransaction.java +++ b/src/test/java/org/qora/test/common/transaction/ArbitraryTestTransaction.java @@ -25,7 +25,7 @@ public class ArbitraryTestTransaction extends TestTransaction { DataType dataType = DataType.RAW_DATA; String recipient = account.getAddress(); - final long assetId = Asset.QORA; + final long assetId = Asset.QORT; BigDecimal amount = BigDecimal.valueOf(123L); List payments = new ArrayList<>(); diff --git a/src/test/java/org/qora/test/common/transaction/AtTestTransaction.java b/src/test/java/org/qora/test/common/transaction/AtTestTransaction.java index e1b5d106..b5ceba18 100644 --- a/src/test/java/org/qora/test/common/transaction/AtTestTransaction.java +++ b/src/test/java/org/qora/test/common/transaction/AtTestTransaction.java @@ -18,7 +18,7 @@ public class AtTestTransaction extends TestTransaction { String atAddress = Crypto.toATAddress(signature); String recipient = account.getAddress(); BigDecimal amount = BigDecimal.valueOf(123); - final long assetId = Asset.QORA; + final long assetId = Asset.QORT; byte[] message = new byte[32]; random.nextBytes(message); diff --git a/src/test/java/org/qora/test/common/transaction/CreateAssetOrderTestTransaction.java b/src/test/java/org/qora/test/common/transaction/CreateAssetOrderTestTransaction.java index f1085d83..dc3911b5 100644 --- a/src/test/java/org/qora/test/common/transaction/CreateAssetOrderTestTransaction.java +++ b/src/test/java/org/qora/test/common/transaction/CreateAssetOrderTestTransaction.java @@ -12,7 +12,7 @@ import org.qora.repository.Repository; public class CreateAssetOrderTestTransaction extends TestTransaction { public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException { - final long haveAssetId = Asset.QORA; + final long haveAssetId = Asset.QORT; final long wantAssetId = 1; BigDecimal amount = BigDecimal.valueOf(123); BigDecimal price = BigDecimal.valueOf(123); diff --git a/src/test/java/org/qora/test/common/transaction/DeployAtTestTransaction.java b/src/test/java/org/qora/test/common/transaction/DeployAtTestTransaction.java index de5807e0..34e25389 100644 --- a/src/test/java/org/qora/test/common/transaction/DeployAtTestTransaction.java +++ b/src/test/java/org/qora/test/common/transaction/DeployAtTestTransaction.java @@ -22,7 +22,7 @@ public class DeployAtTestTransaction extends TestTransaction { byte[] creationBytes = new byte[1024]; random.nextBytes(creationBytes); BigDecimal amount = BigDecimal.valueOf(123); - final long assetId = Asset.QORA; + final long assetId = Asset.QORT; return new DeployAtTransactionData(generateBase(account), name, description, atType, tags, creationBytes, amount, assetId); } diff --git a/src/test/java/org/qora/test/common/transaction/IssueAssetTestTransaction.java b/src/test/java/org/qora/test/common/transaction/IssueAssetTestTransaction.java index 3d3c6537..1347d130 100644 --- a/src/test/java/org/qora/test/common/transaction/IssueAssetTestTransaction.java +++ b/src/test/java/org/qora/test/common/transaction/IssueAssetTestTransaction.java @@ -20,8 +20,9 @@ public class IssueAssetTestTransaction extends TestTransaction { final long quantity = 1_000_000L; final boolean isDivisible = true; String data = AssetUtils.randomData(); + final boolean isUnspendable = false; - return new IssueAssetTransactionData(generateBase(account), owner, assetName, description, quantity, isDivisible, data); + return new IssueAssetTransactionData(generateBase(account), owner, assetName, description, quantity, isDivisible, data, isUnspendable); } } diff --git a/src/test/java/org/qora/test/common/transaction/MessageTestTransaction.java b/src/test/java/org/qora/test/common/transaction/MessageTestTransaction.java index dabd983b..64a8c3eb 100644 --- a/src/test/java/org/qora/test/common/transaction/MessageTestTransaction.java +++ b/src/test/java/org/qora/test/common/transaction/MessageTestTransaction.java @@ -14,7 +14,7 @@ public class MessageTestTransaction extends TestTransaction { public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException { final int version = 3; String recipient = account.getAddress(); - final long assetId = Asset.QORA; + final long assetId = Asset.QORT; BigDecimal amount = BigDecimal.valueOf(123L); byte[] data = "message contents".getBytes(); final boolean isText = true; diff --git a/src/test/java/org/qora/test/common/transaction/MultiPaymentTestTransaction.java b/src/test/java/org/qora/test/common/transaction/MultiPaymentTestTransaction.java index c57de8a0..46e80487 100644 --- a/src/test/java/org/qora/test/common/transaction/MultiPaymentTestTransaction.java +++ b/src/test/java/org/qora/test/common/transaction/MultiPaymentTestTransaction.java @@ -16,7 +16,7 @@ public class MultiPaymentTestTransaction extends TestTransaction { public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException { String recipient = account.getAddress(); - final long assetId = Asset.QORA; + final long assetId = Asset.QORT; BigDecimal amount = BigDecimal.valueOf(123L); List payments = new ArrayList<>(); diff --git a/src/test/java/org/qora/test/common/transaction/TransferAssetTestTransaction.java b/src/test/java/org/qora/test/common/transaction/TransferAssetTestTransaction.java index d7e52530..879c35fe 100644 --- a/src/test/java/org/qora/test/common/transaction/TransferAssetTestTransaction.java +++ b/src/test/java/org/qora/test/common/transaction/TransferAssetTestTransaction.java @@ -13,7 +13,7 @@ public class TransferAssetTestTransaction extends TestTransaction { public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException { String recipient = account.getAddress(); - final long assetId = Asset.QORA; + final long assetId = Asset.QORT; BigDecimal amount = BigDecimal.valueOf(123); return new TransferAssetTransactionData(generateBase(account), recipient, amount, assetId); diff --git a/src/test/java/org/qora/test/forging/RewardTests.java b/src/test/java/org/qora/test/forging/RewardTests.java index c9704307..a78fc750 100644 --- a/src/test/java/org/qora/test/forging/RewardTests.java +++ b/src/test/java/org/qora/test/forging/RewardTests.java @@ -35,7 +35,7 @@ public class RewardTests extends Common { @Test public void testSimpleReward() throws DataException { try (final Repository repository = RepositoryManager.getRepository()) { - Map> initialBalances = AccountUtils.getBalances(repository, Asset.QORA); + Map> initialBalances = AccountUtils.getBalances(repository, Asset.QORT); PrivateKeyAccount forgingAccount = Common.getTestAccount(repository, "alice"); @@ -43,15 +43,15 @@ public class RewardTests extends Common { BlockGenerator.generateTestingBlock(repository, forgingAccount); - BigDecimal expectedBalance = initialBalances.get("alice").get(Asset.QORA).add(blockReward); - AccountUtils.assertBalance(repository, "alice", Asset.QORA, expectedBalance); + BigDecimal expectedBalance = initialBalances.get("alice").get(Asset.QORT).add(blockReward); + AccountUtils.assertBalance(repository, "alice", Asset.QORT, expectedBalance); } } @Test public void testRewards() throws DataException { try (final Repository repository = RepositoryManager.getRepository()) { - Map> initialBalances = AccountUtils.getBalances(repository, Asset.QORA); + Map> initialBalances = AccountUtils.getBalances(repository, Asset.QORT); PrivateKeyAccount forgingAccount = Common.getTestAccount(repository, "alice"); @@ -60,7 +60,7 @@ public class RewardTests extends Common { int rewardIndex = rewards.size() - 1; RewardByHeight rewardInfo = rewards.get(rewardIndex); - BigDecimal expectedBalance = initialBalances.get("alice").get(Asset.QORA); + BigDecimal expectedBalance = initialBalances.get("alice").get(Asset.QORT); for (int height = rewardInfo.height; height > 1; --height) { if (height < rewardInfo.height) { @@ -72,7 +72,7 @@ public class RewardTests extends Common { expectedBalance = expectedBalance.add(rewardInfo.reward); } - AccountUtils.assertBalance(repository, "alice", Asset.QORA, expectedBalance); + AccountUtils.assertBalance(repository, "alice", Asset.QORT, expectedBalance); } } @@ -84,17 +84,17 @@ public class RewardTests extends Common { byte[] proxyPrivateKey = AccountUtils.proxyForging(repository, "alice", "bob", share); PrivateKeyAccount proxyAccount = new PrivateKeyAccount(repository, proxyPrivateKey); - Map> initialBalances = AccountUtils.getBalances(repository, Asset.QORA); + Map> initialBalances = AccountUtils.getBalances(repository, Asset.QORT); BigDecimal blockReward = BlockUtils.getNextBlockReward(repository); BlockGenerator.generateTestingBlock(repository, proxyAccount); // We're expecting reward * 12.8% to Bob, the rest to Alice BigDecimal bobShare = blockReward.multiply(share.movePointLeft(2)).setScale(8, RoundingMode.DOWN); - AccountUtils.assertBalance(repository, "bob", Asset.QORA, initialBalances.get("bob").get(Asset.QORA).add(bobShare)); + AccountUtils.assertBalance(repository, "bob", Asset.QORT, initialBalances.get("bob").get(Asset.QORT).add(bobShare)); BigDecimal aliceShare = blockReward.subtract(bobShare); - AccountUtils.assertBalance(repository, "alice", Asset.QORA, initialBalances.get("alice").get(Asset.QORA).add(aliceShare)); + AccountUtils.assertBalance(repository, "alice", Asset.QORT, initialBalances.get("alice").get(Asset.QORT).add(aliceShare)); } } diff --git a/src/test/java/org/qora/test/group/GroupApprovalTests.java b/src/test/java/org/qora/test/group/GroupApprovalTests.java index fc7ead27..0d0ca29a 100644 --- a/src/test/java/org/qora/test/group/GroupApprovalTests.java +++ b/src/test/java/org/qora/test/group/GroupApprovalTests.java @@ -90,8 +90,8 @@ public class GroupApprovalTests extends Common { PrivateKeyAccount bobAccount = Common.getTestAccount(repository, "bob"); byte[] bobOriginalReference = bobAccount.getLastReference(); - BigDecimal aliceOriginalBalance = aliceAccount.getConfirmedBalance(Asset.QORA); - BigDecimal bobOriginalBalance = bobAccount.getConfirmedBalance(Asset.QORA); + BigDecimal aliceOriginalBalance = aliceAccount.getConfirmedBalance(Asset.QORT); + BigDecimal bobOriginalBalance = bobAccount.getConfirmedBalance(Asset.QORT); BigDecimal blockReward = BlockUtils.getNextBlockReward(repository); Transaction bobAssetTransaction = buildIssueAssetTransaction(repository, "bob", groupId); @@ -106,11 +106,11 @@ public class GroupApprovalTests extends Common { assertFalse("reference should have changed", Arrays.equals(bobOriginalReference, bobPostAssetReference)); // Bob's balance should have the fee removed, even though the transaction itself hasn't been approved yet - BigDecimal bobPostAssetBalance = bobAccount.getConfirmedBalance(Asset.QORA); + BigDecimal bobPostAssetBalance = bobAccount.getConfirmedBalance(Asset.QORT); Common.assertEqualBigDecimals("approval-pending transaction creator's balance incorrect", bobOriginalBalance.subtract(fee), bobPostAssetBalance); // Transaction fee should have ended up in forging account - BigDecimal alicePostAssetBalance = aliceAccount.getConfirmedBalance(Asset.QORA); + BigDecimal alicePostAssetBalance = aliceAccount.getConfirmedBalance(Asset.QORT); Common.assertEqualBigDecimals("block forger's balance incorrect", aliceOriginalBalance.add(blockReward).add(fee), alicePostAssetBalance); // Have Bob do a non-approval transaction to change his last-reference @@ -167,7 +167,7 @@ public class GroupApprovalTests extends Common { assertTrue("reference should be pre-payment", Arrays.equals(bobOriginalReference, bobReference)); // Also check Bob's balance is back to original value - BigDecimal bobBalance = bobAccount.getConfirmedBalance(Asset.QORA); + BigDecimal bobBalance = bobAccount.getConfirmedBalance(Asset.QORT); Common.assertEqualBigDecimals("reverted balance doesn't match original", bobOriginalBalance, bobBalance); } } @@ -438,7 +438,7 @@ public class GroupApprovalTests extends Common { long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1; BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, account.getPublicKey(), fee, null); - TransactionData transactionData = new IssueAssetTransactionData(baseTransactionData, account.getAddress(), "test asset", "test asset desc", 1000L, true, "{}"); + TransactionData transactionData = new IssueAssetTransactionData(baseTransactionData, account.getAddress(), "test asset", "test asset desc", 1000L, true, "{}", false); return Transaction.fromData(repository, transactionData); }