mirror of
https://github.com/Qortal/qortal.git
synced 2025-07-23 04:36:50 +00:00
ProxyForging->RewardShare massive refactor & more...
Unified terminology from block "generator", "forger", etc. to "minter" Unified terminology "proxy forger" to "reward share" as it was incorrect, or at least highly ambiguous, which account had which role. AccountRepository.findRewardShares() has different arg order! Account.canMint() now returns true if account has 'founder' flag set. Added Account.canRewardShare() which returns whether acocunt can create a reward-share (e.g. level 5+ or founder). Fixed HSQLDBAssetRepository.getAllAssets() which had incorrect resultSet column indexes. Removed old traces of EnableForging transaction. ACCOUNT_LEVEL and ACCOUNT_FLAGS (genesis-block-only transaction types) now set target account's last-reference. This is allow later REWARD_SHARE transactions in genesis block and post-genesis transactions by that account. REWARD_SHARE transactions are now FREE, but only if minter is also recipient. If a self-reward-share already exists, then unless share-percent is zero (to terminate reward-share), any subsequent self-reward-share is invalid. Updated SysTray i18n properties file. BlockChain config file requires 'minAccountLevelToRewardShare' and optional 'minAccountLevelToMint'. Added potential, but currently unused, memory-hard PoW algorithm. Fixed/removed/disabled some unit tests. BlockMinter.generateTestingBlock asks Controller to pretend mintingAccount is 'online'. More testing needed!
This commit is contained in:
@@ -31,8 +31,6 @@ import org.bitcoinj.script.ScriptChunk;
|
||||
import org.bitcoinj.script.ScriptOpCodes;
|
||||
import org.bitcoinj.wallet.WalletTransaction.Pool;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.hash.HashCode;
|
||||
import com.google.common.primitives.Bytes;
|
||||
@@ -76,13 +74,9 @@ public class BTCACCTTests {
|
||||
|
||||
private static final boolean doRefundNotRedeem = false;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
public void main(String[] args) throws NoSuchAlgorithmException, InsufficientMoneyException, InterruptedException, ExecutionException, UnknownHostException {
|
||||
Security.insertProviderAt(new BouncyCastleProvider(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildBTCACCTTest() throws NoSuchAlgorithmException, InsufficientMoneyException, InterruptedException, ExecutionException, UnknownHostException {
|
||||
byte[] secret = new byte[32];
|
||||
new SecureRandom().nextBytes(secret);
|
||||
|
||||
|
@@ -7,7 +7,7 @@ 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.BlockMinter;
|
||||
import org.qora.block.GenesisBlock;
|
||||
import org.qora.data.at.ATStateData;
|
||||
import org.qora.data.block.BlockData;
|
||||
@@ -69,7 +69,7 @@ public class BlockTests extends Common {
|
||||
|
||||
assertEquals(Transaction.TransactionType.GENESIS, transactionData.getType());
|
||||
assertTrue(transactionData.getFee().compareTo(BigDecimal.ZERO) == 0);
|
||||
assertNull(transactionData.getReference());
|
||||
// assertNull(transactionData.getReference());
|
||||
|
||||
Transaction transaction = Transaction.fromData(repository, transactionData);
|
||||
assertNotNull(transaction);
|
||||
@@ -106,7 +106,7 @@ public class BlockTests extends Common {
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
BlockGenerator.generateTestingBlock(repository, signingAccount);
|
||||
BlockMinter.mintTestingBlock(repository, signingAccount);
|
||||
|
||||
BlockData blockData = repository.getBlockRepository().getLastBlock();
|
||||
Block block = new Block(repository, blockData);
|
||||
|
@@ -44,7 +44,7 @@ public class ChainWeightTests {
|
||||
}
|
||||
|
||||
private static BigInteger calcBlockWeight(int parentHeight, byte[] parentGeneratorKey, BlockSummaryData blockSummaryData) {
|
||||
BigInteger keyDistance = calcKeyDistance(parentHeight, parentGeneratorKey, blockSummaryData.getGeneratorPublicKey());
|
||||
BigInteger keyDistance = calcKeyDistance(parentHeight, parentGeneratorKey, blockSummaryData.getMinterPublicKey());
|
||||
BigInteger weight = BigInteger.valueOf(blockSummaryData.getOnlineAccountsCount()).shiftLeft(ACCOUNTS_COUNT_SHIFT).add(keyDistance);
|
||||
return weight;
|
||||
}
|
||||
@@ -57,7 +57,7 @@ public class ChainWeightTests {
|
||||
for (BlockSummaryData blockSummaryData : blockSummaries) {
|
||||
cumulativeWeight = cumulativeWeight.shiftLeft(CHAIN_WEIGHT_SHIFT).add(calcBlockWeight(parentHeight, parentGeneratorKey, blockSummaryData));
|
||||
parentHeight = blockSummaryData.getHeight();
|
||||
parentGeneratorKey = blockSummaryData.getGeneratorPublicKey();
|
||||
parentGeneratorKey = blockSummaryData.getMinterPublicKey();
|
||||
}
|
||||
|
||||
return cumulativeWeight;
|
||||
@@ -120,7 +120,7 @@ public class ChainWeightTests {
|
||||
public void testLongerChain() {
|
||||
final int commonBlockHeight = 1;
|
||||
BlockSummaryData commonBlockSummary = genBlockSummary(commonBlockHeight);
|
||||
byte[] commonBlockGeneratorKey = commonBlockSummary.getGeneratorPublicKey();
|
||||
byte[] commonBlockGeneratorKey = commonBlockSummary.getMinterPublicKey();
|
||||
|
||||
List<BlockSummaryData> shorterChain = genBlockSummaries(3, commonBlockSummary);
|
||||
List<BlockSummaryData> longerChain = genBlockSummaries(shorterChain.size() + 1, commonBlockSummary);
|
||||
|
40
src/test/java/org/qora/test/CiyamMemoryPoWTests.java
Normal file
40
src/test/java/org/qora/test/CiyamMemoryPoWTests.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package org.qora.test;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.qora.crypto.CiyamMemoryPoW;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class CiyamMemoryPoWTests {
|
||||
|
||||
@Test
|
||||
public void testCompute() {
|
||||
Random random = new Random();
|
||||
|
||||
byte[] data = new byte[256];
|
||||
random.nextBytes(data);
|
||||
|
||||
int start = 0;
|
||||
int range = 1000000;
|
||||
int difficulty = 1;
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
Integer nonce = CiyamMemoryPoW.compute(data, start, range, difficulty);
|
||||
long finishTime = System.currentTimeMillis();
|
||||
|
||||
System.out.println(String.format("Memory-hard PoW took %dms", finishTime - startTime));
|
||||
|
||||
assertNotNull(nonce);
|
||||
|
||||
System.out.println(String.format("nonce: %d", nonce));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleComputes() {
|
||||
for (int i = 0; i < 10; ++i)
|
||||
testCompute();
|
||||
}
|
||||
|
||||
}
|
@@ -2,17 +2,28 @@ package org.qora.test;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.qora.data.transaction.TransactionData;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.test.common.Common;
|
||||
import org.qora.transaction.CreateAssetOrderTransaction;
|
||||
import org.qora.transaction.CreatePollTransaction;
|
||||
import org.qora.transaction.IssueAssetTransaction;
|
||||
import org.qora.transform.TransformationException;
|
||||
import org.qora.transform.transaction.TransactionTransformer;
|
||||
import org.qora.utils.NTP;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Before;
|
||||
|
||||
import com.google.common.hash.HashCode;
|
||||
|
||||
public class CompatibilityTests {
|
||||
public class CompatibilityTests extends Common {
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws DataException {
|
||||
Common.useSettings("test-settings-v1.json");
|
||||
NTP.testMode();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateOrderTransactionSignature() throws TransformationException {
|
||||
|
@@ -250,7 +250,7 @@ public class CryptoTests extends Common {
|
||||
final String expectedProxyPrivateKey = "6KszntmNuXmpUkzLfuttgMPeownctxrnyZUG9rErKJJx";
|
||||
|
||||
PrivateKeyAccount mintingAccount = new PrivateKeyAccount(null, ourPrivateKey);
|
||||
byte[] proxyPrivateKey = mintingAccount.getProxyPrivateKey(theirPublicKey);
|
||||
byte[] proxyPrivateKey = mintingAccount.getRewardSharePrivateKey(theirPublicKey);
|
||||
|
||||
assertEquals(expectedProxyPrivateKey, Base58.encode(proxyPrivateKey));
|
||||
}
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package org.qora.test;
|
||||
|
||||
import java.awt.TrayIcon.MessageType;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.qora.gui.SplashFrame;
|
||||
import org.qora.gui.SysTray;
|
||||
@@ -19,7 +21,11 @@ public class GuiTests {
|
||||
public void testSysTray() throws InterruptedException {
|
||||
SysTray.getInstance();
|
||||
|
||||
SysTray.getInstance().showMessage("Testing...", "Tray icon should disappear in 10 seconds", MessageType.INFO);
|
||||
|
||||
Thread.sleep(10_000L);
|
||||
|
||||
SysTray.getInstance().dispose();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,316 +0,0 @@
|
||||
package org.qora.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.qora.account.PrivateKeyAccount;
|
||||
import org.qora.account.PublicKeyAccount;
|
||||
import org.qora.data.network.OnlineAccountData;
|
||||
import org.qora.network.message.GetOnlineAccountsMessage;
|
||||
import org.qora.network.message.Message;
|
||||
import org.qora.network.message.OnlineAccountsMessage;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.test.common.Common;
|
||||
import org.qora.test.common.FakePeer;
|
||||
import org.qora.utils.ByteArray;
|
||||
|
||||
import com.google.common.primitives.Longs;
|
||||
|
||||
public class OnlineTests extends Common {
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws DataException {
|
||||
Common.useDefaultSettings();
|
||||
}
|
||||
|
||||
private static final int MAX_PEERS = 100;
|
||||
private static final int MAX_RUNNING_PEERS = 20;
|
||||
private static final boolean LOG_CONNECTION_CHANGES = false;
|
||||
private static final boolean LOG_ACCOUNT_CHANGES = true;
|
||||
private static final boolean GET_ONLINE_UNICAST_NOT_BROADCAST = false;
|
||||
private static final long ONLINE_TIMESTAMP_MODULUS = 5 * 60 * 1000;
|
||||
|
||||
private static List<PrivateKeyAccount> allKnownAccounts;
|
||||
private static final Random random = new Random();
|
||||
|
||||
static class OnlinePeer extends FakePeer {
|
||||
private static final long LAST_SEEN_EXPIRY_PERIOD = 6 * 60 * 1000;
|
||||
private static final long ONLINE_REFRESH_INTERVAL = 4 * 60 * 1000;
|
||||
private static final int MAX_CONNECTED_PEERS = 5;
|
||||
|
||||
private final PrivateKeyAccount account;
|
||||
|
||||
private List<OnlineAccountData> onlineAccounts;
|
||||
private long nextOnlineRefresh = 0;
|
||||
|
||||
public OnlinePeer(int id, PrivateKeyAccount account) {
|
||||
super(id);
|
||||
|
||||
this.account = account;
|
||||
|
||||
this.onlineAccounts = Collections.synchronizedList(new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processMessage(FakePeer peer, Message message) throws InterruptedException {
|
||||
switch (message.getType()) {
|
||||
case GET_ONLINE_ACCOUNTS: {
|
||||
GetOnlineAccountsMessage getOnlineAccountsMessage = (GetOnlineAccountsMessage) message;
|
||||
|
||||
List<OnlineAccountData> excludeAccounts = getOnlineAccountsMessage.getOnlineAccounts();
|
||||
|
||||
// Send online accounts info, excluding entries with matching timestamp & public key from excludeAccounts
|
||||
List<OnlineAccountData> accountsToSend;
|
||||
synchronized (this.onlineAccounts) {
|
||||
accountsToSend = new ArrayList<>(this.onlineAccounts);
|
||||
}
|
||||
|
||||
Iterator<OnlineAccountData> iterator = accountsToSend.iterator();
|
||||
|
||||
SEND_ITERATOR:
|
||||
while (iterator.hasNext()) {
|
||||
OnlineAccountData onlineAccount = iterator.next();
|
||||
|
||||
for (int i = 0; i < excludeAccounts.size(); ++i) {
|
||||
OnlineAccountData excludeAccount = excludeAccounts.get(i);
|
||||
|
||||
if (onlineAccount.getTimestamp() == excludeAccount.getTimestamp() && Arrays.equals(onlineAccount.getPublicKey(), excludeAccount.getPublicKey())) {
|
||||
iterator.remove();
|
||||
continue SEND_ITERATOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Message onlineAccountsMessage = new OnlineAccountsMessage(accountsToSend);
|
||||
this.send(peer, onlineAccountsMessage);
|
||||
|
||||
if (LOG_ACCOUNT_CHANGES)
|
||||
System.out.println(String.format("[%d] sent %d of our %d online accounts to %d", this.getId(), accountsToSend.size(), onlineAccounts.size(), peer.getId()));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ONLINE_ACCOUNTS: {
|
||||
OnlineAccountsMessage onlineAccountsMessage = (OnlineAccountsMessage) message;
|
||||
|
||||
List<OnlineAccountData> onlineAccounts = onlineAccountsMessage.getOnlineAccounts();
|
||||
|
||||
if (LOG_ACCOUNT_CHANGES)
|
||||
System.out.println(String.format("[%d] received %d online accounts from %d", this.getId(), onlineAccounts.size(), peer.getId()));
|
||||
|
||||
for (OnlineAccountData onlineAccount : onlineAccounts)
|
||||
verifyAndAddAccount(onlineAccount);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyAndAddAccount(OnlineAccountData onlineAccount) {
|
||||
// we would check timestamp is 'recent' here
|
||||
|
||||
// Verify
|
||||
byte[] data = Longs.toByteArray(onlineAccount.getTimestamp());
|
||||
PublicKeyAccount otherAccount = new PublicKeyAccount(null, onlineAccount.getPublicKey());
|
||||
if (!otherAccount.verify(onlineAccount.getSignature(), data)) {
|
||||
System.out.println(String.format("[%d] rejecting invalid online account %s", this.getId(), otherAccount.getAddress()));
|
||||
return;
|
||||
}
|
||||
|
||||
ByteArray publicKeyBA = new ByteArray(onlineAccount.getPublicKey());
|
||||
|
||||
synchronized (this.onlineAccounts) {
|
||||
OnlineAccountData existingAccount = this.onlineAccounts.stream().filter(account -> new ByteArray(account.getPublicKey()).equals(publicKeyBA)).findFirst().orElse(null);
|
||||
|
||||
if (existingAccount != null) {
|
||||
if (existingAccount.getTimestamp() < onlineAccount.getTimestamp()) {
|
||||
this.onlineAccounts.remove(existingAccount);
|
||||
|
||||
if (LOG_ACCOUNT_CHANGES)
|
||||
System.out.println(String.format("[%d] updated online account %s with timestamp %d (was %d)", this.getId(), otherAccount.getAddress(), onlineAccount.getTimestamp(), existingAccount.getTimestamp()));
|
||||
} else {
|
||||
if (LOG_ACCOUNT_CHANGES)
|
||||
System.out.println(String.format("[%d] ignoring existing online account %s", this.getId(), otherAccount.getAddress()));
|
||||
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (LOG_ACCOUNT_CHANGES)
|
||||
System.out.println(String.format("[%d] added online account %s with timestamp %d", this.getId(), otherAccount.getAddress(), onlineAccount.getTimestamp()));
|
||||
}
|
||||
|
||||
this.onlineAccounts.add(onlineAccount);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performIdleTasks() {
|
||||
final long now = System.currentTimeMillis();
|
||||
|
||||
// Expire old entries
|
||||
final long cutoffThreshold = now - LAST_SEEN_EXPIRY_PERIOD;
|
||||
synchronized (this.onlineAccounts) {
|
||||
Iterator<OnlineAccountData> iterator = this.onlineAccounts.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
OnlineAccountData onlineAccount = iterator.next();
|
||||
|
||||
if (onlineAccount.getTimestamp() < cutoffThreshold) {
|
||||
iterator.remove();
|
||||
|
||||
if (LOG_ACCOUNT_CHANGES) {
|
||||
PublicKeyAccount otherAccount = new PublicKeyAccount(null, onlineAccount.getPublicKey());
|
||||
System.out.println(String.format("[%d] removed expired online account %s with timestamp %d", this.getId(), otherAccount.getAddress(), onlineAccount.getTimestamp()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Request data from another peer
|
||||
Message message;
|
||||
synchronized (this.onlineAccounts) {
|
||||
message = new GetOnlineAccountsMessage(this.onlineAccounts);
|
||||
}
|
||||
|
||||
if (GET_ONLINE_UNICAST_NOT_BROADCAST) {
|
||||
FakePeer peer = this.pickRandomPeer();
|
||||
if (peer != null)
|
||||
this.send(peer, message);
|
||||
} else {
|
||||
this.broadcast(message);
|
||||
}
|
||||
|
||||
// Refresh our onlineness?
|
||||
if (now >= this.nextOnlineRefresh) {
|
||||
this.nextOnlineRefresh = now + ONLINE_REFRESH_INTERVAL;
|
||||
refreshOnlineness();
|
||||
}
|
||||
|
||||
// Log our online list
|
||||
synchronized (this.onlineAccounts) {
|
||||
System.out.println(String.format("[%d] Connections: %d, online accounts: %d", this.getId(), this.peers.size(), this.onlineAccounts.size()));
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshOnlineness() {
|
||||
// Broadcast signed timestamp
|
||||
final long timestamp = (System.currentTimeMillis() / ONLINE_TIMESTAMP_MODULUS) * ONLINE_TIMESTAMP_MODULUS;
|
||||
|
||||
byte[] data = Longs.toByteArray(timestamp);
|
||||
byte[] signature = this.account.sign(data);
|
||||
byte[] publicKey = this.account.getPublicKey();
|
||||
|
||||
// Our account is online
|
||||
OnlineAccountData onlineAccount = new OnlineAccountData(timestamp, signature, publicKey);
|
||||
synchronized (this.onlineAccounts) {
|
||||
this.onlineAccounts.removeIf(account -> account.getPublicKey() == this.account.getPublicKey());
|
||||
this.onlineAccounts.add(onlineAccount);
|
||||
}
|
||||
|
||||
Message message = new OnlineAccountsMessage(Arrays.asList(onlineAccount));
|
||||
this.broadcast(message);
|
||||
|
||||
if (LOG_ACCOUNT_CHANGES)
|
||||
System.out.println(String.format("[%d] broadcasted online account %s with timestamp %d", this.getId(), this.account.getAddress(), timestamp));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(FakePeer otherPeer) {
|
||||
int totalPeers;
|
||||
synchronized (this.peers) {
|
||||
totalPeers = this.peers.size();
|
||||
}
|
||||
|
||||
if (totalPeers >= MAX_CONNECTED_PEERS)
|
||||
return;
|
||||
|
||||
super.connect(otherPeer);
|
||||
|
||||
if (LOG_CONNECTION_CHANGES)
|
||||
System.out.println(String.format("[%d] Connected to peer %d, total peers: %d", this.getId(), otherPeer.getId(), totalPeers + 1));
|
||||
}
|
||||
|
||||
public void randomDisconnect() {
|
||||
FakePeer peer;
|
||||
int totalPeers;
|
||||
|
||||
synchronized (this.peers) {
|
||||
peer = this.pickRandomPeer();
|
||||
if (peer == null)
|
||||
return;
|
||||
|
||||
totalPeers = this.peers.size();
|
||||
}
|
||||
|
||||
this.disconnect(peer);
|
||||
|
||||
if (LOG_CONNECTION_CHANGES)
|
||||
System.out.println(String.format("[%d] Disconnected peer %d, total peers: %d", this.getId(), peer.getId(), totalPeers - 1));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlineness() throws InterruptedException {
|
||||
allKnownAccounts = new ArrayList<>();
|
||||
|
||||
List<OnlinePeer> allPeers = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < MAX_PEERS; ++i) {
|
||||
byte[] seed = new byte[32];
|
||||
random.nextBytes(seed);
|
||||
PrivateKeyAccount account = new PrivateKeyAccount(null, seed);
|
||||
|
||||
allKnownAccounts.add(account);
|
||||
|
||||
OnlinePeer peer = new OnlinePeer(i, account);
|
||||
allPeers.add(peer);
|
||||
}
|
||||
|
||||
// Start up some peers
|
||||
List<OnlinePeer> runningPeers = new ArrayList<>();
|
||||
ExecutorService peerExecutor = Executors.newCachedThreadPool();
|
||||
|
||||
for (int c = 0; c < MAX_RUNNING_PEERS; ++c) {
|
||||
OnlinePeer newPeer;
|
||||
do {
|
||||
int i = random.nextInt(allPeers.size());
|
||||
newPeer = allPeers.get(i);
|
||||
} while (runningPeers.contains(newPeer));
|
||||
|
||||
runningPeers.add(newPeer);
|
||||
peerExecutor.execute(newPeer);
|
||||
}
|
||||
|
||||
// Randomly connect/disconnect peers
|
||||
while (true) {
|
||||
int i = random.nextInt(runningPeers.size());
|
||||
OnlinePeer peer = runningPeers.get(i);
|
||||
|
||||
if ((random.nextInt() & 0xf) != 0) {
|
||||
// Connect
|
||||
OnlinePeer otherPeer;
|
||||
do {
|
||||
int j = random.nextInt(runningPeers.size());
|
||||
otherPeer = runningPeers.get(j);
|
||||
} while (otherPeer == peer);
|
||||
|
||||
peer.connect(otherPeer);
|
||||
} else {
|
||||
peer.randomDisconnect();
|
||||
}
|
||||
|
||||
Thread.sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -24,13 +24,13 @@ public class AddressesApiTests extends ApiCommon {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetProxying() {
|
||||
assertNotNull(this.addressesResource.getProxying(Collections.singletonList(aliceAddress), null, null, null, null, null));
|
||||
assertNotNull(this.addressesResource.getProxying(null, Collections.singletonList(aliceAddress), null, null, null, null));
|
||||
assertNotNull(this.addressesResource.getProxying(Collections.singletonList(aliceAddress), Collections.singletonList(aliceAddress), null, null, null, null));
|
||||
assertNotNull(this.addressesResource.getProxying(null, null, Collections.singletonList(aliceAddress), null, null, null));
|
||||
assertNotNull(this.addressesResource.getProxying(Collections.singletonList(aliceAddress), Collections.singletonList(aliceAddress), Collections.singletonList(aliceAddress), null, null, null));
|
||||
assertNotNull(this.addressesResource.getProxying(Collections.singletonList(aliceAddress), Collections.singletonList(aliceAddress), Collections.singletonList(aliceAddress), 1, 1, true));
|
||||
public void testGetRewardShares() {
|
||||
assertNotNull(this.addressesResource.getRewardShares(Collections.singletonList(aliceAddress), null, null, null, null, null));
|
||||
assertNotNull(this.addressesResource.getRewardShares(null, Collections.singletonList(aliceAddress), null, null, null, null));
|
||||
assertNotNull(this.addressesResource.getRewardShares(Collections.singletonList(aliceAddress), Collections.singletonList(aliceAddress), null, null, null, null));
|
||||
assertNotNull(this.addressesResource.getRewardShares(null, null, Collections.singletonList(aliceAddress), null, null, null));
|
||||
assertNotNull(this.addressesResource.getRewardShares(Collections.singletonList(aliceAddress), Collections.singletonList(aliceAddress), Collections.singletonList(aliceAddress), null, null, null));
|
||||
assertNotNull(this.addressesResource.getRewardShares(Collections.singletonList(aliceAddress), Collections.singletonList(aliceAddress), Collections.singletonList(aliceAddress), 1, 1, true));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -29,16 +29,16 @@ public class BlockApiTests extends ApiCommon {
|
||||
public void testGetBlockForgers() {
|
||||
List<String> addresses = Arrays.asList(aliceAddress, aliceAddress);
|
||||
|
||||
assertNotNull(this.blocksResource.getBlockForgers(Collections.emptyList(), null, null, null));
|
||||
assertNotNull(this.blocksResource.getBlockForgers(addresses, null, null, null));
|
||||
assertNotNull(this.blocksResource.getBlockForgers(Collections.emptyList(), 1, 1, true));
|
||||
assertNotNull(this.blocksResource.getBlockForgers(addresses, 1, 1, true));
|
||||
assertNotNull(this.blocksResource.getBlockMinters(Collections.emptyList(), null, null, null));
|
||||
assertNotNull(this.blocksResource.getBlockMinters(addresses, null, null, null));
|
||||
assertNotNull(this.blocksResource.getBlockMinters(Collections.emptyList(), 1, 1, true));
|
||||
assertNotNull(this.blocksResource.getBlockMinters(addresses, 1, 1, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBlocksByForger() {
|
||||
assertNotNull(this.blocksResource.getBlocksByForger(aliceAddress, null, null, null));
|
||||
assertNotNull(this.blocksResource.getBlocksByForger(aliceAddress, 1, 1, true));
|
||||
assertNotNull(this.blocksResource.getBlocksByMinter(aliceAddress, null, null, null));
|
||||
assertNotNull(this.blocksResource.getBlocksByMinter(aliceAddress, 1, 1, true));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@ import org.qora.repository.RepositoryManager;
|
||||
import org.qora.test.common.AccountUtils;
|
||||
import org.qora.test.common.AssetUtils;
|
||||
import org.qora.test.common.Common;
|
||||
import org.qora.utils.NTP;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Map;
|
||||
@@ -19,6 +20,7 @@ public class OldTradingTests extends Common {
|
||||
@Before
|
||||
public void beforeTest() throws DataException {
|
||||
Common.useSettings("test-settings-old-asset.json");
|
||||
NTP.testMode();
|
||||
}
|
||||
|
||||
@After
|
||||
|
@@ -5,11 +5,9 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.qora.account.PrivateKeyAccount;
|
||||
import org.qora.crypto.Crypto;
|
||||
import org.qora.data.transaction.BaseTransactionData;
|
||||
import org.qora.data.transaction.EnableForgingTransactionData;
|
||||
import org.qora.data.transaction.PaymentTransactionData;
|
||||
import org.qora.data.transaction.ProxyForgingTransactionData;
|
||||
import org.qora.data.transaction.RewardShareTransactionData;
|
||||
import org.qora.data.transaction.TransactionData;
|
||||
import org.qora.group.Group;
|
||||
import org.qora.repository.DataException;
|
||||
@@ -30,60 +28,35 @@ public class AccountUtils {
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, sendingAccount.getPublicKey(), fee, null);
|
||||
TransactionData transactionData = new PaymentTransactionData(baseTransactionData, recipientAccount.getAddress(), amount);
|
||||
|
||||
TransactionUtils.signAndForge(repository, transactionData, sendingAccount);
|
||||
TransactionUtils.signAndMint(repository, transactionData, sendingAccount);
|
||||
}
|
||||
|
||||
public static TransactionData createProxyForging(Repository repository, String forger, String recipient, BigDecimal share) throws DataException {
|
||||
PrivateKeyAccount forgingAccount = Common.getTestAccount(repository, forger);
|
||||
public static TransactionData createRewardShare(Repository repository, String minter, String recipient, BigDecimal sharePercent) throws DataException {
|
||||
PrivateKeyAccount mintingAccount = Common.getTestAccount(repository, minter);
|
||||
PrivateKeyAccount recipientAccount = Common.getTestAccount(repository, recipient);
|
||||
|
||||
byte[] reference = forgingAccount.getLastReference();
|
||||
byte[] reference = mintingAccount.getLastReference();
|
||||
long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1;
|
||||
|
||||
byte[] proxyPrivateKey = forgingAccount.getSharedSecret(recipientAccount.getPublicKey());
|
||||
PrivateKeyAccount proxyAccount = new PrivateKeyAccount(null, proxyPrivateKey);
|
||||
byte[] rewardSharePrivateKey = mintingAccount.getSharedSecret(recipientAccount.getPublicKey());
|
||||
PrivateKeyAccount rewardShareAccount = new PrivateKeyAccount(null, rewardSharePrivateKey);
|
||||
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, forgingAccount.getPublicKey(), fee, null);
|
||||
TransactionData transactionData = new ProxyForgingTransactionData(baseTransactionData, recipientAccount.getAddress(), proxyAccount.getPublicKey(), share);
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, mintingAccount.getPublicKey(), fee, null);
|
||||
TransactionData transactionData = new RewardShareTransactionData(baseTransactionData, recipientAccount.getAddress(), rewardShareAccount.getPublicKey(), sharePercent);
|
||||
|
||||
return transactionData;
|
||||
}
|
||||
|
||||
public static byte[] proxyForging(Repository repository, String forger, String recipient, BigDecimal share) throws DataException {
|
||||
TransactionData transactionData = createProxyForging(repository, forger, recipient, share);
|
||||
public static byte[] rewardShare(Repository repository, String minter, String recipient, BigDecimal sharePercent) throws DataException {
|
||||
TransactionData transactionData = createRewardShare(repository, minter, recipient, sharePercent);
|
||||
|
||||
PrivateKeyAccount forgingAccount = Common.getTestAccount(repository, forger);
|
||||
TransactionUtils.signAndForge(repository, transactionData, forgingAccount);
|
||||
PrivateKeyAccount rewardShareAccount = Common.getTestAccount(repository, minter);
|
||||
TransactionUtils.signAndMint(repository, transactionData, rewardShareAccount);
|
||||
|
||||
PrivateKeyAccount recipientAccount = Common.getTestAccount(repository, recipient);
|
||||
byte[] proxyPrivateKey = forgingAccount.getSharedSecret(recipientAccount.getPublicKey());
|
||||
byte[] rewardSharePrivateKey = rewardShareAccount.getSharedSecret(recipientAccount.getPublicKey());
|
||||
|
||||
return proxyPrivateKey;
|
||||
}
|
||||
|
||||
public static TransactionData createEnableForging(Repository repository, String forger, byte[] recipientPublicKey) throws DataException {
|
||||
PrivateKeyAccount forgingAccount = Common.getTestAccount(repository, forger);
|
||||
|
||||
byte[] reference = forgingAccount.getLastReference();
|
||||
long timestamp = repository.getTransactionRepository().fromSignature(reference).getTimestamp() + 1;
|
||||
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, forgingAccount.getPublicKey(), fee, null);
|
||||
return new EnableForgingTransactionData(baseTransactionData, Crypto.toAddress(recipientPublicKey));
|
||||
}
|
||||
|
||||
public static TransactionData createEnableForging(Repository repository, String forger, String recipient) throws DataException {
|
||||
PrivateKeyAccount recipientAccount = Common.getTestAccount(repository, recipient);
|
||||
|
||||
return createEnableForging(repository, forger, recipientAccount.getPublicKey());
|
||||
}
|
||||
|
||||
public static TransactionData enableForging(Repository repository, String forger, String recipient) throws DataException {
|
||||
TransactionData transactionData = createEnableForging(repository, forger, recipient);
|
||||
|
||||
PrivateKeyAccount forgingAccount = Common.getTestAccount(repository, forger);
|
||||
TransactionUtils.signAndForge(repository, transactionData, forgingAccount);
|
||||
|
||||
return transactionData;
|
||||
return rewardSharePrivateKey;
|
||||
}
|
||||
|
||||
public static Map<String, Map<Long, BigDecimal>> getBalances(Repository repository, long... assetIds) throws DataException {
|
||||
|
@@ -41,7 +41,7 @@ public class AssetUtils {
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, AssetUtils.txGroupId, reference, account.getPublicKey(), AssetUtils.fee, null);
|
||||
TransactionData transactionData = new IssueAssetTransactionData(baseTransactionData, account.getAddress(), assetName, "desc", quantity, isDivisible, "{}", false);
|
||||
|
||||
TransactionUtils.signAndForge(repository, transactionData, account);
|
||||
TransactionUtils.signAndMint(repository, transactionData, account);
|
||||
|
||||
return repository.getAssetRepository().fromAssetName(assetName).getAssetId();
|
||||
}
|
||||
@@ -56,7 +56,7 @@ public class AssetUtils {
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, AssetUtils.txGroupId, reference, fromAccount.getPublicKey(), AssetUtils.fee, null);
|
||||
TransactionData transactionData = new TransferAssetTransactionData(baseTransactionData, toAccount.getAddress(), amount, assetId);
|
||||
|
||||
TransactionUtils.signAndForge(repository, transactionData, fromAccount);
|
||||
TransactionUtils.signAndMint(repository, transactionData, fromAccount);
|
||||
}
|
||||
|
||||
public static byte[] createOrder(Repository repository, String accountName, long haveAssetId, long wantAssetId, BigDecimal amount, BigDecimal price) throws DataException {
|
||||
@@ -68,7 +68,7 @@ public class AssetUtils {
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, AssetUtils.txGroupId, reference, account.getPublicKey(), AssetUtils.fee, null);
|
||||
TransactionData transactionData = new CreateAssetOrderTransactionData(baseTransactionData, haveAssetId, wantAssetId, amount, price);
|
||||
|
||||
TransactionUtils.signAndForge(repository, transactionData, account);
|
||||
TransactionUtils.signAndMint(repository, transactionData, account);
|
||||
|
||||
return repository.getAssetRepository().getAccountsOrders(account.getPublicKey(), null, null, null, null, true).get(0).getOrderId();
|
||||
}
|
||||
@@ -89,7 +89,7 @@ public class AssetUtils {
|
||||
PrivateKeyAccount account = Common.getTestAccount(repository, accountName);
|
||||
Transaction transaction = buildCancelOrder(repository, accountName, orderId);
|
||||
|
||||
TransactionUtils.signAndForge(repository, transaction.getTransactionData(), account);
|
||||
TransactionUtils.signAndMint(repository, transaction.getTransactionData(), account);
|
||||
}
|
||||
|
||||
public static void genericTradeTest(long haveAssetId, long wantAssetId,
|
||||
|
@@ -72,18 +72,21 @@ public class Common {
|
||||
|
||||
private static Map<String, TestAccount> testAccountsByName = new HashMap<>();
|
||||
static {
|
||||
testAccountsByName.put("alice", new TestAccount(null, "alice", "A9MNsATgQgruBUjxy2rjWY36Yf19uRioKZbiLFT2P7c6"));
|
||||
testAccountsByName.put("bob", new TestAccount(null, "bob", "AdTd9SUEYSdTW8mgK3Gu72K97bCHGdUwi2VvLNjUohot"));
|
||||
testAccountsByName.put("chloe", new TestAccount(null, "chloe", "HqVngdE1AmEyDpfwTZqUdFHB13o4bCmpoTNAKEqki66K"));
|
||||
testAccountsByName.put("dilbert", new TestAccount(null, "dilbert", "Gakhh6Ln4vtBFM88nE9JmDaLBDtUBg51aVFpWfSkyVw5"));
|
||||
testAccountsByName.put("alice", new TestAccount(null, "alice", "A9MNsATgQgruBUjxy2rjWY36Yf19uRioKZbiLFT2P7c6", false));
|
||||
testAccountsByName.put("bob", new TestAccount(null, "bob", "AdTd9SUEYSdTW8mgK3Gu72K97bCHGdUwi2VvLNjUohot", false));
|
||||
testAccountsByName.put("chloe", new TestAccount(null, "chloe", "HqVngdE1AmEyDpfwTZqUdFHB13o4bCmpoTNAKEqki66K", false));
|
||||
testAccountsByName.put("dilbert", new TestAccount(null, "dilbert", "Gakhh6Ln4vtBFM88nE9JmDaLBDtUBg51aVFpWfSkyVw5", false));
|
||||
|
||||
// Alice reward-share with herself. Private key is reward-share private key, derived from Alice's private and public keys.
|
||||
testAccountsByName.put("alice-reward-share", new TestAccount(null, "alice-reward-share", "1CeDCg9TSdBwJNGVTGG7pCKsvsyyoEcaVXYvDT1Xb9f", true));
|
||||
}
|
||||
|
||||
public static TestAccount getTestAccount(Repository repository, String name) {
|
||||
return new TestAccount(repository, name, testAccountsByName.get(name).getPrivateKey());
|
||||
return new TestAccount(repository, testAccountsByName.get(name));
|
||||
}
|
||||
|
||||
public static List<TestAccount> getTestAccounts(Repository repository) {
|
||||
return testAccountsByName.values().stream().map(account -> new TestAccount(repository, account.accountName, account.getPrivateKey())).collect(Collectors.toList());
|
||||
return testAccountsByName.values().stream().map(account -> new TestAccount(repository, account)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static void useSettings(String settingsFilename) throws DataException {
|
||||
@@ -116,7 +119,8 @@ public class Common {
|
||||
|
||||
// Check that each test account can fetch their last reference
|
||||
for (TestAccount testAccount : getTestAccounts(repository))
|
||||
assertNotNull(String.format("Test account %s / %s should have last reference", testAccount.accountName, testAccount.getAddress()), testAccount.getLastReference());
|
||||
if (!testAccount.isRewardShare)
|
||||
assertNotNull(String.format("Test account %s / %s should have last reference", testAccount.accountName, testAccount.getAddress()), testAccount.getLastReference());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -30,7 +30,7 @@ public class GroupUtils {
|
||||
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);
|
||||
TransactionUtils.signAndMint(repository, transactionData, account);
|
||||
|
||||
return repository.getGroupRepository().fromGroupName(groupName).getGroupId();
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public class GroupUtils {
|
||||
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);
|
||||
TransactionUtils.signAndMint(repository, transactionData, account);
|
||||
}
|
||||
|
||||
public static void approveTransaction(Repository repository, String accountName, byte[] pendingSignature, boolean decision) throws DataException {
|
||||
@@ -56,7 +56,7 @@ public class GroupUtils {
|
||||
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);
|
||||
TransactionUtils.signAndMint(repository, transactionData, account);
|
||||
}
|
||||
|
||||
public static ApprovalStatus getApprovalStatus(Repository repository, byte[] signature) throws DataException {
|
||||
|
@@ -7,15 +7,17 @@ import org.qora.utils.Base58;
|
||||
public class TestAccount extends PrivateKeyAccount {
|
||||
|
||||
public final String accountName;
|
||||
public final boolean isRewardShare;
|
||||
|
||||
public TestAccount(Repository repository, String accountName, byte[] privateKey) {
|
||||
super(repository, privateKey);
|
||||
public TestAccount(Repository repository, String accountName, String privateKey, boolean isRewardShare) {
|
||||
super(repository, Base58.decode(privateKey));
|
||||
|
||||
this.accountName = accountName;
|
||||
this.isRewardShare = isRewardShare;
|
||||
}
|
||||
|
||||
public TestAccount(Repository repository, String accountName, String privateKey) {
|
||||
this(repository, accountName, Base58.decode(privateKey));
|
||||
public TestAccount(Repository repository, TestAccount testAccount) {
|
||||
this(repository, testAccount.accountName, Base58.encode(testAccount.getPrivateKey()), testAccount.isRewardShare);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.qora.account.PrivateKeyAccount;
|
||||
import org.qora.block.BlockGenerator;
|
||||
import org.qora.block.BlockMinter;
|
||||
import org.qora.data.transaction.TransactionData;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
@@ -37,12 +37,12 @@ public class TransactionUtils {
|
||||
}
|
||||
|
||||
/** Signs transaction using given account and forges a new block, using "alice" account. */
|
||||
public static void signAndForge(Repository repository, TransactionData transactionData, PrivateKeyAccount signingAccount) throws DataException {
|
||||
public static void signAndMint(Repository repository, TransactionData transactionData, PrivateKeyAccount signingAccount) throws DataException {
|
||||
signAsUnconfirmed(repository, transactionData, signingAccount);
|
||||
|
||||
// Generate block
|
||||
PrivateKeyAccount generatorAccount = Common.getTestAccount(repository, "alice");
|
||||
BlockGenerator.generateTestingBlock(repository, generatorAccount);
|
||||
PrivateKeyAccount minterAccount = Common.getTestAccount(repository, "alice-reward-share");
|
||||
BlockMinter.mintTestingBlock(repository, minterAccount);
|
||||
}
|
||||
|
||||
public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, TransactionType txType, boolean wantValid) throws DataException {
|
||||
|
@@ -1,17 +0,0 @@
|
||||
package org.qora.test.common.transaction;
|
||||
|
||||
import org.qora.account.PrivateKeyAccount;
|
||||
import org.qora.data.transaction.EnableForgingTransactionData;
|
||||
import org.qora.data.transaction.TransactionData;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
|
||||
public class EnableForgingTestTransaction extends TestTransaction {
|
||||
|
||||
public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException {
|
||||
String target = account.getAddress();
|
||||
|
||||
return new EnableForgingTransactionData(generateBase(account), target);
|
||||
}
|
||||
|
||||
}
|
@@ -3,19 +3,19 @@ package org.qora.test.common.transaction;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.qora.account.PrivateKeyAccount;
|
||||
import org.qora.data.transaction.ProxyForgingTransactionData;
|
||||
import org.qora.data.transaction.RewardShareTransactionData;
|
||||
import org.qora.data.transaction.TransactionData;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
|
||||
public class ProxyForgingTestTransaction extends TestTransaction {
|
||||
public class RewardShareTestTransaction extends TestTransaction {
|
||||
|
||||
public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException {
|
||||
String recipient = account.getAddress();
|
||||
byte[] proxyPublicKey = account.getProxyPrivateKey(account.getPublicKey());
|
||||
BigDecimal share = BigDecimal.valueOf(50);
|
||||
byte[] rewardSharePublicKey = account.getRewardSharePrivateKey(account.getPublicKey());
|
||||
BigDecimal sharePercent = BigDecimal.valueOf(50);
|
||||
|
||||
return new ProxyForgingTransactionData(generateBase(account), recipient, proxyPublicKey, share);
|
||||
return new RewardShareTransactionData(generateBase(account), recipient, rewardSharePublicKey, sharePercent);
|
||||
}
|
||||
|
||||
}
|
@@ -1,127 +0,0 @@
|
||||
package org.qora.test.forging;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.qora.account.PrivateKeyAccount;
|
||||
import org.qora.data.account.ProxyForgerData;
|
||||
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.AccountUtils;
|
||||
import org.qora.test.common.BlockUtils;
|
||||
import org.qora.test.common.Common;
|
||||
import org.qora.transaction.Transaction;
|
||||
import org.qora.transaction.Transaction.ValidationResult;
|
||||
import org.qora.utils.Base58;
|
||||
|
||||
public class ProxyForgingTests extends Common {
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws DataException {
|
||||
Common.useDefaultSettings();
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterTest() throws DataException {
|
||||
Common.orphanCheck();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRelationship() throws DataException {
|
||||
final BigDecimal share = new BigDecimal("12.8");
|
||||
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount aliceAccount = Common.getTestAccount(repository, "alice");
|
||||
PrivateKeyAccount bobAccount = Common.getTestAccount(repository, "bob");
|
||||
|
||||
// Create relationship
|
||||
byte[] proxyPrivateKey = AccountUtils.proxyForging(repository, "alice", "bob", share);
|
||||
PrivateKeyAccount proxyAccount = new PrivateKeyAccount(repository, proxyPrivateKey);
|
||||
|
||||
// Confirm relationship info set correctly
|
||||
|
||||
// Fetch using proxy public key
|
||||
ProxyForgerData proxyForgerData = repository.getAccountRepository().getProxyForgeData(proxyAccount.getPublicKey());
|
||||
assertEquals("Incorrect generator public key", Base58.encode(aliceAccount.getPublicKey()), Base58.encode(proxyForgerData.getForgerPublicKey()));
|
||||
assertEquals("Incorrect recipient", bobAccount.getAddress(), proxyForgerData.getRecipient());
|
||||
assertEqualBigDecimals("Incorrect reward share", share, proxyForgerData.getShare());
|
||||
|
||||
// Fetch using generator public key and recipient address combination
|
||||
proxyForgerData = repository.getAccountRepository().getProxyForgeData(aliceAccount.getPublicKey(), bobAccount.getAddress());
|
||||
assertEquals("Incorrect generator public key", Base58.encode(aliceAccount.getPublicKey()), Base58.encode(proxyForgerData.getForgerPublicKey()));
|
||||
assertEquals("Incorrect recipient", bobAccount.getAddress(), proxyForgerData.getRecipient());
|
||||
assertEqualBigDecimals("Incorrect reward share", share, proxyForgerData.getShare());
|
||||
|
||||
// Delete relationship
|
||||
byte[] newProxyPrivateKey = AccountUtils.proxyForging(repository, "alice", "bob", BigDecimal.ZERO);
|
||||
PrivateKeyAccount newProxyAccount = new PrivateKeyAccount(repository, newProxyPrivateKey);
|
||||
|
||||
// Confirm proxy keys match
|
||||
assertEquals("Proxy private keys differ", Base58.encode(proxyPrivateKey), Base58.encode(newProxyPrivateKey));
|
||||
assertEquals("Proxy public keys differ", Base58.encode(proxyAccount.getPublicKey()), Base58.encode(newProxyAccount.getPublicKey()));
|
||||
|
||||
// Confirm relationship no longer exists in repository
|
||||
|
||||
// Fetch using proxy public key
|
||||
ProxyForgerData newProxyForgerData = repository.getAccountRepository().getProxyForgeData(proxyAccount.getPublicKey());
|
||||
assertNull("Proxy relationship data shouldn't exist", newProxyForgerData);
|
||||
|
||||
// Fetch using generator public key and recipient address combination
|
||||
newProxyForgerData = repository.getAccountRepository().getProxyForgeData(aliceAccount.getPublicKey(), bobAccount.getAddress());
|
||||
assertNull("Proxy relationship data shouldn't exist", newProxyForgerData);
|
||||
|
||||
// Orphan last block to restore prior proxy relationship
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Confirm proxy relationship restored correctly
|
||||
|
||||
// Fetch using proxy public key
|
||||
newProxyForgerData = repository.getAccountRepository().getProxyForgeData(proxyAccount.getPublicKey());
|
||||
assertNotNull("Proxy relationship data should have been restored", newProxyForgerData);
|
||||
assertEquals("Incorrect generator public key", Base58.encode(aliceAccount.getPublicKey()), Base58.encode(newProxyForgerData.getForgerPublicKey()));
|
||||
assertEquals("Incorrect recipient", bobAccount.getAddress(), newProxyForgerData.getRecipient());
|
||||
assertEqualBigDecimals("Incorrect reward share", share, newProxyForgerData.getShare());
|
||||
|
||||
// Fetch using generator public key and recipient address combination
|
||||
newProxyForgerData = repository.getAccountRepository().getProxyForgeData(aliceAccount.getPublicKey(), bobAccount.getAddress());
|
||||
assertNotNull("Proxy relationship data should have been restored", newProxyForgerData);
|
||||
assertEquals("Incorrect generator public key", Base58.encode(aliceAccount.getPublicKey()), Base58.encode(newProxyForgerData.getForgerPublicKey()));
|
||||
assertEquals("Incorrect recipient", bobAccount.getAddress(), newProxyForgerData.getRecipient());
|
||||
assertEqualBigDecimals("Incorrect reward share", share, newProxyForgerData.getShare());
|
||||
|
||||
// Orphan another block to remove initial proxy relationship
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Confirm proxy relationship no longer exists
|
||||
|
||||
// Fetch using proxy public key
|
||||
newProxyForgerData = repository.getAccountRepository().getProxyForgeData(proxyAccount.getPublicKey());
|
||||
assertNull("Proxy relationship data shouldn't exist", newProxyForgerData);
|
||||
|
||||
// Fetch using generator public key and recipient address combination
|
||||
newProxyForgerData = repository.getAccountRepository().getProxyForgeData(aliceAccount.getPublicKey(), bobAccount.getAddress());
|
||||
assertNull("Proxy relationship data shouldn't exist", newProxyForgerData);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZeroInitialShareInvalid() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
// Create invalid PROXY_FORGING transaction with initial 0% reward share
|
||||
TransactionData transactionData = AccountUtils.createProxyForging(repository, "alice", "bob", BigDecimal.ZERO);
|
||||
|
||||
// Confirm transaction is invalid
|
||||
Transaction transaction = Transaction.fromData(repository, transactionData);
|
||||
|
||||
ValidationResult validationResult = transaction.isValidUnconfirmed();
|
||||
assertEquals("Initial 0% share should be invalid", ValidationResult.INVALID_FORGE_SHARE, validationResult);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
127
src/test/java/org/qora/test/forging/RewardShareTests.java
Normal file
127
src/test/java/org/qora/test/forging/RewardShareTests.java
Normal file
@@ -0,0 +1,127 @@
|
||||
package org.qora.test.forging;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.qora.account.PrivateKeyAccount;
|
||||
import org.qora.data.account.RewardShareData;
|
||||
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.AccountUtils;
|
||||
import org.qora.test.common.BlockUtils;
|
||||
import org.qora.test.common.Common;
|
||||
import org.qora.transaction.Transaction;
|
||||
import org.qora.transaction.Transaction.ValidationResult;
|
||||
import org.qora.utils.Base58;
|
||||
|
||||
public class RewardShareTests extends Common {
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws DataException {
|
||||
Common.useDefaultSettings();
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterTest() throws DataException {
|
||||
Common.orphanCheck();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRewardShare() throws DataException {
|
||||
final BigDecimal sharePercent = new BigDecimal("12.8");
|
||||
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount aliceAccount = Common.getTestAccount(repository, "alice");
|
||||
PrivateKeyAccount bobAccount = Common.getTestAccount(repository, "bob");
|
||||
|
||||
// Create reward-share
|
||||
byte[] rewardSharePrivateKey = AccountUtils.rewardShare(repository, "alice", "bob", sharePercent);
|
||||
PrivateKeyAccount rewardShareAccount = new PrivateKeyAccount(repository, rewardSharePrivateKey);
|
||||
|
||||
// Confirm reward-share info set correctly
|
||||
|
||||
// Fetch using reward-share public key
|
||||
RewardShareData rewardShareData = repository.getAccountRepository().getRewardShare(rewardShareAccount.getPublicKey());
|
||||
assertEquals("Incorrect minter public key", Base58.encode(aliceAccount.getPublicKey()), Base58.encode(rewardShareData.getMinterPublicKey()));
|
||||
assertEquals("Incorrect recipient", bobAccount.getAddress(), rewardShareData.getRecipient());
|
||||
assertEqualBigDecimals("Incorrect share percentage", sharePercent, rewardShareData.getSharePercent());
|
||||
|
||||
// Fetch using minter public key and recipient address combination
|
||||
rewardShareData = repository.getAccountRepository().getRewardShare(aliceAccount.getPublicKey(), bobAccount.getAddress());
|
||||
assertEquals("Incorrect minter public key", Base58.encode(aliceAccount.getPublicKey()), Base58.encode(rewardShareData.getMinterPublicKey()));
|
||||
assertEquals("Incorrect recipient", bobAccount.getAddress(), rewardShareData.getRecipient());
|
||||
assertEqualBigDecimals("Incorrect share percentage", sharePercent, rewardShareData.getSharePercent());
|
||||
|
||||
// Delete reward-share
|
||||
byte[] newRewardSharePrivateKey = AccountUtils.rewardShare(repository, "alice", "bob", BigDecimal.ZERO);
|
||||
PrivateKeyAccount newRewardShareAccount = new PrivateKeyAccount(repository, newRewardSharePrivateKey);
|
||||
|
||||
// Confirm reward-share keys match
|
||||
assertEquals("Reward-share private keys differ", Base58.encode(rewardSharePrivateKey), Base58.encode(newRewardSharePrivateKey));
|
||||
assertEquals("Reward-share public keys differ", Base58.encode(rewardShareAccount.getPublicKey()), Base58.encode(newRewardShareAccount.getPublicKey()));
|
||||
|
||||
// Confirm reward-share no longer exists in repository
|
||||
|
||||
// Fetch using reward-share public key
|
||||
RewardShareData newRewardShareData = repository.getAccountRepository().getRewardShare(rewardShareAccount.getPublicKey());
|
||||
assertNull("Reward-share shouldn't exist", newRewardShareData);
|
||||
|
||||
// Fetch using minter public key and recipient address combination
|
||||
newRewardShareData = repository.getAccountRepository().getRewardShare(aliceAccount.getPublicKey(), bobAccount.getAddress());
|
||||
assertNull("Reward-share shouldn't exist", newRewardShareData);
|
||||
|
||||
// Orphan last block to restore prior reward-share
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Confirm reward-share restored correctly
|
||||
|
||||
// Fetch using reward-share public key
|
||||
newRewardShareData = repository.getAccountRepository().getRewardShare(rewardShareAccount.getPublicKey());
|
||||
assertNotNull("Reward-share should have been restored", newRewardShareData);
|
||||
assertEquals("Incorrect minter public key", Base58.encode(aliceAccount.getPublicKey()), Base58.encode(newRewardShareData.getMinterPublicKey()));
|
||||
assertEquals("Incorrect recipient", bobAccount.getAddress(), newRewardShareData.getRecipient());
|
||||
assertEqualBigDecimals("Incorrect share percentage", sharePercent, newRewardShareData.getSharePercent());
|
||||
|
||||
// Fetch using minter public key and recipient address combination
|
||||
newRewardShareData = repository.getAccountRepository().getRewardShare(aliceAccount.getPublicKey(), bobAccount.getAddress());
|
||||
assertNotNull("Reward-share should have been restored", newRewardShareData);
|
||||
assertEquals("Incorrect minter public key", Base58.encode(aliceAccount.getPublicKey()), Base58.encode(newRewardShareData.getMinterPublicKey()));
|
||||
assertEquals("Incorrect recipient", bobAccount.getAddress(), newRewardShareData.getRecipient());
|
||||
assertEqualBigDecimals("Incorrect share percentage", sharePercent, newRewardShareData.getSharePercent());
|
||||
|
||||
// Orphan another block to remove initial reward-share
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Confirm reward-share no longer exists
|
||||
|
||||
// Fetch using reward-share public key
|
||||
newRewardShareData = repository.getAccountRepository().getRewardShare(rewardShareAccount.getPublicKey());
|
||||
assertNull("Reward-share shouldn't exist", newRewardShareData);
|
||||
|
||||
// Fetch using minter public key and recipient address combination
|
||||
newRewardShareData = repository.getAccountRepository().getRewardShare(aliceAccount.getPublicKey(), bobAccount.getAddress());
|
||||
assertNull("Reward-share shouldn't exist", newRewardShareData);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZeroInitialShareInvalid() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
// Create invalid REWARD_SHARE transaction with initial 0% reward share
|
||||
TransactionData transactionData = AccountUtils.createRewardShare(repository, "alice", "bob", BigDecimal.ZERO);
|
||||
|
||||
// Confirm transaction is invalid
|
||||
Transaction transaction = Transaction.fromData(repository, transactionData);
|
||||
|
||||
ValidationResult validationResult = transaction.isValidUnconfirmed();
|
||||
assertEquals("Initial 0% share should be invalid", ValidationResult.INVALID_REWARD_SHARE_PERCENT, validationResult);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -12,7 +12,7 @@ import org.qora.account.PrivateKeyAccount;
|
||||
import org.qora.asset.Asset;
|
||||
import org.qora.block.BlockChain;
|
||||
import org.qora.block.BlockChain.RewardByHeight;
|
||||
import org.qora.block.BlockGenerator;
|
||||
import org.qora.block.BlockMinter;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
import org.qora.repository.RepositoryManager;
|
||||
@@ -41,7 +41,7 @@ public class RewardTests extends Common {
|
||||
|
||||
BigDecimal blockReward = BlockUtils.getNextBlockReward(repository);
|
||||
|
||||
BlockGenerator.generateTestingBlock(repository, forgingAccount);
|
||||
BlockMinter.mintTestingBlock(repository, forgingAccount);
|
||||
|
||||
BigDecimal expectedBalance = initialBalances.get("alice").get(Asset.QORT).add(blockReward);
|
||||
AccountUtils.assertBalance(repository, "alice", Asset.QORT, expectedBalance);
|
||||
@@ -68,7 +68,7 @@ public class RewardTests extends Common {
|
||||
rewardInfo = rewards.get(rewardIndex);
|
||||
}
|
||||
|
||||
BlockGenerator.generateTestingBlock(repository, forgingAccount);
|
||||
BlockMinter.mintTestingBlock(repository, forgingAccount);
|
||||
expectedBalance = expectedBalance.add(rewardInfo.reward);
|
||||
}
|
||||
|
||||
@@ -81,12 +81,12 @@ public class RewardTests extends Common {
|
||||
final BigDecimal share = new BigDecimal("12.8");
|
||||
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
byte[] proxyPrivateKey = AccountUtils.proxyForging(repository, "alice", "bob", share);
|
||||
byte[] proxyPrivateKey = AccountUtils.rewardShare(repository, "alice", "bob", share);
|
||||
PrivateKeyAccount proxyAccount = new PrivateKeyAccount(repository, proxyPrivateKey);
|
||||
|
||||
Map<String, Map<Long, BigDecimal>> initialBalances = AccountUtils.getBalances(repository, Asset.QORT);
|
||||
BigDecimal blockReward = BlockUtils.getNextBlockReward(repository);
|
||||
BlockGenerator.generateTestingBlock(repository, proxyAccount);
|
||||
BlockMinter.mintTestingBlock(repository, proxyAccount);
|
||||
|
||||
// We're expecting reward * 12.8% to Bob, the rest to Alice
|
||||
|
||||
|
@@ -5,7 +5,7 @@ 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.block.BlockMinter;
|
||||
import org.qora.data.transaction.BaseTransactionData;
|
||||
import org.qora.data.transaction.IssueAssetTransactionData;
|
||||
import org.qora.data.transaction.PaymentTransactionData;
|
||||
@@ -69,7 +69,7 @@ public class GroupApprovalTests extends Common {
|
||||
int groupId = GroupUtils.createGroup(repository, "alice", "test", true, ApprovalThreshold.ONE, minBlockDelay, maxBlockDelay);
|
||||
|
||||
Transaction transaction = buildIssueAssetTransaction(repository, "alice", groupId);
|
||||
TransactionUtils.signAndForge(repository, transaction.getTransactionData(), aliceAccount);
|
||||
TransactionUtils.signAndMint(repository, transaction.getTransactionData(), aliceAccount);
|
||||
|
||||
// Confirm transaction doesn't need approval
|
||||
ApprovalStatus approvalStatus = GroupUtils.getApprovalStatus(repository, transaction.getTransactionData().getSignature());
|
||||
@@ -95,7 +95,7 @@ public class GroupApprovalTests extends Common {
|
||||
|
||||
BigDecimal blockReward = BlockUtils.getNextBlockReward(repository);
|
||||
Transaction bobAssetTransaction = buildIssueAssetTransaction(repository, "bob", groupId);
|
||||
TransactionUtils.signAndForge(repository, bobAssetTransaction.getTransactionData(), bobAccount);
|
||||
TransactionUtils.signAndMint(repository, bobAssetTransaction.getTransactionData(), bobAccount);
|
||||
|
||||
// Confirm transaction needs approval, and hasn't been approved
|
||||
ApprovalStatus approvalStatus = GroupUtils.getApprovalStatus(repository, bobAssetTransaction.getTransactionData().getSignature());
|
||||
@@ -115,7 +115,7 @@ public class GroupApprovalTests extends Common {
|
||||
|
||||
// Have Bob do a non-approval transaction to change his last-reference
|
||||
Transaction bobPaymentTransaction = buildPaymentTransaction(repository, "bob", "chloe", amount, Group.NO_GROUP);
|
||||
TransactionUtils.signAndForge(repository, bobPaymentTransaction.getTransactionData(), bobAccount);
|
||||
TransactionUtils.signAndMint(repository, bobPaymentTransaction.getTransactionData(), bobAccount);
|
||||
|
||||
byte[] bobPostPaymentReference = bobAccount.getLastReference();
|
||||
assertFalse("reference should have changed", Arrays.equals(bobPostAssetReference, bobPostPaymentReference));
|
||||
@@ -125,7 +125,7 @@ public class GroupApprovalTests extends Common {
|
||||
|
||||
// Now forge a few blocks so transaction is approved
|
||||
for (int blockCount = 0; blockCount < minBlockDelay; ++blockCount)
|
||||
BlockGenerator.generateTestingBlock(repository, aliceAccount);
|
||||
BlockMinter.mintTestingBlock(repository, aliceAccount);
|
||||
|
||||
// Confirm transaction now approved
|
||||
approvalStatus = GroupUtils.getApprovalStatus(repository, bobAssetTransaction.getTransactionData().getSignature());
|
||||
@@ -184,7 +184,7 @@ public class GroupApprovalTests extends Common {
|
||||
|
||||
// Bob's issue-asset transaction needs group-approval
|
||||
Transaction bobAssetTransaction = buildIssueAssetTransaction(repository, "bob", groupId);
|
||||
TransactionUtils.signAndForge(repository, bobAssetTransaction.getTransactionData(), bobAccount);
|
||||
TransactionUtils.signAndMint(repository, bobAssetTransaction.getTransactionData(), bobAccount);
|
||||
|
||||
// Confirm transaction needs approval, and hasn't been approved
|
||||
ApprovalStatus approvalStatus = GroupUtils.getApprovalStatus(repository, bobAssetTransaction.getTransactionData().getSignature());
|
||||
@@ -199,7 +199,7 @@ public class GroupApprovalTests extends Common {
|
||||
|
||||
// Now forge a few blocks so transaction is approved
|
||||
for (int blockCount = 0; blockCount < minBlockDelay; ++blockCount)
|
||||
BlockGenerator.generateTestingBlock(repository, aliceAccount);
|
||||
BlockMinter.mintTestingBlock(repository, aliceAccount);
|
||||
|
||||
// Confirm transaction now approved
|
||||
approvalStatus = GroupUtils.getApprovalStatus(repository, bobAssetTransaction.getTransactionData().getSignature());
|
||||
@@ -246,7 +246,7 @@ public class GroupApprovalTests extends Common {
|
||||
|
||||
// Bob's issue-asset transaction needs group-approval
|
||||
Transaction bobAssetTransaction = buildIssueAssetTransaction(repository, "bob", groupId);
|
||||
TransactionUtils.signAndForge(repository, bobAssetTransaction.getTransactionData(), bobAccount);
|
||||
TransactionUtils.signAndMint(repository, bobAssetTransaction.getTransactionData(), bobAccount);
|
||||
|
||||
// Confirm transaction needs approval, and hasn't been approved
|
||||
ApprovalStatus approvalStatus = GroupUtils.getApprovalStatus(repository, bobAssetTransaction.getTransactionData().getSignature());
|
||||
@@ -261,7 +261,7 @@ public class GroupApprovalTests extends Common {
|
||||
|
||||
// Now forge a few blocks so transaction is approved
|
||||
for (int blockCount = 0; blockCount < minBlockDelay; ++blockCount)
|
||||
BlockGenerator.generateTestingBlock(repository, aliceAccount);
|
||||
BlockMinter.mintTestingBlock(repository, aliceAccount);
|
||||
|
||||
// Confirm transaction now rejected
|
||||
approvalStatus = GroupUtils.getApprovalStatus(repository, bobAssetTransaction.getTransactionData().getSignature());
|
||||
@@ -308,7 +308,7 @@ public class GroupApprovalTests extends Common {
|
||||
|
||||
// Bob's issue-asset transaction needs group-approval
|
||||
Transaction bobAssetTransaction = buildIssueAssetTransaction(repository, "bob", groupId);
|
||||
TransactionUtils.signAndForge(repository, bobAssetTransaction.getTransactionData(), bobAccount);
|
||||
TransactionUtils.signAndMint(repository, bobAssetTransaction.getTransactionData(), bobAccount);
|
||||
|
||||
// Confirm transaction needs approval, and hasn't been approved
|
||||
ApprovalStatus approvalStatus = GroupUtils.getApprovalStatus(repository, bobAssetTransaction.getTransactionData().getSignature());
|
||||
@@ -320,7 +320,7 @@ public class GroupApprovalTests extends Common {
|
||||
|
||||
// Now forge a few blocks so group-approval for transaction expires
|
||||
for (int blockCount = 0; blockCount <= maxBlockDelay; ++blockCount)
|
||||
BlockGenerator.generateTestingBlock(repository, aliceAccount);
|
||||
BlockMinter.mintTestingBlock(repository, aliceAccount);
|
||||
|
||||
// Confirm transaction now expired
|
||||
approvalStatus = GroupUtils.getApprovalStatus(repository, bobAssetTransaction.getTransactionData().getSignature());
|
||||
@@ -356,7 +356,7 @@ public class GroupApprovalTests extends Common {
|
||||
|
||||
// Bob's issue-asset transaction needs group-approval
|
||||
Transaction bobAssetTransaction = buildIssueAssetTransaction(repository, "bob", groupId);
|
||||
TransactionUtils.signAndForge(repository, bobAssetTransaction.getTransactionData(), bobAccount);
|
||||
TransactionUtils.signAndMint(repository, bobAssetTransaction.getTransactionData(), bobAccount);
|
||||
|
||||
// Confirm transaction needs approval, and hasn't been approved
|
||||
ApprovalStatus approvalStatus = GroupUtils.getApprovalStatus(repository, bobAssetTransaction.getTransactionData().getSignature());
|
||||
@@ -372,7 +372,7 @@ public class GroupApprovalTests extends Common {
|
||||
// But wait! Alice issues an asset with the same name before Bob's asset is issued!
|
||||
// This transaction will be auto-approved as Alice is the group owner (and admin)
|
||||
Transaction aliceAssetTransaction = buildIssueAssetTransaction(repository, "alice", groupId);
|
||||
TransactionUtils.signAndForge(repository, aliceAssetTransaction.getTransactionData(), aliceAccount);
|
||||
TransactionUtils.signAndMint(repository, aliceAssetTransaction.getTransactionData(), aliceAccount);
|
||||
|
||||
// Confirm Alice's transaction auto-approved
|
||||
approvalStatus = GroupUtils.getApprovalStatus(repository, aliceAssetTransaction.getTransactionData().getSignature());
|
||||
@@ -380,7 +380,7 @@ public class GroupApprovalTests extends Common {
|
||||
|
||||
// Now forge a few blocks so transaction is approved
|
||||
for (int blockCount = 0; blockCount < minBlockDelay; ++blockCount)
|
||||
BlockGenerator.generateTestingBlock(repository, aliceAccount);
|
||||
BlockMinter.mintTestingBlock(repository, aliceAccount);
|
||||
|
||||
// Confirm Bob's transaction now invalid
|
||||
approvalStatus = GroupUtils.getApprovalStatus(repository, bobAssetTransaction.getTransactionData().getSignature());
|
||||
|
@@ -9,7 +9,7 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.qora.account.PrivateKeyAccount;
|
||||
import org.qora.block.BlockGenerator;
|
||||
import org.qora.block.BlockMinter;
|
||||
import org.qora.data.naming.NameData;
|
||||
import org.qora.data.transaction.BuyNameTransactionData;
|
||||
import org.qora.data.transaction.RegisterNameTransactionData;
|
||||
@@ -60,7 +60,7 @@ public class OrphaningTests extends Common {
|
||||
public void testRegisterName() throws DataException {
|
||||
// Register-name
|
||||
RegisterNameTransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), alice.getAddress(), name, "{}");
|
||||
TransactionUtils.signAndForge(repository, transactionData, alice);
|
||||
TransactionUtils.signAndMint(repository, transactionData, alice);
|
||||
|
||||
String name = transactionData.getName();
|
||||
|
||||
@@ -74,7 +74,7 @@ public class OrphaningTests extends Common {
|
||||
assertFalse(repository.getNameRepository().nameExists(name));
|
||||
|
||||
// Re-process register-name
|
||||
BlockGenerator.generateTestingBlock(repository, alice);
|
||||
BlockMinter.mintTestingBlock(repository, alice);
|
||||
|
||||
// Check name does exist
|
||||
assertTrue(repository.getNameRepository().nameExists(name));
|
||||
@@ -87,7 +87,7 @@ public class OrphaningTests extends Common {
|
||||
|
||||
// Sell-name
|
||||
SellNameTransactionData transactionData = new SellNameTransactionData(TestTransaction.generateBase(alice), name, price);
|
||||
TransactionUtils.signAndForge(repository, transactionData, alice);
|
||||
TransactionUtils.signAndMint(repository, transactionData, alice);
|
||||
|
||||
NameData nameData;
|
||||
|
||||
@@ -105,7 +105,7 @@ public class OrphaningTests extends Common {
|
||||
// Not concerned about price
|
||||
|
||||
// Re-process sell-name
|
||||
BlockGenerator.generateTestingBlock(repository, alice);
|
||||
BlockMinter.mintTestingBlock(repository, alice);
|
||||
|
||||
// Check name is for sale
|
||||
nameData = repository.getNameRepository().fromName(name);
|
||||
@@ -121,10 +121,10 @@ public class OrphaningTests extends Common {
|
||||
assertNull(nameData);
|
||||
|
||||
// Re-process register-name and sell-name
|
||||
BlockGenerator.generateTestingBlock(repository, alice);
|
||||
BlockMinter.mintTestingBlock(repository, alice);
|
||||
// Unconfirmed sell-name transaction not included in previous block
|
||||
// as it isn't valid until name exists thanks to register-name transaction.
|
||||
BlockGenerator.generateTestingBlock(repository, alice);
|
||||
BlockMinter.mintTestingBlock(repository, alice);
|
||||
|
||||
// Check name does exist
|
||||
assertTrue(repository.getNameRepository().nameExists(name));
|
||||
@@ -144,7 +144,7 @@ public class OrphaningTests extends Common {
|
||||
|
||||
// Buy-name
|
||||
BuyNameTransactionData transactionData = new BuyNameTransactionData(TestTransaction.generateBase(bob), name, price, seller);
|
||||
TransactionUtils.signAndForge(repository, transactionData, bob);
|
||||
TransactionUtils.signAndMint(repository, transactionData, bob);
|
||||
|
||||
NameData nameData;
|
||||
|
||||
@@ -162,7 +162,7 @@ public class OrphaningTests extends Common {
|
||||
assertEqualBigDecimals("price incorrect", price, nameData.getSalePrice());
|
||||
|
||||
// Re-process buy-name
|
||||
BlockGenerator.generateTestingBlock(repository, alice);
|
||||
BlockMinter.mintTestingBlock(repository, alice);
|
||||
|
||||
// Check name is sold
|
||||
nameData = repository.getNameRepository().fromName(name);
|
||||
@@ -180,10 +180,10 @@ public class OrphaningTests extends Common {
|
||||
assertEquals(alice.getAddress(), nameData.getOwner());
|
||||
|
||||
// Re-process sell-name and buy-name
|
||||
BlockGenerator.generateTestingBlock(repository, alice);
|
||||
BlockMinter.mintTestingBlock(repository, alice);
|
||||
// Unconfirmed buy-name transaction not included in previous block
|
||||
// as it isn't valid until name is for sale thanks to sell-name transaction.
|
||||
BlockGenerator.generateTestingBlock(repository, alice);
|
||||
BlockMinter.mintTestingBlock(repository, alice);
|
||||
|
||||
// Check name is sold
|
||||
nameData = repository.getNameRepository().fromName(name);
|
||||
@@ -200,7 +200,7 @@ public class OrphaningTests extends Common {
|
||||
// Sell-name
|
||||
BigDecimal newPrice = new BigDecimal(random.nextInt(1000)).setScale(8);
|
||||
SellNameTransactionData transactionData = new SellNameTransactionData(TestTransaction.generateBase(bob), name, newPrice);
|
||||
TransactionUtils.signAndForge(repository, transactionData, bob);
|
||||
TransactionUtils.signAndMint(repository, transactionData, bob);
|
||||
|
||||
NameData nameData;
|
||||
|
||||
@@ -218,7 +218,7 @@ public class OrphaningTests extends Common {
|
||||
// Not concerned about price
|
||||
|
||||
// Re-process sell-name
|
||||
BlockGenerator.generateTestingBlock(repository, alice);
|
||||
BlockMinter.mintTestingBlock(repository, alice);
|
||||
|
||||
// Check name is for sale
|
||||
nameData = repository.getNameRepository().fromName(name);
|
||||
@@ -236,10 +236,10 @@ public class OrphaningTests extends Common {
|
||||
assertEquals(alice.getAddress(), nameData.getOwner());
|
||||
|
||||
// Re-process buy-name and sell-name
|
||||
BlockGenerator.generateTestingBlock(repository, bob);
|
||||
BlockMinter.mintTestingBlock(repository, bob);
|
||||
// Unconfirmed sell-name transaction not included in previous block
|
||||
// as it isn't valid until name owned by bob thanks to buy-name transaction.
|
||||
BlockGenerator.generateTestingBlock(repository, bob);
|
||||
BlockMinter.mintTestingBlock(repository, bob);
|
||||
|
||||
// Check name does exist
|
||||
assertTrue(repository.getNameRepository().nameExists(name));
|
||||
|
@@ -1,28 +1,32 @@
|
||||
{
|
||||
"isTestChain": true,
|
||||
"maxBalance": "10000000000",
|
||||
"blockDifficultyInterval": 10,
|
||||
"minBlockTime": 30,
|
||||
"maxBlockTime": 60,
|
||||
"blockTimestampMargin": 500,
|
||||
"transactionExpiryPeriod": 86400000,
|
||||
"maxBlockSize": 2097152,
|
||||
"maxBytesPerUnitFee": 1024,
|
||||
"unitFee": "0.1",
|
||||
"requireGroupForApproval": false,
|
||||
"genesisInfo": {
|
||||
"version": 4,
|
||||
"timestamp": 0,
|
||||
"generatingBalance": "10000000",
|
||||
"transactions": [
|
||||
{ "type": "ISSUE_ASSET", "owner": "QcFmNxSArv5tWEzCtTKb2Lqc5QkKuQ7RNs", "assetName": "QORA", "description": "QORA native coin", "data": "", "quantity": 10000000000, "isDivisible": true, "fee": 0, "reference": "3Verk6ZKBJc3WTTVfxFC9icSjKdM8b92eeJEpJP8qNizG4ZszNFq8wdDYdSjJXq2iogDFR1njyhsBdVpbvDfjzU7" },
|
||||
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000", "fee": 0 },
|
||||
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000", "fee": 0 },
|
||||
{ "type": "GENESIS", "recipient": "QaUpHNhT3Ygx6avRiKobuLdusppR5biXjL", "amount": "1000000", "fee": 0 },
|
||||
{ "type": "GENESIS", "recipient": "Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er", "amount": "1000000", "fee": 0 },
|
||||
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "TEST", "description": "test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||
{ "type": "ISSUE_ASSET", "owner": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 }
|
||||
]
|
||||
},
|
||||
"minAccountLevelToRewardShare": 5,
|
||||
"maxRewardSharesPerMintingAccount": 20,
|
||||
"onlineAccountSignaturesMinLifetime": 3600000,
|
||||
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
{ "height": 21, "reward": 1 }
|
||||
],
|
||||
"sharesByLevel": [
|
||||
{ "levels": [ 1, 2 ], "share": 0.05 },
|
||||
{ "levels": [ 3, 4 ], "share": 0.10 },
|
||||
{ "levels": [ 5, 6 ], "share": 0.15 },
|
||||
{ "levels": [ 7, 8 ], "share": 0.20 },
|
||||
{ "levels": [ 9, 10 ], "share": 0.25 }
|
||||
],
|
||||
"qoraHoldersShare": 0.20,
|
||||
"blocksNeededByLevel": [ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 ],
|
||||
"blockTimingsByHeight": [
|
||||
{ "height": 1, "target": 60000, "deviation": 30000, "power": 0.2 }
|
||||
],
|
||||
"featureTriggers": {
|
||||
"messageHeight": 0,
|
||||
"atHeight": 0,
|
||||
@@ -31,6 +35,23 @@
|
||||
"arbitraryTimestamp": 0,
|
||||
"powfixTimestamp": 0,
|
||||
"v2Timestamp": 0,
|
||||
"newAssetPricingTimestamp": 1600000000000
|
||||
"newAssetPricingTimestamp": 1600000000000,
|
||||
"groupApprovalTimestamp": 0
|
||||
},
|
||||
"genesisInfo": {
|
||||
"version": 4,
|
||||
"timestamp": 0,
|
||||
"transactions": [
|
||||
{ "type": "ISSUE_ASSET", "owner": "QcFmNxSArv5tWEzCtTKb2Lqc5QkKuQ7RNs", "assetName": "QORA", "description": "QORA native coin", "data": "", "quantity": 10000000000, "isDivisible": true, "fee": 0, "reference": "3Verk6ZKBJc3WTTVfxFC9icSjKdM8b92eeJEpJP8qNizG4ZszNFq8wdDYdSjJXq2iogDFR1njyhsBdVpbvDfjzU7" },
|
||||
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000", "fee": 0 },
|
||||
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000", "fee": 0 },
|
||||
{ "type": "GENESIS", "recipient": "QaUpHNhT3Ygx6avRiKobuLdusppR5biXjL", "amount": "1000000", "fee": 0 },
|
||||
{ "type": "GENESIS", "recipient": "Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er", "amount": "1000000", "fee": 0 },
|
||||
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "TEST", "description": "test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||
{ "type": "ISSUE_ASSET", "owner": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
|
||||
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
52
src/test/resources/test-chain-v1.json
Normal file
52
src/test/resources/test-chain-v1.json
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"isTestChain": true,
|
||||
"blockTimestampMargin": 500,
|
||||
"transactionExpiryPeriod": 86400000,
|
||||
"maxBlockSize": 2097152,
|
||||
"maxBytesPerUnitFee": 1024,
|
||||
"unitFee": "0.1",
|
||||
"requireGroupForApproval": false,
|
||||
"minAccountLevelToRewardShare": 5,
|
||||
"maxRewardSharesPerMintingAccount": 20,
|
||||
"onlineAccountSignaturesMinLifetime": 3600000,
|
||||
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
{ "height": 21, "reward": 1 }
|
||||
],
|
||||
"sharesByLevel": [
|
||||
{ "levels": [ 1, 2 ], "share": 0.05 },
|
||||
{ "levels": [ 3, 4 ], "share": 0.10 },
|
||||
{ "levels": [ 5, 6 ], "share": 0.15 },
|
||||
{ "levels": [ 7, 8 ], "share": 0.20 },
|
||||
{ "levels": [ 9, 10 ], "share": 0.25 }
|
||||
],
|
||||
"qoraHoldersShare": 0.20,
|
||||
"blocksNeededByLevel": [ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 ],
|
||||
"blockTimingsByHeight": [
|
||||
{ "height": 1, "target": 60000, "deviation": 30000, "power": 0.2 }
|
||||
],
|
||||
"featureTriggers": {
|
||||
"messageHeight": 0,
|
||||
"atHeight": 0,
|
||||
"assetsTimestamp": 0,
|
||||
"votingTimestamp": 0,
|
||||
"arbitraryTimestamp": 0,
|
||||
"powfixTimestamp": 0,
|
||||
"v2Timestamp": 1600000000000,
|
||||
"newAssetPricingTimestamp": 1600000000000,
|
||||
"groupApprovalTimestamp": 0
|
||||
},
|
||||
"genesisInfo": {
|
||||
"version": 1,
|
||||
"timestamp": 1400247274336,
|
||||
"transactions": [
|
||||
{ "type": "ISSUE_ASSET", "owner": "QcFmNxSArv5tWEzCtTKb2Lqc5QkKuQ7RNs", "assetName": "QORA", "description": "QORA native coin", "data": "", "quantity": 10000000000, "isDivisible": true, "fee": 0, "reference": "3Verk6ZKBJc3WTTVfxFC9icSjKdM8b92eeJEpJP8qNizG4ZszNFq8wdDYdSjJXq2iogDFR1njyhsBdVpbvDfjzU7" },
|
||||
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000", "fee": 0 },
|
||||
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000", "fee": 0 },
|
||||
{ "type": "GENESIS", "recipient": "QaUpHNhT3Ygx6avRiKobuLdusppR5biXjL", "amount": "1000000", "fee": 0 },
|
||||
{ "type": "GENESIS", "recipient": "Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er", "amount": "1000000", "fee": 0 }
|
||||
]
|
||||
}
|
||||
}
|
@@ -1,40 +1,31 @@
|
||||
{
|
||||
"isTestChain": true,
|
||||
"maxBalance": "10000000000",
|
||||
"blockDifficultyInterval": 10,
|
||||
"minBlockTime": 30,
|
||||
"maxBlockTime": 60,
|
||||
"blockTimestampMargin": 500,
|
||||
"transactionExpiryPeriod": 86400000,
|
||||
"maxBlockSize": 2097152,
|
||||
"maxBytesPerUnitFee": 1024,
|
||||
"unitFee": "0.1",
|
||||
"requireGroupForApproval": false,
|
||||
"maxProxyRelationships": 8,
|
||||
"genesisInfo": {
|
||||
"version": 4,
|
||||
"timestamp": 0,
|
||||
"generatingBalance": "10000000",
|
||||
"transactions": [
|
||||
{ "type": "ISSUE_ASSET", "owner": "QcFmNxSArv5tWEzCtTKb2Lqc5QkKuQ7RNs", "assetName": "QORA", "description": "QORA native coin", "data": "", "quantity": 10000000000, "isDivisible": true, "fee": 0, "reference": "3Verk6ZKBJc3WTTVfxFC9icSjKdM8b92eeJEpJP8qNizG4ZszNFq8wdDYdSjJXq2iogDFR1njyhsBdVpbvDfjzU7" },
|
||||
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000", "fee": 0 },
|
||||
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000", "fee": 0 },
|
||||
{ "type": "GENESIS", "recipient": "QaUpHNhT3Ygx6avRiKobuLdusppR5biXjL", "amount": "1000000", "fee": 0 },
|
||||
{ "type": "GENESIS", "recipient": "Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er", "amount": "1000000", "fee": 0 },
|
||||
{ "type": "CREATE_GROUP", "creatorPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT100", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 },
|
||||
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "TEST", "description": "test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||
{ "type": "ISSUE_ASSET", "owner": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 }
|
||||
]
|
||||
},
|
||||
"minAccountLevelToRewardShare": 5,
|
||||
"maxRewardSharesPerMintingAccount": 20,
|
||||
"onlineAccountSignaturesMinLifetime": 3600000,
|
||||
"onlineAccountSignaturesMaxLifetime": 86400000,
|
||||
"rewardsByHeight": [
|
||||
{ "height": 1, "reward": 100 },
|
||||
{ "height": 11, "reward": 10 },
|
||||
{ "height": 21, "reward": 1 }
|
||||
],
|
||||
"forgingTiers": [
|
||||
{ "minBlocks": 5, "maxSubAccounts": 5 },
|
||||
{ "minBlocks": 4, "maxSubAccounts": 3 },
|
||||
{ "minBlocks": 0, "maxSubAccounts": 0 }
|
||||
"sharesByLevel": [
|
||||
{ "levels": [ 1, 2 ], "share": 0.05 },
|
||||
{ "levels": [ 3, 4 ], "share": 0.10 },
|
||||
{ "levels": [ 5, 6 ], "share": 0.15 },
|
||||
{ "levels": [ 7, 8 ], "share": 0.20 },
|
||||
{ "levels": [ 9, 10 ], "share": 0.25 }
|
||||
],
|
||||
"qoraHoldersShare": 0.20,
|
||||
"blocksNeededByLevel": [ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 ],
|
||||
"blockTimingsByHeight": [
|
||||
{ "height": 1, "target": 60000, "deviation": 30000, "power": 0.2 }
|
||||
],
|
||||
"featureTriggers": {
|
||||
"messageHeight": 0,
|
||||
@@ -46,5 +37,22 @@
|
||||
"v2Timestamp": 0,
|
||||
"newAssetPricingTimestamp": 0,
|
||||
"groupApprovalTimestamp": 0
|
||||
},
|
||||
"genesisInfo": {
|
||||
"version": 4,
|
||||
"timestamp": 0,
|
||||
"transactions": [
|
||||
{ "type": "ISSUE_ASSET", "owner": "QcFmNxSArv5tWEzCtTKb2Lqc5QkKuQ7RNs", "assetName": "QORA", "description": "QORA native coin", "data": "", "quantity": 10000000000, "isDivisible": true, "fee": 0, "reference": "3Verk6ZKBJc3WTTVfxFC9icSjKdM8b92eeJEpJP8qNizG4ZszNFq8wdDYdSjJXq2iogDFR1njyhsBdVpbvDfjzU7" },
|
||||
{ "type": "GENESIS", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "amount": "1000000000", "fee": 0 },
|
||||
{ "type": "GENESIS", "recipient": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "amount": "1000000", "fee": 0 },
|
||||
{ "type": "GENESIS", "recipient": "QaUpHNhT3Ygx6avRiKobuLdusppR5biXjL", "amount": "1000000", "fee": 0 },
|
||||
{ "type": "GENESIS", "recipient": "Qci5m9k4rcwe4ruKrZZQKka4FzUUMut3er", "amount": "1000000", "fee": 0 },
|
||||
{ "type": "CREATE_GROUP", "creatorPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "groupName": "dev-group", "description": "developer group", "isOpen": false, "approvalThreshold": "PCT100", "minimumBlockDelay": 0, "maximumBlockDelay": 1440 },
|
||||
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "TEST", "description": "test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||
{ "type": "ISSUE_ASSET", "owner": "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK", "assetName": "OTHER", "description": "other test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||
{ "type": "ISSUE_ASSET", "owner": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "assetName": "GOLD", "description": "gold test asset", "data": "", "quantity": 1000000, "isDivisible": true, "fee": 0 },
|
||||
{ "type": "ACCOUNT_FLAGS", "target": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "andMask": -1, "orMask": 1, "xorMask": 0 },
|
||||
{ "type": "REWARD_SHARE", "minterPublicKey": "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP", "recipient": "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v", "rewardSharePublicKey": "7PpfnvLSG7y4HPh8hE7KoqAjLCkv7Ui6xw4mKAkbZtox", "sharePercent": 100 }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
6
src/test/resources/test-settings-v1.json
Normal file
6
src/test/resources/test-settings-v1.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"restrictedApi": false,
|
||||
"blockchainConfig": "src/test/resources/test-chain-v1.json",
|
||||
"wipeUnconfirmedOnStart": false,
|
||||
"minPeers": 0
|
||||
}
|
Reference in New Issue
Block a user