forked from Qortal/qortal
MAJOR: Don't delete transactions when orphaning - make them unconfirmed again
Lots of edits to Transaction subclasses to change/remove 'delete'. Corresponding extra changes to help reset some transaction fields to pre-process state during orphaning. Changed Block, GenesisBlock & Synchronizer to save transactions where appropriate. Added enhanced GET_SIGNATURES_V2 network message to reduce the number of block signatures sent over network. Peers are now version 2 if they send a new-style build version string, instead of using first digit from build version.
This commit is contained in:
parent
07e8e01865
commit
a3d4cf2900
@ -156,6 +156,9 @@ public class Asset {
|
||||
|
||||
// Save reverted asset
|
||||
this.repository.getAssetRepository().save(this.assetData);
|
||||
|
||||
// Remove reference to previous asset-changing transaction
|
||||
updateAssetTransactionData.setOrphanReference(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import org.qora.repository.Repository;
|
||||
import org.qora.transaction.AtTransaction;
|
||||
import org.qora.transaction.GenesisTransaction;
|
||||
import org.qora.transaction.Transaction;
|
||||
import org.qora.transaction.Transaction.TransactionType;
|
||||
import org.qora.transform.TransformationException;
|
||||
import org.qora.transform.block.BlockTransformer;
|
||||
import org.qora.transform.transaction.TransactionTransformer;
|
||||
@ -1045,10 +1046,15 @@ public class Block {
|
||||
processBlockRewards();
|
||||
|
||||
// Process transactions (we'll link them to this block after saving the block itself)
|
||||
// AT-generated transactions are already added to our transactions so no special handling is needed here.
|
||||
// AT-generated transactions are already prepended to our transactions at this point.
|
||||
List<Transaction> transactions = this.getTransactions();
|
||||
for (Transaction transaction : transactions)
|
||||
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());
|
||||
|
||||
transaction.process();
|
||||
}
|
||||
|
||||
// Give transaction fees to generator/proxy
|
||||
rewardTransactionFees();
|
||||
@ -1158,9 +1164,11 @@ public class Block {
|
||||
transaction.getTransactionData().getSignature());
|
||||
this.repository.getBlockRepository().delete(blockTransactionData);
|
||||
|
||||
// Add to unconfirmed pile
|
||||
// XXX WE CAN'T ADD TO UNCONFIRMED AS TRANSACTION HAS BEEN DELETED BY transaction.orphan() ABOVE
|
||||
// this.repository.getTransactionRepository().unconfirmTransaction(transaction.getTransactionData());
|
||||
// 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());
|
||||
}
|
||||
|
@ -318,6 +318,10 @@ public class GenesisBlock extends Block {
|
||||
this.repository.rollbackToSavepoint();
|
||||
}
|
||||
|
||||
// Save transactions into repository ready for processing
|
||||
for (Transaction transaction : this.getTransactions())
|
||||
this.repository.getTransactionRepository().save(transaction.getTransactionData());
|
||||
|
||||
super.process();
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ import org.qora.network.message.GetBlockMessage;
|
||||
import org.qora.network.message.GetBlockSummariesMessage;
|
||||
import org.qora.network.message.GetPeersMessage;
|
||||
import org.qora.network.message.GetSignaturesMessage;
|
||||
import org.qora.network.message.GetSignaturesV2Message;
|
||||
import org.qora.network.message.HeightMessage;
|
||||
import org.qora.network.message.Message;
|
||||
import org.qora.network.message.SignaturesMessage;
|
||||
@ -165,6 +166,7 @@ public class Controller extends Thread {
|
||||
LOGGER.info("Validating blockchain");
|
||||
try {
|
||||
BlockChain.validate();
|
||||
LOGGER.info(String.format("Our chain height at start-up: %d", getInstance().getChainHeight()));
|
||||
} catch (DataException e) {
|
||||
LOGGER.error("Couldn't validate blockchain", e);
|
||||
System.exit(2);
|
||||
@ -415,6 +417,32 @@ public class Controller extends Thread {
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_SIGNATURES_V2:
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
GetSignaturesV2Message getSignaturesMessage = (GetSignaturesV2Message) message;
|
||||
byte[] parentSignature = getSignaturesMessage.getParentSignature();
|
||||
|
||||
List<byte[]> signatures = new ArrayList<>();
|
||||
|
||||
do {
|
||||
BlockData blockData = repository.getBlockRepository().fromReference(parentSignature);
|
||||
|
||||
if (blockData == null)
|
||||
break;
|
||||
|
||||
parentSignature = blockData.getSignature();
|
||||
signatures.add(parentSignature);
|
||||
} while (signatures.size() < getSignaturesMessage.getNumberRequested());
|
||||
|
||||
Message signaturesMessage = new SignaturesMessage(signatures);
|
||||
signaturesMessage.setId(message.getId());
|
||||
if (!peer.sendMessage(signaturesMessage))
|
||||
peer.disconnect();
|
||||
} catch (DataException e) {
|
||||
LOGGER.error(String.format("Repository issue while responding to %s from peer %s", message.getType().name(), peer), e);
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_BLOCK:
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
GetBlockMessage getBlockMessage = (GetBlockMessage) message;
|
||||
|
@ -18,12 +18,14 @@ import org.qora.network.message.BlockSummariesMessage;
|
||||
import org.qora.network.message.GetBlockMessage;
|
||||
import org.qora.network.message.GetBlockSummariesMessage;
|
||||
import org.qora.network.message.GetSignaturesMessage;
|
||||
import org.qora.network.message.GetSignaturesV2Message;
|
||||
import org.qora.network.message.Message;
|
||||
import org.qora.network.message.Message.MessageType;
|
||||
import org.qora.network.message.SignaturesMessage;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
import org.qora.repository.RepositoryManager;
|
||||
import org.qora.transaction.Transaction;
|
||||
|
||||
public class Synchronizer {
|
||||
|
||||
@ -168,10 +170,11 @@ public class Synchronizer {
|
||||
|
||||
// Fetch, and apply, blocks from peer
|
||||
byte[] signature = commonBlockData.getSignature();
|
||||
while (ourHeight < peerHeight && ourHeight < commonBlockHeight + SYNC_BATCH_SIZE) {
|
||||
int maxBatchHeight = commonBlockHeight + SYNC_BATCH_SIZE;
|
||||
while (ourHeight < peerHeight && ourHeight < maxBatchHeight) {
|
||||
// Do we need more signatures?
|
||||
if (signatures.isEmpty()) {
|
||||
signatures = this.getBlockSignatures(peer, signature, MAXIMUM_BLOCK_STEP);
|
||||
signatures = this.getBlockSignatures(peer, signature, maxBatchHeight - ourHeight);
|
||||
if (signatures == null || signatures.isEmpty()) {
|
||||
LOGGER.info(String.format("Peer %s failed to respond with more block signatures after height %d", peer, ourHeight));
|
||||
return SynchronizationResult.NO_REPLY;
|
||||
@ -200,6 +203,10 @@ public class Synchronizer {
|
||||
return SynchronizationResult.INVALID_DATA;
|
||||
}
|
||||
|
||||
// Save transactions attached to this block
|
||||
for (Transaction transaction : newBlock.getTransactions())
|
||||
repository.getTransactionRepository().save(transaction.getTransactionData());
|
||||
|
||||
newBlock.process();
|
||||
|
||||
// If we've grown our blockchain then at least save progress so far
|
||||
@ -316,8 +323,9 @@ public class Synchronizer {
|
||||
}
|
||||
|
||||
private List<byte[]> getBlockSignatures(Peer peer, byte[] parentSignature, int numberRequested) {
|
||||
// TODO numberRequested is v2+ feature
|
||||
Message getSignaturesMessage = new GetSignaturesMessage(parentSignature);
|
||||
// numberRequested is v2+ feature
|
||||
Message getSignaturesMessage = peer.getVersion() >= 2 ? new GetSignaturesV2Message(parentSignature, numberRequested) : new GetSignaturesMessage(parentSignature);
|
||||
// Message getSignaturesMessage = new GetSignaturesMessage(parentSignature);
|
||||
|
||||
Message message = peer.getResponse(getSignaturesMessage);
|
||||
if (message == null || message.getType() != MessageType.SIGNATURES)
|
||||
|
@ -65,7 +65,7 @@ public class SetGroupTransactionData extends TransactionData {
|
||||
return this.previousDefaultGroupId;
|
||||
}
|
||||
|
||||
public void setPreviousDefaultGroupId(int previousDefaultGroupId) {
|
||||
public void setPreviousDefaultGroupId(Integer previousDefaultGroupId) {
|
||||
this.previousDefaultGroupId = previousDefaultGroupId;
|
||||
}
|
||||
|
||||
|
@ -361,6 +361,9 @@ public class Group {
|
||||
if (Arrays.equals(groupMemberData.getReference(), updateGroupTransactionData.getSignature()))
|
||||
this.deleteMember(newOwner);
|
||||
}
|
||||
|
||||
// Remove cached reference to previous group change from transaction data
|
||||
updateGroupTransactionData.setGroupReference(null);
|
||||
}
|
||||
|
||||
/** Reverts groupData using previous values stored in referenced transaction. */
|
||||
@ -485,27 +488,27 @@ public class Group {
|
||||
if (joinReference != null) {
|
||||
// Rebuild join-request
|
||||
this.rebuildJoinRequest(member, joinReference);
|
||||
} else {
|
||||
// Rebuild member entry using stored transaction reference
|
||||
this.rebuildMember(member, groupKickTransactionData.getMemberReference());
|
||||
|
||||
return;
|
||||
// Revert member's defaultGroupId if necessary
|
||||
Integer previousDefaultGroupId = groupKickTransactionData.getPreviousGroupId();
|
||||
if (previousDefaultGroupId != null) {
|
||||
Account memberAccount = new Account(this.repository, member);
|
||||
memberAccount.setDefaultGroupId(previousDefaultGroupId);
|
||||
}
|
||||
|
||||
if (groupKickTransactionData.getAdminReference() != null)
|
||||
// Rebuild admin entry using stored transaction reference
|
||||
this.rebuildAdmin(member, groupKickTransactionData.getAdminReference());
|
||||
}
|
||||
|
||||
// Rebuild member entry using stored transaction reference
|
||||
this.rebuildMember(member, groupKickTransactionData.getMemberReference());
|
||||
|
||||
// Revert member's defaultGroupId if necessary
|
||||
Integer previousDefaultGroupId = groupKickTransactionData.getPreviousGroupId();
|
||||
if (previousDefaultGroupId != null) {
|
||||
Account memberAccount = new Account(this.repository, member);
|
||||
memberAccount.setDefaultGroupId(previousDefaultGroupId);
|
||||
}
|
||||
|
||||
if (groupKickTransactionData.getAdminReference() != null)
|
||||
// Rebuild admin entry using stored transaction reference
|
||||
this.rebuildAdmin(member, groupKickTransactionData.getAdminReference());
|
||||
|
||||
// Clean cached references to transactions used to rebuild member/admin info
|
||||
groupKickTransactionData.setMemberReference(null);
|
||||
groupKickTransactionData.setAdminReference(null);
|
||||
groupKickTransactionData.setJoinReference(null);
|
||||
groupKickTransactionData.setPreviousGroupId(null);
|
||||
}
|
||||
|
||||
public void ban(GroupBanTransactionData groupBanTransactionData) throws DataException {
|
||||
@ -622,6 +625,12 @@ public class Group {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any group-related references from transaction data
|
||||
groupBanTransactionData.setMemberReference(null);
|
||||
groupBanTransactionData.setAdminReference(null);
|
||||
groupBanTransactionData.setJoinInviteReference(null);
|
||||
groupBanTransactionData.setPreviousGroupId(null);
|
||||
}
|
||||
|
||||
public void cancelBan(CancelGroupBanTransactionData groupUnbanTransactionData) throws DataException {
|
||||
@ -697,6 +706,10 @@ public class Group {
|
||||
|
||||
// Delete invite
|
||||
this.deleteInvite(invitee);
|
||||
|
||||
// Clear cached references
|
||||
groupInviteTransactionData.setJoinReference(null);
|
||||
groupInviteTransactionData.setPreviousGroupId(null);
|
||||
}
|
||||
|
||||
public void cancelInvite(CancelGroupInviteTransactionData cancelGroupInviteTransactionData) throws DataException {
|
||||
@ -769,27 +782,29 @@ public class Group {
|
||||
if (inviteReference == null && !groupData.getIsOpen()) {
|
||||
// Delete join request
|
||||
this.deleteJoinRequest(joiner.getAddress());
|
||||
} else {
|
||||
// Any invite to rebuild?
|
||||
if (inviteReference != null) {
|
||||
// Rebuild invite using cache reference to invite transaction
|
||||
TransactionData transactionData = this.repository.getTransactionRepository().fromSignature(inviteReference);
|
||||
this.addInvite((GroupInviteTransactionData) transactionData);
|
||||
|
||||
return;
|
||||
// Clear cached reference to invite transaction
|
||||
joinGroupTransactionData.setInviteReference(null);
|
||||
}
|
||||
|
||||
// Delete member
|
||||
this.deleteMember(joiner.getAddress());
|
||||
|
||||
// Revert joiner's defaultGroupId if necessary
|
||||
Integer previousDefaultGroupId = joinGroupTransactionData.getPreviousGroupId();
|
||||
if (previousDefaultGroupId != null)
|
||||
joiner.setDefaultGroupId(previousDefaultGroupId);
|
||||
}
|
||||
|
||||
// Any invite to rebuild?
|
||||
if (inviteReference != null) {
|
||||
// Rebuild invite using cache reference to invite transaction
|
||||
TransactionData transactionData = this.repository.getTransactionRepository().fromSignature(inviteReference);
|
||||
this.addInvite((GroupInviteTransactionData) transactionData);
|
||||
|
||||
// Clear cached reference to invite transaction
|
||||
joinGroupTransactionData.setInviteReference(null);
|
||||
}
|
||||
|
||||
// Delete member
|
||||
this.deleteMember(joiner.getAddress());
|
||||
|
||||
// Revert joiner's defaultGroupId if necessary
|
||||
Integer previousDefaultGroupId = joinGroupTransactionData.getPreviousGroupId();
|
||||
if (previousDefaultGroupId != null)
|
||||
joiner.setDefaultGroupId(previousDefaultGroupId);
|
||||
// Clear cached references
|
||||
joinGroupTransactionData.setInviteReference(null);
|
||||
joinGroupTransactionData.setPreviousGroupId(null);
|
||||
}
|
||||
|
||||
public void leave(LeaveGroupTransactionData leaveGroupTransactionData) throws DataException {
|
||||
@ -842,6 +857,11 @@ public class Group {
|
||||
Integer previousDefaultGroupId = leaveGroupTransactionData.getPreviousGroupId();
|
||||
if (previousDefaultGroupId != null)
|
||||
leaver.setDefaultGroupId(previousDefaultGroupId);
|
||||
|
||||
// Clear cached references
|
||||
leaveGroupTransactionData.setAdminReference(null);
|
||||
leaveGroupTransactionData.setMemberReference(null);
|
||||
leaveGroupTransactionData.setPreviousGroupId(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -113,6 +113,9 @@ public class Name {
|
||||
|
||||
// Save reverted name data
|
||||
this.repository.getNameRepository().save(this.nameData);
|
||||
|
||||
// Remove reference to previous name-changing transaction
|
||||
updateNameTransactionData.setNameReference(null);
|
||||
}
|
||||
|
||||
public void sell(SellNameTransactionData sellNameTransactionData) throws DataException {
|
||||
@ -133,7 +136,7 @@ public class Name {
|
||||
this.repository.getNameRepository().save(this.nameData);
|
||||
}
|
||||
|
||||
public void sell(CancelSellNameTransactionData cancelSellNameTransactionData) throws DataException {
|
||||
public void cancelSell(CancelSellNameTransactionData cancelSellNameTransactionData) throws DataException {
|
||||
// Mark not for-sale but leave price in case we want to orphan
|
||||
this.nameData.setIsForSale(false);
|
||||
|
||||
@ -141,7 +144,7 @@ public class Name {
|
||||
this.repository.getNameRepository().save(this.nameData);
|
||||
}
|
||||
|
||||
public void unsell(CancelSellNameTransactionData cancelSellNameTransactionData) throws DataException {
|
||||
public void uncancelSell(CancelSellNameTransactionData cancelSellNameTransactionData) throws DataException {
|
||||
// Mark as for-sale using existing price
|
||||
this.nameData.setIsForSale(true);
|
||||
|
||||
@ -180,6 +183,9 @@ public class Name {
|
||||
// Previous name reference is taken from this transaction's cached copy
|
||||
this.nameData.setReference(buyNameTransactionData.getNameReference());
|
||||
|
||||
// Remove reference in transaction data
|
||||
buyNameTransactionData.setNameReference(null);
|
||||
|
||||
// Revert buyer's balance
|
||||
Account buyer = new PublicKeyAccount(this.repository, buyNameTransactionData.getBuyerPublicKey());
|
||||
buyer.setConfirmedBalance(Asset.QORA, buyer.getConfirmedBalance(Asset.QORA).add(buyNameTransactionData.getAmount()));
|
||||
|
@ -99,14 +99,9 @@ public class Peer implements Runnable {
|
||||
this.versionMessage = versionMessage;
|
||||
|
||||
if (this.versionMessage.getVersionString().startsWith(Controller.VERSION_PREFIX)) {
|
||||
int index = Controller.VERSION_PREFIX.length();
|
||||
try {
|
||||
this.version = Integer.parseInt(this.versionMessage.getVersionString().substring(index, index + 1));
|
||||
} catch (NumberFormatException e) {
|
||||
this.version = 1;
|
||||
}
|
||||
this.version = 2; // enhanced protocol
|
||||
} else {
|
||||
this.version = 1;
|
||||
this.version = 1; // legacy protocol
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,67 @@
|
||||
package org.qora.network.message;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.qora.transform.Transformer;
|
||||
import org.qora.transform.block.BlockTransformer;
|
||||
|
||||
import com.google.common.primitives.Ints;
|
||||
|
||||
public class GetSignaturesV2Message extends Message {
|
||||
|
||||
private static final int BLOCK_SIGNATURE_LENGTH = BlockTransformer.BLOCK_SIGNATURE_LENGTH;
|
||||
private static final int NUMBER_REQUESTED_LENGTH = Transformer.INT_LENGTH;
|
||||
|
||||
private byte[] parentSignature;
|
||||
private int numberRequested;
|
||||
|
||||
public GetSignaturesV2Message(byte[] parentSignature, int numberRequested) {
|
||||
this(-1, parentSignature, numberRequested);
|
||||
}
|
||||
|
||||
private GetSignaturesV2Message(int id, byte[] parentSignature, int numberRequested) {
|
||||
super(id, MessageType.GET_SIGNATURES_V2);
|
||||
|
||||
this.parentSignature = parentSignature;
|
||||
this.numberRequested = numberRequested;
|
||||
}
|
||||
|
||||
public byte[] getParentSignature() {
|
||||
return this.parentSignature;
|
||||
}
|
||||
|
||||
public int getNumberRequested() {
|
||||
return this.numberRequested;
|
||||
}
|
||||
|
||||
public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException {
|
||||
if (bytes.remaining() != BLOCK_SIGNATURE_LENGTH + NUMBER_REQUESTED_LENGTH)
|
||||
return null;
|
||||
|
||||
byte[] parentSignature = new byte[BLOCK_SIGNATURE_LENGTH];
|
||||
bytes.get(parentSignature);
|
||||
|
||||
int numberRequested = bytes.getInt();
|
||||
|
||||
return new GetSignaturesV2Message(id, parentSignature, numberRequested);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] toData() {
|
||||
try {
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
|
||||
bytes.write(this.parentSignature);
|
||||
|
||||
bytes.write(Ints.toByteArray(this.numberRequested));
|
||||
|
||||
return bytes.toByteArray();
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -42,7 +42,8 @@ public abstract class Message {
|
||||
PROOF(12),
|
||||
PEERS_V2(13),
|
||||
GET_BLOCK_SUMMARIES(14),
|
||||
BLOCK_SUMMARIES(15);
|
||||
BLOCK_SUMMARIES(15),
|
||||
GET_SIGNATURES_V2(16);
|
||||
|
||||
public final int value;
|
||||
public final Method fromByteBuffer;
|
||||
|
@ -129,8 +129,9 @@ public class AccountFlagsTransaction extends Transaction {
|
||||
else
|
||||
target.setFlags(previousFlags);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(accountFlagsTransactionData);
|
||||
// Remove previous flags from transaction itself
|
||||
accountFlagsTransactionData.setPreviousFlags(null);
|
||||
this.repository.getTransactionRepository().save(accountFlagsTransactionData);
|
||||
|
||||
Account creator = getCreator();
|
||||
|
||||
|
@ -121,8 +121,7 @@ public class AddGroupAdminTransaction extends Transaction {
|
||||
Group group = new Group(this.repository, addGroupAdminTransactionData.getGroupId());
|
||||
group.promoteToAdmin(addGroupAdminTransactionData);
|
||||
|
||||
// Save this transaction
|
||||
this.repository.getTransactionRepository().save(addGroupAdminTransactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
// Update owner's balance
|
||||
Account owner = getOwner();
|
||||
@ -138,8 +137,7 @@ public class AddGroupAdminTransaction extends Transaction {
|
||||
Group group = new Group(this.repository, addGroupAdminTransactionData.getGroupId());
|
||||
group.unpromoteToAdmin(addGroupAdminTransactionData);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(addGroupAdminTransactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
// Update owner's balance
|
||||
Account owner = getOwner();
|
||||
|
@ -115,14 +115,7 @@ public class ArbitraryTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void process() throws DataException {
|
||||
/*
|
||||
* Save the transaction.
|
||||
*
|
||||
* We might have either raw data or only a hash of data, depending on content filtering.
|
||||
* If we have raw data then the repository save will store the raw data somewhere and save the data's hash in the repository.
|
||||
* This also modifies the passed transactionData.
|
||||
*/
|
||||
this.repository.getTransactionRepository().save(this.transactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
// Wrap and delegate payment processing to Payment class. Always update recipients' last references regardless of asset.
|
||||
new Payment(this.repository).process(arbitraryTransactionData.getSenderPublicKey(), arbitraryTransactionData.getPayments(),
|
||||
@ -131,16 +124,11 @@ public class ArbitraryTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void orphan() throws DataException {
|
||||
/*
|
||||
* Delete the transaction.
|
||||
*
|
||||
* The repository will also remove the stored raw data, if present.
|
||||
*/
|
||||
this.repository.getTransactionRepository().delete(this.transactionData);
|
||||
|
||||
// Wrap and delegate payment processing to Payment class. Always revert recipients' last references regardless of asset.
|
||||
new Payment(this.repository).orphan(arbitraryTransactionData.getSenderPublicKey(), arbitraryTransactionData.getPayments(),
|
||||
arbitraryTransactionData.getFee(), arbitraryTransactionData.getSignature(), arbitraryTransactionData.getReference(), true);
|
||||
|
||||
// We would save transaction in orphaned form at this point, but it hasn't been modified
|
||||
}
|
||||
|
||||
// Data access
|
||||
|
@ -159,8 +159,7 @@ public class AtTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void process() throws DataException {
|
||||
// Save this transaction itself
|
||||
this.repository.getTransactionRepository().save(this.transactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
if (this.atTransactionData.getAmount() != null) {
|
||||
Account sender = getATAccount();
|
||||
@ -185,9 +184,6 @@ public class AtTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void orphan() throws DataException {
|
||||
// Delete this transaction
|
||||
this.repository.getTransactionRepository().delete(this.transactionData);
|
||||
|
||||
if (this.atTransactionData.getAmount() != null) {
|
||||
Account sender = getATAccount();
|
||||
Account recipient = getRecipient();
|
||||
@ -208,6 +204,10 @@ 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
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ public class BuyNameTransaction extends Transaction {
|
||||
Name name = new Name(this.repository, buyNameTransactionData.getName());
|
||||
name.buy(buyNameTransactionData);
|
||||
|
||||
// Save this transaction, now with updated "name reference" to previous transaction that updated name
|
||||
// Save transaction with updated "name reference" pointing to previous transaction that updated name
|
||||
this.repository.getTransactionRepository().save(buyNameTransactionData);
|
||||
|
||||
// Update buyer's balance
|
||||
@ -144,8 +144,8 @@ public class BuyNameTransaction extends Transaction {
|
||||
Name name = new Name(this.repository, buyNameTransactionData.getName());
|
||||
name.unbuy(buyNameTransactionData);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(buyNameTransactionData);
|
||||
// Save this transaction, with removed "name reference"
|
||||
this.repository.getTransactionRepository().save(buyNameTransactionData);
|
||||
|
||||
// Update buyer's balance
|
||||
Account buyer = getBuyer();
|
||||
|
@ -101,8 +101,7 @@ public class CancelAssetOrderTransaction extends Transaction {
|
||||
public void process() throws DataException {
|
||||
Account creator = getCreator();
|
||||
|
||||
// Save this transaction itself
|
||||
this.repository.getTransactionRepository().save(this.transactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
// Update creator's balance regarding fee
|
||||
creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).subtract(cancelOrderTransactionData.getFee()));
|
||||
@ -120,8 +119,7 @@ public class CancelAssetOrderTransaction extends Transaction {
|
||||
public void orphan() throws DataException {
|
||||
Account creator = getCreator();
|
||||
|
||||
// Save this transaction itself
|
||||
this.repository.getTransactionRepository().delete(this.transactionData);
|
||||
// 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()));
|
||||
|
@ -134,8 +134,8 @@ public class CancelGroupBanTransaction extends Transaction {
|
||||
Group group = new Group(this.repository, groupUnbanTransactionData.getGroupId());
|
||||
group.uncancelBan(groupUnbanTransactionData);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(groupUnbanTransactionData);
|
||||
// Save this transaction with removed member/admin references
|
||||
this.repository.getTransactionRepository().save(groupUnbanTransactionData);
|
||||
|
||||
// Update admin's balance
|
||||
Account admin = getAdmin();
|
||||
|
@ -134,8 +134,8 @@ public class CancelGroupInviteTransaction extends Transaction {
|
||||
Group group = new Group(this.repository, cancelGroupInviteTransactionData.getGroupId());
|
||||
group.uncancelInvite(cancelGroupInviteTransactionData);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(cancelGroupInviteTransactionData);
|
||||
// Save this transaction with removed member/admin references
|
||||
this.repository.getTransactionRepository().save(cancelGroupInviteTransactionData);
|
||||
|
||||
// Update admin's balance
|
||||
Account admin = getAdmin();
|
||||
|
@ -112,9 +112,9 @@ public class CancelSellNameTransaction extends Transaction {
|
||||
public void process() throws DataException {
|
||||
// Update Name
|
||||
Name name = new Name(this.repository, cancelSellNameTransactionData.getName());
|
||||
name.sell(cancelSellNameTransactionData);
|
||||
name.cancelSell(cancelSellNameTransactionData);
|
||||
|
||||
// Save this transaction, now with updated "name reference" to previous transaction that updated name
|
||||
// Save this transaction, with updated "name reference" to previous transaction that updated name
|
||||
this.repository.getTransactionRepository().save(cancelSellNameTransactionData);
|
||||
|
||||
// Update owner's balance
|
||||
@ -129,10 +129,10 @@ public class CancelSellNameTransaction extends Transaction {
|
||||
public void orphan() throws DataException {
|
||||
// Revert name
|
||||
Name name = new Name(this.repository, cancelSellNameTransactionData.getName());
|
||||
name.unsell(cancelSellNameTransactionData);
|
||||
name.uncancelSell(cancelSellNameTransactionData);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(cancelSellNameTransactionData);
|
||||
// Save this transaction, with removed "name reference"
|
||||
this.repository.getTransactionRepository().save(cancelSellNameTransactionData);
|
||||
|
||||
// Update owner's balance
|
||||
Account owner = getOwner();
|
||||
|
@ -186,8 +186,7 @@ public class CreateAssetOrderTransaction extends Transaction {
|
||||
// Update creator's last reference
|
||||
creator.setLastReference(createOrderTransactionData.getSignature());
|
||||
|
||||
// Save this transaction itself
|
||||
this.repository.getTransactionRepository().save(createOrderTransactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
// Order Id is transaction's signature
|
||||
byte[] orderId = createOrderTransactionData.getSignature();
|
||||
@ -217,8 +216,7 @@ public class CreateAssetOrderTransaction extends Transaction {
|
||||
OrderData orderData = this.repository.getAssetRepository().fromOrderId(orderId);
|
||||
new Order(this.repository, orderData).orphan();
|
||||
|
||||
// Delete this transaction
|
||||
this.repository.getTransactionRepository().delete(createOrderTransactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -139,8 +139,11 @@ public class CreateGroupTransaction extends Transaction {
|
||||
Group group = new Group(this.repository, createGroupTransactionData.getGroupId());
|
||||
group.uncreate();
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(createGroupTransactionData);
|
||||
// Remove assigned group ID from transaction record
|
||||
createGroupTransactionData.setGroupId(null);
|
||||
|
||||
// Save this transaction with removed group ID
|
||||
this.repository.getTransactionRepository().save(createGroupTransactionData);
|
||||
|
||||
// Update creator's balance
|
||||
Account creator = getCreator();
|
||||
|
@ -153,8 +153,7 @@ public class CreatePollTransaction extends Transaction {
|
||||
Poll poll = new Poll(this.repository, createPollTransactionData);
|
||||
poll.publish();
|
||||
|
||||
// Save this transaction, now with corresponding pollId
|
||||
this.repository.getTransactionRepository().save(createPollTransactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
// Update creator's balance
|
||||
Account creator = getCreator();
|
||||
@ -170,8 +169,7 @@ public class CreatePollTransaction extends Transaction {
|
||||
Poll poll = new Poll(this.repository, createPollTransactionData.getPollName());
|
||||
poll.unpublish();
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(createPollTransactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
// Update creator's balance
|
||||
Account creator = getCreator();
|
||||
|
@ -216,8 +216,7 @@ public class DeployAtTransaction extends Transaction {
|
||||
AT at = new AT(this.repository, this.deployATTransactionData);
|
||||
at.deploy();
|
||||
|
||||
// Save this transaction itself
|
||||
this.repository.getTransactionRepository().save(this.transactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
long assetId = deployATTransactionData.getAssetId();
|
||||
|
||||
@ -243,8 +242,7 @@ public class DeployAtTransaction extends Transaction {
|
||||
AT at = new AT(this.repository, this.deployATTransactionData);
|
||||
at.undeploy();
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(deployATTransactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
long assetId = deployATTransactionData.getAssetId();
|
||||
|
||||
|
@ -152,8 +152,7 @@ public class EnableForgingTransaction extends Transaction {
|
||||
target.setFlags(targetFlags);
|
||||
target.setForgingEnabler(creator.getAddress());
|
||||
|
||||
// Save this transaction
|
||||
this.repository.getTransactionRepository().save(enableForgingTransactionData);
|
||||
// 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).subtract(enableForgingTransactionData.getFee()));
|
||||
@ -182,8 +181,7 @@ public class EnableForgingTransaction extends Transaction {
|
||||
target.setFlags(targetFlags);
|
||||
target.setForgingEnabler(null);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(enableForgingTransactionData);
|
||||
// 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()));
|
||||
|
@ -136,8 +136,7 @@ public class GenesisTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void process() throws DataException {
|
||||
// Save this transaction itself
|
||||
this.repository.getTransactionRepository().save(this.transactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
Account recipient = new Account(repository, genesisTransactionData.getRecipient());
|
||||
|
||||
@ -150,8 +149,7 @@ public class GenesisTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void orphan() throws DataException {
|
||||
// Delete this transaction
|
||||
this.repository.getTransactionRepository().delete(this.transactionData);
|
||||
// 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());
|
||||
|
@ -115,10 +115,9 @@ public class GroupApprovalTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void orphan() throws DataException {
|
||||
// Revert?
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(groupApprovalTransactionData);
|
||||
// Save this transaction with removed prior reference
|
||||
groupApprovalTransactionData.setPriorReference(null);
|
||||
this.repository.getTransactionRepository().save(groupApprovalTransactionData);
|
||||
|
||||
// Update admin's balance
|
||||
Account admin = getAdmin();
|
||||
|
@ -135,8 +135,8 @@ public class GroupBanTransaction extends Transaction {
|
||||
Group group = new Group(this.repository, groupBanTransactionData.getGroupId());
|
||||
group.unban(groupBanTransactionData);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(groupBanTransactionData);
|
||||
// Save this transaction with removed member/admin references
|
||||
this.repository.getTransactionRepository().save(groupBanTransactionData);
|
||||
|
||||
// Update admin's balance
|
||||
Account admin = getAdmin();
|
||||
|
@ -141,8 +141,8 @@ public class GroupInviteTransaction extends Transaction {
|
||||
Group group = new Group(this.repository, groupInviteTransactionData.getGroupId());
|
||||
group.uninvite(groupInviteTransactionData);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(groupInviteTransactionData);
|
||||
// Save this transaction with removed member/admin references
|
||||
this.repository.getTransactionRepository().save(groupInviteTransactionData);
|
||||
|
||||
// Update admin's balance
|
||||
Account admin = getAdmin();
|
||||
|
@ -141,8 +141,8 @@ public class GroupKickTransaction extends Transaction {
|
||||
Group group = new Group(this.repository, groupKickTransactionData.getGroupId());
|
||||
group.unkick(groupKickTransactionData);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(groupKickTransactionData);
|
||||
// Save this transaction with removed member/admin references
|
||||
this.repository.getTransactionRepository().save(groupKickTransactionData);
|
||||
|
||||
// Update admin's balance
|
||||
Account admin = getAdmin();
|
||||
|
@ -170,8 +170,11 @@ public class IssueAssetTransaction extends Transaction {
|
||||
Asset asset = new Asset(this.repository, issueAssetTransactionData.getAssetId());
|
||||
asset.deissue();
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(issueAssetTransactionData);
|
||||
// Remove assigned asset ID from transaction info
|
||||
issueAssetTransactionData.setAssetId(null);
|
||||
|
||||
// Save this transaction, with removed assetId
|
||||
this.repository.getTransactionRepository().save(issueAssetTransactionData);
|
||||
|
||||
// Update issuer's balance
|
||||
Account issuer = getIssuer();
|
||||
|
@ -104,7 +104,7 @@ public class JoinGroupTransaction extends Transaction {
|
||||
Group group = new Group(this.repository, joinGroupTransactionData.getGroupId());
|
||||
group.join(joinGroupTransactionData);
|
||||
|
||||
// Save this transaction
|
||||
// Save this transaction with cached references to transactions that can help restore state
|
||||
this.repository.getTransactionRepository().save(joinGroupTransactionData);
|
||||
|
||||
// Update joiner's balance
|
||||
@ -122,8 +122,8 @@ public class JoinGroupTransaction extends Transaction {
|
||||
Group group = new Group(this.repository, joinGroupTransactionData.getGroupId());
|
||||
group.unjoin(joinGroupTransactionData);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(joinGroupTransactionData);
|
||||
// Save this transaction with removed references
|
||||
this.repository.getTransactionRepository().save(joinGroupTransactionData);
|
||||
|
||||
// Update joiner's balance
|
||||
Account joiner = getJoiner();
|
||||
|
@ -120,8 +120,8 @@ public class LeaveGroupTransaction extends Transaction {
|
||||
Group group = new Group(this.repository, leaveGroupTransactionData.getGroupId());
|
||||
group.unleave(leaveGroupTransactionData);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(leaveGroupTransactionData);
|
||||
// Save this transaction with removed member/admin references
|
||||
this.repository.getTransactionRepository().save(leaveGroupTransactionData);
|
||||
|
||||
// Update leaver's balance
|
||||
Account leaver = getLeaver();
|
||||
|
@ -116,8 +116,7 @@ public class MessageTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void process() throws DataException {
|
||||
// Save this transaction itself
|
||||
this.repository.getTransactionRepository().save(this.transactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
// Wrap and delegate payment processing to Payment class. Only update recipient's last reference if transferring QORA.
|
||||
new Payment(this.repository).process(messageTransactionData.getSenderPublicKey(), getPaymentData(), messageTransactionData.getFee(),
|
||||
@ -126,12 +125,11 @@ public class MessageTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void orphan() throws DataException {
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(this.transactionData);
|
||||
|
||||
// Wrap and delegate payment processing to Payment class. Only revert recipient's last reference if transferring QORA.
|
||||
new Payment(this.repository).orphan(messageTransactionData.getSenderPublicKey(), getPaymentData(), messageTransactionData.getFee(),
|
||||
messageTransactionData.getSignature(), messageTransactionData.getReference(), false);
|
||||
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -116,8 +116,7 @@ public class MultiPaymentTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void process() throws DataException {
|
||||
// Save this transaction itself
|
||||
this.repository.getTransactionRepository().save(this.transactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
// Wrap and delegate payment processing to Payment class. Always update recipients' last references regardless of asset.
|
||||
new Payment(this.repository).process(multiPaymentTransactionData.getSenderPublicKey(), multiPaymentTransactionData.getPayments(),
|
||||
@ -126,12 +125,11 @@ public class MultiPaymentTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void orphan() throws DataException {
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(this.transactionData);
|
||||
|
||||
// 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);
|
||||
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -88,8 +88,7 @@ public class PaymentTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void process() throws DataException {
|
||||
// Save this transaction itself
|
||||
this.repository.getTransactionRepository().save(this.transactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
// Wrap and delegate payment processing to Payment class. Only update recipient's last reference if transferring QORA.
|
||||
new Payment(this.repository).process(paymentTransactionData.getSenderPublicKey(), getPaymentData(), paymentTransactionData.getFee(),
|
||||
@ -98,12 +97,11 @@ public class PaymentTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void orphan() throws DataException {
|
||||
// Delete this transaction
|
||||
this.repository.getTransactionRepository().delete(this.transactionData);
|
||||
|
||||
// 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);
|
||||
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -163,8 +163,9 @@ public class ProxyForgingTransaction extends Transaction {
|
||||
this.repository.getAccountRepository().delete(forger.getPublicKey(), proxyForgingTransactionData.getRecipient());
|
||||
}
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(proxyForgingTransactionData);
|
||||
// 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()));
|
||||
|
@ -125,8 +125,7 @@ public class RegisterNameTransaction extends Transaction {
|
||||
Name name = new Name(this.repository, registerNameTransactionData);
|
||||
name.register();
|
||||
|
||||
// Save this transaction
|
||||
this.repository.getTransactionRepository().save(registerNameTransactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
// Update registrant's balance
|
||||
Account registrant = getRegistrant();
|
||||
@ -142,8 +141,7 @@ public class RegisterNameTransaction extends Transaction {
|
||||
Name name = new Name(this.repository, registerNameTransactionData.getName());
|
||||
name.unregister();
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(registerNameTransactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
// Update registrant's balance
|
||||
Account registrant = getRegistrant();
|
||||
|
@ -117,7 +117,7 @@ public class RemoveGroupAdminTransaction extends Transaction {
|
||||
Group group = new Group(this.repository, removeGroupAdminTransactionData.getGroupId());
|
||||
group.demoteFromAdmin(removeGroupAdminTransactionData);
|
||||
|
||||
// Save this transaction
|
||||
// Save this transaction with cached references to transactions that can help restore state
|
||||
this.repository.getTransactionRepository().save(removeGroupAdminTransactionData);
|
||||
|
||||
// Update owner's balance
|
||||
@ -134,8 +134,8 @@ public class RemoveGroupAdminTransaction extends Transaction {
|
||||
Group group = new Group(this.repository, removeGroupAdminTransactionData.getGroupId());
|
||||
group.undemoteFromAdmin(removeGroupAdminTransactionData);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(removeGroupAdminTransactionData);
|
||||
// Save this transaction with removed group references
|
||||
this.repository.getTransactionRepository().save(removeGroupAdminTransactionData);
|
||||
|
||||
// Update owner's balance
|
||||
Account owner = getOwner();
|
||||
|
@ -118,12 +118,11 @@ public class SellNameTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void process() throws DataException {
|
||||
// Update Name
|
||||
// Sell Name
|
||||
Name name = new Name(this.repository, sellNameTransactionData.getName());
|
||||
name.sell(sellNameTransactionData);
|
||||
|
||||
// Save this transaction, now with updated "name reference" to previous transaction that updated name
|
||||
this.repository.getTransactionRepository().save(sellNameTransactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
// Update owner's balance
|
||||
Account owner = getOwner();
|
||||
@ -139,8 +138,7 @@ public class SellNameTransaction extends Transaction {
|
||||
Name name = new Name(this.repository, sellNameTransactionData.getName());
|
||||
name.unsell(sellNameTransactionData);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(sellNameTransactionData);
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
|
||||
// Update owner's balance
|
||||
Account owner = getOwner();
|
||||
|
@ -119,8 +119,9 @@ public class SetGroupTransaction extends Transaction {
|
||||
|
||||
creator.setDefaultGroupId(previousDefaultGroupId);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(setGroupTransactionData);
|
||||
// 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()));
|
||||
|
@ -101,8 +101,7 @@ public class TransferAssetTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void process() throws DataException {
|
||||
// Save this transaction itself
|
||||
this.repository.getTransactionRepository().save(this.transactionData);
|
||||
// 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(),
|
||||
@ -111,12 +110,11 @@ public class TransferAssetTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void orphan() throws DataException {
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(this.transactionData);
|
||||
|
||||
// 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);
|
||||
|
||||
// We would save updated transaction at this point, but it hasn't been modified
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -130,8 +130,7 @@ public class UpdateAssetTransaction extends Transaction {
|
||||
Asset asset = new Asset(this.repository, updateAssetTransactionData.getAssetId());
|
||||
asset.update(updateAssetTransactionData);
|
||||
|
||||
// Save this transaction, now with updated "name reference" to previous
|
||||
// transaction that updated name
|
||||
// Save this transaction, with updated "name reference" to previous transaction that updated name
|
||||
this.repository.getTransactionRepository().save(updateAssetTransactionData);
|
||||
|
||||
// Update old owner's balance
|
||||
@ -149,8 +148,8 @@ public class UpdateAssetTransaction extends Transaction {
|
||||
Asset asset = new Asset(this.repository, updateAssetTransactionData.getAssetId());
|
||||
asset.revert(updateAssetTransactionData);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(updateAssetTransactionData);
|
||||
// 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();
|
||||
|
@ -149,8 +149,8 @@ public class UpdateGroupTransaction extends Transaction {
|
||||
Group group = new Group(this.repository, updateGroupTransactionData.getGroupId());
|
||||
group.unupdateGroup(updateGroupTransactionData);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(updateGroupTransactionData);
|
||||
// Save this transaction, now with removed "group reference"
|
||||
this.repository.getTransactionRepository().save(updateGroupTransactionData);
|
||||
|
||||
// Update owner's balance
|
||||
Account owner = getOwner();
|
||||
|
@ -151,8 +151,8 @@ public class UpdateNameTransaction extends Transaction {
|
||||
Name name = new Name(this.repository, updateNameTransactionData.getName());
|
||||
name.revert(updateNameTransactionData);
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(updateNameTransactionData);
|
||||
// Save this transaction, now with removed "name reference"
|
||||
this.repository.getTransactionRepository().save(updateNameTransactionData);
|
||||
|
||||
// Update owner's balance
|
||||
Account owner = getOwner();
|
||||
|
@ -177,8 +177,9 @@ public class VoteOnPollTransaction extends Transaction {
|
||||
votingRepository.delete(voteOnPollTransactionData.getPollName(), voteOnPollTransactionData.getVoterPublicKey());
|
||||
}
|
||||
|
||||
// Delete this transaction itself
|
||||
this.repository.getTransactionRepository().delete(voteOnPollTransactionData);
|
||||
// Save this transaction, with removed previous vote info
|
||||
voteOnPollTransactionData.setPreviousOptionIndex(null);
|
||||
this.repository.getTransactionRepository().save(voteOnPollTransactionData);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,23 +3,37 @@ package org.qora.test;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.qora.account.PrivateKeyAccount;
|
||||
import org.qora.block.Block;
|
||||
import org.qora.block.BlockGenerator;
|
||||
import org.qora.block.GenesisBlock;
|
||||
import org.qora.data.at.ATStateData;
|
||||
import org.qora.data.block.BlockData;
|
||||
import org.qora.data.transaction.TransactionData;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
import org.qora.repository.RepositoryManager;
|
||||
import org.qora.test.common.Common;
|
||||
import org.qora.test.common.TransactionUtils;
|
||||
import org.qora.transaction.Transaction;
|
||||
import org.qora.transaction.Transaction.TransactionType;
|
||||
import org.qora.transform.TransformationException;
|
||||
import org.qora.transform.block.BlockTransformer;
|
||||
import org.qora.transform.transaction.TransactionTransformer;
|
||||
import org.qora.utils.Base58;
|
||||
import org.qora.utils.Triple;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class BlockTests extends Common {
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws DataException {
|
||||
Common.useDefaultSettings();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenesisBlockTransactions() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
@ -33,20 +47,24 @@ public class BlockTests extends Common {
|
||||
List<Transaction> transactions = block.getTransactions();
|
||||
assertNotNull(transactions);
|
||||
|
||||
byte[] lastGenesisSignature = null;
|
||||
for (Transaction transaction : transactions) {
|
||||
assertNotNull(transaction);
|
||||
|
||||
TransactionData transactionData = transaction.getTransactionData();
|
||||
|
||||
assertEquals(Transaction.TransactionType.GENESIS, transactionData.getType());
|
||||
if (transactionData.getType() != Transaction.TransactionType.GENESIS)
|
||||
continue;
|
||||
|
||||
assertTrue(transactionData.getFee().compareTo(BigDecimal.ZERO) == 0);
|
||||
assertNull(transactionData.getReference());
|
||||
assertTrue(transaction.isSignatureValid());
|
||||
assertEquals(Transaction.ValidationResult.OK, transaction.isValid());
|
||||
|
||||
lastGenesisSignature = transactionData.getSignature();
|
||||
}
|
||||
|
||||
// Attempt to load first transaction directly from database
|
||||
TransactionData transactionData = repository.getTransactionRepository().fromSignature(transactions.get(0).getTransactionData().getSignature());
|
||||
// Attempt to load last GENESIS transaction directly from database
|
||||
TransactionData transactionData = repository.getTransactionRepository().fromSignature(lastGenesisSignature);
|
||||
assertNotNull(transactionData);
|
||||
|
||||
assertEquals(Transaction.TransactionType.GENESIS, transactionData.getType());
|
||||
@ -61,61 +79,59 @@ public class BlockTests extends Common {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBlockPaymentTransactions() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
// Block 949 has lots of varied transactions
|
||||
// Blocks 390 & 754 have only payment transactions
|
||||
BlockData blockData = repository.getBlockRepository().fromHeight(754);
|
||||
assertNotNull("Block 754 is required for this test", blockData);
|
||||
|
||||
Block block = new Block(repository, blockData);
|
||||
assertTrue(block.isSignatureValid());
|
||||
|
||||
List<Transaction> transactions = block.getTransactions();
|
||||
assertNotNull(transactions);
|
||||
|
||||
for (Transaction transaction : transactions) {
|
||||
assertNotNull(transaction);
|
||||
|
||||
TransactionData transactionData = transaction.getTransactionData();
|
||||
|
||||
assertEquals(Transaction.TransactionType.PAYMENT, transactionData.getType());
|
||||
assertFalse(transactionData.getFee().compareTo(BigDecimal.ZERO) == 0);
|
||||
assertNotNull(transactionData.getReference());
|
||||
|
||||
assertTrue(transaction.isSignatureValid());
|
||||
}
|
||||
|
||||
// Attempt to load first transaction directly from database
|
||||
TransactionData transactionData = repository.getTransactionRepository().fromSignature(transactions.get(0).getTransactionData().getSignature());
|
||||
assertNotNull(transactionData);
|
||||
|
||||
assertEquals(Transaction.TransactionType.PAYMENT, transactionData.getType());
|
||||
assertFalse(transactionData.getFee().compareTo(BigDecimal.ZERO) == 0);
|
||||
assertNotNull(transactionData.getReference());
|
||||
|
||||
Transaction transaction = Transaction.fromData(repository, transactionData);
|
||||
assertNotNull(transaction);
|
||||
|
||||
assertTrue(transaction.isSignatureValid());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBlockSerialization() throws DataException, TransformationException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
// Block 949 has lots of varied transactions
|
||||
// Blocks 390 & 754 have only payment transactions
|
||||
BlockData blockData = repository.getBlockRepository().fromHeight(754);
|
||||
assertNotNull("Block 754 is required for this test", blockData);
|
||||
PrivateKeyAccount signingAccount = Common.getTestAccount(repository, "alice");
|
||||
|
||||
// TODO: Fill block with random, valid transactions of every type (except GENESIS or AT)
|
||||
for (Transaction.TransactionType txType : Transaction.TransactionType.values()) {
|
||||
if (txType == TransactionType.GENESIS || txType == TransactionType.AT)
|
||||
continue;
|
||||
|
||||
TransactionData transactionData = TransactionUtils.randomTransaction(repository, signingAccount, txType, true);
|
||||
Transaction transaction = Transaction.fromData(repository, transactionData);
|
||||
transaction.sign(signingAccount);
|
||||
|
||||
repository.getTransactionRepository().save(transactionData);
|
||||
repository.getTransactionRepository().unconfirmTransaction(transactionData);
|
||||
repository.saveChanges();
|
||||
|
||||
// TODO: more transactions
|
||||
break;
|
||||
}
|
||||
|
||||
// We might need to wait until transactions' timestamps are valid for the block we're about to generate
|
||||
try {
|
||||
Thread.sleep(1L);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
BlockGenerator.generateTestingBlock(repository, signingAccount);
|
||||
|
||||
BlockData blockData = repository.getBlockRepository().getLastBlock();
|
||||
Block block = new Block(repository, blockData);
|
||||
assertTrue(block.isSignatureValid());
|
||||
|
||||
byte[] bytes = BlockTransformer.toBytes(block);
|
||||
|
||||
assertEquals(BlockTransformer.getDataLength(block), bytes.length);
|
||||
|
||||
Triple<BlockData, List<TransactionData>, List<ATStateData>> blockInfo = BlockTransformer.fromBytes(bytes);
|
||||
|
||||
// Compare transactions
|
||||
List<TransactionData> deserializedTransactions = blockInfo.getB();
|
||||
assertEquals("Transaction count differs", blockData.getTransactionCount(), deserializedTransactions.size());
|
||||
|
||||
for (int i = 0; i < blockData.getTransactionCount(); ++i) {
|
||||
TransactionData deserializedTransactionData = deserializedTransactions.get(i);
|
||||
Transaction originalTransaction = block.getTransactions().get(i);
|
||||
TransactionData originalTransactionData = originalTransaction.getTransactionData();
|
||||
|
||||
assertEquals("Transaction signature differs", Base58.encode(originalTransactionData.getSignature()), Base58.encode(deserializedTransactionData.getSignature()));
|
||||
assertEquals("Transaction declared length differs", TransactionTransformer.getDataLength(originalTransactionData), TransactionTransformer.getDataLength(deserializedTransactionData));
|
||||
assertEquals("Transaction serialized length differs", TransactionTransformer.toBytes(originalTransactionData).length, TransactionTransformer.toBytes(deserializedTransactionData).length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,15 +0,0 @@
|
||||
package org.qora.test;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.qora.block.BlockChain;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.test.common.Common;
|
||||
|
||||
public class BlockchainTests extends Common {
|
||||
|
||||
@Test
|
||||
public void testValidateOrRebuild() throws DataException {
|
||||
BlockChain.validate();
|
||||
}
|
||||
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
package org.qora.test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.qora.block.Block;
|
||||
import org.qora.block.GenesisBlock;
|
||||
import org.qora.data.transaction.TransactionData;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
import org.qora.repository.RepositoryManager;
|
||||
import org.qora.test.common.Common;
|
||||
import org.qora.transaction.Transaction;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class GenesisTests extends Common {
|
||||
|
||||
@Test
|
||||
public void testGenesisBlockTransactions() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
assertEquals("Blockchain should be empty for this test", 0, repository.getBlockRepository().getBlockchainHeight());
|
||||
|
||||
GenesisBlock block = GenesisBlock.getInstance(repository);
|
||||
|
||||
assertNotNull("No genesis block?", block);
|
||||
assertTrue(block.isSignatureValid());
|
||||
// Note: only true if blockchain is empty
|
||||
assertEquals("Block invalid", Block.ValidationResult.OK, block.isValid());
|
||||
|
||||
List<Transaction> transactions = block.getTransactions();
|
||||
assertNotNull("No transactions?", transactions);
|
||||
|
||||
for (Transaction transaction : transactions) {
|
||||
assertNotNull(transaction);
|
||||
|
||||
TransactionData transactionData = transaction.getTransactionData();
|
||||
|
||||
assertEquals(Transaction.TransactionType.GENESIS, transactionData.getType());
|
||||
assertTrue(transactionData.getFee().compareTo(BigDecimal.ZERO) == 0);
|
||||
assertNull(transactionData.getReference());
|
||||
assertNotNull(transactionData.getSignature());
|
||||
assertTrue(transaction.isSignatureValid());
|
||||
assertEquals(Transaction.ValidationResult.OK, transaction.isValid());
|
||||
}
|
||||
|
||||
// Actually try to process genesis block onto empty blockchain
|
||||
block.process();
|
||||
repository.saveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
package org.qora.test;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.qora.account.PublicKeyAccount;
|
||||
import org.qora.data.transaction.PaymentTransactionData;
|
||||
import org.qora.data.transaction.TransactionData;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
import org.qora.repository.RepositoryManager;
|
||||
import org.qora.repository.TransactionRepository;
|
||||
import org.qora.test.common.Common;
|
||||
import org.qora.transaction.Transaction.TransactionType;
|
||||
import org.qora.utils.Base58;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class LoadTests extends Common {
|
||||
|
||||
@Test
|
||||
public void testLoadPaymentTransaction() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
TransactionRepository transactionRepository = repository.getTransactionRepository();
|
||||
|
||||
assertTrue("Migrate from old database to at least block 49778 before running this test", repository.getBlockRepository().getBlockchainHeight() >= 49778);
|
||||
|
||||
String signature58 = "1211ZPwG3hk5evWzXCZi9hMDRpwumWmkENjwWkeTCik9xA5uoYnxzF7rwR5hmHH3kG2RXo7ToCAaRc7dvnynByJt";
|
||||
byte[] signature = Base58.decode(signature58);
|
||||
|
||||
TransactionData transactionData = transactionRepository.fromSignature(signature);
|
||||
assertNotNull("Transaction data not loaded from repository", transactionData);
|
||||
assertEquals("Transaction data not PAYMENT type", TransactionType.PAYMENT, transactionData.getType());
|
||||
assertEquals("QXwu8924WdgPoRmtiWQBUMF6eedmp1Hu2E", PublicKeyAccount.getAddress(transactionData.getCreatorPublicKey()));
|
||||
|
||||
PaymentTransactionData paymentTransactionData = (PaymentTransactionData) transactionData;
|
||||
|
||||
assertNotNull(paymentTransactionData);
|
||||
assertEquals("QXwu8924WdgPoRmtiWQBUMF6eedmp1Hu2E", PublicKeyAccount.getAddress(paymentTransactionData.getSenderPublicKey()));
|
||||
assertEquals("QZsv8vbJ6QfrBNba4LMp5UtHhAzhrxvVUU", paymentTransactionData.getRecipient());
|
||||
assertEquals(1416209264000L, paymentTransactionData.getTimestamp());
|
||||
assertEquals("31dC6kHHBeG5vYb8LMaZDjLEmhc9kQB2VUApVd8xWncSRiXu7yMejdprjYFMP2rUnzZxWd4KJhkq6LsV7rQvU1kY",
|
||||
Base58.encode(paymentTransactionData.getReference()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadFactory() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
TransactionRepository transactionRepository = repository.getTransactionRepository();
|
||||
|
||||
assertTrue("Migrate from old database to at least block 49778 before running this test", repository.getBlockRepository().getBlockchainHeight() >= 49778);
|
||||
|
||||
String signature58 = "1211ZPwG3hk5evWzXCZi9hMDRpwumWmkENjwWkeTCik9xA5uoYnxzF7rwR5hmHH3kG2RXo7ToCAaRc7dvnynByJt";
|
||||
byte[] signature = Base58.decode(signature58);
|
||||
|
||||
while (true) {
|
||||
TransactionData transactionData = transactionRepository.fromSignature(signature);
|
||||
if (transactionData == null)
|
||||
break;
|
||||
|
||||
if (transactionData.getType() != TransactionType.PAYMENT)
|
||||
break;
|
||||
|
||||
PaymentTransactionData paymentTransactionData = (PaymentTransactionData) transactionData;
|
||||
System.out.println(PublicKeyAccount.getAddress(paymentTransactionData.getSenderPublicKey()) + " sent " + paymentTransactionData.getAmount()
|
||||
+ " QORA to " + paymentTransactionData.getRecipient());
|
||||
|
||||
signature = transactionData.getReference();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadNonexistentTransaction() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
TransactionRepository transactionRepository = repository.getTransactionRepository();
|
||||
|
||||
String signature58 = "1111222233334444";
|
||||
byte[] signature = Base58.decode(signature58);
|
||||
|
||||
TransactionData transactionData = transactionRepository.fromSignature(signature);
|
||||
|
||||
if (transactionData != null) {
|
||||
PaymentTransactionData paymentTransactionData = (PaymentTransactionData) transactionData;
|
||||
|
||||
System.out.println(PublicKeyAccount.getAddress(paymentTransactionData.getSenderPublicKey()) + " sent " + paymentTransactionData.getAmount()
|
||||
+ " QORA to " + paymentTransactionData.getRecipient());
|
||||
|
||||
fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package org.qora.test;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.qora.data.block.BlockData;
|
||||
import org.qora.data.transaction.TransactionData;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
import org.qora.repository.RepositoryManager;
|
||||
import org.qora.repository.TransactionRepository;
|
||||
import org.qora.test.common.Common;
|
||||
import org.qora.transaction.Transaction.TransactionType;
|
||||
import org.qora.utils.Base58;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class NavigationTests extends Common {
|
||||
|
||||
@Test
|
||||
public void testNavigateFromTransactionToBlock() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
TransactionRepository transactionRepository = repository.getTransactionRepository();
|
||||
|
||||
assertTrue("Migrate from old database to at least block 49778 before running this test", repository.getBlockRepository().getBlockchainHeight() >= 49778);
|
||||
|
||||
String signature58 = "1211ZPwG3hk5evWzXCZi9hMDRpwumWmkENjwWkeTCik9xA5uoYnxzF7rwR5hmHH3kG2RXo7ToCAaRc7dvnynByJt";
|
||||
byte[] signature = Base58.decode(signature58);
|
||||
|
||||
System.out.println("Navigating to Block from transaction " + signature58);
|
||||
|
||||
TransactionData transactionData = transactionRepository.fromSignature(signature);
|
||||
assertNotNull("Transaction data not loaded from repository", transactionData);
|
||||
assertEquals("Transaction data not PAYMENT type", TransactionType.PAYMENT, transactionData.getType());
|
||||
|
||||
int transactionHeight = transactionRepository.getHeightFromSignature(signature);
|
||||
assertFalse("Transaction not found or transaction's block not found", transactionHeight == 0);
|
||||
assertEquals("Transaction's block height expected to be 49778", 49778, transactionHeight);
|
||||
|
||||
BlockData blockData = repository.getBlockRepository().fromHeight(transactionHeight);
|
||||
assertNotNull("Block 49778 not loaded from database", blockData);
|
||||
System.out.println("Block " + blockData.getHeight() + ", signature: " + Base58.encode(blockData.getSignature()));
|
||||
|
||||
assertEquals((Integer) 49778, blockData.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package org.qora.test;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.qora.account.Account;
|
||||
import org.qora.asset.Asset;
|
||||
@ -19,6 +20,11 @@ public class RepositoryTests extends Common {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(RepositoryTests.class);
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws DataException {
|
||||
Common.useDefaultSettings();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRepository() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
@ -44,7 +50,7 @@ public class RepositoryTests extends Common {
|
||||
|
||||
@Test
|
||||
public void testAccessAfterClose() throws DataException {
|
||||
try (Repository repository = RepositoryManager.getRepository()) {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
assertNotNull(repository);
|
||||
|
||||
repository.close();
|
||||
@ -61,17 +67,15 @@ public class RepositoryTests extends Common {
|
||||
|
||||
@Test
|
||||
public void testDeadlock() throws DataException {
|
||||
Common.useDefaultSettings();
|
||||
|
||||
// Open connection 1
|
||||
try (Repository repository1 = RepositoryManager.getRepository()) {
|
||||
try (final Repository repository1 = RepositoryManager.getRepository()) {
|
||||
|
||||
// Do a database 'read'
|
||||
Account account1 = Common.getTestAccount(repository1, "alice");
|
||||
account1.getLastReference();
|
||||
|
||||
// Open connection 2
|
||||
try (Repository repository2 = RepositoryManager.getRepository()) {
|
||||
try (final Repository repository2 = RepositoryManager.getRepository()) {
|
||||
// Update account in 2
|
||||
Account account2 = Common.getTestAccount(repository2, "alice");
|
||||
account2.setConfirmedBalance(Asset.QORA, BigDecimal.valueOf(1234L));
|
||||
|
@ -3,17 +3,21 @@ package org.qora.test.common;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.qora.account.PrivateKeyAccount;
|
||||
import org.qora.block.BlockGenerator;
|
||||
import org.qora.data.transaction.TransactionData;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
import org.qora.transaction.Transaction;
|
||||
import org.qora.transaction.Transaction.TransactionType;
|
||||
import org.qora.transaction.Transaction.ValidationResult;
|
||||
|
||||
public class TransactionUtils {
|
||||
|
||||
public static void signAndForge(Repository repository, TransactionData transactionData, PrivateKeyAccount signingAccount) throws DataException {
|
||||
public static void signAsUnconfirmed(Repository repository, TransactionData transactionData, PrivateKeyAccount signingAccount) throws DataException {
|
||||
Transaction transaction = Transaction.fromData(repository, transactionData);
|
||||
transaction.sign(signingAccount);
|
||||
|
||||
@ -32,10 +36,29 @@ public class TransactionUtils {
|
||||
repository.getTransactionRepository().save(transactionData);
|
||||
repository.getTransactionRepository().unconfirmTransaction(transactionData);
|
||||
repository.saveChanges();
|
||||
}
|
||||
|
||||
public static void signAndForge(Repository repository, TransactionData transactionData, PrivateKeyAccount signingAccount) throws DataException {
|
||||
signAsUnconfirmed(repository, transactionData, signingAccount);
|
||||
|
||||
// Generate block
|
||||
PrivateKeyAccount generatorAccount = Common.getTestAccount(repository, "alice");
|
||||
BlockGenerator.generateTestingBlock(repository, generatorAccount);
|
||||
}
|
||||
|
||||
public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, TransactionType txType, boolean wantValid) throws DataException {
|
||||
try {
|
||||
Class <?> clazz = Class.forName(String.join("", org.qora.test.common.transaction.Transaction.class.getPackage().getName(), ".", txType.className, "Transaction"));
|
||||
|
||||
try {
|
||||
Method method = clazz.getDeclaredMethod("randomTransaction", Repository.class, PrivateKeyAccount.class, boolean.class);
|
||||
return (TransactionData) method.invoke(null, repository, account, wantValid);
|
||||
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new RuntimeException(String.format("Transaction subclass constructor not found for transaction type \"%s\"", txType.name()), e);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(String.format("Transaction subclass not found for transaction type \"%s\"", txType.name()), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
package org.qora.test.common.transaction;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.qora.account.PrivateKeyAccount;
|
||||
import org.qora.data.transaction.PaymentTransactionData;
|
||||
import org.qora.data.transaction.TransactionData;
|
||||
import org.qora.group.Group;
|
||||
import org.qora.repository.Repository;
|
||||
import org.qora.utils.NTP;
|
||||
|
||||
public class PaymentTransaction {
|
||||
|
||||
public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) {
|
||||
return new PaymentTransactionData(NTP.getTime(), Group.NO_GROUP, new byte[32], account.getPublicKey(), account.getAddress(), BigDecimal.valueOf(123L), BigDecimal.ONE);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package org.qora.test.common.transaction;
|
||||
|
||||
public abstract class Transaction {
|
||||
}
|
@ -22,7 +22,6 @@ import org.qora.transaction.Transaction.ValidationResult;
|
||||
|
||||
public class GrantForgingTests extends Common {
|
||||
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws DataException {
|
||||
Common.useDefaultSettings();
|
||||
|
Loading…
Reference in New Issue
Block a user