forked from Qortal/qortal
group approval tests and fixes
This commit is contained in:
parent
8af761c1c3
commit
c9f226cf88
@ -1090,7 +1090,7 @@ public class Block {
|
||||
}
|
||||
|
||||
protected void processBlockRewards() throws DataException {
|
||||
BigDecimal reward = getRewardAtHeight(this.blockData.getHeight());
|
||||
BigDecimal reward = Block.getRewardAtHeight(this.blockData.getHeight());
|
||||
|
||||
// No reward for our height?
|
||||
if (reward == null)
|
||||
@ -1335,7 +1335,7 @@ public class Block {
|
||||
}
|
||||
|
||||
protected void orphanBlockRewards() throws DataException {
|
||||
BigDecimal reward = getRewardAtHeight(this.blockData.getHeight());
|
||||
BigDecimal reward = Block.getRewardAtHeight(this.blockData.getHeight());
|
||||
|
||||
// No reward for our height?
|
||||
if (reward == null)
|
||||
@ -1397,7 +1397,7 @@ public class Block {
|
||||
atRepository.deleteATStates(this.blockData.getHeight());
|
||||
}
|
||||
|
||||
protected BigDecimal getRewardAtHeight(int ourHeight) {
|
||||
public static BigDecimal getRewardAtHeight(int ourHeight) {
|
||||
List<RewardByHeight> rewardsByHeight = BlockChain.getInstance().getBlockRewardsByHeight();
|
||||
|
||||
// No rewards configured?
|
||||
|
@ -68,9 +68,13 @@ public class GroupApprovalTransaction extends Transaction {
|
||||
if (pendingTransactionData == null)
|
||||
return ValidationResult.TRANSACTION_UNKNOWN;
|
||||
|
||||
// Check pending transaction is not already in a block
|
||||
if (this.repository.getTransactionRepository().getHeightFromSignature(groupApprovalTransactionData.getPendingSignature()) != 0)
|
||||
return ValidationResult.TRANSACTION_ALREADY_CONFIRMED;
|
||||
// Check pending transaction is actually needs group approval
|
||||
if (pendingTransactionData.getApprovalStatus() == ApprovalStatus.NOT_REQUIRED)
|
||||
return ValidationResult.GROUP_APPROVAL_NOT_REQUIRED;
|
||||
|
||||
// Check pending transaction is actually pending
|
||||
if (pendingTransactionData.getApprovalStatus() != ApprovalStatus.PENDING)
|
||||
return ValidationResult.GROUP_APPROVAL_DECIDED;
|
||||
|
||||
Account admin = getAdmin();
|
||||
|
||||
|
@ -230,6 +230,8 @@ public abstract class Transaction {
|
||||
INVALID_PUBLIC_KEY(79),
|
||||
AT_UNKNOWN(80),
|
||||
AT_ALREADY_EXISTS(81),
|
||||
GROUP_APPROVAL_NOT_REQUIRED(82),
|
||||
GROUP_APPROVAL_DECIDED(83),
|
||||
NOT_YET_RELEASED(1000);
|
||||
|
||||
public final int value;
|
||||
|
@ -1,101 +0,0 @@
|
||||
package org.qora.test;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.qora.account.PrivateKeyAccount;
|
||||
import org.qora.block.BlockChain;
|
||||
import org.qora.block.BlockGenerator;
|
||||
import org.qora.data.transaction.BaseTransactionData;
|
||||
import org.qora.data.transaction.CreateGroupTransactionData;
|
||||
import org.qora.data.transaction.PaymentTransactionData;
|
||||
import org.qora.data.transaction.TransactionData;
|
||||
import org.qora.group.Group;
|
||||
import org.qora.group.Group.ApprovalThreshold;
|
||||
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.CreateGroupTransaction;
|
||||
import org.qora.transaction.PaymentTransaction;
|
||||
import org.qora.transaction.Transaction;
|
||||
import org.qora.transaction.Transaction.ValidationResult;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class GroupApprovalTests extends Common {
|
||||
|
||||
/** Check that a tx type that doesn't need approval doesn't accept txGroupId apart from NO_GROUP */
|
||||
@Test
|
||||
public void testNonApprovalTxGroupId() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
BlockChain.validate();
|
||||
|
||||
TransactionData transactionData = buildPayment(repository, Group.NO_GROUP);
|
||||
Transaction transaction = new PaymentTransaction(repository, transactionData);
|
||||
assertEquals(ValidationResult.OK, transaction.isValidUnconfirmed());
|
||||
|
||||
int groupId = createGroup(repository);
|
||||
|
||||
transactionData = buildPayment(repository, groupId);
|
||||
transaction = new PaymentTransaction(repository, transactionData);
|
||||
assertEquals(ValidationResult.INVALID_TX_GROUP_ID, transaction.isValidUnconfirmed());
|
||||
}
|
||||
}
|
||||
|
||||
private PaymentTransactionData buildPayment(Repository repository, int txGroupId) throws DataException {
|
||||
long timestamp = System.currentTimeMillis() - 1000L;
|
||||
byte[] reference = repository.getAccountRepository().getLastReference(v2testAddress);
|
||||
byte[] senderPublicKey = v2testPublicKey;
|
||||
String recipient = v2testAddress;
|
||||
BigDecimal amount = BigDecimal.ONE.setScale(8);
|
||||
BigDecimal fee = BigDecimal.ONE.setScale(8);
|
||||
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, senderPublicKey, fee, null);
|
||||
return new PaymentTransactionData(baseTransactionData, recipient, amount);
|
||||
}
|
||||
|
||||
private int createGroup(Repository repository) throws DataException {
|
||||
long timestamp = System.currentTimeMillis() - 1000L;
|
||||
int txGroupId = Group.NO_GROUP;
|
||||
byte[] reference = repository.getAccountRepository().getLastReference(v2testAddress);
|
||||
byte[] creatorPublicKey = v2testPublicKey;
|
||||
String owner = v2testAddress;
|
||||
String groupName = "test-group";
|
||||
String description = "test group description";
|
||||
boolean isOpen = false;
|
||||
ApprovalThreshold approvalThreshold = ApprovalThreshold.ONE;
|
||||
int minimumBlockDelay = 0;
|
||||
int maximumBlockDelay = 1440;
|
||||
BigDecimal fee = BigDecimal.ONE.setScale(8);
|
||||
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, creatorPublicKey, fee, null);
|
||||
TransactionData transactionData = new CreateGroupTransactionData(baseTransactionData, owner, groupName, description,
|
||||
isOpen, approvalThreshold, minimumBlockDelay, maximumBlockDelay);
|
||||
Transaction transaction = new CreateGroupTransaction(repository, transactionData);
|
||||
|
||||
// Sign transaction
|
||||
PrivateKeyAccount signer = new PrivateKeyAccount(repository, v2testPrivateKey);
|
||||
transaction.sign(signer);
|
||||
|
||||
// Add to unconfirmed
|
||||
if (!transaction.isSignatureValid())
|
||||
throw new RuntimeException("CREATE_GROUP transaction's signature invalid");
|
||||
|
||||
ValidationResult result = transaction.isValidUnconfirmed();
|
||||
if (result != ValidationResult.OK)
|
||||
throw new RuntimeException(String.format("CREATE_GROUP transaction invalid: %s", result.name()));
|
||||
|
||||
repository.getTransactionRepository().save(transactionData);
|
||||
repository.getTransactionRepository().unconfirmTransaction(transactionData);
|
||||
repository.saveChanges();
|
||||
|
||||
// Generate block
|
||||
BlockGenerator.generateTestingBlock(repository, signer);
|
||||
|
||||
// Return assigned groupId
|
||||
transactionData = repository.getTransactionRepository().fromSignature(transactionData.getSignature());
|
||||
return ((CreateGroupTransactionData) transactionData).getGroupId();
|
||||
}
|
||||
|
||||
}
|
25
src/test/java/org/qora/test/common/BlockUtils.java
Normal file
25
src/test/java/org/qora/test/common/BlockUtils.java
Normal file
@ -0,0 +1,25 @@
|
||||
package org.qora.test.common;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.qora.block.Block;
|
||||
import org.qora.data.block.BlockData;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
|
||||
public class BlockUtils {
|
||||
|
||||
public static BigDecimal getNextBlockReward(Repository repository) throws DataException {
|
||||
int currentHeight = repository.getBlockRepository().getBlockchainHeight();
|
||||
|
||||
return Block.getRewardAtHeight(currentHeight + 1);
|
||||
}
|
||||
|
||||
public static void orphanLastBlock(Repository repository) throws DataException {
|
||||
BlockData blockData = repository.getBlockRepository().getLastBlock();
|
||||
Block block = new Block(repository, blockData);
|
||||
block.orphan();
|
||||
repository.saveChanges();
|
||||
}
|
||||
|
||||
}
|
66
src/test/java/org/qora/test/common/GroupUtils.java
Normal file
66
src/test/java/org/qora/test/common/GroupUtils.java
Normal file
@ -0,0 +1,66 @@
|
||||
package org.qora.test.common;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.qora.account.PrivateKeyAccount;
|
||||
import org.qora.data.transaction.BaseTransactionData;
|
||||
import org.qora.data.transaction.CreateGroupTransactionData;
|
||||
import org.qora.data.transaction.GroupApprovalTransactionData;
|
||||
import org.qora.data.transaction.JoinGroupTransactionData;
|
||||
import org.qora.data.transaction.TransactionData;
|
||||
import org.qora.group.Group;
|
||||
import org.qora.group.Group.ApprovalThreshold;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
import org.qora.transaction.Transaction.ApprovalStatus;
|
||||
|
||||
public class GroupUtils {
|
||||
|
||||
public static final int txGroupId = Group.NO_GROUP;
|
||||
public static final BigDecimal fee = BigDecimal.ONE.setScale(8);
|
||||
|
||||
public static int createGroup(Repository repository, String creatorAccountName, String groupName, boolean isOpen, ApprovalThreshold approvalThreshold,
|
||||
int minimumBlockDelay, int maximumBlockDelay) throws DataException {
|
||||
PrivateKeyAccount account = Common.getTestAccount(repository, creatorAccountName);
|
||||
|
||||
byte[] reference = account.getLastReference();
|
||||
long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1;
|
||||
String groupDescription = groupName + " (test group)";
|
||||
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, account.getPublicKey(), GroupUtils.fee, null);
|
||||
TransactionData transactionData = new CreateGroupTransactionData(baseTransactionData, account.getAddress(), groupName, groupDescription, isOpen, approvalThreshold, minimumBlockDelay, maximumBlockDelay);
|
||||
|
||||
TransactionUtils.signAndForge(repository, transactionData, account);
|
||||
|
||||
return repository.getGroupRepository().fromGroupName(groupName).getGroupId();
|
||||
}
|
||||
|
||||
public static void joinGroup(Repository repository, String joinerAccountName, int groupId) throws DataException {
|
||||
PrivateKeyAccount account = Common.getTestAccount(repository, joinerAccountName);
|
||||
|
||||
byte[] reference = account.getLastReference();
|
||||
long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1;
|
||||
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, account.getPublicKey(), GroupUtils.fee, null);
|
||||
TransactionData transactionData = new JoinGroupTransactionData(baseTransactionData, groupId);
|
||||
|
||||
TransactionUtils.signAndForge(repository, transactionData, account);
|
||||
}
|
||||
|
||||
public static void approveTransaction(Repository repository, String accountName, byte[] pendingSignature, boolean decision) throws DataException {
|
||||
PrivateKeyAccount account = Common.getTestAccount(repository, accountName);
|
||||
|
||||
byte[] reference = account.getLastReference();
|
||||
long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1;
|
||||
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, account.getPublicKey(), GroupUtils.fee, null);
|
||||
TransactionData transactionData = new GroupApprovalTransactionData(baseTransactionData, pendingSignature, decision);
|
||||
|
||||
TransactionUtils.signAndForge(repository, transactionData, account);
|
||||
}
|
||||
|
||||
public static ApprovalStatus getApprovalStatus(Repository repository, byte[] signature) throws DataException {
|
||||
return repository.getTransactionRepository().fromSignature(signature).getApprovalStatus();
|
||||
}
|
||||
|
||||
}
|
@ -5,6 +5,7 @@ import org.qora.repository.Repository;
|
||||
import org.qora.utils.Base58;
|
||||
|
||||
public class TestAccount extends PrivateKeyAccount {
|
||||
|
||||
public final String accountName;
|
||||
|
||||
public TestAccount(Repository repository, String accountName, byte[] privateKey) {
|
||||
@ -16,4 +17,5 @@ public class TestAccount extends PrivateKeyAccount {
|
||||
public TestAccount(Repository repository, String accountName, String privateKey) {
|
||||
this(repository, accountName, Base58.decode(privateKey));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
import org.qora.repository.RepositoryManager;
|
||||
import org.qora.test.common.AccountUtils;
|
||||
import org.qora.test.common.BlockUtils;
|
||||
import org.qora.test.common.Common;
|
||||
|
||||
public class RewardTests extends Common {
|
||||
@ -38,11 +39,11 @@ public class RewardTests extends Common {
|
||||
|
||||
PrivateKeyAccount forgingAccount = Common.getTestAccount(repository, "alice");
|
||||
|
||||
BigDecimal firstReward = BlockChain.getInstance().getBlockRewardsByHeight().get(0).reward;
|
||||
BigDecimal blockReward = BlockUtils.getNextBlockReward(repository);
|
||||
|
||||
BlockGenerator.generateTestingBlock(repository, forgingAccount);
|
||||
|
||||
BigDecimal expectedBalance = initialBalances.get("alice").get(Asset.QORA).add(firstReward);
|
||||
BigDecimal expectedBalance = initialBalances.get("alice").get(Asset.QORA).add(blockReward);
|
||||
AccountUtils.assertBalance(repository, "alice", Asset.QORA, expectedBalance);
|
||||
}
|
||||
}
|
||||
@ -84,16 +85,15 @@ public class RewardTests extends Common {
|
||||
PrivateKeyAccount proxyAccount = new PrivateKeyAccount(repository, proxyPrivateKey);
|
||||
|
||||
Map<String, Map<Long, BigDecimal>> initialBalances = AccountUtils.getBalances(repository, Asset.QORA);
|
||||
BigDecimal blockReward = BlockUtils.getNextBlockReward(repository);
|
||||
BlockGenerator.generateTestingBlock(repository, proxyAccount);
|
||||
|
||||
// We're expected reward * 12.8% to Bob, the rest to Alice
|
||||
// (first reward is good for first 10 blocks)
|
||||
BigDecimal firstReward = BlockChain.getInstance().getBlockRewardsByHeight().get(0).reward;
|
||||
// We're expecting reward * 12.8% to Bob, the rest to Alice
|
||||
|
||||
BigDecimal bobShare = firstReward.multiply(share.movePointLeft(2)).setScale(8, RoundingMode.DOWN);
|
||||
BigDecimal bobShare = blockReward.multiply(share.movePointLeft(2)).setScale(8, RoundingMode.DOWN);
|
||||
AccountUtils.assertBalance(repository, "bob", Asset.QORA, initialBalances.get("bob").get(Asset.QORA).add(bobShare));
|
||||
|
||||
BigDecimal aliceShare = firstReward.subtract(bobShare);
|
||||
BigDecimal aliceShare = blockReward.subtract(bobShare);
|
||||
AccountUtils.assertBalance(repository, "alice", Asset.QORA, initialBalances.get("alice").get(Asset.QORA).add(aliceShare));
|
||||
}
|
||||
}
|
||||
|
184
src/test/java/org/qora/test/group/GroupApprovalTests.java
Normal file
184
src/test/java/org/qora/test/group/GroupApprovalTests.java
Normal file
@ -0,0 +1,184 @@
|
||||
package org.qora.test.group;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.qora.account.PrivateKeyAccount;
|
||||
import org.qora.asset.Asset;
|
||||
import org.qora.block.BlockGenerator;
|
||||
import org.qora.data.transaction.BaseTransactionData;
|
||||
import org.qora.data.transaction.IssueAssetTransactionData;
|
||||
import org.qora.data.transaction.PaymentTransactionData;
|
||||
import org.qora.data.transaction.TransactionData;
|
||||
import org.qora.group.Group;
|
||||
import org.qora.group.Group.ApprovalThreshold;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
import org.qora.repository.RepositoryManager;
|
||||
import org.qora.test.common.BlockUtils;
|
||||
import org.qora.test.common.Common;
|
||||
import org.qora.test.common.GroupUtils;
|
||||
import org.qora.test.common.TransactionUtils;
|
||||
import org.qora.transaction.Transaction;
|
||||
import org.qora.transaction.Transaction.ApprovalStatus;
|
||||
import org.qora.transaction.Transaction.ValidationResult;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class GroupApprovalTests extends Common {
|
||||
|
||||
private static final BigDecimal amount = BigDecimal.valueOf(5000L).setScale(8);
|
||||
private static final BigDecimal fee = BigDecimal.ONE.setScale(8);
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws DataException {
|
||||
Common.useDefaultSettings();
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterTest() throws DataException {
|
||||
Common.orphanCheck();
|
||||
}
|
||||
|
||||
@Test
|
||||
/** Check that a transaction type that doesn't need approval doesn't accept txGroupId apart from NO_GROUP */
|
||||
public void testNonApprovalTxGroupId() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
Transaction transaction = buildPaymentTransaction(repository, "alice", "bob", amount, Group.NO_GROUP);
|
||||
assertEquals(ValidationResult.OK, transaction.isValidUnconfirmed());
|
||||
|
||||
int groupId = GroupUtils.createGroup(repository, "alice", "test", true, ApprovalThreshold.NONE, 0, 10);
|
||||
|
||||
transaction = buildPaymentTransaction(repository, "alice", "bob", amount, groupId);
|
||||
assertEquals(ValidationResult.INVALID_TX_GROUP_ID, transaction.isValidUnconfirmed());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
/** Check that a transaction, that requires approval, updates references and fees properly. */
|
||||
public void testReferencesAndFees() throws DataException {
|
||||
final int minBlockDelay = 5;
|
||||
final int maxBlockDelay = 20;
|
||||
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount aliceAccount = Common.getTestAccount(repository, "alice");
|
||||
|
||||
int groupId = GroupUtils.createGroup(repository, "alice", "test", true, ApprovalThreshold.ONE, minBlockDelay, maxBlockDelay);
|
||||
|
||||
GroupUtils.joinGroup(repository, "bob", groupId);
|
||||
|
||||
PrivateKeyAccount bobAccount = Common.getTestAccount(repository, "bob");
|
||||
byte[] bobOriginalReference = bobAccount.getLastReference();
|
||||
|
||||
BigDecimal aliceOriginalBalance = aliceAccount.getConfirmedBalance(Asset.QORA);
|
||||
BigDecimal bobOriginalBalance = bobAccount.getConfirmedBalance(Asset.QORA);
|
||||
|
||||
BigDecimal blockReward = BlockUtils.getNextBlockReward(repository);
|
||||
Transaction bobAssetTransaction = buildIssueAssetTransaction(repository, "bob", groupId);
|
||||
TransactionUtils.signAndForge(repository, bobAssetTransaction.getTransactionData(), bobAccount);
|
||||
|
||||
// Confirm transaction needs approval, and hasn't been approved
|
||||
ApprovalStatus approvalStatus = GroupUtils.getApprovalStatus(repository, bobAssetTransaction.getTransactionData().getSignature());
|
||||
assertEquals("incorrect transaction approval status", ApprovalStatus.PENDING, approvalStatus);
|
||||
|
||||
// Bob's last-reference should have changed, even though the transaction itself hasn't been approved yet
|
||||
byte[] bobPostAssetReference = bobAccount.getLastReference();
|
||||
assertFalse("reference should have changed", Arrays.equals(bobOriginalReference, bobPostAssetReference));
|
||||
|
||||
// Bob's balance should have the fee removed, even though the transaction itself hasn't been approved yet
|
||||
BigDecimal bobPostAssetBalance = bobAccount.getConfirmedBalance(Asset.QORA);
|
||||
Common.assertEqualBigDecimals("approval-pending transaction creator's balance incorrect", bobOriginalBalance.subtract(fee), bobPostAssetBalance);
|
||||
|
||||
// Transaction fee should have ended up in forging account
|
||||
BigDecimal alicePostAssetBalance = aliceAccount.getConfirmedBalance(Asset.QORA);
|
||||
Common.assertEqualBigDecimals("block forger's balance incorrect", aliceOriginalBalance.add(blockReward).add(fee), alicePostAssetBalance);
|
||||
|
||||
// Have Bob do a non-approval transaction to change his last-reference
|
||||
Transaction bobPaymentTransaction = buildPaymentTransaction(repository, "bob", "chloe", amount, Group.NO_GROUP);
|
||||
TransactionUtils.signAsUnconfirmed(repository, bobPaymentTransaction.getTransactionData(), bobAccount);
|
||||
BlockGenerator.generateTestingBlock(repository, aliceAccount);
|
||||
|
||||
byte[] bobPostPaymentReference = bobAccount.getLastReference();
|
||||
assertFalse("reference should have changed", Arrays.equals(bobPostAssetReference, bobPostPaymentReference));
|
||||
|
||||
// Have Alice approve Bob's approval-needed transaction
|
||||
GroupUtils.approveTransaction(repository, "alice", bobAssetTransaction.getTransactionData().getSignature(), true);
|
||||
|
||||
// Now forge a few blocks so transaction is approved
|
||||
for (int blockCount = 0; blockCount < minBlockDelay; ++blockCount)
|
||||
BlockGenerator.generateTestingBlock(repository, aliceAccount);
|
||||
|
||||
// Confirm transaction now approved
|
||||
approvalStatus = GroupUtils.getApprovalStatus(repository, bobAssetTransaction.getTransactionData().getSignature());
|
||||
assertEquals("incorrect transaction approval status", ApprovalStatus.APPROVED, approvalStatus);
|
||||
|
||||
// Check Bob's last reference hasn't been changed by transaction approval
|
||||
byte[] bobPostApprovalReference = bobAccount.getLastReference();
|
||||
assertTrue("reference should be unchanged", Arrays.equals(bobPostPaymentReference, bobPostApprovalReference));
|
||||
|
||||
// Ok, now unwind/orphan all the above to double-check
|
||||
|
||||
// Orphan blocks that decided transaction approval
|
||||
for (int blockCount = 0; blockCount < minBlockDelay; ++blockCount)
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Check Bob's last reference is still correct
|
||||
byte[] bobReference = bobAccount.getLastReference();
|
||||
assertTrue("reference should be unchanged", Arrays.equals(bobPostPaymentReference, bobReference));
|
||||
|
||||
// Orphan block containing Alice's group-approval transaction
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Check Bob's last reference is still correct
|
||||
bobReference = bobAccount.getLastReference();
|
||||
assertTrue("reference should be unchanged", Arrays.equals(bobPostPaymentReference, bobReference));
|
||||
|
||||
// Orphan block containing Bob's non-approval payment transaction
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Check Bob's last reference has reverted to pre-payment value
|
||||
bobReference = bobAccount.getLastReference();
|
||||
assertTrue("reference should be pre-payment", Arrays.equals(bobPostAssetReference, bobReference));
|
||||
|
||||
// Orphan block containing Bob's issue-asset approval-needed transaction
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Check Bob's last reference has reverted to original value
|
||||
bobReference = bobAccount.getLastReference();
|
||||
assertTrue("reference should be pre-payment", Arrays.equals(bobOriginalReference, bobReference));
|
||||
|
||||
// Also check Bob's balance is back to original value
|
||||
BigDecimal bobBalance = bobAccount.getConfirmedBalance(Asset.QORA);
|
||||
Common.assertEqualBigDecimals("reverted balance doesn't match original", bobOriginalBalance, bobBalance);
|
||||
}
|
||||
}
|
||||
|
||||
private Transaction buildPaymentTransaction(Repository repository, String sender, String recipient, BigDecimal amount, int txGroupId) throws DataException {
|
||||
PrivateKeyAccount sendingAccount = Common.getTestAccount(repository, sender);
|
||||
PrivateKeyAccount recipientAccount = Common.getTestAccount(repository, recipient);
|
||||
|
||||
byte[] reference = sendingAccount.getLastReference();
|
||||
long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1;
|
||||
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, sendingAccount.getPublicKey(), fee, null);
|
||||
PaymentTransactionData transactionData = new PaymentTransactionData(baseTransactionData, recipientAccount.getAddress(), amount);
|
||||
|
||||
return Transaction.fromData(repository, transactionData);
|
||||
}
|
||||
|
||||
private Transaction buildIssueAssetTransaction(Repository repository, String testAccountName, int txGroupId) throws DataException {
|
||||
PrivateKeyAccount account = Common.getTestAccount(repository, testAccountName);
|
||||
|
||||
byte[] reference = account.getLastReference();
|
||||
long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1;
|
||||
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, account.getPublicKey(), fee, null);
|
||||
TransactionData transactionData = new IssueAssetTransactionData(baseTransactionData, account.getAddress(), "test asset", "test asset desc", 1000L, true, "{}");
|
||||
|
||||
return Transaction.fromData(repository, transactionData);
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user