Updated orphaning code of Block and Transaction subclasses

This commit is contained in:
catbref 2019-06-02 14:41:42 +01:00
parent 4b3f877dc0
commit 8af761c1c3
44 changed files with 361 additions and 417 deletions

View File

@ -31,6 +31,7 @@ import org.qora.repository.ATRepository;
import org.qora.repository.BlockRepository;
import org.qora.repository.DataException;
import org.qora.repository.Repository;
import org.qora.repository.TransactionRepository;
import org.qora.transaction.AtTransaction;
import org.qora.transaction.Transaction;
import org.qora.transaction.Transaction.ApprovalStatus;
@ -1064,21 +1065,7 @@ public class Block {
processBlockRewards();
// Process transactions (we'll link them to this block after saving the block itself)
// AT-generated transactions are already prepended to our transactions at this point.
List<Transaction> transactions = this.getTransactions();
for (Transaction transaction : transactions) {
// AT_TRANSACTIONs are created locally and need saving into repository before processing
if (transaction.getTransactionData().getType() == TransactionType.AT)
this.repository.getTransactionRepository().save(transaction.getTransactionData());
// Only process transactions that don't require group-approval.
// Group-approval transactions are dealt with later.
if (transaction.getTransactionData().getApprovalStatus() == ApprovalStatus.NOT_REQUIRED)
transaction.process();
// Regardless of group-approval, update relevant info for creator (e.g. lastReference)
transaction.processReferencesAndFees();
}
processTransactions();
// Group-approval transactions
processGroupApprovalTransactions();
@ -1087,86 +1074,19 @@ public class Block {
rewardTransactionFees();
// Process AT fees and save AT states into repository
ATRepository atRepository = this.repository.getATRepository();
for (ATStateData atState : this.getATStates()) {
Account atAccount = new Account(this.repository, atState.getATAddress());
// Subtract AT-generated fees from AT accounts
atAccount.setConfirmedBalance(Asset.QORA, atAccount.getConfirmedBalance(Asset.QORA).subtract(atState.getFees()));
atRepository.save(atState);
}
processAtFeesAndStates();
// Link block into blockchain by fetching signature of highest block and setting that as our reference
BlockData latestBlockData = this.repository.getBlockRepository().fromHeight(blockchainHeight);
if (latestBlockData != null)
this.blockData.setReference(latestBlockData.getSignature());
// Save block
this.repository.getBlockRepository().save(this.blockData);
// Link transactions to this block, thus removing them from unconfirmed transactions list.
// Also update "transaction participants" in repository for "transactions involving X" support in API
for (int sequence = 0; sequence < transactions.size(); ++sequence) {
Transaction transaction = transactions.get(sequence);
// Link transaction to this block
BlockTransactionData blockTransactionData = new BlockTransactionData(this.getSignature(), sequence,
transaction.getTransactionData().getSignature());
this.repository.getBlockRepository().save(blockTransactionData);
// Update transaction's height in repository
this.repository.getTransactionRepository().updateBlockHeight(transaction.getTransactionData().getSignature(), this.blockData.getHeight());
// Update local transactionData's height too
transaction.getTransactionData().setBlockHeight(this.blockData.getHeight());
// No longer unconfirmed
this.repository.getTransactionRepository().confirmTransaction(transaction.getTransactionData().getSignature());
List<Account> participants = transaction.getInvolvedAccounts();
List<String> participantAddresses = participants.stream().map(account -> account.getAddress()).collect(Collectors.toList());
this.repository.getTransactionRepository().saveParticipants(transaction.getTransactionData(), participantAddresses);
}
}
protected void processGroupApprovalTransactions() throws DataException {
// Search for pending transactions that have now expired
List<TransactionData> approvalExpiringTransactions = this.repository.getTransactionRepository().getApprovalExpiringTransactions(this.blockData.getHeight());
for (TransactionData transactionData : approvalExpiringTransactions) {
transactionData.setApprovalStatus(ApprovalStatus.EXPIRED);
this.repository.getTransactionRepository().save(transactionData);
}
// Search for pending transactions within min/max block delay range
List<TransactionData> approvalPendingTransactions = this.repository.getTransactionRepository().getApprovalPendingTransactions(this.blockData.getHeight());
for (TransactionData transactionData : approvalPendingTransactions) {
Transaction transaction = Transaction.fromData(this.repository, transactionData);
// something like:
Boolean isApproved = transaction.getApprovalDecision();
if (isApproved == null)
continue; // approve/reject threshold not yet met
if (!isApproved) {
// REJECT
transactionData.setApprovalStatus(ApprovalStatus.REJECTED);
this.repository.getTransactionRepository().save(transactionData);
continue;
}
// Approved, but check transaction can still be processed
if (transaction.isProcessable() != Transaction.ValidationResult.OK) {
transactionData.setApprovalStatus(ApprovalStatus.INVALID);
this.repository.getTransactionRepository().save(transactionData);
continue;
}
// APPROVED, in which case do transaction.process();
transactionData.setApprovalStatus(ApprovalStatus.APPROVED);
this.repository.getTransactionRepository().save(transactionData);
transaction.process();
}
linkTransactionsToBlock();
}
protected void processBlockRewards() throws DataException {
@ -1194,6 +1114,76 @@ public class Block {
this.generator.setConfirmedBalance(Asset.QORA, this.generator.getConfirmedBalance(Asset.QORA).add(reward));
}
protected void processTransactions() throws DataException {
// Process transactions (we'll link them to this block after saving the block itself)
// AT-generated transactions are already prepended to our transactions at this point.
List<Transaction> transactions = this.getTransactions();
for (Transaction transaction : transactions) {
TransactionData transactionData = transaction.getTransactionData();
// AT_TRANSACTIONs are created locally and need saving into repository before processing
if (transactionData.getType() == TransactionType.AT)
this.repository.getTransactionRepository().save(transactionData);
// Only process transactions that don't require group-approval.
// Group-approval transactions are dealt with later.
if (transactionData.getApprovalStatus() == ApprovalStatus.NOT_REQUIRED)
transaction.process();
// Regardless of group-approval, update relevant info for creator (e.g. lastReference)
transaction.processReferencesAndFees();
}
}
protected void processGroupApprovalTransactions() throws DataException {
TransactionRepository transactionRepository = this.repository.getTransactionRepository();
// Search for pending transactions that have now expired
List<TransactionData> approvalExpiringTransactions = transactionRepository.getApprovalExpiringTransactions(this.blockData.getHeight());
for (TransactionData transactionData : approvalExpiringTransactions) {
transactionData.setApprovalStatus(ApprovalStatus.EXPIRED);
transactionRepository.save(transactionData);
}
// Search for pending transactions within min/max block delay range
List<TransactionData> approvalPendingTransactions = transactionRepository.getApprovalPendingTransactions(this.blockData.getHeight());
for (TransactionData transactionData : approvalPendingTransactions) {
Transaction transaction = Transaction.fromData(this.repository, transactionData);
// something like:
Boolean isApproved = transaction.getApprovalDecision();
if (isApproved == null)
continue; // approve/reject threshold not yet met
// Update approval height for transaction in repository
transactionRepository.updateApprovalHeight(transactionData.getSignature(), this.blockData.getHeight());
if (!isApproved) {
// REJECT
transactionData.setApprovalStatus(ApprovalStatus.REJECTED);
transactionRepository.save(transactionData);
continue;
}
// Approved, but check transaction can still be processed
if (transaction.isProcessable() != Transaction.ValidationResult.OK) {
transactionData.setApprovalStatus(ApprovalStatus.INVALID);
transactionRepository.save(transactionData);
continue;
}
// APPROVED, in which case do transaction.process();
transactionData.setApprovalStatus(ApprovalStatus.APPROVED);
transactionRepository.save(transactionData);
transaction.process();
}
}
protected void rewardTransactionFees() throws DataException {
BigDecimal blockFees = this.blockData.getTotalFees();
@ -1219,32 +1209,57 @@ public class Block {
this.generator.setConfirmedBalance(Asset.QORA, this.generator.getConfirmedBalance(Asset.QORA).add(blockFees));
}
protected void processAtFeesAndStates() throws DataException {
ATRepository atRepository = this.repository.getATRepository();
for (ATStateData atState : this.getATStates()) {
Account atAccount = new Account(this.repository, atState.getATAddress());
// Subtract AT-generated fees from AT accounts
atAccount.setConfirmedBalance(Asset.QORA, atAccount.getConfirmedBalance(Asset.QORA).subtract(atState.getFees()));
atRepository.save(atState);
}
}
protected void linkTransactionsToBlock() throws DataException {
TransactionRepository transactionRepository = this.repository.getTransactionRepository();
for (int sequence = 0; sequence < transactions.size(); ++sequence) {
Transaction transaction = transactions.get(sequence);
TransactionData transactionData = transaction.getTransactionData();
// Link transaction to this block
BlockTransactionData blockTransactionData = new BlockTransactionData(this.getSignature(), sequence,
transactionData.getSignature());
this.repository.getBlockRepository().save(blockTransactionData);
// Update transaction's height in repository
transactionRepository.updateBlockHeight(transactionData.getSignature(), this.blockData.getHeight());
// Update local transactionData's height too
transaction.getTransactionData().setBlockHeight(this.blockData.getHeight());
// No longer unconfirmed
transactionRepository.confirmTransaction(transactionData.getSignature());
List<Account> participants = transaction.getInvolvedAccounts();
List<String> participantAddresses = participants.stream().map(account -> account.getAddress()).collect(Collectors.toList());
transactionRepository.saveParticipants(transactionData, participantAddresses);
}
}
/**
* Removes block from blockchain undoing transactions and adding them to unconfirmed pile.
*
* @throws DataException
*/
public void orphan() throws DataException {
// Orphan transactions in reverse order, and unlink them from this block
// AT-generated transactions are already added to our transactions so no special handling is needed here.
List<Transaction> transactions = this.getTransactions();
for (int sequence = transactions.size() - 1; sequence >= 0; --sequence) {
Transaction transaction = transactions.get(sequence);
transaction.orphan();
// Orphan, and unlink, transactions from this block
orphanTransactionsFromBlock();
// Unlink transaction from this block
BlockTransactionData blockTransactionData = new BlockTransactionData(this.getSignature(), sequence,
transaction.getTransactionData().getSignature());
this.repository.getBlockRepository().delete(blockTransactionData);
// Add to unconfirmed pile, or delete if AT_TRANSACTION
if (transaction.getTransactionData().getType() == TransactionType.AT)
this.repository.getTransactionRepository().delete(transaction.getTransactionData());
else
this.repository.getTransactionRepository().unconfirmTransaction(transaction.getTransactionData());
this.repository.getTransactionRepository().deleteParticipants(transaction.getTransactionData());
}
// Undo any group-approval decisions that happen at this block
orphanGroupApprovalTransactions();
// Block rewards removed after transactions undone
orphanBlockRewards();
@ -1253,18 +1268,70 @@ public class Block {
deductTransactionFees();
// Return AT fees and delete AT states from repository
ATRepository atRepository = this.repository.getATRepository();
for (ATStateData atState : this.getATStates()) {
Account atAccount = new Account(this.repository, atState.getATAddress());
// Return AT-generated fees to AT accounts
atAccount.setConfirmedBalance(Asset.QORA, atAccount.getConfirmedBalance(Asset.QORA).add(atState.getFees()));
}
// Delete ATStateData for this height
atRepository.deleteATStates(this.blockData.getHeight());
orphanAtFeesAndStates();
// Delete block from blockchain
this.repository.getBlockRepository().delete(this.blockData);
this.blockData.setHeight(null);
}
protected void orphanTransactionsFromBlock() throws DataException {
TransactionRepository transactionRepository = this.repository.getTransactionRepository();
// AT-generated transactions are already added to our transactions so no special handling is needed here.
List<Transaction> transactions = this.getTransactions();
for (int sequence = transactions.size() - 1; sequence >= 0; --sequence) {
Transaction transaction = transactions.get(sequence);
TransactionData transactionData = transaction.getTransactionData();
// Orphan transaction
// Only orphan transactions that didn't require group-approval.
// Group-approval transactions are dealt with later.
if (transactionData.getApprovalStatus() == ApprovalStatus.NOT_REQUIRED)
transaction.orphan();
// Regardless of group-approval, update relevant info for creator (e.g. lastReference)
transaction.orphanReferencesAndFees();
// Unlink transaction from this block
BlockTransactionData blockTransactionData = new BlockTransactionData(this.getSignature(), sequence,
transactionData.getSignature());
this.repository.getBlockRepository().delete(blockTransactionData);
// Add to unconfirmed pile and remove height, or delete if AT_TRANSACTION
if (transaction.getTransactionData().getType() == TransactionType.AT) {
transactionRepository.delete(transactionData);
} else {
// Add to unconfirmed pile
transactionRepository.unconfirmTransaction(transactionData);
// Unset height
transactionRepository.updateBlockHeight(transactionData.getSignature(), null);
}
transactionRepository.deleteParticipants(transactionData);
}
}
protected void orphanGroupApprovalTransactions() throws DataException {
TransactionRepository transactionRepository = this.repository.getTransactionRepository();
// Find all transactions where decision happened at this block height
List<TransactionData> transactions = transactionRepository.getApprovalTransactionDecidedAtHeight(this.blockData.getHeight());
for (TransactionData transactionData : transactions) {
// Orphan/un-process transaction
Transaction transaction = Transaction.fromData(repository, transactionData);
transaction.orphan();
// Revert back to PENDING
transactionData.setApprovalStatus(ApprovalStatus.PENDING);
transactionRepository.save(transactionData);
// Undo approval decision height
transactionRepository.updateApprovalHeight(transactionData.getSignature(), null);
}
}
protected void orphanBlockRewards() throws DataException {
@ -1317,6 +1384,19 @@ public class Block {
this.generator.setConfirmedBalance(Asset.QORA, this.generator.getConfirmedBalance(Asset.QORA).subtract(blockFees));
}
protected void orphanAtFeesAndStates() throws DataException {
ATRepository atRepository = this.repository.getATRepository();
for (ATStateData atState : this.getATStates()) {
Account atAccount = new Account(this.repository, atState.getATAddress());
// Return AT-generated fees to AT accounts
atAccount.setConfirmedBalance(Asset.QORA, atAccount.getConfirmedBalance(Asset.QORA).add(atState.getFees()));
}
// Delete ATStateData for this height
atRepository.deleteATStates(this.blockData.getHeight());
}
protected BigDecimal getRewardAtHeight(int ourHeight) {
List<RewardByHeight> rewardsByHeight = BlockChain.getInstance().getBlockRewardsByHeight();

View File

@ -33,6 +33,9 @@ public class Payment {
// Processing
// isValid
/** Are payments valid? */
public ValidationResult isValid(byte[] senderPublicKey, List<PaymentData> payments, BigDecimal fee, boolean isZeroAmountValid) throws DataException {
AssetRepository assetRepository = this.repository.getAssetRepository();
@ -115,6 +118,8 @@ public class Payment {
return isValid(senderPublicKey, paymentData, fee, false);
}
// isProcessable
/** Are multiple payments processable? */
public ValidationResult isProcessable(byte[] senderPublicKey, List<PaymentData> payments, BigDecimal fee, boolean isZeroAmountValid) throws DataException {
// Essentially the same as isValid...
@ -136,6 +141,8 @@ public class Payment {
return isProcessable(senderPublicKey, paymentData, fee, false);
}
// process
/** Multiple payment processing */
public void process(byte[] senderPublicKey, List<PaymentData> payments, BigDecimal fee, byte[] signature)
throws DataException {
@ -162,6 +169,8 @@ public class Payment {
process(senderPublicKey, Collections.singletonList(paymentData), fee, signature);
}
// processReferenceAndFees
/** Multiple payment reference processing */
public void processReferencesAndFees(byte[] senderPublicKey, List<PaymentData> payments, BigDecimal fee, byte[] signature, boolean alwaysInitializeRecipientReference)
throws DataException {
@ -173,7 +182,7 @@ public class Payment {
// Update sender's reference
sender.setLastReference(signature);
// Process all payments
// Process all recipients
for (PaymentData paymentData : payments) {
Account recipient = new Account(this.repository, paymentData.getRecipient());
@ -191,16 +200,11 @@ public class Payment {
processReferencesAndFees(senderPublicKey, Collections.singletonList(payment), fee, signature, alwaysInitializeRecipientReference);
}
public void orphan(byte[] senderPublicKey, List<PaymentData> payments, BigDecimal fee, byte[] signature, byte[] reference,
boolean alwaysUninitializeRecipientReference) throws DataException {
// orphan
public void orphan(byte[] senderPublicKey, List<PaymentData> payments, BigDecimal fee, byte[] signature, byte[] reference) throws DataException {
Account sender = new PublicKeyAccount(this.repository, senderPublicKey);
// Update sender's balance due to fee
sender.setConfirmedBalance(Asset.QORA, sender.getConfirmedBalance(Asset.QORA).add(fee));
// Update sender's reference
sender.setLastReference(reference);
// Orphan all payments
for (PaymentData paymentData : payments) {
Account recipient = new Account(this.repository, paymentData.getRecipient());
@ -212,6 +216,29 @@ public class Payment {
// Update recipient's balance
recipient.setConfirmedBalance(assetId, recipient.getConfirmedBalance(assetId).subtract(amount));
}
}
public void orphan(byte[] senderPublicKey, PaymentData paymentData, BigDecimal fee, byte[] signature, byte[] reference) throws DataException {
orphan(senderPublicKey, Collections.singletonList(paymentData), fee, signature, reference);
}
// orphanReferencesAndFees
public void orphanReferencesAndFees(byte[] senderPublicKey, List<PaymentData> payments, BigDecimal fee, byte[] signature, byte[] reference,
boolean alwaysUninitializeRecipientReference) throws DataException {
Account sender = new PublicKeyAccount(this.repository, senderPublicKey);
// Update sender's balance due to fee
sender.setConfirmedBalance(Asset.QORA, sender.getConfirmedBalance(Asset.QORA).add(fee));
// Update sender's reference
sender.setLastReference(reference);
// Orphan all recipients
for (PaymentData paymentData : payments) {
Account recipient = new Account(this.repository, paymentData.getRecipient());
long assetId = paymentData.getAssetId();
/*
* 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
@ -222,9 +249,9 @@ public class Payment {
}
}
public void orphan(byte[] senderPublicKey, PaymentData paymentData, BigDecimal fee, byte[] signature, byte[] reference,
public void orphanReferencesAndFees(byte[] senderPublicKey, PaymentData paymentData, BigDecimal fee, byte[] signature, byte[] reference,
boolean alwaysUninitializeRecipientReference) throws DataException {
orphan(senderPublicKey, Collections.singletonList(paymentData), fee, signature, reference, alwaysUninitializeRecipientReference);
orphanReferencesAndFees(senderPublicKey, Collections.singletonList(paymentData), fee, signature, reference, alwaysUninitializeRecipientReference);
}
}

View File

@ -113,6 +113,9 @@ public interface TransactionRepository {
*/
public List<TransactionData> getApprovalExpiringTransactions(int blockHeight) throws DataException;
/** Returns list of transactions that had group-approval decided at passed block height. */
public List<TransactionData> getApprovalTransactionDecidedAtHeight(int approvalHeight) throws DataException;
/** Returns latest approval decision by given admin for given pending transaction signature. */
public GroupApprovalTransactionData getLatestApproval(byte[] pendingSignature, byte[] adminPublicKey) throws DataException;

View File

@ -25,9 +25,9 @@ public class HSQLDBATRepository implements ATRepository {
@Override
public ATData fromATAddress(String atAddress) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute(
"SELECT creator, creation, version, asset_id, code_bytes, is_sleeping, sleep_until_height, is_finished, had_fatal_error, is_frozen, frozen_balance FROM ATs WHERE AT_address = ?",
atAddress)) {
final String sql = "SELECT creator, creation, version, asset_id, code_bytes, is_sleeping, sleep_until_height, is_finished, had_fatal_error, is_frozen, frozen_balance FROM ATs WHERE AT_address = ?";
try (ResultSet resultSet = this.repository.checkedExecute(sql, atAddress)) {
if (resultSet == null)
return null;
@ -39,7 +39,7 @@ public class HSQLDBATRepository implements ATRepository {
boolean isSleeping = resultSet.getBoolean(6);
Integer sleepUntilHeight = resultSet.getInt(7);
if (resultSet.wasNull())
if (sleepUntilHeight == 0 && resultSet.wasNull())
sleepUntilHeight = null;
boolean isFinished = resultSet.getBoolean(8);
@ -47,8 +47,6 @@ public class HSQLDBATRepository implements ATRepository {
boolean isFrozen = resultSet.getBoolean(10);
BigDecimal frozenBalance = resultSet.getBigDecimal(11);
if (resultSet.wasNull())
frozenBalance = null;
return new ATData(atAddress, creatorPublicKey, creation, version, assetId, codeBytes, isSleeping, sleepUntilHeight, isFinished, hadFatalError,
isFrozen, frozenBalance);
@ -68,10 +66,11 @@ public class HSQLDBATRepository implements ATRepository {
@Override
public List<ATData> getAllExecutableATs() throws DataException {
final String sql = "SELECT AT_address, creator, creation, version, asset_id, code_bytes, is_sleeping, sleep_until_height, had_fatal_error, is_frozen, frozen_balance FROM ATs WHERE is_finished = false ORDER BY creation ASC";
List<ATData> executableATs = new ArrayList<ATData>();
try (ResultSet resultSet = this.repository.checkedExecute(
"SELECT AT_address, creator, creation, version, asset_id, code_bytes, is_sleeping, sleep_until_height, had_fatal_error, is_frozen, frozen_balance FROM ATs WHERE is_finished = false ORDER BY creation ASC")) {
try (ResultSet resultSet = this.repository.checkedExecute(sql)) {
if (resultSet == null)
return executableATs;
@ -87,15 +86,13 @@ public class HSQLDBATRepository implements ATRepository {
boolean isSleeping = resultSet.getBoolean(7);
Integer sleepUntilHeight = resultSet.getInt(8);
if (resultSet.wasNull())
if (sleepUntilHeight == 0 && resultSet.wasNull())
sleepUntilHeight = null;
boolean hadFatalError = resultSet.getBoolean(9);
boolean isFrozen = resultSet.getBoolean(10);
BigDecimal frozenBalance = resultSet.getBigDecimal(11);
if (resultSet.wasNull())
frozenBalance = null;
ATData atData = new ATData(atAddress, creatorPublicKey, creation, version, assetId, codeBytes, isSleeping, sleepUntilHeight, isFinished,
hadFatalError, isFrozen, frozenBalance);
@ -111,9 +108,9 @@ public class HSQLDBATRepository implements ATRepository {
@Override
public Integer getATCreationBlockHeight(String atAddress) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute(
"SELECT height from DeployATTransactions JOIN BlockTransactions ON transaction_signature = signature JOIN Blocks ON Blocks.signature = block_signature WHERE AT_address = ?",
atAddress)) {
final String sql = "SELECT height from DeployATTransactions JOIN BlockTransactions ON transaction_signature = signature JOIN Blocks ON Blocks.signature = block_signature WHERE AT_address = ?";
try (ResultSet resultSet = this.repository.checkedExecute(sql, atAddress)) {
if (resultSet == null)
return null;

View File

@ -29,8 +29,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public GroupData fromGroupId(int groupId) throws DataException {
try (ResultSet resultSet = this.repository
.checkedExecute("SELECT group_name, owner, description, created, updated, reference, is_open, approval_threshold, min_block_delay, max_block_delay, creation_group_id FROM Groups WHERE group_id = ?", groupId)) {
final String sql = "SELECT group_name, owner, description, created, updated, reference, is_open, approval_threshold, min_block_delay, max_block_delay, creation_group_id FROM Groups WHERE group_id = ?";
try (ResultSet resultSet = this.repository.checkedExecute(sql, groupId)) {
if (resultSet == null)
return null;
@ -41,7 +42,7 @@ public class HSQLDBGroupRepository implements GroupRepository {
// Special handling for possibly-NULL "updated" column
Timestamp updatedTimestamp = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC));
Long updated = resultSet.wasNull() ? null : updatedTimestamp.getTime();
Long updated = updatedTimestamp == null ? null : updatedTimestamp.getTime();
byte[] reference = resultSet.getBytes(6);
boolean isOpen = resultSet.getBoolean(7);
@ -73,7 +74,7 @@ public class HSQLDBGroupRepository implements GroupRepository {
// Special handling for possibly-NULL "updated" column
Timestamp updatedTimestamp = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC));
Long updated = resultSet.wasNull() ? null : updatedTimestamp.getTime();
Long updated = updatedTimestamp == null ? null : updatedTimestamp.getTime();
byte[] reference = resultSet.getBytes(6);
boolean isOpen = resultSet.getBoolean(7);
@ -131,7 +132,7 @@ public class HSQLDBGroupRepository implements GroupRepository {
// Special handling for possibly-NULL "updated" column
Timestamp updatedTimestamp = resultSet.getTimestamp(6, Calendar.getInstance(HSQLDBRepository.UTC));
Long updated = resultSet.wasNull() ? null : updatedTimestamp.getTime();
Long updated = updatedTimestamp == null ? null : updatedTimestamp.getTime();
byte[] reference = resultSet.getBytes(7);
boolean isOpen = resultSet.getBoolean(8);

View File

@ -38,7 +38,7 @@ public class HSQLDBNetworkRepository implements NetworkRepository {
Long lastAttempted = HSQLDBRepository.getZonedTimestampMilli(resultSet, 3);
Integer lastHeight = resultSet.getInt(4);
if (resultSet.wasNull())
if (lastHeight == 0 && resultSet.wasNull())
lastHeight = null;
byte[] lastBlockSignature = resultSet.getBytes(5);

View File

@ -736,6 +736,34 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
}
}
@Override
public List<TransactionData> getApprovalTransactionDecidedAtHeight(int approvalHeight) throws DataException {
final String sql = "SELECT signature from Transactions WHERE approval_height = ?";
List<TransactionData> transactions = new ArrayList<>();
try (ResultSet resultSet = this.repository.checkedExecute(sql, approvalHeight)) {
if (resultSet == null)
return transactions;
do {
byte[] signature = resultSet.getBytes(1);
TransactionData transactionData = this.fromSignature(signature);
if (transactionData == null)
// Something inconsistent with the repository
throw new DataException("Unable to fetch approval-decided transaction from repository?");
transactions.add(transactionData);
} while (resultSet.next());
return transactions;
} catch (SQLException | DataException e) {
throw new DataException("Unable to fetch approval-decided transactions from repository", e);
}
}
@Override
public GroupApprovalTransactionData getLatestApproval(byte[] pendingSignature, byte[] adminPublicKey) throws DataException {
String sql = "SELECT signature FROM GroupApprovalTransactions "

View File

@ -20,7 +20,7 @@ public class HSQLDBTransferAssetTransactionRepository extends HSQLDBTransactionR
TransactionData fromBase(BaseTransactionData baseTransactionData) throws DataException {
String sql = "SELECT recipient, asset_id, amount, asset_name FROM TransferAssetTransactions JOIN Assets USING (asset_id) WHERE signature = ?";
try (ResultSet resultSet = this.repository.checkedExecute(sql)) {
try (ResultSet resultSet = this.repository.checkedExecute(sql, baseTransactionData.getSignature())) {
if (resultSet == null)
return null;

View File

@ -120,14 +120,6 @@ public class AccountFlagsTransaction extends Transaction {
// Remove previous flags from transaction itself
accountFlagsTransactionData.setPreviousFlags(null);
this.repository.getTransactionRepository().save(accountFlagsTransactionData);
Account creator = getCreator();
// Update creator's balance
creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).add(accountFlagsTransactionData.getFee()));
// Update creator's reference
creator.setLastReference(accountFlagsTransactionData.getReference());
}
}

View File

@ -113,8 +113,6 @@ public class AddGroupAdminTransaction extends Transaction {
// Update Group adminship
Group group = new Group(this.repository, addGroupAdminTransactionData.getGroupId());
group.promoteToAdmin(addGroupAdminTransactionData);
// We would save updated transaction at this point, but it hasn't been modified
}
@Override
@ -122,15 +120,6 @@ public class AddGroupAdminTransaction extends Transaction {
// Revert group adminship
Group group = new Group(this.repository, addGroupAdminTransactionData.getGroupId());
group.unpromoteToAdmin(addGroupAdminTransactionData);
// We would save updated transaction at this point, but it hasn't been modified
// Update owner's balance
Account owner = getOwner();
owner.setConfirmedBalance(Asset.QORA, owner.getConfirmedBalance(Asset.QORA).add(addGroupAdminTransactionData.getFee()));
// Update owner's reference
owner.setLastReference(addGroupAdminTransactionData.getReference());
}
}

View File

@ -116,8 +116,6 @@ public class ArbitraryTransaction extends Transaction {
@Override
public void process() throws DataException {
// We would save updated transaction at this point, but it hasn't been modified
// Wrap and delegate payment processing to Payment class.
new Payment(this.repository).process(arbitraryTransactionData.getSenderPublicKey(), arbitraryTransactionData.getPayments(),
arbitraryTransactionData.getFee(), arbitraryTransactionData.getSignature());
@ -132,11 +130,16 @@ public class ArbitraryTransaction extends Transaction {
@Override
public void orphan() throws DataException {
// Wrap and delegate payment processing to Payment class. Always revert recipients' last references regardless of asset.
// Wrap and delegate payment processing to Payment class.
new Payment(this.repository).orphan(arbitraryTransactionData.getSenderPublicKey(), arbitraryTransactionData.getPayments(),
arbitraryTransactionData.getFee(), arbitraryTransactionData.getSignature(), arbitraryTransactionData.getReference(), true);
arbitraryTransactionData.getFee(), arbitraryTransactionData.getSignature(), arbitraryTransactionData.getReference());
}
// We would save transaction in orphaned form at this point, but it hasn't been modified
@Override
public void orphanReferencesAndFees() throws DataException {
// Wrap and delegate reference and fee processing to Payment class. Always revert recipients' last references regardless of asset.
new Payment(this.repository).orphanReferencesAndFees(arbitraryTransactionData.getSenderPublicKey(), arbitraryTransactionData.getPayments(),
arbitraryTransactionData.getFee(), arbitraryTransactionData.getSignature(), arbitraryTransactionData.getReference(), true);
}
// Data access

View File

@ -161,8 +161,6 @@ public class AtTransaction extends Transaction {
@Override
public void process() throws DataException {
// We would save updated transaction at this point, but it hasn't been modified
if (this.atTransactionData.getAmount() != null) {
Account sender = getATAccount();
Account recipient = getRecipient();
@ -206,6 +204,17 @@ public class AtTransaction extends Transaction {
// Update recipient's balance
recipient.setConfirmedBalance(assetId, recipient.getConfirmedBalance(assetId).subtract(amount));
}
// As AT_TRANSACTIONs are really part of a block, the caller (Block) will probably delete this transaction after orphaning
}
@Override
public void orphanReferencesAndFees() throws DataException {
if (this.atTransactionData.getAmount() != null) {
Account recipient = getRecipient();
long assetId = this.atTransactionData.getAssetId();
/*
* 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
@ -214,10 +223,6 @@ public class AtTransaction extends Transaction {
if (assetId == Asset.QORA && Arrays.equals(recipient.getLastReference(), this.atTransactionData.getSignature()))
recipient.setLastReference(null);
}
// We would save updated transaction at this point, but it hasn't been modified
// As AT_TRANSACTIONs are really part of a block, the caller (Block) will probably delete this transaction after orphaning
}
}

View File

@ -134,13 +134,6 @@ public class BuyNameTransaction extends Transaction {
// Save this transaction, with removed "name reference"
this.repository.getTransactionRepository().save(buyNameTransactionData);
// Update buyer's balance
Account buyer = getBuyer();
buyer.setConfirmedBalance(Asset.QORA, buyer.getConfirmedBalance(Asset.QORA).add(buyNameTransactionData.getFee()));
// Update buyer's reference
buyer.setLastReference(buyNameTransactionData.getReference());
}
}

View File

@ -94,8 +94,6 @@ public class CancelAssetOrderTransaction extends Transaction {
@Override
public void process() throws DataException {
// We would save updated transaction at this point, but it hasn't been modified
// Mark Order as completed so no more trades can happen
OrderData orderData = this.repository.getAssetRepository().fromOrderId(cancelOrderTransactionData.getOrderId());
Order order = new Order(this.repository, orderData);
@ -104,16 +102,6 @@ public class CancelAssetOrderTransaction extends Transaction {
@Override
public void orphan() throws DataException {
Account creator = getCreator();
// We would save transaction in orphaned form at this point, but it hasn't been modified
// Update creator's balance regarding fee
creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).add(cancelOrderTransactionData.getFee()));
// Update creator's last reference
creator.setLastReference(cancelOrderTransactionData.getReference());
// Unmark Order as completed so trades can happen again
OrderData orderData = this.repository.getAssetRepository().fromOrderId(cancelOrderTransactionData.getOrderId());
Order order = new Order(this.repository, orderData);

View File

@ -124,13 +124,6 @@ public class CancelGroupBanTransaction extends Transaction {
// Save this transaction with removed member/admin references
this.repository.getTransactionRepository().save(groupUnbanTransactionData);
// Update admin's balance
Account admin = getAdmin();
admin.setConfirmedBalance(Asset.QORA, admin.getConfirmedBalance(Asset.QORA).add(groupUnbanTransactionData.getFee()));
// Update admin's reference
admin.setLastReference(groupUnbanTransactionData.getReference());
}
}

View File

@ -124,13 +124,6 @@ public class CancelGroupInviteTransaction extends Transaction {
// Save this transaction with removed member/admin references
this.repository.getTransactionRepository().save(cancelGroupInviteTransactionData);
// Update admin's balance
Account admin = getAdmin();
admin.setConfirmedBalance(Asset.QORA, admin.getConfirmedBalance(Asset.QORA).add(cancelGroupInviteTransactionData.getFee()));
// Update admin's reference
admin.setLastReference(cancelGroupInviteTransactionData.getReference());
}
}

View File

@ -121,13 +121,6 @@ public class CancelSellNameTransaction extends Transaction {
// Save this transaction, with removed "name reference"
this.repository.getTransactionRepository().save(cancelSellNameTransactionData);
// Update owner's balance
Account owner = getOwner();
owner.setConfirmedBalance(Asset.QORA, owner.getConfirmedBalance(Asset.QORA).add(cancelSellNameTransactionData.getFee()));
// Update owner's reference
owner.setLastReference(cancelSellNameTransactionData.getReference());
}
}

View File

@ -178,16 +178,6 @@ public class CreateAssetOrderTransaction extends Transaction {
@Override
public void process() throws DataException {
Account creator = getCreator();
// Update creator's balance due to fee
creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).subtract(createOrderTransactionData.getFee()));
// Update creator's last reference
creator.setLastReference(createOrderTransactionData.getSignature());
// We would save updated transaction at this point, but it hasn't been modified
// Order Id is transaction's signature
byte[] orderId = createOrderTransactionData.getSignature();
@ -201,22 +191,12 @@ public class CreateAssetOrderTransaction extends Transaction {
@Override
public void orphan() throws DataException {
Account creator = getCreator();
// Update creator's balance due to fee
creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).add(createOrderTransactionData.getFee()));
// Update creator's last reference
creator.setLastReference(createOrderTransactionData.getReference());
// Order Id is transaction's signature
byte[] orderId = createOrderTransactionData.getSignature();
// Orphan the order itself
OrderData orderData = this.repository.getAssetRepository().fromOrderId(orderId);
new Order(this.repository, orderData).orphan();
// We would save updated transaction at this point, but it hasn't been modified
}
}

View File

@ -122,7 +122,7 @@ public class CreateGroupTransaction extends Transaction {
// Note newly assigned group ID in our transaction record
createGroupTransactionData.setGroupId(group.getGroupData().getGroupId());
// Save this transaction
// Save this transaction with newly assigned group ID
this.repository.getTransactionRepository().save(createGroupTransactionData);
}
@ -137,13 +137,6 @@ public class CreateGroupTransaction extends Transaction {
// Save this transaction with removed group ID
this.repository.getTransactionRepository().save(createGroupTransactionData);
// Update creator's balance
Account creator = getCreator();
creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).add(createGroupTransactionData.getFee()));
// Update creator's reference
creator.setLastReference(createGroupTransactionData.getReference());
}
}

View File

@ -153,8 +153,6 @@ public class CreatePollTransaction extends Transaction {
// Publish poll to allow voting
Poll poll = new Poll(this.repository, createPollTransactionData);
poll.publish();
// We would save updated transaction at this point, but it hasn't been modified
}
@Override
@ -162,15 +160,6 @@ public class CreatePollTransaction extends Transaction {
// Unpublish poll
Poll poll = new Poll(this.repository, createPollTransactionData.getPollName());
poll.unpublish();
// We would save updated transaction at this point, but it hasn't been modified
// Update creator's balance
Account creator = getCreator();
creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).add(createPollTransactionData.getFee()));
// Update creator's reference
creator.setLastReference(createPollTransactionData.getReference());
}
}

View File

@ -238,8 +238,6 @@ public class DeployAtTransaction extends Transaction {
AT at = new AT(this.repository, this.deployATTransactionData);
at.deploy();
// We would save updated transaction at this point, but it hasn't been modified
long assetId = deployATTransactionData.getAssetId();
// Update creator's balance regarding initial payment to AT
@ -260,17 +258,11 @@ public class DeployAtTransaction extends Transaction {
AT at = new AT(this.repository, this.deployATTransactionData);
at.undeploy();
// We would save updated transaction at this point, but it hasn't been modified
long assetId = deployATTransactionData.getAssetId();
// Update creator's balance
// Update creator's balance regarding initial payment to AT
Account creator = getCreator();
creator.setConfirmedBalance(assetId, creator.getConfirmedBalance(assetId).add(deployATTransactionData.getAmount()));
creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).add(deployATTransactionData.getFee()));
// Update creator's reference
creator.setLastReference(deployATTransactionData.getReference());
// Delete AT's account (and hence its balance)
this.repository.getAccountRepository().delete(this.deployATTransactionData.getAtAddress());

View File

@ -146,8 +146,6 @@ public class EnableForgingTransaction extends Transaction {
target.setFlags(targetFlags);
target.setForgingEnabler(creator.getAddress());
// We would save updated transaction at this point, but it hasn't been modified
}
@Override
@ -169,14 +167,6 @@ public class EnableForgingTransaction extends Transaction {
target.setFlags(targetFlags);
target.setForgingEnabler(null);
// We would save updated transaction at this point, but it hasn't been modified
// Update creator's balance
creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).add(enableForgingTransactionData.getFee()));
// Update creator's reference
creator.setLastReference(enableForgingTransactionData.getReference());
}
}

View File

@ -136,8 +136,6 @@ public class GenesisTransaction extends Transaction {
@Override
public void process() throws DataException {
// We would save updated transaction at this point, but it hasn't been modified
Account recipient = new Account(repository, genesisTransactionData.getRecipient());
// Update recipient's balance
@ -156,10 +154,13 @@ public class GenesisTransaction extends Transaction {
@Override
public void orphan() throws DataException {
// We would save updated transaction at this point, but it hasn't been modified
// Delete recipient's account (and balance)
this.repository.getAccountRepository().delete(genesisTransactionData.getRecipient());
}
@Override
public void orphanReferencesAndFees() throws DataException {
// Recipient's last reference removed thanks to delete() called by orphan() above.
}
}

View File

@ -106,13 +106,6 @@ public class GroupApprovalTransaction extends Transaction {
// Save this transaction with removed prior reference
groupApprovalTransactionData.setPriorReference(null);
this.repository.getTransactionRepository().save(groupApprovalTransactionData);
// Update admin's balance
Account admin = getAdmin();
admin.setConfirmedBalance(Asset.QORA, admin.getConfirmedBalance(Asset.QORA).add(groupApprovalTransactionData.getFee()));
// Update admin's reference
admin.setLastReference(groupApprovalTransactionData.getReference());
}
}

View File

@ -125,13 +125,6 @@ public class GroupBanTransaction extends Transaction {
// Save this transaction with removed member/admin references
this.repository.getTransactionRepository().save(groupBanTransactionData);
// Update admin's balance
Account admin = getAdmin();
admin.setConfirmedBalance(Asset.QORA, admin.getConfirmedBalance(Asset.QORA).add(groupBanTransactionData.getFee()));
// Update admin's reference
admin.setLastReference(groupBanTransactionData.getReference());
}
}

View File

@ -131,13 +131,6 @@ public class GroupInviteTransaction extends Transaction {
// Save this transaction with removed member/admin references
this.repository.getTransactionRepository().save(groupInviteTransactionData);
// Update admin's balance
Account admin = getAdmin();
admin.setConfirmedBalance(Asset.QORA, admin.getConfirmedBalance(Asset.QORA).add(groupInviteTransactionData.getFee()));
// Update admin's reference
admin.setLastReference(groupInviteTransactionData.getReference());
}
}

View File

@ -131,13 +131,6 @@ public class GroupKickTransaction extends Transaction {
// Save this transaction with removed member/admin references
this.repository.getTransactionRepository().save(groupKickTransactionData);
// Update admin's balance
Account admin = getAdmin();
admin.setConfirmedBalance(Asset.QORA, admin.getConfirmedBalance(Asset.QORA).add(groupKickTransactionData.getFee()));
// Update admin's reference
admin.setLastReference(groupKickTransactionData.getReference());
}
}

View File

@ -142,15 +142,15 @@ public class IssueAssetTransaction extends Transaction {
Asset asset = new Asset(this.repository, issueAssetTransactionData);
asset.issue();
// Add asset to owner
Account owner = getOwner();
owner.setConfirmedBalance(asset.getAssetData().getAssetId(), BigDecimal.valueOf(issueAssetTransactionData.getQuantity()).setScale(8));
// Note newly assigned asset ID in our transaction record
issueAssetTransactionData.setAssetId(asset.getAssetData().getAssetId());
// Save this transaction, now with corresponding assetId
// Save this transaction with newly assigned assetId
this.repository.getTransactionRepository().save(issueAssetTransactionData);
// Add asset to owner
Account owner = getOwner();
owner.setConfirmedBalance(issueAssetTransactionData.getAssetId(), BigDecimal.valueOf(issueAssetTransactionData.getQuantity()).setScale(8));
}
@Override
@ -168,13 +168,6 @@ public class IssueAssetTransaction extends Transaction {
// Save this transaction, with removed assetId
this.repository.getTransactionRepository().save(issueAssetTransactionData);
// Update issuer's balance
Account issuer = getIssuer();
issuer.setConfirmedBalance(Asset.QORA, issuer.getConfirmedBalance(Asset.QORA).add(issueAssetTransactionData.getFee()));
// Update issuer's reference
issuer.setLastReference(issueAssetTransactionData.getReference());
}
}

View File

@ -111,13 +111,6 @@ public class JoinGroupTransaction extends Transaction {
// Save this transaction with removed references
this.repository.getTransactionRepository().save(joinGroupTransactionData);
// Update joiner's balance
Account joiner = getJoiner();
joiner.setConfirmedBalance(Asset.QORA, joiner.getConfirmedBalance(Asset.QORA).add(joinGroupTransactionData.getFee()));
// Update joiner's reference
joiner.setLastReference(joinGroupTransactionData.getReference());
}
}

View File

@ -110,13 +110,6 @@ public class LeaveGroupTransaction extends Transaction {
// Save this transaction with removed member/admin references
this.repository.getTransactionRepository().save(leaveGroupTransactionData);
// Update leaver's balance
Account leaver = getLeaver();
leaver.setConfirmedBalance(Asset.QORA, leaver.getConfirmedBalance(Asset.QORA).add(leaveGroupTransactionData.getFee()));
// Update leaver's reference
leaver.setLastReference(leaveGroupTransactionData.getReference());
}
}

View File

@ -120,8 +120,6 @@ public class MessageTransaction extends Transaction {
@Override
public void process() throws DataException {
// We would save updated transaction at this point, but it hasn't been modified
// Wrap and delegate payment processing to Payment class.
new Payment(this.repository).process(messageTransactionData.getSenderPublicKey(), getPaymentData(), messageTransactionData.getFee(),
messageTransactionData.getSignature());
@ -136,11 +134,16 @@ public class MessageTransaction extends Transaction {
@Override
public void orphan() throws DataException {
// Wrap and delegate payment processing to Payment class. Only revert recipient's last reference if transferring QORA.
// Wrap and delegate payment processing to Payment class.
new Payment(this.repository).orphan(messageTransactionData.getSenderPublicKey(), getPaymentData(), messageTransactionData.getFee(),
messageTransactionData.getSignature(), messageTransactionData.getReference(), false);
messageTransactionData.getSignature(), messageTransactionData.getReference());
}
// We would save updated transaction at this point, but it hasn't been modified
@Override
public void orphanReferencesAndFees() throws DataException {
// Wrap and delegate references processing to Payment class. Only revert recipient's last reference if transferring QORA.
new Payment(this.repository).orphanReferencesAndFees(messageTransactionData.getSenderPublicKey(), getPaymentData(), messageTransactionData.getFee(),
messageTransactionData.getSignature(), messageTransactionData.getReference(), false);
}
}

View File

@ -119,8 +119,6 @@ public class MultiPaymentTransaction extends Transaction {
@Override
public void process() throws DataException {
// We would save updated transaction at this point, but it hasn't been modified
// Wrap and delegate payment processing to Payment class.
new Payment(this.repository).process(multiPaymentTransactionData.getSenderPublicKey(), multiPaymentTransactionData.getPayments(),
multiPaymentTransactionData.getFee(), multiPaymentTransactionData.getSignature());
@ -128,8 +126,6 @@ public class MultiPaymentTransaction extends Transaction {
@Override
public void processReferencesAndFees() throws DataException {
// We would save updated transaction at this point, but it hasn't been modified
// Wrap and delegate reference processing to Payment class. Always update recipients' last references regardless of asset.
new Payment(this.repository).processReferencesAndFees(multiPaymentTransactionData.getSenderPublicKey(), multiPaymentTransactionData.getPayments(),
multiPaymentTransactionData.getFee(), multiPaymentTransactionData.getSignature(), true);
@ -139,9 +135,14 @@ public class MultiPaymentTransaction extends Transaction {
public void orphan() throws DataException {
// Wrap and delegate payment processing to Payment class. Always revert recipients' last references regardless of asset.
new Payment(this.repository).orphan(multiPaymentTransactionData.getSenderPublicKey(), multiPaymentTransactionData.getPayments(),
multiPaymentTransactionData.getFee(), multiPaymentTransactionData.getSignature(), multiPaymentTransactionData.getReference(), true);
multiPaymentTransactionData.getFee(), multiPaymentTransactionData.getSignature(), multiPaymentTransactionData.getReference());
}
// We would save updated transaction at this point, but it hasn't been modified
@Override
public void orphanReferencesAndFees() throws DataException {
// Wrap and delegate reference processing to Payment class. Always revert recipients' last references regardless of asset.
new Payment(this.repository).orphanReferencesAndFees(multiPaymentTransactionData.getSenderPublicKey(), multiPaymentTransactionData.getPayments(),
multiPaymentTransactionData.getFee(), multiPaymentTransactionData.getSignature(), multiPaymentTransactionData.getReference(), true);
}
}

View File

@ -88,8 +88,6 @@ public class PaymentTransaction extends Transaction {
@Override
public void process() throws DataException {
// We would save updated transaction at this point, but it hasn't been modified
// Wrap and delegate payment processing to Payment class.
new Payment(this.repository).process(paymentTransactionData.getSenderPublicKey(), getPaymentData(), paymentTransactionData.getFee(),
paymentTransactionData.getSignature());
@ -106,9 +104,14 @@ public class PaymentTransaction extends Transaction {
public void orphan() throws DataException {
// Wrap and delegate payment processing to Payment class. Only revert recipient's last reference if transferring QORA.
new Payment(this.repository).orphan(paymentTransactionData.getSenderPublicKey(), getPaymentData(), paymentTransactionData.getFee(),
paymentTransactionData.getSignature(), paymentTransactionData.getReference(), false);
paymentTransactionData.getSignature(), paymentTransactionData.getReference());
}
// We would save updated transaction at this point, but it hasn't been modified
@Override
public void orphanReferencesAndFees() throws DataException {
// Wrap and delegate payment processing to Payment class. Only revert recipient's last reference if transferring QORA.
new Payment(this.repository).orphanReferencesAndFees(paymentTransactionData.getSenderPublicKey(), getPaymentData(), paymentTransactionData.getFee(),
paymentTransactionData.getSignature(), paymentTransactionData.getReference(), false);
}
}

View File

@ -161,12 +161,11 @@ public class ProxyForgingTransaction extends Transaction {
// Save this transaction, with removed previous share info
proxyForgingTransactionData.setPreviousShare(null);
this.repository.getTransactionRepository().save(proxyForgingTransactionData);
}
// Update forger's balance
forger.setConfirmedBalance(Asset.QORA, forger.getConfirmedBalance(Asset.QORA).add(proxyForgingTransactionData.getFee()));
// Update forger's reference
forger.setLastReference(proxyForgingTransactionData.getReference());
@Override
public void orphanReferencesAndFees() throws DataException {
super.orphanReferencesAndFees();
// If recipient didn't have a last-reference prior to this transaction then remove it
Account recipient = new Account(this.repository, proxyForgingTransactionData.getRecipient());

View File

@ -126,8 +126,6 @@ public class RegisterNameTransaction extends Transaction {
// Register Name
Name name = new Name(this.repository, registerNameTransactionData);
name.register();
// We would save updated transaction at this point, but it hasn't been modified
}
@Override
@ -135,15 +133,6 @@ public class RegisterNameTransaction extends Transaction {
// Unregister name
Name name = new Name(this.repository, registerNameTransactionData.getName());
name.unregister();
// We would save updated transaction at this point, but it hasn't been modified
// Update registrant's balance
Account registrant = getRegistrant();
registrant.setConfirmedBalance(Asset.QORA, registrant.getConfirmedBalance(Asset.QORA).add(registerNameTransactionData.getFee()));
// Update registrant's reference
registrant.setLastReference(registerNameTransactionData.getReference());
}
}

View File

@ -124,13 +124,6 @@ public class RemoveGroupAdminTransaction extends Transaction {
// Save this transaction with removed group references
this.repository.getTransactionRepository().save(removeGroupAdminTransactionData);
// Update owner's balance
Account owner = getOwner();
owner.setConfirmedBalance(Asset.QORA, owner.getConfirmedBalance(Asset.QORA).add(removeGroupAdminTransactionData.getFee()));
// Update owner's reference
owner.setLastReference(removeGroupAdminTransactionData.getReference());
}
}

View File

@ -116,8 +116,6 @@ public class SellNameTransaction extends Transaction {
// Sell Name
Name name = new Name(this.repository, sellNameTransactionData.getName());
name.sell(sellNameTransactionData);
// We would save updated transaction at this point, but it hasn't been modified
}
@Override
@ -125,15 +123,6 @@ public class SellNameTransaction extends Transaction {
// Revert name
Name name = new Name(this.repository, sellNameTransactionData.getName());
name.unsell(sellNameTransactionData);
// We would save updated transaction at this point, but it hasn't been modified
// Update owner's balance
Account owner = getOwner();
owner.setConfirmedBalance(Asset.QORA, owner.getConfirmedBalance(Asset.QORA).add(sellNameTransactionData.getFee()));
// Update owner's reference
owner.setLastReference(sellNameTransactionData.getReference());
}
}

View File

@ -111,12 +111,6 @@ public class SetGroupTransaction extends Transaction {
// Save this transaction with removed previous defaultGroupId value
setGroupTransactionData.setPreviousDefaultGroupId(null);
this.repository.getTransactionRepository().save(setGroupTransactionData);
// Update creator's balance
creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).add(setGroupTransactionData.getFee()));
// Update admin's reference
creator.setLastReference(setGroupTransactionData.getReference());
}
}

View File

@ -909,6 +909,22 @@ public abstract class Transaction {
*/
public abstract void orphan() throws DataException;
/**
* Update last references, subtract transaction fees, etc.
*
* @throws DataException
*/
public void orphanReferencesAndFees() throws DataException {
Account creator = getCreator();
// Update transaction creator's balance
creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).add(transactionData.getFee()));
// Update transaction creator's reference
creator.setLastReference(transactionData.getReference());
}
// Comparison
/** Returns comparator that sorts ATTransactions first, then by timestamp, then by signature */

View File

@ -100,8 +100,6 @@ public class TransferAssetTransaction extends Transaction {
@Override
public void process() throws DataException {
// We would save updated transaction at this point, but it hasn't been modified
// Wrap asset transfer as a payment and delegate processing to Payment class. Only update recipient's last reference if transferring QORA.
new Payment(this.repository).process(transferAssetTransactionData.getSenderPublicKey(), getPaymentData(), transferAssetTransactionData.getFee(),
transferAssetTransactionData.getSignature());
@ -118,9 +116,14 @@ public class TransferAssetTransaction extends Transaction {
public void orphan() throws DataException {
// Wrap asset transfer as a payment and delegate processing to Payment class. Only revert recipient's last reference if transferring QORA.
new Payment(this.repository).orphan(transferAssetTransactionData.getSenderPublicKey(), getPaymentData(), transferAssetTransactionData.getFee(),
transferAssetTransactionData.getSignature(), transferAssetTransactionData.getReference(), false);
transferAssetTransactionData.getSignature(), transferAssetTransactionData.getReference());
}
// We would save updated transaction at this point, but it hasn't been modified
@Override
public void orphanReferencesAndFees() throws DataException {
// Wrap asset transfer as a payment and delegate processing to Payment class. Only revert recipient's last reference if transferring QORA.
new Payment(this.repository).orphanReferencesAndFees(transferAssetTransactionData.getSenderPublicKey(), getPaymentData(), transferAssetTransactionData.getFee(),
transferAssetTransactionData.getSignature(), transferAssetTransactionData.getReference(), false);
}
}

View File

@ -146,14 +146,6 @@ public class UpdateAssetTransaction extends Transaction {
// Save this transaction, with removed "name reference" to previous transaction that updated name
this.repository.getTransactionRepository().save(updateAssetTransactionData);
// Update owner's balance
Account owner = getOwner();
owner.setConfirmedBalance(Asset.QORA,
owner.getConfirmedBalance(Asset.QORA).add(updateAssetTransactionData.getFee()));
// Update owner's reference
owner.setLastReference(updateAssetTransactionData.getReference());
}
}

View File

@ -148,13 +148,6 @@ public class UpdateGroupTransaction extends Transaction {
// Save this transaction, now with removed "group reference"
this.repository.getTransactionRepository().save(updateGroupTransactionData);
// Update owner's balance
Account owner = getOwner();
owner.setConfirmedBalance(Asset.QORA, owner.getConfirmedBalance(Asset.QORA).add(updateGroupTransactionData.getFee()));
// Update owner's reference
owner.setLastReference(updateGroupTransactionData.getReference());
}
}

View File

@ -151,13 +151,6 @@ public class UpdateNameTransaction extends Transaction {
// Save this transaction, now with removed "name reference"
this.repository.getTransactionRepository().save(updateNameTransactionData);
// Update owner's balance
Account owner = getOwner();
owner.setConfirmedBalance(Asset.QORA, owner.getConfirmedBalance(Asset.QORA).add(updateNameTransactionData.getFee()));
// Update owner's reference
owner.setLastReference(updateNameTransactionData.getReference());
}
}

View File

@ -144,12 +144,7 @@ public class VoteOnPollTransaction extends Transaction {
@Override
public void orphan() throws DataException {
// Update voter's balance
Account voter = getVoter();
voter.setConfirmedBalance(Asset.QORA, voter.getConfirmedBalance(Asset.QORA).add(voteOnPollTransactionData.getFee()));
// Update voter's reference
voter.setLastReference(voteOnPollTransactionData.getReference());
// Does this transaction have previous vote info?
VotingRepository votingRepository = this.repository.getVotingRepository();