forked from Qortal/qortal
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.
This commit is contained in:
parent
a1e83109a8
commit
54d49e0f1d
@ -233,4 +233,11 @@ public class Account {
|
|||||||
this.repository.getAccountRepository().setLevel(accountData);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ public class AddressesResource {
|
|||||||
|
|
||||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
Account account = new Account(repository, address);
|
Account account = new Account(repository, address);
|
||||||
return account.getConfirmedBalance(Asset.QORA);
|
return account.getConfirmedBalance(Asset.QORT);
|
||||||
} catch (ApiException e) {
|
} catch (ApiException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (DataException e) {
|
} catch (DataException e) {
|
||||||
|
@ -318,14 +318,14 @@ public class AssetsResource {
|
|||||||
) @QueryParam("reverse") Boolean reverse) {
|
) @QueryParam("reverse") Boolean reverse) {
|
||||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
if (assetIds.isEmpty())
|
if (assetIds.isEmpty())
|
||||||
assetIds = Collections.singletonList(Asset.QORA);
|
assetIds = Collections.singletonList(Asset.QORT);
|
||||||
else
|
else
|
||||||
for (long assetId : assetIds)
|
for (long assetId : assetIds)
|
||||||
if (!repository.getAssetRepository().assetExists(assetId))
|
if (!repository.getAssetRepository().assetExists(assetId))
|
||||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ASSET_ID);
|
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ASSET_ID);
|
||||||
|
|
||||||
if (otherAssetIds.isEmpty())
|
if (otherAssetIds.isEmpty())
|
||||||
otherAssetIds = Collections.singletonList(Asset.QORA);
|
otherAssetIds = Collections.singletonList(Asset.QORT);
|
||||||
else
|
else
|
||||||
for (long assetId : otherAssetIds)
|
for (long assetId : otherAssetIds)
|
||||||
if (!repository.getAssetRepository().assetExists(assetId))
|
if (!repository.getAssetRepository().assetExists(assetId))
|
||||||
|
@ -10,9 +10,12 @@ import org.qora.repository.Repository;
|
|||||||
public class Asset {
|
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
|
// Other useful constants
|
||||||
|
|
||||||
@ -41,6 +44,7 @@ public class Asset {
|
|||||||
this.assetData = new AssetData(issueAssetTransactionData.getOwner(), issueAssetTransactionData.getAssetName(),
|
this.assetData = new AssetData(issueAssetTransactionData.getOwner(), issueAssetTransactionData.getAssetName(),
|
||||||
issueAssetTransactionData.getDescription(), issueAssetTransactionData.getQuantity(),
|
issueAssetTransactionData.getDescription(), issueAssetTransactionData.getQuantity(),
|
||||||
issueAssetTransactionData.getIsDivisible(), issueAssetTransactionData.getData(),
|
issueAssetTransactionData.getIsDivisible(), issueAssetTransactionData.getData(),
|
||||||
|
issueAssetTransactionData.getIsUnspendable(),
|
||||||
issueAssetTransactionData.getTxGroupId(), issueAssetTransactionData.getSignature());
|
issueAssetTransactionData.getTxGroupId(), issueAssetTransactionData.getSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ public class AT {
|
|||||||
boolean isFrozen = false;
|
boolean isFrozen = false;
|
||||||
Long frozenBalance = null;
|
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);
|
hadFatalError, isFrozen, frozenBalance);
|
||||||
|
|
||||||
this.atStateData = new ATStateData(atAddress, height, creation, null, null, BigDecimal.ZERO.setScale(8));
|
this.atStateData = new ATStateData(atAddress, height, creation, null, null, BigDecimal.ZERO.setScale(8));
|
||||||
|
@ -254,7 +254,7 @@ public class QoraATAPI extends API {
|
|||||||
try {
|
try {
|
||||||
Account atAccount = this.getATAccount();
|
Account atAccount = this.getATAccount();
|
||||||
|
|
||||||
return atAccount.getConfirmedBalance(Asset.QORA).unscaledValue().longValue();
|
return atAccount.getConfirmedBalance(Asset.QORT).unscaledValue().longValue();
|
||||||
} catch (DataException e) {
|
} catch (DataException e) {
|
||||||
throw new RuntimeException("AT API unable to fetch AT's current balance?", e);
|
throw new RuntimeException("AT API unable to fetch AT's current balance?", e);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import org.qora.block.BlockChain.BlockTimingByHeight;
|
|||||||
import org.qora.block.BlockChain.ShareByLevel;
|
import org.qora.block.BlockChain.ShareByLevel;
|
||||||
import org.qora.controller.Controller;
|
import org.qora.controller.Controller;
|
||||||
import org.qora.crypto.Crypto;
|
import org.qora.crypto.Crypto;
|
||||||
|
import org.qora.data.account.AccountBalanceData;
|
||||||
import org.qora.data.account.ProxyForgerData;
|
import org.qora.data.account.ProxyForgerData;
|
||||||
import org.qora.data.at.ATData;
|
import org.qora.data.at.ATData;
|
||||||
import org.qora.data.at.ATStateData;
|
import org.qora.data.at.ATStateData;
|
||||||
@ -1193,7 +1194,7 @@ public class Block {
|
|||||||
Account atAccount = new Account(this.repository, atState.getATAddress());
|
Account atAccount = new Account(this.repository, atState.getATAddress());
|
||||||
|
|
||||||
// Subtract AT-generated fees from AT accounts
|
// 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);
|
atRepository.save(atState);
|
||||||
}
|
}
|
||||||
@ -1341,7 +1342,7 @@ public class Block {
|
|||||||
Account atAccount = new Account(this.repository, atState.getATAddress());
|
Account atAccount = new Account(this.repository, atState.getATAddress());
|
||||||
|
|
||||||
// Return AT-generated fees to AT accounts
|
// 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
|
// Delete ATStateData for this height
|
||||||
@ -1359,6 +1360,7 @@ public class Block {
|
|||||||
final boolean isFounder;
|
final boolean isFounder;
|
||||||
final int level;
|
final int level;
|
||||||
final int shareBin;
|
final int shareBin;
|
||||||
|
final BigDecimal qoraAmount;
|
||||||
final Account recipientAccount;
|
final Account recipientAccount;
|
||||||
|
|
||||||
AccountInfo(Repository repository, int accountIndex, List<ShareByLevel> sharesByLevel) throws DataException {
|
AccountInfo(Repository repository, int accountIndex, List<ShareByLevel> sharesByLevel) throws DataException {
|
||||||
@ -1367,6 +1369,12 @@ public class Block {
|
|||||||
this.forgerAccount = new PublicKeyAccount(repository, this.proxyForgerData.getForgerPublicKey());
|
this.forgerAccount = new PublicKeyAccount(repository, this.proxyForgerData.getForgerPublicKey());
|
||||||
this.recipientAccount = new Account(repository, this.proxyForgerData.getRecipient());
|
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()) {
|
if (this.forgerAccount.isFounder()) {
|
||||||
this.isFounder = true;
|
this.isFounder = true;
|
||||||
this.level = 0;
|
this.level = 0;
|
||||||
@ -1395,17 +1403,17 @@ public class Block {
|
|||||||
if (forgerAccount.getAddress().equals(recipientAccount.getAddress())) {
|
if (forgerAccount.getAddress().equals(recipientAccount.getAddress())) {
|
||||||
// forger & recipient the same - simpler case
|
// forger & recipient the same - simpler case
|
||||||
LOGGER.trace(() -> String.format("Forger/recipient account %s share: %s", forgerAccount.getAddress(), accountAmount.toPlainString()));
|
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 {
|
} else {
|
||||||
// forger & recipient different - extra work needed
|
// forger & recipient different - extra work needed
|
||||||
BigDecimal recipientAmount = accountAmount.multiply(this.proxyForgerData.getShare()).divide(ONE_HUNDRED, RoundingMode.DOWN);
|
BigDecimal recipientAmount = accountAmount.multiply(this.proxyForgerData.getShare()).divide(ONE_HUNDRED, RoundingMode.DOWN);
|
||||||
BigDecimal forgerAmount = accountAmount.subtract(recipientAmount);
|
BigDecimal forgerAmount = accountAmount.subtract(recipientAmount);
|
||||||
|
|
||||||
LOGGER.trace(() -> String.format("Forger account %s share: %s", forgerAccount.getAddress(), forgerAmount.toPlainString()));
|
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()));
|
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<AccountInfo> 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
|
// Spread remainder across founder accounts
|
||||||
BigDecimal foundersAmount = totalAmount.subtract(sharedAmount);
|
BigDecimal foundersAmount = totalAmount.subtract(sharedAmount);
|
||||||
LOGGER.debug(String.format("Shared %s of %s, remaining %s to founders", sharedAmount.toPlainString(), totalAmount.toPlainString(), foundersAmount.toPlainString()));
|
LOGGER.debug(String.format("Shared %s of %s, remaining %s to founders", sharedAmount.toPlainString(), totalAmount.toPlainString(), foundersAmount.toPlainString()));
|
||||||
|
@ -106,6 +106,9 @@ public class BlockChain {
|
|||||||
}
|
}
|
||||||
List<ShareByLevel> sharesByLevel;
|
List<ShareByLevel> sharesByLevel;
|
||||||
|
|
||||||
|
/** Share of block reward/fees to legacy QORA coin holders */
|
||||||
|
BigDecimal qoraHoldersShare;
|
||||||
|
|
||||||
/** Block times by block height */
|
/** Block times by block height */
|
||||||
public static class BlockTimingByHeight {
|
public static class BlockTimingByHeight {
|
||||||
public int height;
|
public int height;
|
||||||
@ -284,6 +287,10 @@ public class BlockChain {
|
|||||||
return this.sharesByLevel;
|
return this.sharesByLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigDecimal getQoraHoldersShare() {
|
||||||
|
return this.qoraHoldersShare;
|
||||||
|
}
|
||||||
|
|
||||||
public List<ForgingTier> getForgingTiers() {
|
public List<ForgingTier> getForgingTiers() {
|
||||||
return this.forgingTiers;
|
return this.forgingTiers;
|
||||||
}
|
}
|
||||||
@ -368,6 +375,9 @@ public class BlockChain {
|
|||||||
if (this.sharesByLevel == null)
|
if (this.sharesByLevel == null)
|
||||||
Settings.throwValidationError("No \"sharesByLevel\" entry found in blockchain config");
|
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)
|
if (this.blockTimingsByHeight == null)
|
||||||
Settings.throwValidationError("No \"blockTimingsByHeight\" entry found in blockchain config");
|
Settings.throwValidationError("No \"blockTimingsByHeight\" entry found in blockchain config");
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ public class GenesisBlock extends Block {
|
|||||||
IssueAssetTransactionData issueAssetTransactionData = (IssueAssetTransactionData) transactionData;
|
IssueAssetTransactionData issueAssetTransactionData = (IssueAssetTransactionData) transactionData;
|
||||||
|
|
||||||
return new AssetData(issueAssetTransactionData.getOwner(), issueAssetTransactionData.getAssetName(), issueAssetTransactionData.getDescription(),
|
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());
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ public class AccountData {
|
|||||||
protected int defaultGroupId;
|
protected int defaultGroupId;
|
||||||
protected int flags;
|
protected int flags;
|
||||||
protected String forgingEnabler;
|
protected String forgingEnabler;
|
||||||
|
protected int initialLevel;
|
||||||
protected int level;
|
protected int level;
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
@ -24,18 +25,19 @@ public class AccountData {
|
|||||||
protected 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.address = address;
|
||||||
this.reference = reference;
|
this.reference = reference;
|
||||||
this.publicKey = publicKey;
|
this.publicKey = publicKey;
|
||||||
this.defaultGroupId = defaultGroupId;
|
this.defaultGroupId = defaultGroupId;
|
||||||
this.flags = flags;
|
this.flags = flags;
|
||||||
this.forgingEnabler = forgingEnabler;
|
this.forgingEnabler = forgingEnabler;
|
||||||
|
this.initialLevel = initialLevel;
|
||||||
this.level = level;
|
this.level = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccountData(String address) {
|
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
|
// Getters/Setters
|
||||||
@ -84,6 +86,14 @@ public class AccountData {
|
|||||||
this.forgingEnabler = forgingEnabler;
|
this.forgingEnabler = forgingEnabler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getInitialLevel() {
|
||||||
|
return this.initialLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInitialLevel(int level) {
|
||||||
|
this.initialLevel = level;
|
||||||
|
}
|
||||||
|
|
||||||
public int getLevel() {
|
public int getLevel() {
|
||||||
return this.level;
|
return this.level;
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ public class AssetData {
|
|||||||
private long quantity;
|
private long quantity;
|
||||||
private boolean isDivisible;
|
private boolean isDivisible;
|
||||||
private String data;
|
private String data;
|
||||||
|
private boolean isUnspendable;
|
||||||
private int creationGroupId;
|
private int creationGroupId;
|
||||||
// No need to expose this via API
|
// No need to expose this via API
|
||||||
@XmlTransient
|
@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.
|
// 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.assetId = assetId;
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@ -39,13 +40,14 @@ public class AssetData {
|
|||||||
this.quantity = quantity;
|
this.quantity = quantity;
|
||||||
this.isDivisible = isDivisible;
|
this.isDivisible = isDivisible;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
this.isUnspendable = isUnspendable;
|
||||||
this.creationGroupId = creationGroupId;
|
this.creationGroupId = creationGroupId;
|
||||||
this.reference = reference;
|
this.reference = reference;
|
||||||
}
|
}
|
||||||
|
|
||||||
// New asset with unassigned assetId
|
// New asset with unassigned assetId
|
||||||
public AssetData(String owner, String name, String description, long quantity, boolean isDivisible, String data, int creationGroupId, byte[] 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, creationGroupId, reference);
|
this(null, owner, name, description, quantity, isDivisible, data, isUnspendable, creationGroupId, reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getters/Setters
|
// Getters/Setters
|
||||||
@ -94,6 +96,10 @@ public class AssetData {
|
|||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getIsUnspendable() {
|
||||||
|
return this.isUnspendable;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCreationGroupId() {
|
public int getCreationGroupId() {
|
||||||
return this.creationGroupId;
|
return this.creationGroupId;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ public class GenesisTransactionData extends TransactionData {
|
|||||||
|
|
||||||
/** From repository (V1, where asset locked to QORA) */
|
/** From repository (V1, where asset locked to QORA) */
|
||||||
public GenesisTransactionData(BaseTransactionData baseTransactionData, String recipient, BigDecimal amount) {
|
public GenesisTransactionData(BaseTransactionData baseTransactionData, String recipient, BigDecimal amount) {
|
||||||
this(baseTransactionData, recipient, amount, Asset.QORA);
|
this(baseTransactionData, recipient, amount, Asset.QORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getters/Setters
|
// Getters/Setters
|
||||||
|
@ -37,6 +37,8 @@ public class IssueAssetTransactionData extends TransactionData {
|
|||||||
private boolean isDivisible;
|
private boolean isDivisible;
|
||||||
@Schema(description = "non-human-readable asset-related data, typically JSON", example = "{\"logo\": \"data:image/jpeg;base64,/9j/4AAQSkZJRgA==\"}")
|
@Schema(description = "non-human-readable asset-related data, typically JSON", example = "{\"logo\": \"data:image/jpeg;base64,/9j/4AAQSkZJRgA==\"}")
|
||||||
private String data;
|
private String data;
|
||||||
|
@Schema(description = "whether non-owner holders of asset are barred from using asset", example = "false")
|
||||||
|
private boolean isUnspendable;
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
@ -59,7 +61,7 @@ public class IssueAssetTransactionData extends TransactionData {
|
|||||||
|
|
||||||
/** From repository */
|
/** From repository */
|
||||||
public IssueAssetTransactionData(BaseTransactionData baseTransactionData,
|
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);
|
super(TransactionType.ISSUE_ASSET, baseTransactionData);
|
||||||
|
|
||||||
this.assetId = assetId;
|
this.assetId = assetId;
|
||||||
@ -70,11 +72,13 @@ public class IssueAssetTransactionData extends TransactionData {
|
|||||||
this.quantity = quantity;
|
this.quantity = quantity;
|
||||||
this.isDivisible = isDivisible;
|
this.isDivisible = isDivisible;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
this.isUnspendable = isUnspendable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** From network/API */
|
/** From network/API */
|
||||||
public IssueAssetTransactionData(BaseTransactionData baseTransactionData, String owner, String assetName, String description, long quantity, boolean isDivisible, String data) {
|
public IssueAssetTransactionData(BaseTransactionData baseTransactionData, String owner, String assetName, String description,
|
||||||
this(baseTransactionData, null, owner, assetName, description, quantity, isDivisible, data);
|
long quantity, boolean isDivisible, String data, boolean isUnspendable) {
|
||||||
|
this(baseTransactionData, null, owner, assetName, description, quantity, isDivisible, data, isUnspendable);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getters/Setters
|
// Getters/Setters
|
||||||
@ -119,4 +123,8 @@ public class IssueAssetTransactionData extends TransactionData {
|
|||||||
return this.data;
|
return this.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getIsUnspendable() {
|
||||||
|
return this.isUnspendable;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ public class MessageTransactionData extends TransactionData {
|
|||||||
if (assetId != null)
|
if (assetId != null)
|
||||||
this.assetId = assetId;
|
this.assetId = assetId;
|
||||||
else
|
else
|
||||||
this.assetId = Asset.QORA;
|
this.assetId = Asset.QORT;
|
||||||
|
|
||||||
this.amount = amount;
|
this.amount = amount;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
@ -158,13 +158,13 @@ public class Name {
|
|||||||
|
|
||||||
// Update seller's balance
|
// Update seller's balance
|
||||||
Account seller = new Account(this.repository, this.nameData.getOwner());
|
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
|
// Set new owner
|
||||||
Account buyer = new PublicKeyAccount(this.repository, buyNameTransactionData.getBuyerPublicKey());
|
Account buyer = new PublicKeyAccount(this.repository, buyNameTransactionData.getBuyerPublicKey());
|
||||||
this.nameData.setOwner(buyer.getAddress());
|
this.nameData.setOwner(buyer.getAddress());
|
||||||
// Update buyer's balance
|
// 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
|
// Update reference in transaction data
|
||||||
buyNameTransactionData.setNameReference(this.nameData.getReference());
|
buyNameTransactionData.setNameReference(this.nameData.getReference());
|
||||||
@ -189,14 +189,14 @@ public class Name {
|
|||||||
|
|
||||||
// Revert buyer's balance
|
// Revert buyer's balance
|
||||||
Account buyer = new PublicKeyAccount(this.repository, buyNameTransactionData.getBuyerPublicKey());
|
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
|
// Previous Name's owner and/or data taken from referenced transaction
|
||||||
this.revert();
|
this.revert();
|
||||||
|
|
||||||
// Revert seller's balance
|
// Revert seller's balance
|
||||||
Account seller = new Account(this.repository, this.nameData.getOwner());
|
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
|
// Save reverted name data
|
||||||
this.repository.getNameRepository().save(this.nameData);
|
this.repository.getNameRepository().save(this.nameData);
|
||||||
|
@ -47,7 +47,10 @@ public class Payment {
|
|||||||
// Total up payment amounts by assetId
|
// Total up payment amounts by assetId
|
||||||
Map<Long, BigDecimal> amountsByAssetId = new HashMap<Long, BigDecimal>();
|
Map<Long, BigDecimal> amountsByAssetId = new HashMap<Long, BigDecimal>();
|
||||||
// Add transaction fee to start with
|
// 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
|
// Check payments, and calculate amount total by assetId
|
||||||
for (PaymentData paymentData : payments) {
|
for (PaymentData paymentData : payments) {
|
||||||
@ -82,6 +85,10 @@ public class Payment {
|
|||||||
if (assetData == null)
|
if (assetData == null)
|
||||||
return ValidationResult.ASSET_DOES_NOT_EXIST;
|
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 we're sending to an AT then assetId must match AT's assetId
|
||||||
if (atData != null && atData.getAssetId() != paymentData.getAssetId())
|
if (atData != null && atData.getAssetId() != paymentData.getAssetId())
|
||||||
return ValidationResult.ASSET_DOES_NOT_MATCH_AT;
|
return ValidationResult.ASSET_DOES_NOT_MATCH_AT;
|
||||||
@ -95,7 +102,6 @@ public class Payment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check sender has enough of each asset
|
// Check sender has enough of each asset
|
||||||
Account sender = new PublicKeyAccount(this.repository, senderPublicKey);
|
|
||||||
for (Entry<Long, BigDecimal> pair : amountsByAssetId.entrySet())
|
for (Entry<Long, BigDecimal> pair : amountsByAssetId.entrySet())
|
||||||
if (sender.getConfirmedBalance(pair.getKey()).compareTo(pair.getValue()) < 0)
|
if (sender.getConfirmedBalance(pair.getKey()).compareTo(pair.getValue()) < 0)
|
||||||
return ValidationResult.NO_BALANCE;
|
return ValidationResult.NO_BALANCE;
|
||||||
@ -177,7 +183,7 @@ public class Payment {
|
|||||||
Account sender = new PublicKeyAccount(this.repository, senderPublicKey);
|
Account sender = new PublicKeyAccount(this.repository, senderPublicKey);
|
||||||
|
|
||||||
// Update sender's balance due to fee
|
// 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
|
// Update sender's reference
|
||||||
sender.setLastReference(signature);
|
sender.setLastReference(signature);
|
||||||
@ -189,7 +195,7 @@ public class Payment {
|
|||||||
long assetId = paymentData.getAssetId();
|
long assetId = paymentData.getAssetId();
|
||||||
|
|
||||||
// For QORA amounts only: if recipient has no reference yet, then this is their starting reference
|
// 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);
|
recipient.setLastReference(signature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,7 +236,7 @@ public class Payment {
|
|||||||
Account sender = new PublicKeyAccount(this.repository, senderPublicKey);
|
Account sender = new PublicKeyAccount(this.repository, senderPublicKey);
|
||||||
|
|
||||||
// Update sender's balance due to fee
|
// 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
|
// Update sender's reference
|
||||||
sender.setLastReference(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
|
* 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.
|
* (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);
|
recipient.setLastReference(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,13 @@ public interface AccountRepository {
|
|||||||
*/
|
*/
|
||||||
public void setLevel(AccountData accountData) throws DataException;
|
public void setLevel(AccountData accountData) throws DataException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves account's initial & current level, and public key if present, in repository.
|
||||||
|
* <p>
|
||||||
|
* 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.
|
* Saves account's forging enabler, and public key if present, in repository.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -26,7 +26,7 @@ public class HSQLDBAccountRepository implements AccountRepository {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AccountData getAccount(String address) throws DataException {
|
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)) {
|
try (ResultSet resultSet = this.repository.checkedExecute(sql, address)) {
|
||||||
if (resultSet == null)
|
if (resultSet == null)
|
||||||
@ -37,9 +37,10 @@ public class HSQLDBAccountRepository implements AccountRepository {
|
|||||||
int defaultGroupId = resultSet.getInt(3);
|
int defaultGroupId = resultSet.getInt(3);
|
||||||
int flags = resultSet.getInt(4);
|
int flags = resultSet.getInt(4);
|
||||||
String forgingEnabler = resultSet.getString(5);
|
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) {
|
} catch (SQLException e) {
|
||||||
throw new DataException("Unable to fetch account info from repository", 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
|
@Override
|
||||||
public void setForgingEnabler(AccountData accountData) throws DataException {
|
public void setForgingEnabler(AccountData accountData) throws DataException {
|
||||||
HSQLDBSaver saveHelper = new HSQLDBSaver("Accounts");
|
HSQLDBSaver saveHelper = new HSQLDBSaver("Accounts");
|
||||||
|
@ -28,7 +28,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AssetData fromAssetId(long assetId) throws DataException {
|
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)) {
|
try (ResultSet resultSet = this.repository.checkedExecute(sql, assetId)) {
|
||||||
if (resultSet == null)
|
if (resultSet == null)
|
||||||
@ -40,11 +40,12 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
|||||||
long quantity = resultSet.getLong(4);
|
long quantity = resultSet.getLong(4);
|
||||||
boolean isDivisible = resultSet.getBoolean(5);
|
boolean isDivisible = resultSet.getBoolean(5);
|
||||||
String data = resultSet.getString(6);
|
String data = resultSet.getString(6);
|
||||||
int creationGroupId = resultSet.getInt(7);
|
boolean isUnspendable = resultSet.getBoolean(7);
|
||||||
byte[] reference = resultSet.getBytes(8);
|
int creationGroupId = resultSet.getInt(8);
|
||||||
|
byte[] reference = resultSet.getBytes(9);
|
||||||
|
|
||||||
return new AssetData(assetId, owner, assetName, description, quantity, isDivisible, data, creationGroupId,
|
return new AssetData(assetId, owner, assetName, description, quantity, isDivisible, data, isUnspendable,
|
||||||
reference);
|
creationGroupId, reference);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new DataException("Unable to fetch asset from repository", e);
|
throw new DataException("Unable to fetch asset from repository", e);
|
||||||
}
|
}
|
||||||
@ -52,7 +53,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AssetData fromAssetName(String assetName) throws DataException {
|
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)) {
|
try (ResultSet resultSet = this.repository.checkedExecute(sql, assetName)) {
|
||||||
if (resultSet == null)
|
if (resultSet == null)
|
||||||
@ -64,11 +65,12 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
|||||||
long quantity = resultSet.getLong(4);
|
long quantity = resultSet.getLong(4);
|
||||||
boolean isDivisible = resultSet.getBoolean(5);
|
boolean isDivisible = resultSet.getBoolean(5);
|
||||||
String data = resultSet.getString(6);
|
String data = resultSet.getString(6);
|
||||||
int creationGroupId = resultSet.getInt(7);
|
boolean isUnspendable = resultSet.getBoolean(7);
|
||||||
byte[] reference = resultSet.getBytes(8);
|
int creationGroupId = resultSet.getInt(8);
|
||||||
|
byte[] reference = resultSet.getBytes(9);
|
||||||
|
|
||||||
return new AssetData(assetId, owner, assetName, description, quantity, isDivisible, data, creationGroupId,
|
return new AssetData(assetId, owner, assetName, description, quantity, isDivisible, data, isUnspendable,
|
||||||
reference);
|
creationGroupId, reference);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new DataException("Unable to fetch asset from repository", e);
|
throw new DataException("Unable to fetch asset from repository", e);
|
||||||
}
|
}
|
||||||
@ -95,7 +97,8 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
|||||||
@Override
|
@Override
|
||||||
public List<AssetData> getAllAssets(Integer limit, Integer offset, Boolean reverse) throws DataException {
|
public List<AssetData> getAllAssets(Integer limit, Integer offset, Boolean reverse) throws DataException {
|
||||||
StringBuilder sql = new StringBuilder(256);
|
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)
|
if (reverse != null && reverse)
|
||||||
sql.append(" DESC");
|
sql.append(" DESC");
|
||||||
|
|
||||||
@ -115,11 +118,12 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
|||||||
long quantity = resultSet.getLong(5);
|
long quantity = resultSet.getLong(5);
|
||||||
boolean isDivisible = resultSet.getBoolean(6);
|
boolean isDivisible = resultSet.getBoolean(6);
|
||||||
String data = resultSet.getString(7);
|
String data = resultSet.getString(7);
|
||||||
|
boolean isUnspendable = resultSet.getBoolean(7);
|
||||||
int creationGroupId = resultSet.getInt(8);
|
int creationGroupId = resultSet.getInt(8);
|
||||||
byte[] reference = resultSet.getBytes(9);
|
byte[] reference = resultSet.getBytes(9);
|
||||||
|
|
||||||
assets.add(new AssetData(assetId, owner, assetName, description, quantity, isDivisible, data,
|
assets.add(new AssetData(assetId, owner, assetName, description, quantity, isDivisible, data,
|
||||||
creationGroupId, reference));
|
isUnspendable,creationGroupId, reference));
|
||||||
} while (resultSet.next());
|
} while (resultSet.next());
|
||||||
|
|
||||||
return assets;
|
return assets;
|
||||||
@ -159,8 +163,8 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
|||||||
saveHelper.bind("asset_id", assetData.getAssetId()).bind("owner", assetData.getOwner())
|
saveHelper.bind("asset_id", assetData.getAssetId()).bind("owner", assetData.getOwner())
|
||||||
.bind("asset_name", assetData.getName()).bind("description", assetData.getDescription())
|
.bind("asset_name", assetData.getName()).bind("description", assetData.getDescription())
|
||||||
.bind("quantity", assetData.getQuantity()).bind("is_divisible", assetData.getIsDivisible())
|
.bind("quantity", assetData.getQuantity()).bind("is_divisible", assetData.getIsDivisible())
|
||||||
.bind("data", assetData.getData()).bind("creation_group_id", assetData.getCreationGroupId())
|
.bind("data", assetData.getData()).bind("is_unspendable", assetData.getIsUnspendable())
|
||||||
.bind("reference", assetData.getReference());
|
.bind("creation_group_id", assetData.getCreationGroupId()).bind("reference", assetData.getReference());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
saveHelper.execute(this.repository);
|
saveHelper.execute(this.repository);
|
||||||
|
@ -778,10 +778,11 @@ public class HSQLDBDatabaseUpdates {
|
|||||||
|
|
||||||
case 54:
|
case 54:
|
||||||
// Account 'level'
|
// 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");
|
stmt.execute("ALTER TABLE Accounts ADD COLUMN level TINYINT NOT NULL DEFAULT 0");
|
||||||
// Corresponding transaction to set level
|
// Corresponding transaction to set level
|
||||||
stmt.execute("CREATE TABLE AccountLevelTransactions (signature Signature, creator QoraPublicKey NOT NULL, target QoraAddress NOT NULL, level INT NOT NULL, "
|
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;
|
break;
|
||||||
|
|
||||||
case 55:
|
case 55:
|
||||||
@ -792,6 +793,12 @@ public class HSQLDBDatabaseUpdates {
|
|||||||
stmt.execute("ALTER TABLE Blocks ADD COLUMN online_accounts_signatures BLOB");
|
stmt.execute("ALTER TABLE Blocks ADD COLUMN online_accounts_signatures BLOB");
|
||||||
break;
|
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:
|
default:
|
||||||
// nothing to do
|
// nothing to do
|
||||||
return false;
|
return false;
|
||||||
|
@ -17,7 +17,7 @@ public class HSQLDBIssueAssetTransactionRepository extends HSQLDBTransactionRepo
|
|||||||
}
|
}
|
||||||
|
|
||||||
TransactionData fromBase(BaseTransactionData baseTransactionData) throws DataException {
|
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())) {
|
try (ResultSet resultSet = this.repository.checkedExecute(sql, baseTransactionData.getSignature())) {
|
||||||
if (resultSet == null)
|
if (resultSet == null)
|
||||||
@ -29,14 +29,15 @@ public class HSQLDBIssueAssetTransactionRepository extends HSQLDBTransactionRepo
|
|||||||
long quantity = resultSet.getLong(4);
|
long quantity = resultSet.getLong(4);
|
||||||
boolean isDivisible = resultSet.getBoolean(5);
|
boolean isDivisible = resultSet.getBoolean(5);
|
||||||
String data = resultSet.getString(6);
|
String data = resultSet.getString(6);
|
||||||
|
boolean isUnspendable = resultSet.getBoolean(7);
|
||||||
|
|
||||||
// Special null-checking for asset ID
|
// Special null-checking for asset ID
|
||||||
Long assetId = resultSet.getLong(7);
|
Long assetId = resultSet.getLong(8);
|
||||||
if (assetId == 0 && resultSet.wasNull())
|
if (assetId == 0 && resultSet.wasNull())
|
||||||
assetId = null;
|
assetId = null;
|
||||||
|
|
||||||
return new IssueAssetTransactionData(baseTransactionData, assetId, owner, assetName, description, quantity, isDivisible,
|
return new IssueAssetTransactionData(baseTransactionData, assetId, owner, assetName, description, quantity, isDivisible,
|
||||||
data);
|
data, isUnspendable);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new DataException("Unable to fetch issue asset transaction from repository", 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())
|
saveHelper.bind("signature", issueAssetTransactionData.getSignature()).bind("issuer", issueAssetTransactionData.getIssuerPublicKey())
|
||||||
.bind("owner", issueAssetTransactionData.getOwner()).bind("asset_name", issueAssetTransactionData.getAssetName())
|
.bind("owner", issueAssetTransactionData.getOwner()).bind("asset_name", issueAssetTransactionData.getAssetName())
|
||||||
.bind("description", issueAssetTransactionData.getDescription()).bind("quantity", issueAssetTransactionData.getQuantity())
|
.bind("description", issueAssetTransactionData.getDescription()).bind("quantity", issueAssetTransactionData.getQuantity())
|
||||||
.bind("is_divisible", issueAssetTransactionData.getIsDivisible())
|
.bind("is_divisible", issueAssetTransactionData.getIsDivisible()).bind("data", issueAssetTransactionData.getData())
|
||||||
.bind("data", issueAssetTransactionData.getData()).bind("asset_id", issueAssetTransactionData.getAssetId());
|
.bind("is_unspendable", issueAssetTransactionData.getIsUnspendable()).bind("asset_id", issueAssetTransactionData.getAssetId());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
saveHelper.execute(this.repository);
|
saveHelper.execute(this.repository);
|
||||||
|
@ -77,7 +77,7 @@ public class AccountFlagsTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check creator has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -77,7 +77,7 @@ public class AccountLevelTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check creator has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
@ -86,15 +86,12 @@ public class AccountLevelTransaction extends Transaction {
|
|||||||
@Override
|
@Override
|
||||||
public void process() throws DataException {
|
public void process() throws DataException {
|
||||||
Account target = getTarget();
|
Account target = getTarget();
|
||||||
Integer previousLevel = target.getLevel();
|
|
||||||
|
|
||||||
accountLevelTransactionData.setPreviousLevel(previousLevel);
|
// Save this transaction
|
||||||
|
|
||||||
// Save this transaction with target account's previous level value
|
|
||||||
this.repository.getTransactionRepository().save(accountLevelTransactionData);
|
this.repository.getTransactionRepository().save(accountLevelTransactionData);
|
||||||
|
|
||||||
// Set account's new level
|
// Set account's initial level
|
||||||
target.setLevel(this.accountLevelTransactionData.getLevel());
|
target.setInitialLevel(this.accountLevelTransactionData.getLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -102,17 +99,8 @@ public class AccountLevelTransaction extends Transaction {
|
|||||||
// Revert
|
// Revert
|
||||||
Account target = getTarget();
|
Account target = getTarget();
|
||||||
|
|
||||||
Integer previousLevel = accountLevelTransactionData.getPreviousLevel();
|
// This is only ever a genesis block transaction so simply delete account
|
||||||
|
this.repository.getAccountRepository().delete(target.getAddress());
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ public class AddGroupAdminTransaction extends Transaction {
|
|||||||
return ValidationResult.ALREADY_GROUP_ADMIN;
|
return ValidationResult.ALREADY_GROUP_ADMIN;
|
||||||
|
|
||||||
// Check group owner has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -71,7 +71,7 @@ public class ArbitraryTransaction extends Transaction {
|
|||||||
if (arbitraryTransactionData.getVersion() != 1)
|
if (arbitraryTransactionData.getVersion() != 1)
|
||||||
for (PaymentData paymentData : arbitraryTransactionData.getPayments())
|
for (PaymentData paymentData : arbitraryTransactionData.getPayments())
|
||||||
// We're only interested in QORA
|
// We're only interested in QORA
|
||||||
if (paymentData.getAssetId() == Asset.QORA) {
|
if (paymentData.getAssetId() == Asset.QORT) {
|
||||||
if (address.equals(paymentData.getRecipient()))
|
if (address.equals(paymentData.getRecipient()))
|
||||||
amount = amount.add(paymentData.getAmount());
|
amount = amount.add(paymentData.getAmount());
|
||||||
else if (address.equals(senderAddress))
|
else if (address.equals(senderAddress))
|
||||||
|
@ -84,12 +84,12 @@ public class AtTransaction extends Transaction {
|
|||||||
if (address.equals(atAddress)) {
|
if (address.equals(atAddress)) {
|
||||||
amount = amount.subtract(this.atTransactionData.getFee());
|
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());
|
amount = amount.subtract(this.atTransactionData.getAmount());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address.equals(this.atTransactionData.getRecipient()) && this.atTransactionData.getAmount() != null
|
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());
|
amount = amount.add(this.atTransactionData.getAmount());
|
||||||
|
|
||||||
return amount;
|
return amount;
|
||||||
@ -183,7 +183,7 @@ public class AtTransaction extends Transaction {
|
|||||||
long assetId = this.atTransactionData.getAssetId();
|
long assetId = this.atTransactionData.getAssetId();
|
||||||
|
|
||||||
// For QORA amounts only: if recipient has no reference yet, then this is their starting reference
|
// 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 Qora1 last reference was set to 64-bytes of zero
|
||||||
// In Qora2 we use AT-Transction's signature, which makes more sense
|
// In Qora2 we use AT-Transction's signature, which makes more sense
|
||||||
recipient.setLastReference(this.atTransactionData.getSignature());
|
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
|
* 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.
|
* (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);
|
recipient.setLastReference(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ public class BuyNameTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check issuer has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -89,7 +89,7 @@ public class CancelAssetOrderTransaction extends Transaction {
|
|||||||
return ValidationResult.INVALID_ORDER_CREATOR;
|
return ValidationResult.INVALID_ORDER_CREATOR;
|
||||||
|
|
||||||
// Check creator has enough QORA for fee
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -100,7 +100,7 @@ public class CancelGroupBanTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check creator has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -100,7 +100,7 @@ public class CancelGroupInviteTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check creator has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -96,7 +96,7 @@ public class CancelSellNameTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check issuer has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -101,6 +101,10 @@ public class CreateAssetOrderTransaction extends Transaction {
|
|||||||
if (wantAssetData == null)
|
if (wantAssetData == null)
|
||||||
return ValidationResult.ASSET_DOES_NOT_EXIST;
|
return ValidationResult.ASSET_DOES_NOT_EXIST;
|
||||||
|
|
||||||
|
// Unspendable assets are not tradable
|
||||||
|
if (haveAssetData.getIsUnspendable() || wantAssetData.getIsUnspendable())
|
||||||
|
return ValidationResult.ASSET_NOT_SPENDABLE;
|
||||||
|
|
||||||
Account creator = getCreator();
|
Account creator = getCreator();
|
||||||
|
|
||||||
boolean isNewPricing = createOrderTransactionData.getTimestamp() >= BlockChain.getInstance().getNewAssetPricingTimestamp();
|
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
|
// 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 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
|
// 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;
|
return ValidationResult.NO_BALANCE;
|
||||||
} else {
|
} else {
|
||||||
// Check creator has enough funds for amount in whatever asset
|
// 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
|
// Check creator has enough funds for fee in QORA
|
||||||
// NOTE: in Gen1 pre-POWFIX-RELEASE transactions didn't have this check
|
// NOTE: in Gen1 pre-POWFIX-RELEASE transactions didn't have this check
|
||||||
if (createOrderTransactionData.getTimestamp() >= BlockChain.getInstance().getPowFixReleaseTimestamp()
|
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;
|
return ValidationResult.NO_BALANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ public class CreateGroupTransaction extends Transaction {
|
|||||||
Account creator = getCreator();
|
Account creator = getCreator();
|
||||||
|
|
||||||
// Check creator has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -133,7 +133,7 @@ public class CreatePollTransaction extends Transaction {
|
|||||||
Account creator = getCreator();
|
Account creator = getCreator();
|
||||||
|
|
||||||
// Check issuer has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -162,6 +162,10 @@ public class DeployAtTransaction extends Transaction {
|
|||||||
if (assetData == null)
|
if (assetData == null)
|
||||||
return ValidationResult.ASSET_DOES_NOT_EXIST;
|
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
|
// Check asset amount is integer if asset is not divisible
|
||||||
if (!assetData.getIsDivisible() && deployATTransactionData.getAmount().stripTrailingZeros().scale() > 0)
|
if (!assetData.getIsDivisible() && deployATTransactionData.getAmount().stripTrailingZeros().scale() > 0)
|
||||||
return ValidationResult.INVALID_AMOUNT;
|
return ValidationResult.INVALID_AMOUNT;
|
||||||
@ -173,14 +177,14 @@ public class DeployAtTransaction extends Transaction {
|
|||||||
Account creator = getCreator();
|
Account creator = getCreator();
|
||||||
|
|
||||||
// Check creator has enough funds
|
// Check creator has enough funds
|
||||||
if (assetId == Asset.QORA) {
|
if (assetId == Asset.QORT) {
|
||||||
// Simple case: amount and fee both in Qora
|
// Simple case: amount and fee both in Qora
|
||||||
BigDecimal minimumBalance = deployATTransactionData.getFee().add(deployATTransactionData.getAmount());
|
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;
|
return ValidationResult.NO_BALANCE;
|
||||||
} else {
|
} else {
|
||||||
if (creator.getConfirmedBalance(Asset.QORA).compareTo(deployATTransactionData.getFee()) < 0)
|
if (creator.getConfirmedBalance(Asset.QORT).compareTo(deployATTransactionData.getFee()) < 0)
|
||||||
return ValidationResult.NO_BALANCE;
|
return ValidationResult.NO_BALANCE;
|
||||||
|
|
||||||
if (creator.getConfirmedBalance(assetId).compareTo(deployATTransactionData.getAmount()) < 0)
|
if (creator.getConfirmedBalance(assetId).compareTo(deployATTransactionData.getAmount()) < 0)
|
||||||
@ -209,14 +213,14 @@ public class DeployAtTransaction extends Transaction {
|
|||||||
long assetId = deployATTransactionData.getAssetId();
|
long assetId = deployATTransactionData.getAssetId();
|
||||||
|
|
||||||
// Check creator has enough funds
|
// Check creator has enough funds
|
||||||
if (assetId == Asset.QORA) {
|
if (assetId == Asset.QORT) {
|
||||||
// Simple case: amount and fee both in Qora
|
// Simple case: amount and fee both in Qora
|
||||||
BigDecimal minimumBalance = deployATTransactionData.getFee().add(deployATTransactionData.getAmount());
|
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;
|
return ValidationResult.NO_BALANCE;
|
||||||
} else {
|
} else {
|
||||||
if (creator.getConfirmedBalance(Asset.QORA).compareTo(deployATTransactionData.getFee()) < 0)
|
if (creator.getConfirmedBalance(Asset.QORT).compareTo(deployATTransactionData.getFee()) < 0)
|
||||||
return ValidationResult.NO_BALANCE;
|
return ValidationResult.NO_BALANCE;
|
||||||
|
|
||||||
if (creator.getConfirmedBalance(assetId).compareTo(deployATTransactionData.getAmount()) < 0)
|
if (creator.getConfirmedBalance(assetId).compareTo(deployATTransactionData.getAmount()) < 0)
|
||||||
|
@ -121,7 +121,7 @@ public class EnableForgingTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check creator has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -139,7 +139,7 @@ public class GenesisTransaction extends Transaction {
|
|||||||
Account recipient = new Account(repository, genesisTransactionData.getRecipient());
|
Account recipient = new Account(repository, genesisTransactionData.getRecipient());
|
||||||
|
|
||||||
// Update recipient's balance
|
// Update recipient's balance
|
||||||
recipient.setConfirmedBalance(Asset.QORA, genesisTransactionData.getAmount());
|
recipient.setConfirmedBalance(Asset.QORT, genesisTransactionData.getAmount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -87,7 +87,7 @@ public class GroupApprovalTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check creator has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -101,7 +101,7 @@ public class GroupBanTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check admin has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -107,7 +107,7 @@ public class GroupInviteTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check creator has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -107,7 +107,7 @@ public class GroupKickTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check creator has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -120,7 +120,7 @@ public class IssueAssetTransaction extends Transaction {
|
|||||||
Account issuer = getIssuer();
|
Account issuer = getIssuer();
|
||||||
|
|
||||||
// Check issuer has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -87,7 +87,7 @@ public class JoinGroupTransaction extends Transaction {
|
|||||||
if (joinGroupTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
|
if (joinGroupTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
|
||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
// Check creator has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -86,7 +86,7 @@ public class LeaveGroupTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check creator has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -61,7 +61,7 @@ public class MessageTransaction extends Transaction {
|
|||||||
amount = amount.subtract(this.transactionData.getFee());
|
amount = amount.subtract(this.transactionData.getFee());
|
||||||
|
|
||||||
// We're only interested in QORA
|
// We're only interested in QORA
|
||||||
if (messageTransactionData.getAssetId() == Asset.QORA) {
|
if (messageTransactionData.getAssetId() == Asset.QORT) {
|
||||||
if (address.equals(messageTransactionData.getRecipient()))
|
if (address.equals(messageTransactionData.getRecipient()))
|
||||||
amount = amount.add(messageTransactionData.getAmount());
|
amount = amount.add(messageTransactionData.getAmount());
|
||||||
else if (address.equals(senderAddress))
|
else if (address.equals(senderAddress))
|
||||||
|
@ -68,7 +68,7 @@ public class MultiPaymentTransaction extends Transaction {
|
|||||||
|
|
||||||
// We're only interested in QORA
|
// We're only interested in QORA
|
||||||
for (PaymentData paymentData : multiPaymentTransactionData.getPayments())
|
for (PaymentData paymentData : multiPaymentTransactionData.getPayments())
|
||||||
if (paymentData.getAssetId() == Asset.QORA) {
|
if (paymentData.getAssetId() == Asset.QORT) {
|
||||||
if (address.equals(paymentData.getRecipient()))
|
if (address.equals(paymentData.getRecipient()))
|
||||||
amount = amount.add(paymentData.getAmount());
|
amount = amount.add(paymentData.getAmount());
|
||||||
else if (address.equals(senderAddress))
|
else if (address.equals(senderAddress))
|
||||||
@ -104,7 +104,7 @@ public class MultiPaymentTransaction extends Transaction {
|
|||||||
// Check sender has enough funds for fee
|
// Check sender has enough funds for fee
|
||||||
// NOTE: in Gen1 pre-POWFIX-RELEASE transactions didn't have this check
|
// NOTE: in Gen1 pre-POWFIX-RELEASE transactions didn't have this check
|
||||||
if (multiPaymentTransactionData.getTimestamp() >= BlockChain.getInstance().getPowFixReleaseTimestamp()
|
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 ValidationResult.NO_BALANCE;
|
||||||
|
|
||||||
return new Payment(this.repository).isValid(multiPaymentTransactionData.getSenderPublicKey(), payments, multiPaymentTransactionData.getFee());
|
return new Payment(this.repository).isValid(multiPaymentTransactionData.getSenderPublicKey(), payments, multiPaymentTransactionData.getFee());
|
||||||
|
@ -71,7 +71,7 @@ public class PaymentTransaction extends Transaction {
|
|||||||
// Processing
|
// Processing
|
||||||
|
|
||||||
private PaymentData getPaymentData() {
|
private PaymentData getPaymentData() {
|
||||||
return new PaymentData(paymentTransactionData.getRecipient(), Asset.QORA, paymentTransactionData.getAmount());
|
return new PaymentData(paymentTransactionData.getRecipient(), Asset.QORT, paymentTransactionData.getAmount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -120,7 +120,7 @@ public class ProxyForgingTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check creator has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -100,7 +100,7 @@ public class RegisterNameTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check issuer has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -100,7 +100,7 @@ public class RemoveGroupAdminTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check creator has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -107,7 +107,7 @@ public class SellNameTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check issuer has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -74,7 +74,7 @@ public class SetGroupTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check creator has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -239,6 +239,7 @@ public abstract class Transaction {
|
|||||||
NO_BLOCKCHAIN_LOCK(86),
|
NO_BLOCKCHAIN_LOCK(86),
|
||||||
ORDER_ALREADY_CLOSED(87),
|
ORDER_ALREADY_CLOSED(87),
|
||||||
CLOCK_NOT_SYNCED(88),
|
CLOCK_NOT_SYNCED(88),
|
||||||
|
ASSET_NOT_SPENDABLE(89),
|
||||||
NOT_YET_RELEASED(1000);
|
NOT_YET_RELEASED(1000);
|
||||||
|
|
||||||
public final int value;
|
public final int value;
|
||||||
@ -946,7 +947,7 @@ public abstract class Transaction {
|
|||||||
Account creator = getCreator();
|
Account creator = getCreator();
|
||||||
|
|
||||||
// Update transaction creator's balance
|
// 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
|
// Update transaction creator's reference
|
||||||
creator.setLastReference(transactionData.getSignature());
|
creator.setLastReference(transactionData.getSignature());
|
||||||
@ -970,7 +971,7 @@ public abstract class Transaction {
|
|||||||
Account creator = getCreator();
|
Account creator = getCreator();
|
||||||
|
|
||||||
// Update transaction creator's balance
|
// 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
|
// Update transaction creator's reference
|
||||||
creator.setLastReference(transactionData.getReference());
|
creator.setLastReference(transactionData.getReference());
|
||||||
|
@ -58,7 +58,7 @@ public class TransferAssetTransaction extends Transaction {
|
|||||||
amount = amount.subtract(this.transactionData.getFee());
|
amount = amount.subtract(this.transactionData.getFee());
|
||||||
|
|
||||||
// We're only interested in QORA amounts
|
// We're only interested in QORA amounts
|
||||||
if (transferAssetTransactionData.getAssetId() == Asset.QORA) {
|
if (transferAssetTransactionData.getAssetId() == Asset.QORT) {
|
||||||
if (address.equals(transferAssetTransactionData.getRecipient()))
|
if (address.equals(transferAssetTransactionData.getRecipient()))
|
||||||
amount = amount.add(transferAssetTransactionData.getAmount());
|
amount = amount.add(transferAssetTransactionData.getAmount());
|
||||||
else if (address.equals(senderAddress))
|
else if (address.equals(senderAddress))
|
||||||
|
@ -110,7 +110,7 @@ public class UpdateAssetTransaction extends Transaction {
|
|||||||
Account currentOwner = getOwner();
|
Account currentOwner = getOwner();
|
||||||
|
|
||||||
// Check current owner has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -105,7 +105,7 @@ public class UpdateGroupTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check creator has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -110,7 +110,7 @@ public class UpdateNameTransaction extends Transaction {
|
|||||||
return ValidationResult.NEGATIVE_FEE;
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
// Check issuer has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -110,7 +110,7 @@ public class VoteOnPollTransaction extends Transaction {
|
|||||||
Account voter = getVoter();
|
Account voter = getVoter();
|
||||||
|
|
||||||
// Check voter has enough funds
|
// 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.NO_BALANCE;
|
||||||
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
|
@ -87,7 +87,7 @@ public class DeployAtTransactionTransformer extends TransactionTransformer {
|
|||||||
|
|
||||||
BigDecimal amount = Serialization.deserializeBigDecimal(byteBuffer);
|
BigDecimal amount = Serialization.deserializeBigDecimal(byteBuffer);
|
||||||
|
|
||||||
long assetId = Asset.QORA;
|
long assetId = Asset.QORT;
|
||||||
if (version >= 4)
|
if (version >= 4)
|
||||||
assetId = byteBuffer.getLong();
|
assetId = byteBuffer.getLong();
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ public class GenesisTransactionTransformer extends TransactionTransformer {
|
|||||||
|
|
||||||
BigDecimal amount = Serialization.deserializeBigDecimal(byteBuffer);
|
BigDecimal amount = Serialization.deserializeBigDecimal(byteBuffer);
|
||||||
|
|
||||||
long assetId = Asset.QORA;
|
long assetId = Asset.QORT;
|
||||||
if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
|
if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
|
||||||
assetId = byteBuffer.getLong();
|
assetId = byteBuffer.getLong();
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
|||||||
private static final int IS_DIVISIBLE_LENGTH = BOOLEAN_LENGTH;
|
private static final int IS_DIVISIBLE_LENGTH = BOOLEAN_LENGTH;
|
||||||
private static final int ASSET_REFERENCE_LENGTH = REFERENCE_LENGTH;
|
private static final int ASSET_REFERENCE_LENGTH = REFERENCE_LENGTH;
|
||||||
private static final int DATA_SIZE_LENGTH = INT_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
|
private static final int EXTRAS_LENGTH = OWNER_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + QUANTITY_LENGTH
|
||||||
+ IS_DIVISIBLE_LENGTH;
|
+ IS_DIVISIBLE_LENGTH;
|
||||||
@ -50,6 +51,7 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
|||||||
layout.add("can asset quantities be fractional?", TransformationType.BOOLEAN);
|
layout.add("can asset quantities be fractional?", TransformationType.BOOLEAN);
|
||||||
layout.add("asset data length", TransformationType.INT);
|
layout.add("asset data length", TransformationType.INT);
|
||||||
layout.add("asset data", TransformationType.STRING);
|
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("fee", TransformationType.AMOUNT);
|
||||||
layout.add("signature", TransformationType.SIGNATURE);
|
layout.add("signature", TransformationType.SIGNATURE);
|
||||||
}
|
}
|
||||||
@ -76,16 +78,18 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
|||||||
|
|
||||||
boolean isDivisible = byteBuffer.get() != 0;
|
boolean isDivisible = byteBuffer.get() != 0;
|
||||||
|
|
||||||
// in v2, assets have "data" field
|
|
||||||
String data = "";
|
|
||||||
if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
|
|
||||||
data = Serialization.deserializeSizedString(byteBuffer, Asset.MAX_DATA_SIZE);
|
|
||||||
|
|
||||||
byte[] assetReference = new byte[ASSET_REFERENCE_LENGTH];
|
byte[] assetReference = new byte[ASSET_REFERENCE_LENGTH];
|
||||||
// In v1, IssueAssetTransaction uses Asset.parse which also deserializes
|
String data = "";
|
||||||
// reference.
|
boolean isUnspendable = false;
|
||||||
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);
|
byteBuffer.get(assetReference);
|
||||||
|
}
|
||||||
|
|
||||||
BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer);
|
BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer);
|
||||||
|
|
||||||
@ -94,7 +98,7 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
|||||||
|
|
||||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, issuerPublicKey, fee, signature);
|
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 {
|
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
||||||
@ -104,14 +108,13 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
|||||||
+ Utf8.encodedLength(issueAssetTransactionData.getAssetName())
|
+ Utf8.encodedLength(issueAssetTransactionData.getAssetName())
|
||||||
+ Utf8.encodedLength(issueAssetTransactionData.getDescription());
|
+ Utf8.encodedLength(issueAssetTransactionData.getDescription());
|
||||||
|
|
||||||
// In v2, assets have "data" field
|
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());
|
dataLength += DATA_SIZE_LENGTH + Utf8.encodedLength(issueAssetTransactionData.getData()) + IS_UNSPENDABLE_LENGTH;
|
||||||
|
} else {
|
||||||
// In v1, IssueAssetTransaction uses Asset.toBytes which also serializes
|
// In v1, IssueAssetTransaction uses Asset.toBytes which also serializes reference.
|
||||||
// reference.
|
|
||||||
if (transactionData.getTimestamp() < BlockChain.getInstance().getQoraV2Timestamp())
|
|
||||||
dataLength += ASSET_REFERENCE_LENGTH;
|
dataLength += ASSET_REFERENCE_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
return dataLength;
|
return dataLength;
|
||||||
}
|
}
|
||||||
@ -133,14 +136,14 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
|
|||||||
bytes.write(Longs.toByteArray(issueAssetTransactionData.getQuantity()));
|
bytes.write(Longs.toByteArray(issueAssetTransactionData.getQuantity()));
|
||||||
bytes.write((byte) (issueAssetTransactionData.getIsDivisible() ? 1 : 0));
|
bytes.write((byte) (issueAssetTransactionData.getIsDivisible() ? 1 : 0));
|
||||||
|
|
||||||
// In v2, assets have "data"
|
// In v2, assets have additional fields.
|
||||||
if (transactionData.getTimestamp() >= BlockChain.getInstance().getQoraV2Timestamp())
|
if (transactionData.getTimestamp() >= BlockChain.getInstance().getQoraV2Timestamp()) {
|
||||||
Serialization.serializeSizedString(bytes, issueAssetTransactionData.getData());
|
Serialization.serializeSizedString(bytes, issueAssetTransactionData.getData());
|
||||||
|
bytes.write((byte) (issueAssetTransactionData.getIsUnspendable() ? 1 : 0));
|
||||||
// In v1, IssueAssetTransaction uses Asset.toBytes which also
|
} else {
|
||||||
// serializes Asset's reference which is the IssueAssetTransaction's
|
// In v1, IssueAssetTransaction uses Asset.toBytes which also
|
||||||
// signature
|
// serializes Asset's reference which is the IssueAssetTransaction's
|
||||||
if (transactionData.getTimestamp() < BlockChain.getInstance().getQoraV2Timestamp()) {
|
// signature
|
||||||
byte[] assetReference = issueAssetTransactionData.getSignature();
|
byte[] assetReference = issueAssetTransactionData.getSignature();
|
||||||
if (assetReference != null)
|
if (assetReference != null)
|
||||||
bytes.write(assetReference);
|
bytes.write(assetReference);
|
||||||
|
@ -68,7 +68,7 @@ public class MessageTransactionTransformer extends TransactionTransformer {
|
|||||||
|
|
||||||
long assetId;
|
long assetId;
|
||||||
if (version == 1)
|
if (version == 1)
|
||||||
assetId = Asset.QORA;
|
assetId = Asset.QORT;
|
||||||
else
|
else
|
||||||
assetId = byteBuffer.getLong();
|
assetId = byteBuffer.getLong();
|
||||||
|
|
||||||
|
@ -78,14 +78,14 @@ public class RepositoryTests extends Common {
|
|||||||
try (final Repository repository2 = RepositoryManager.getRepository()) {
|
try (final Repository repository2 = RepositoryManager.getRepository()) {
|
||||||
// Update account in 2
|
// Update account in 2
|
||||||
Account account2 = Common.getTestAccount(repository2, "alice");
|
Account account2 = Common.getTestAccount(repository2, "alice");
|
||||||
account2.setConfirmedBalance(Asset.QORA, BigDecimal.valueOf(1234L));
|
account2.setConfirmedBalance(Asset.QORT, BigDecimal.valueOf(1234L));
|
||||||
repository2.saveChanges();
|
repository2.saveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
repository1.discardChanges();
|
repository1.discardChanges();
|
||||||
|
|
||||||
// Update account in 1
|
// Update account in 1
|
||||||
account1.setConfirmedBalance(Asset.QORA, BigDecimal.valueOf(5678L));
|
account1.setConfirmedBalance(Asset.QORT, BigDecimal.valueOf(5678L));
|
||||||
repository1.saveChanges();
|
repository1.saveChanges();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,18 +105,18 @@ public class TransactionTests extends Common {
|
|||||||
|
|
||||||
// Create test generator account
|
// Create test generator account
|
||||||
generator = new PrivateKeyAccount(repository, generatorSeed);
|
generator = new PrivateKeyAccount(repository, generatorSeed);
|
||||||
accountRepository.setLastReference(new AccountData(generator.getAddress(), generatorSeed, generator.getPublicKey(), Group.NO_GROUP, 0, null, 0));
|
accountRepository.setLastReference(new AccountData(generator.getAddress(), generatorSeed, generator.getPublicKey(), Group.NO_GROUP, 0, null, 0, 0));
|
||||||
accountRepository.save(new AccountBalanceData(generator.getAddress(), Asset.QORA, initialGeneratorBalance));
|
accountRepository.save(new AccountBalanceData(generator.getAddress(), Asset.QORT, initialGeneratorBalance));
|
||||||
|
|
||||||
// Create test sender account
|
// Create test sender account
|
||||||
sender = new PrivateKeyAccount(repository, senderSeed);
|
sender = new PrivateKeyAccount(repository, senderSeed);
|
||||||
|
|
||||||
// Mock account
|
// Mock account
|
||||||
reference = senderSeed;
|
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
|
// Mock balance
|
||||||
accountRepository.save(new AccountBalanceData(sender.getAddress(), Asset.QORA, initialSenderBalance));
|
accountRepository.save(new AccountBalanceData(sender.getAddress(), Asset.QORT, initialSenderBalance));
|
||||||
|
|
||||||
repository.saveChanges();
|
repository.saveChanges();
|
||||||
}
|
}
|
||||||
@ -170,17 +170,17 @@ public class TransactionTests extends Common {
|
|||||||
|
|
||||||
// Check sender's balance
|
// Check sender's balance
|
||||||
BigDecimal expectedBalance = initialSenderBalance.subtract(amount).subtract(fee);
|
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);
|
assertTrue("Sender's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Fee should be in generator's balance
|
// Fee should be in generator's balance
|
||||||
expectedBalance = initialGeneratorBalance.add(fee);
|
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);
|
assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Amount should be in recipient's balance
|
// Amount should be in recipient's balance
|
||||||
expectedBalance = amount;
|
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);
|
assertTrue("Recipient's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Check recipient's reference
|
// Check recipient's reference
|
||||||
@ -192,11 +192,11 @@ public class TransactionTests extends Common {
|
|||||||
repository.saveChanges();
|
repository.saveChanges();
|
||||||
|
|
||||||
// Check sender's balance
|
// 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);
|
assertTrue("Sender's reverted balance incorrect", initialSenderBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Check generator's balance
|
// 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);
|
assertTrue("Generator's new balance incorrect", initialGeneratorBalance.compareTo(actualBalance) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,12 +230,12 @@ public class TransactionTests extends Common {
|
|||||||
|
|
||||||
// Check sender's balance
|
// Check sender's balance
|
||||||
BigDecimal expectedBalance = initialSenderBalance.subtract(fee);
|
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);
|
assertTrue("Sender's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Fee should be in generator's balance
|
// Fee should be in generator's balance
|
||||||
expectedBalance = initialGeneratorBalance.add(fee);
|
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);
|
assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Check name was registered
|
// Check name was registered
|
||||||
@ -494,12 +494,12 @@ public class TransactionTests extends Common {
|
|||||||
|
|
||||||
// Check sender's balance
|
// Check sender's balance
|
||||||
BigDecimal expectedBalance = initialSenderBalance.subtract(fee);
|
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);
|
assertTrue("Sender's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Fee should be in generator's balance
|
// Fee should be in generator's balance
|
||||||
expectedBalance = initialGeneratorBalance.add(fee);
|
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);
|
assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Check poll was created
|
// Check poll was created
|
||||||
@ -598,9 +598,10 @@ public class TransactionTests extends Common {
|
|||||||
BigDecimal fee = BigDecimal.ONE;
|
BigDecimal fee = BigDecimal.ONE;
|
||||||
long timestamp = parentBlockData.getTimestamp() + 1_000;
|
long timestamp = parentBlockData.getTimestamp() + 1_000;
|
||||||
String data = (timestamp >= BlockChain.getInstance().getQoraV2Timestamp()) ? "{}" : null;
|
String data = (timestamp >= BlockChain.getInstance().getQoraV2Timestamp()) ? "{}" : null;
|
||||||
|
boolean isUnspendable = false;
|
||||||
|
|
||||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, sender.getPublicKey(), fee, null);
|
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);
|
Transaction issueAssetTransaction = new IssueAssetTransaction(repository, issueAssetTransactionData);
|
||||||
issueAssetTransaction.sign(sender);
|
issueAssetTransaction.sign(sender);
|
||||||
@ -618,19 +619,19 @@ public class TransactionTests extends Common {
|
|||||||
|
|
||||||
// Check sender's balance
|
// Check sender's balance
|
||||||
BigDecimal expectedBalance = initialSenderBalance.subtract(fee);
|
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);
|
assertTrue("Sender's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Fee should be in generator's balance
|
// Fee should be in generator's balance
|
||||||
expectedBalance = initialGeneratorBalance.add(fee);
|
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);
|
assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Check we now have an assetId
|
// Check we now have an assetId
|
||||||
Long assetId = issueAssetTransactionData.getAssetId();
|
Long assetId = issueAssetTransactionData.getAssetId();
|
||||||
assertNotNull(assetId);
|
assertNotNull(assetId);
|
||||||
// Should NOT collide with Asset.QORA
|
// Should NOT collide with Asset.QORA
|
||||||
assertFalse(assetId == Asset.QORA);
|
assertFalse(assetId == Asset.QORT);
|
||||||
|
|
||||||
// Check asset now exists
|
// Check asset now exists
|
||||||
AssetRepository assetRepo = this.repository.getAssetRepository();
|
AssetRepository assetRepo = this.repository.getAssetRepository();
|
||||||
@ -647,11 +648,11 @@ public class TransactionTests extends Common {
|
|||||||
repository.saveChanges();
|
repository.saveChanges();
|
||||||
|
|
||||||
// Check sender's balance
|
// 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);
|
assertTrue("Sender's reverted balance incorrect", initialSenderBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Check generator's balance
|
// 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);
|
assertTrue("Generator's reverted balance incorrect", initialGeneratorBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Check asset no longer exists
|
// Check asset no longer exists
|
||||||
@ -678,8 +679,8 @@ public class TransactionTests extends Common {
|
|||||||
AssetRepository assetRepo = this.repository.getAssetRepository();
|
AssetRepository assetRepo = this.repository.getAssetRepository();
|
||||||
AssetData originalAssetData = assetRepo.fromAssetName(assetName);
|
AssetData originalAssetData = assetRepo.fromAssetName(assetName);
|
||||||
long assetId = originalAssetData.getAssetId();
|
long assetId = originalAssetData.getAssetId();
|
||||||
BigDecimal originalSenderBalance = sender.getConfirmedBalance(Asset.QORA);
|
BigDecimal originalSenderBalance = sender.getConfirmedBalance(Asset.QORT);
|
||||||
BigDecimal originalGeneratorBalance = generator.getConfirmedBalance(Asset.QORA);
|
BigDecimal originalGeneratorBalance = generator.getConfirmedBalance(Asset.QORT);
|
||||||
|
|
||||||
// Transfer asset to new recipient
|
// Transfer asset to new recipient
|
||||||
Account recipient = new PublicKeyAccount(repository, recipientSeed);
|
Account recipient = new PublicKeyAccount(repository, recipientSeed);
|
||||||
@ -706,12 +707,12 @@ public class TransactionTests extends Common {
|
|||||||
|
|
||||||
// Check sender's balance
|
// Check sender's balance
|
||||||
BigDecimal expectedBalance = originalSenderBalance.subtract(fee);
|
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);
|
assertTrue("Sender's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Fee should be in generator's balance
|
// Fee should be in generator's balance
|
||||||
expectedBalance = originalGeneratorBalance.add(fee);
|
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);
|
assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Check asset balances
|
// Check asset balances
|
||||||
@ -729,11 +730,11 @@ public class TransactionTests extends Common {
|
|||||||
repository.saveChanges();
|
repository.saveChanges();
|
||||||
|
|
||||||
// Check sender's balance
|
// 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);
|
assertTrue("Sender's reverted balance incorrect", originalSenderBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Check generator's balance
|
// 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);
|
assertTrue("Generator's reverted balance incorrect", originalGeneratorBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Check asset balances
|
// Check asset balances
|
||||||
@ -781,7 +782,7 @@ public class TransactionTests extends Common {
|
|||||||
parentBlockData = block.getBlockData();
|
parentBlockData = block.getBlockData();
|
||||||
|
|
||||||
// Order: buyer has 10 QORA and wants to buy "test asset" at a price of 50 "test asset" per QORA.
|
// 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);
|
BigDecimal amount = BigDecimal.valueOf(10).setScale(8);
|
||||||
long wantAssetId = assetId;
|
long wantAssetId = assetId;
|
||||||
BigDecimal price = BigDecimal.valueOf(50).setScale(8);
|
BigDecimal price = BigDecimal.valueOf(50).setScale(8);
|
||||||
@ -852,7 +853,7 @@ public class TransactionTests extends Common {
|
|||||||
PrivateKeyAccount buyer = new PrivateKeyAccount(repository, recipientSeed);
|
PrivateKeyAccount buyer = new PrivateKeyAccount(repository, recipientSeed);
|
||||||
|
|
||||||
// Fetch orders
|
// Fetch orders
|
||||||
long haveAssetId = Asset.QORA;
|
long haveAssetId = Asset.QORT;
|
||||||
long wantAssetId = assetId;
|
long wantAssetId = assetId;
|
||||||
List<OrderData> orders = assetRepo.getOpenOrders(haveAssetId, wantAssetId);
|
List<OrderData> orders = assetRepo.getOpenOrders(haveAssetId, wantAssetId);
|
||||||
|
|
||||||
@ -917,7 +918,7 @@ public class TransactionTests extends Common {
|
|||||||
PrivateKeyAccount buyer = new PrivateKeyAccount(repository, recipientSeed);
|
PrivateKeyAccount buyer = new PrivateKeyAccount(repository, recipientSeed);
|
||||||
|
|
||||||
// Fetch orders
|
// Fetch orders
|
||||||
long originalHaveAssetId = Asset.QORA;
|
long originalHaveAssetId = Asset.QORT;
|
||||||
long originalWantAssetId = assetId;
|
long originalWantAssetId = assetId;
|
||||||
List<OrderData> orders = assetRepo.getOpenOrders(originalHaveAssetId, originalWantAssetId);
|
List<OrderData> 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
|
// This order should be a partial match for original order, and at a better price than asked
|
||||||
long haveAssetId = assetId;
|
long haveAssetId = assetId;
|
||||||
BigDecimal amount = BigDecimal.valueOf(40).setScale(8);
|
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 price = BigDecimal.ONE.setScale(8).divide(BigDecimal.valueOf(60).setScale(8), RoundingMode.DOWN);
|
||||||
BigDecimal fee = BigDecimal.ONE;
|
BigDecimal fee = BigDecimal.ONE;
|
||||||
long timestamp = parentBlockData.getTimestamp() + 1_000;
|
long timestamp = parentBlockData.getTimestamp() + 1_000;
|
||||||
@ -1041,7 +1042,7 @@ public class TransactionTests extends Common {
|
|||||||
byte[] seed = recipientSeed.clone();
|
byte[] seed = recipientSeed.clone();
|
||||||
seed[0] += i;
|
seed[0] += i;
|
||||||
Account recipient = new PublicKeyAccount(repository, seed);
|
Account recipient = new PublicKeyAccount(repository, seed);
|
||||||
long assetId = Asset.QORA;
|
long assetId = Asset.QORT;
|
||||||
|
|
||||||
BigDecimal amount = BigDecimal.valueOf(1_000L + i).setScale(8);
|
BigDecimal amount = BigDecimal.valueOf(1_000L + i).setScale(8);
|
||||||
expectedSenderBalance = expectedSenderBalance.subtract(amount);
|
expectedSenderBalance = expectedSenderBalance.subtract(amount);
|
||||||
@ -1069,12 +1070,12 @@ public class TransactionTests extends Common {
|
|||||||
repository.saveChanges();
|
repository.saveChanges();
|
||||||
|
|
||||||
// Check sender's balance
|
// 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);
|
assertTrue("Sender's new balance incorrect", expectedSenderBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Fee should be in generator's balance
|
// Fee should be in generator's balance
|
||||||
BigDecimal expectedBalance = initialGeneratorBalance.add(fee);
|
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);
|
assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Check recipients
|
// Check recipients
|
||||||
@ -1087,7 +1088,7 @@ public class TransactionTests extends Common {
|
|||||||
|
|
||||||
// Amount should be in recipient's balance
|
// Amount should be in recipient's balance
|
||||||
expectedBalance = paymentData.getAmount();
|
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);
|
assertTrue("Recipient's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1097,11 +1098,11 @@ public class TransactionTests extends Common {
|
|||||||
repository.saveChanges();
|
repository.saveChanges();
|
||||||
|
|
||||||
// Check sender's balance
|
// 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);
|
assertTrue("Sender's reverted balance incorrect", initialSenderBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Check generator's balance
|
// 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);
|
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);
|
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, sender.getPublicKey(), fee, null);
|
||||||
MessageTransactionData messageTransactionData = new MessageTransactionData(baseTransactionData, version,
|
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);
|
Transaction messageTransaction = new MessageTransaction(repository, messageTransactionData);
|
||||||
messageTransaction.sign(sender);
|
messageTransaction.sign(sender);
|
||||||
@ -1139,17 +1140,17 @@ public class TransactionTests extends Common {
|
|||||||
|
|
||||||
// Check sender's balance
|
// Check sender's balance
|
||||||
BigDecimal expectedBalance = initialSenderBalance.subtract(amount).subtract(fee);
|
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);
|
assertTrue("Sender's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Fee should be in generator's balance
|
// Fee should be in generator's balance
|
||||||
expectedBalance = initialGeneratorBalance.add(fee);
|
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);
|
assertTrue("Generator's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||||
|
|
||||||
// Amount should be in recipient's balance
|
// Amount should be in recipient's balance
|
||||||
expectedBalance = amount;
|
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);
|
assertTrue("Recipient's new balance incorrect", expectedBalance.compareTo(actualBalance) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ public class AssetUtils {
|
|||||||
long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1;
|
long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1;
|
||||||
|
|
||||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, AssetUtils.txGroupId, reference, account.getPublicKey(), AssetUtils.fee, null);
|
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);
|
TransactionUtils.signAndForge(repository, transactionData, account);
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ public class ArbitraryTestTransaction extends TestTransaction {
|
|||||||
DataType dataType = DataType.RAW_DATA;
|
DataType dataType = DataType.RAW_DATA;
|
||||||
|
|
||||||
String recipient = account.getAddress();
|
String recipient = account.getAddress();
|
||||||
final long assetId = Asset.QORA;
|
final long assetId = Asset.QORT;
|
||||||
BigDecimal amount = BigDecimal.valueOf(123L);
|
BigDecimal amount = BigDecimal.valueOf(123L);
|
||||||
|
|
||||||
List<PaymentData> payments = new ArrayList<>();
|
List<PaymentData> payments = new ArrayList<>();
|
||||||
|
@ -18,7 +18,7 @@ public class AtTestTransaction extends TestTransaction {
|
|||||||
String atAddress = Crypto.toATAddress(signature);
|
String atAddress = Crypto.toATAddress(signature);
|
||||||
String recipient = account.getAddress();
|
String recipient = account.getAddress();
|
||||||
BigDecimal amount = BigDecimal.valueOf(123);
|
BigDecimal amount = BigDecimal.valueOf(123);
|
||||||
final long assetId = Asset.QORA;
|
final long assetId = Asset.QORT;
|
||||||
byte[] message = new byte[32];
|
byte[] message = new byte[32];
|
||||||
random.nextBytes(message);
|
random.nextBytes(message);
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import org.qora.repository.Repository;
|
|||||||
public class CreateAssetOrderTestTransaction extends TestTransaction {
|
public class CreateAssetOrderTestTransaction extends TestTransaction {
|
||||||
|
|
||||||
public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException {
|
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;
|
final long wantAssetId = 1;
|
||||||
BigDecimal amount = BigDecimal.valueOf(123);
|
BigDecimal amount = BigDecimal.valueOf(123);
|
||||||
BigDecimal price = BigDecimal.valueOf(123);
|
BigDecimal price = BigDecimal.valueOf(123);
|
||||||
|
@ -22,7 +22,7 @@ public class DeployAtTestTransaction extends TestTransaction {
|
|||||||
byte[] creationBytes = new byte[1024];
|
byte[] creationBytes = new byte[1024];
|
||||||
random.nextBytes(creationBytes);
|
random.nextBytes(creationBytes);
|
||||||
BigDecimal amount = BigDecimal.valueOf(123);
|
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);
|
return new DeployAtTransactionData(generateBase(account), name, description, atType, tags, creationBytes, amount, assetId);
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,9 @@ public class IssueAssetTestTransaction extends TestTransaction {
|
|||||||
final long quantity = 1_000_000L;
|
final long quantity = 1_000_000L;
|
||||||
final boolean isDivisible = true;
|
final boolean isDivisible = true;
|
||||||
String data = AssetUtils.randomData();
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ public class MessageTestTransaction extends TestTransaction {
|
|||||||
public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException {
|
public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException {
|
||||||
final int version = 3;
|
final int version = 3;
|
||||||
String recipient = account.getAddress();
|
String recipient = account.getAddress();
|
||||||
final long assetId = Asset.QORA;
|
final long assetId = Asset.QORT;
|
||||||
BigDecimal amount = BigDecimal.valueOf(123L);
|
BigDecimal amount = BigDecimal.valueOf(123L);
|
||||||
byte[] data = "message contents".getBytes();
|
byte[] data = "message contents".getBytes();
|
||||||
final boolean isText = true;
|
final boolean isText = true;
|
||||||
|
@ -16,7 +16,7 @@ public class MultiPaymentTestTransaction extends TestTransaction {
|
|||||||
|
|
||||||
public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException {
|
public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException {
|
||||||
String recipient = account.getAddress();
|
String recipient = account.getAddress();
|
||||||
final long assetId = Asset.QORA;
|
final long assetId = Asset.QORT;
|
||||||
BigDecimal amount = BigDecimal.valueOf(123L);
|
BigDecimal amount = BigDecimal.valueOf(123L);
|
||||||
|
|
||||||
List<PaymentData> payments = new ArrayList<>();
|
List<PaymentData> payments = new ArrayList<>();
|
||||||
|
@ -13,7 +13,7 @@ public class TransferAssetTestTransaction extends TestTransaction {
|
|||||||
|
|
||||||
public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException {
|
public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException {
|
||||||
String recipient = account.getAddress();
|
String recipient = account.getAddress();
|
||||||
final long assetId = Asset.QORA;
|
final long assetId = Asset.QORT;
|
||||||
BigDecimal amount = BigDecimal.valueOf(123);
|
BigDecimal amount = BigDecimal.valueOf(123);
|
||||||
|
|
||||||
return new TransferAssetTransactionData(generateBase(account), recipient, amount, assetId);
|
return new TransferAssetTransactionData(generateBase(account), recipient, amount, assetId);
|
||||||
|
@ -35,7 +35,7 @@ public class RewardTests extends Common {
|
|||||||
@Test
|
@Test
|
||||||
public void testSimpleReward() throws DataException {
|
public void testSimpleReward() throws DataException {
|
||||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
Map<String, Map<Long, BigDecimal>> initialBalances = AccountUtils.getBalances(repository, Asset.QORA);
|
Map<String, Map<Long, BigDecimal>> initialBalances = AccountUtils.getBalances(repository, Asset.QORT);
|
||||||
|
|
||||||
PrivateKeyAccount forgingAccount = Common.getTestAccount(repository, "alice");
|
PrivateKeyAccount forgingAccount = Common.getTestAccount(repository, "alice");
|
||||||
|
|
||||||
@ -43,15 +43,15 @@ public class RewardTests extends Common {
|
|||||||
|
|
||||||
BlockGenerator.generateTestingBlock(repository, forgingAccount);
|
BlockGenerator.generateTestingBlock(repository, forgingAccount);
|
||||||
|
|
||||||
BigDecimal expectedBalance = initialBalances.get("alice").get(Asset.QORA).add(blockReward);
|
BigDecimal expectedBalance = initialBalances.get("alice").get(Asset.QORT).add(blockReward);
|
||||||
AccountUtils.assertBalance(repository, "alice", Asset.QORA, expectedBalance);
|
AccountUtils.assertBalance(repository, "alice", Asset.QORT, expectedBalance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRewards() throws DataException {
|
public void testRewards() throws DataException {
|
||||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
Map<String, Map<Long, BigDecimal>> initialBalances = AccountUtils.getBalances(repository, Asset.QORA);
|
Map<String, Map<Long, BigDecimal>> initialBalances = AccountUtils.getBalances(repository, Asset.QORT);
|
||||||
|
|
||||||
PrivateKeyAccount forgingAccount = Common.getTestAccount(repository, "alice");
|
PrivateKeyAccount forgingAccount = Common.getTestAccount(repository, "alice");
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ public class RewardTests extends Common {
|
|||||||
int rewardIndex = rewards.size() - 1;
|
int rewardIndex = rewards.size() - 1;
|
||||||
|
|
||||||
RewardByHeight rewardInfo = rewards.get(rewardIndex);
|
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) {
|
for (int height = rewardInfo.height; height > 1; --height) {
|
||||||
if (height < rewardInfo.height) {
|
if (height < rewardInfo.height) {
|
||||||
@ -72,7 +72,7 @@ public class RewardTests extends Common {
|
|||||||
expectedBalance = expectedBalance.add(rewardInfo.reward);
|
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);
|
byte[] proxyPrivateKey = AccountUtils.proxyForging(repository, "alice", "bob", share);
|
||||||
PrivateKeyAccount proxyAccount = new PrivateKeyAccount(repository, proxyPrivateKey);
|
PrivateKeyAccount proxyAccount = new PrivateKeyAccount(repository, proxyPrivateKey);
|
||||||
|
|
||||||
Map<String, Map<Long, BigDecimal>> initialBalances = AccountUtils.getBalances(repository, Asset.QORA);
|
Map<String, Map<Long, BigDecimal>> initialBalances = AccountUtils.getBalances(repository, Asset.QORT);
|
||||||
BigDecimal blockReward = BlockUtils.getNextBlockReward(repository);
|
BigDecimal blockReward = BlockUtils.getNextBlockReward(repository);
|
||||||
BlockGenerator.generateTestingBlock(repository, proxyAccount);
|
BlockGenerator.generateTestingBlock(repository, proxyAccount);
|
||||||
|
|
||||||
// We're expecting reward * 12.8% to Bob, the rest to Alice
|
// We're expecting reward * 12.8% to Bob, the rest to Alice
|
||||||
|
|
||||||
BigDecimal bobShare = blockReward.multiply(share.movePointLeft(2)).setScale(8, RoundingMode.DOWN);
|
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);
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,8 +90,8 @@ public class GroupApprovalTests extends Common {
|
|||||||
PrivateKeyAccount bobAccount = Common.getTestAccount(repository, "bob");
|
PrivateKeyAccount bobAccount = Common.getTestAccount(repository, "bob");
|
||||||
byte[] bobOriginalReference = bobAccount.getLastReference();
|
byte[] bobOriginalReference = bobAccount.getLastReference();
|
||||||
|
|
||||||
BigDecimal aliceOriginalBalance = aliceAccount.getConfirmedBalance(Asset.QORA);
|
BigDecimal aliceOriginalBalance = aliceAccount.getConfirmedBalance(Asset.QORT);
|
||||||
BigDecimal bobOriginalBalance = bobAccount.getConfirmedBalance(Asset.QORA);
|
BigDecimal bobOriginalBalance = bobAccount.getConfirmedBalance(Asset.QORT);
|
||||||
|
|
||||||
BigDecimal blockReward = BlockUtils.getNextBlockReward(repository);
|
BigDecimal blockReward = BlockUtils.getNextBlockReward(repository);
|
||||||
Transaction bobAssetTransaction = buildIssueAssetTransaction(repository, "bob", groupId);
|
Transaction bobAssetTransaction = buildIssueAssetTransaction(repository, "bob", groupId);
|
||||||
@ -106,11 +106,11 @@ public class GroupApprovalTests extends Common {
|
|||||||
assertFalse("reference should have changed", Arrays.equals(bobOriginalReference, bobPostAssetReference));
|
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
|
// 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);
|
Common.assertEqualBigDecimals("approval-pending transaction creator's balance incorrect", bobOriginalBalance.subtract(fee), bobPostAssetBalance);
|
||||||
|
|
||||||
// Transaction fee should have ended up in forging account
|
// 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);
|
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
|
// 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));
|
assertTrue("reference should be pre-payment", Arrays.equals(bobOriginalReference, bobReference));
|
||||||
|
|
||||||
// Also check Bob's balance is back to original value
|
// 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);
|
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;
|
long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1;
|
||||||
|
|
||||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, account.getPublicKey(), fee, null);
|
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);
|
return Transaction.fromData(repository, transactionData);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user