Loads of work on CIYAM AT support, including BTC-QORT cross-chain trading.

We require AT v1.3.4 now!

Updated AT-related logging.

Added "isInitial" flag to AT state data so that state data created at
deployment is not added to serialized block data.

Updated BTC-QORT AT code and tests to cover various scenarios.

Added missing 'testNtpOffset' to various test versions of 'settings.json'.
Added missing 'ciyamAtSettings' to various test blockchain configs.

Loads of AT-related additions/fixes/etc. to core code, e.g Block
This commit is contained in:
catbref
2020-04-14 17:19:44 +01:00
parent 3eaeb927ec
commit 98506a038b
38 changed files with 3144 additions and 266 deletions

View File

@@ -13,17 +13,23 @@ import org.qortal.settings.Settings;
public class orphan {
public static void main(String[] args) {
if (args.length == 0) {
System.err.println("usage: orphan <new-blockchain-tip-height>");
if (args.length < 1 || args.length > 2) {
System.err.println("usage: orphan [<settings-file>] <new-blockchain-tip-height>");
System.exit(1);
}
int targetHeight = Integer.parseInt(args[0]);
Security.insertProviderAt(new BouncyCastleProvider(), 0);
// Load/check settings, which potentially sets up blockchain config, etc.
Settings.getInstance();
int argIndex = 0;
if (args.length > 1) {
Settings.fileInstance(args[argIndex++]);
} else {
// Load/check settings, which potentially sets up blockchain config, etc.
Settings.getInstance();
}
int targetHeight = Integer.parseInt(args[argIndex]);
try {
RepositoryFactory repositoryFactory = new HSQLDBRepositoryFactory(Controller.getRepositoryUrl());

View File

@@ -0,0 +1,403 @@
package org.qortal.test.btcacct;
import static org.junit.Assert.assertTrue;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Arrays;
import java.util.List;
import org.ciyam.at.MachineState;
import org.junit.Before;
import org.junit.Test;
import org.qortal.account.Account;
import org.qortal.account.PrivateKeyAccount;
import org.qortal.asset.Asset;
import org.qortal.at.QortalAtLoggerFactory;
import org.qortal.crosschain.BTCACCT;
import org.qortal.crypto.Crypto;
import org.qortal.data.at.ATData;
import org.qortal.data.at.ATStateData;
import org.qortal.data.transaction.BaseTransactionData;
import org.qortal.data.transaction.DeployAtTransactionData;
import org.qortal.data.transaction.MessageTransactionData;
import org.qortal.data.transaction.TransactionData;
import org.qortal.group.Group;
import org.qortal.repository.DataException;
import org.qortal.repository.Repository;
import org.qortal.repository.RepositoryManager;
import org.qortal.test.common.BlockUtils;
import org.qortal.test.common.Common;
import org.qortal.test.common.TransactionUtils;
import org.qortal.transaction.DeployAtTransaction;
import org.qortal.transaction.MessageTransaction;
import com.google.common.hash.HashCode;
public class AtTests extends Common {
public static final byte[] secret = "This string is exactly 32 bytes!".getBytes();
public static final byte[] secretHash = Crypto.hash160(secret); // daf59884b4d1aec8c1b17102530909ee43c0151a
public static final int refundTimeout = 10; // blocks
public static final BigDecimal initialPayout = new BigDecimal("0.001").setScale(8);
public static final BigDecimal redeemAmount = new BigDecimal("80.4020").setScale(8);
public static final BigDecimal fundingAmount = new BigDecimal("123.456").setScale(8);
@Before
public void beforeTest() throws DataException {
Common.useDefaultSettings();
}
@Test
public void testCompile() {
String redeemAddress = Common.getTestAccount(null, "chloe").getAddress();
byte[] creationBytes = BTCACCT.buildQortalAT(secretHash, redeemAddress, refundTimeout, initialPayout, redeemAmount);
System.out.println("CIYAM AT creation bytes: " + HashCode.fromBytes(creationBytes).toString());
}
@Test
public void testDeploy() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
PrivateKeyAccount deployer = Common.getTestAccount(repository, "chloe");
PrivateKeyAccount recipient = Common.getTestAccount(repository, "dilbert");
BigDecimal deployersInitialBalance = deployer.getBalance(Asset.QORT);
BigDecimal recipientsInitialBalance = recipient.getBalance(Asset.QORT);
DeployAtTransaction deployAtTransaction = doDeploy(repository, deployer, recipient);
BigDecimal expectedBalance = deployersInitialBalance.subtract(fundingAmount).subtract(deployAtTransaction.getTransactionData().getFee());
BigDecimal actualBalance = deployer.getBalance(Asset.QORT);
Common.assertEqualBigDecimals("Deployer's post-deployment balance incorrect", expectedBalance, actualBalance);
expectedBalance = fundingAmount;
actualBalance = deployAtTransaction.getATAccount().getConfirmedBalance(Asset.QORT);
Common.assertEqualBigDecimals("AT's post-deployment balance incorrect", expectedBalance, actualBalance);
expectedBalance = recipientsInitialBalance;
actualBalance = recipient.getBalance(Asset.QORT);
Common.assertEqualBigDecimals("Recipient's post-deployment balance incorrect", expectedBalance, actualBalance);
// Test orphaning
BlockUtils.orphanLastBlock(repository);
expectedBalance = deployersInitialBalance;
actualBalance = deployer.getBalance(Asset.QORT);
Common.assertEqualBigDecimals("Deployer's post-orphan/pre-deployment balance incorrect", expectedBalance, actualBalance);
expectedBalance = BigDecimal.ZERO;
actualBalance = deployAtTransaction.getATAccount().getConfirmedBalance(Asset.QORT);
Common.assertEqualBigDecimals("AT's post-orphan/pre-deployment balance incorrect", expectedBalance, actualBalance);
expectedBalance = recipientsInitialBalance;
actualBalance = recipient.getBalance(Asset.QORT);
Common.assertEqualBigDecimals("Recipient's post-orphan/pre-deployment balance incorrect", expectedBalance, actualBalance);
}
}
@SuppressWarnings("unused")
@Test
public void testInitialPayment() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
PrivateKeyAccount deployer = Common.getTestAccount(repository, "chloe");
PrivateKeyAccount recipient = Common.getTestAccount(repository, "dilbert");
BigDecimal deployersInitialBalance = deployer.getBalance(Asset.QORT);
BigDecimal recipientsInitialBalance = recipient.getBalance(Asset.QORT);
DeployAtTransaction deployAtTransaction = doDeploy(repository, deployer, recipient);
// Initial payment should happen 1st block after deployment
BlockUtils.mintBlock(repository);
BigDecimal expectedBalance = recipientsInitialBalance.add(initialPayout);
BigDecimal actualBalance = recipient.getConfirmedBalance(Asset.QORT);
Common.assertEqualBigDecimals("Recipient's post-initial-payout balance incorrect", expectedBalance, actualBalance);
// Test orphaning
BlockUtils.orphanLastBlock(repository);
expectedBalance = recipientsInitialBalance;
actualBalance = recipient.getBalance(Asset.QORT);
Common.assertEqualBigDecimals("Recipient's pre-initial-payout balance incorrect", expectedBalance, actualBalance);
}
}
@SuppressWarnings("unused")
@Test
public void testAutomaticRefund() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
PrivateKeyAccount deployer = Common.getTestAccount(repository, "chloe");
PrivateKeyAccount recipient = Common.getTestAccount(repository, "dilbert");
BigDecimal deployersInitialBalance = deployer.getBalance(Asset.QORT);
BigDecimal recipientsInitialBalance = recipient.getBalance(Asset.QORT);
DeployAtTransaction deployAtTransaction = doDeploy(repository, deployer, recipient);
BigDecimal deployAtFee = deployAtTransaction.getTransactionData().getFee();
BigDecimal deployersPostDeploymentBalance = deployersInitialBalance.subtract(fundingAmount).subtract(deployAtFee);
checkAtRefund(repository, deployer, deployersInitialBalance, deployAtFee);
// Test orphaning
BlockUtils.orphanLastBlock(repository);
BigDecimal expectedBalance = deployersPostDeploymentBalance;
BigDecimal actualBalance = deployer.getBalance(Asset.QORT);
Common.assertEqualBigDecimals("Deployer's post-orphan/pre-refund balance incorrect", expectedBalance, actualBalance);
}
}
@SuppressWarnings("unused")
@Test
public void testCorrectSecretCorrectSender() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
PrivateKeyAccount deployer = Common.getTestAccount(repository, "chloe");
PrivateKeyAccount recipient = Common.getTestAccount(repository, "dilbert");
BigDecimal deployersInitialBalance = deployer.getBalance(Asset.QORT);
BigDecimal recipientsInitialBalance = recipient.getBalance(Asset.QORT);
DeployAtTransaction deployAtTransaction = doDeploy(repository, deployer, recipient);
Account at = deployAtTransaction.getATAccount();
String atAddress = at.getAddress();
// Send correct secret to AT
MessageTransaction messageTransaction = sendSecret(repository, recipient, secret, atAddress);
// AT should send funds in the next block
ATStateData preRedeemAtStateData = repository.getATRepository().getLatestATState(atAddress);
BlockUtils.mintBlock(repository);
BigDecimal expectedBalance = recipientsInitialBalance.add(initialPayout).subtract(messageTransaction.getTransactionData().getFee()).add(redeemAmount);
BigDecimal actualBalance = recipient.getConfirmedBalance(Asset.QORT);
Common.assertEqualBigDecimals("Recipent's post-redeem balance incorrect", expectedBalance, actualBalance);
// Orphan redeem
BlockUtils.orphanLastBlock(repository);
expectedBalance = recipientsInitialBalance.add(initialPayout).subtract(messageTransaction.getTransactionData().getFee());
actualBalance = recipient.getBalance(Asset.QORT);
Common.assertEqualBigDecimals("Recipent's post-orphan/pre-redeem balance incorrect", expectedBalance, actualBalance);
// Check AT state
ATStateData postOrphanAtStateData = repository.getATRepository().getLatestATState(atAddress);
assertTrue("AT states mismatch", Arrays.equals(preRedeemAtStateData.getStateData(), postOrphanAtStateData.getStateData()));
}
}
@SuppressWarnings("unused")
@Test
public void testCorrectSecretIncorrectSender() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
PrivateKeyAccount deployer = Common.getTestAccount(repository, "chloe");
PrivateKeyAccount recipient = Common.getTestAccount(repository, "dilbert");
PrivateKeyAccount bystander = Common.getTestAccount(repository, "bob");
BigDecimal deployersInitialBalance = deployer.getBalance(Asset.QORT);
BigDecimal recipientsInitialBalance = recipient.getBalance(Asset.QORT);
DeployAtTransaction deployAtTransaction = doDeploy(repository, deployer, recipient);
BigDecimal deployAtFee = deployAtTransaction.getTransactionData().getFee();
Account at = deployAtTransaction.getATAccount();
String atAddress = at.getAddress();
// Send correct secret to AT, but from wrong account
MessageTransaction messageTransaction = sendSecret(repository, bystander, secret, atAddress);
// AT should NOT send funds in the next block
ATStateData preRedeemAtStateData = repository.getATRepository().getLatestATState(atAddress);
BlockUtils.mintBlock(repository);
BigDecimal expectedBalance = recipientsInitialBalance.add(initialPayout);
BigDecimal actualBalance = recipient.getConfirmedBalance(Asset.QORT);
Common.assertEqualBigDecimals("Recipent's balance incorrect", expectedBalance, actualBalance);
checkAtRefund(repository, deployer, deployersInitialBalance, deployAtFee);
}
}
@SuppressWarnings("unused")
@Test
public void testIncorrectSecretCorrectSender() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
PrivateKeyAccount deployer = Common.getTestAccount(repository, "chloe");
PrivateKeyAccount recipient = Common.getTestAccount(repository, "dilbert");
BigDecimal deployersInitialBalance = deployer.getBalance(Asset.QORT);
BigDecimal recipientsInitialBalance = recipient.getBalance(Asset.QORT);
DeployAtTransaction deployAtTransaction = doDeploy(repository, deployer, recipient);
BigDecimal deployAtFee = deployAtTransaction.getTransactionData().getFee();
Account at = deployAtTransaction.getATAccount();
String atAddress = at.getAddress();
// Send correct secret to AT, but from wrong account
byte[] wrongSecret = Crypto.digest(secret);
MessageTransaction messageTransaction = sendSecret(repository, recipient, wrongSecret, atAddress);
// AT should NOT send funds in the next block
ATStateData preRedeemAtStateData = repository.getATRepository().getLatestATState(atAddress);
BlockUtils.mintBlock(repository);
BigDecimal expectedBalance = recipientsInitialBalance.add(initialPayout).subtract(messageTransaction.getTransactionData().getFee());
BigDecimal actualBalance = recipient.getConfirmedBalance(Asset.QORT);
Common.assertEqualBigDecimals("Recipent's balance incorrect", expectedBalance, actualBalance);
checkAtRefund(repository, deployer, deployersInitialBalance, deployAtFee);
}
}
@SuppressWarnings("unused")
@Test
public void testDescribeDeployed() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
PrivateKeyAccount deployer = Common.getTestAccount(repository, "chloe");
PrivateKeyAccount recipient = Common.getTestAccount(repository, "dilbert");
BigDecimal deployersInitialBalance = deployer.getBalance(Asset.QORT);
BigDecimal recipientsInitialBalance = recipient.getBalance(Asset.QORT);
DeployAtTransaction deployAtTransaction = doDeploy(repository, deployer, recipient);
List<ATData> executableAts = repository.getATRepository().getAllExecutableATs();
for (ATData atData : executableAts) {
String atAddress = atData.getATAddress();
byte[] codeBytes = atData.getCodeBytes();
byte[] codeHash = Crypto.digest(codeBytes);
System.out.println(String.format("%s: code length: %d byte%s, code hash: %s",
atAddress,
codeBytes.length,
(codeBytes.length != 1 ? "s": ""),
HashCode.fromBytes(codeHash)));
// Not one of ours?
if (!Arrays.equals(codeHash, BTCACCT.CODE_BYTES_HASH))
continue;
ATStateData atStateData = repository.getATRepository().getLatestATState(atAddress);
byte[] stateData = atStateData.getStateData();
QortalAtLoggerFactory loggerFactory = QortalAtLoggerFactory.getInstance();
byte[] dataBytes = MachineState.extractDataBytes(loggerFactory, stateData);
BTCACCT.AtConstants atConstants = BTCACCT.extractAtConstants(dataBytes);
long autoRefundTimestamp = atData.getCreation() + atConstants.refundMinutes * 60 * 1000L;
String autoRefundString = LocalDateTime.ofInstant(Instant.ofEpochMilli(autoRefundTimestamp), ZoneOffset.UTC).format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM));
System.out.println(String.format("%s:\n"
+ "\tcreator: %s,\n"
+ "\tHASH160 of secret: %s,\n"
+ "\trecipient: %s,\n"
+ "\tinitial payout: %s QORT,\n"
+ "\tredeem payout: %s QORT,\n"
+ "\tauto-refund at: %s (local time)",
atAddress,
Crypto.toAddress(atData.getCreatorPublicKey()),
HashCode.fromBytes(atConstants.secretHash).toString().substring(0, 40),
atConstants.recipient,
atConstants.initialPayout.toPlainString(),
atConstants.redeemPayout.toPlainString(),
autoRefundString));
}
}
}
private DeployAtTransaction doDeploy(Repository repository, PrivateKeyAccount deployer, Account recipient) throws DataException {
byte[] creationBytes = BTCACCT.buildQortalAT(secretHash, recipient.getAddress(), refundTimeout, initialPayout, redeemAmount);
long txTimestamp = System.currentTimeMillis();
byte[] lastReference = deployer.getLastReference();
if (lastReference == null) {
System.err.println(String.format("Qortal account %s has no last reference", deployer.getAddress()));
System.exit(2);
}
BigDecimal fee = BigDecimal.ZERO;
String name = "QORT-BTC cross-chain trade";
String description = String.format("Qortal-Bitcoin cross-chain trade between %s and %s", deployer.getAddress(), recipient.getAddress());
String atType = "ACCT";
String tags = "QORT-BTC ACCT";
BaseTransactionData baseTransactionData = new BaseTransactionData(txTimestamp, Group.NO_GROUP, lastReference, deployer.getPublicKey(), fee, null);
TransactionData deployAtTransactionData = new DeployAtTransactionData(baseTransactionData, name, description, atType, tags, creationBytes, fundingAmount, Asset.QORT);
DeployAtTransaction deployAtTransaction = new DeployAtTransaction(repository, deployAtTransactionData);
fee = deployAtTransaction.calcRecommendedFee();
deployAtTransactionData.setFee(fee);
TransactionUtils.signAndMint(repository, deployAtTransactionData, deployer);
return deployAtTransaction;
}
private MessageTransaction sendSecret(Repository repository, PrivateKeyAccount sender, byte[] data, String recipient) throws DataException {
long txTimestamp = System.currentTimeMillis();
byte[] lastReference = sender.getLastReference();
if (lastReference == null) {
System.err.println(String.format("Qortal account %s has no last reference", sender.getAddress()));
System.exit(2);
}
BigDecimal fee = BigDecimal.ZERO;
BigDecimal amount = BigDecimal.ZERO;
BaseTransactionData baseTransactionData = new BaseTransactionData(txTimestamp, Group.NO_GROUP, lastReference, sender.getPublicKey(), fee, null);
TransactionData messageTransactionData = new MessageTransactionData(baseTransactionData, 4, recipient, Asset.QORT, amount, data, false, false);
MessageTransaction messageTransaction = new MessageTransaction(repository, messageTransactionData);
fee = messageTransaction.calcRecommendedFee();
messageTransactionData.setFee(fee);
TransactionUtils.signAndMint(repository, messageTransactionData, sender);
return messageTransaction;
}
private void checkAtRefund(Repository repository, Account deployer, BigDecimal deployersInitialBalance, BigDecimal deployAtFee) throws DataException {
BigDecimal deployersPostDeploymentBalance = deployersInitialBalance.subtract(fundingAmount).subtract(deployAtFee);
// AT should automatically refund deployer after 'refundTimeout' blocks
for (int blockCount = 0; blockCount <= refundTimeout; ++blockCount)
BlockUtils.mintBlock(repository);
// We don't bother to exactly calculate QORT spent running AT for several blocks, but we do know the expected range
BigDecimal expectedMinimumBalance = deployersPostDeploymentBalance;
BigDecimal expectedMaximumBalance = deployersInitialBalance.subtract(deployAtFee).subtract(initialPayout);
BigDecimal actualBalance = deployer.getConfirmedBalance(Asset.QORT);
assertTrue(String.format("Deployer's balance %s should be above minimum %s", actualBalance.toPlainString(), expectedMinimumBalance.toPlainString()), actualBalance.compareTo(expectedMinimumBalance) > 0);
assertTrue(String.format("Deployer's balance %s should be below maximum %s", actualBalance.toPlainString(), expectedMaximumBalance.toPlainString()), actualBalance.compareTo(expectedMaximumBalance) < 0);
}
}

View File

@@ -34,7 +34,7 @@ public class BuildP2SH {
+ "mrTDPdM15cFWJC4g223BXX5snicfVJBx6M \\\n"
+ "\t0.00008642 \\\n"
+ "\tn2N5VKrzq39nmuefZwp3wBiF4icdXX2B6o \\\n"
+ "\td1b64100879ad93ceaa3c15929b6fe8550f54967 \\\n"
+ "\tdaf59884b4d1aec8c1b17102530909ee43c0151a \\\n"
+ "\t1585920000"));
System.exit(1);
}

View File

@@ -37,7 +37,7 @@ public class CheckP2SH {
+ "mrTDPdM15cFWJC4g223BXX5snicfVJBx6M \\\n"
+ "\t0.00008642 \\\n"
+ "\tn2N5VKrzq39nmuefZwp3wBiF4icdXX2B6o \\\n"
+ "\td1b64100879ad93ceaa3c15929b6fe8550f54967 \\\n"
+ "\tdaf59884b4d1aec8c1b17102530909ee43c0151a \\\n"
+ "\t1585920000"));
System.exit(1);
}

View File

@@ -32,34 +32,37 @@ import com.google.common.hash.HashCode;
public class DeployAT {
public static final BigDecimal atFundingExtra = new BigDecimal("0.2").setScale(8);
private static void usage(String error) {
if (error != null)
System.err.println(error);
System.err.println(String.format("usage: DeployAT <your Qortal PRIVATE key> <QORT amount> <redeem Qortal address> <HASH160-of-secret> <locktime> (<initial QORT payout>)"));
System.err.println(String.format("usage: DeployAT <your Qortal PRIVATE key> <QORT amount> <redeem Qortal address> <HASH160-of-secret> <locktime> [<initial QORT payout> [<AT funding amount>]]"));
System.err.println(String.format("example: DeployAT "
+ "AdTd9SUEYSdTW8mgK3Gu72K97bCHGdUwi2VvLNjUohot \\\n"
+ "\t3.1415 \\\n"
+ "\tQgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v \\\n"
+ "\td1b64100879ad93ceaa3c15929b6fe8550f54967 \\\n"
+ "\tdaf59884b4d1aec8c1b17102530909ee43c0151a \\\n"
+ "\t1585920000 \\\n"
+ "\t0.0001"));
System.exit(1);
}
public static void main(String[] args) {
if (args.length < 5 || args.length > 6)
if (args.length < 5 || args.length > 7)
usage(null);
Security.insertProviderAt(new BouncyCastleProvider(), 0);
Settings.fileInstance("settings-test.json");
byte[] refundPrivateKey = null;
BigDecimal qortAmount = null;
BigDecimal redeemAmount = null;
String redeemAddress = null;
byte[] secretHash = null;
int lockTime = 0;
BigDecimal initialPayout = BigDecimal.ZERO.setScale(8);
BigDecimal fundingAmount = null;
int argIndex = 0;
try {
@@ -67,8 +70,8 @@ public class DeployAT {
if (refundPrivateKey.length != 32)
usage("Refund private key must be 32 bytes");
qortAmount = new BigDecimal(args[argIndex++]);
if (qortAmount.signum() <= 0)
redeemAmount = new BigDecimal(args[argIndex++]).setScale(8);
if (redeemAmount.signum() <= 0)
usage("QORT amount must be positive");
redeemAddress = args[argIndex++];
@@ -83,6 +86,13 @@ public class DeployAT {
if (args.length > argIndex)
initialPayout = new BigDecimal(args[argIndex++]).setScale(8);
if (args.length > argIndex) {
fundingAmount = new BigDecimal(args[argIndex++]).setScale(8);
if (fundingAmount.compareTo(redeemAmount) <= 0)
usage("AT funding amount must be greater than QORT redeem amount");
}
} catch (IllegalArgumentException e) {
usage(String.format("Invalid argument %d: %s", argIndex, e.getMessage()));
}
@@ -100,7 +110,11 @@ public class DeployAT {
PrivateKeyAccount refundAccount = new PrivateKeyAccount(repository, refundPrivateKey);
System.out.println(String.format("Refund Qortal address: %s", refundAccount.getAddress()));
System.out.println(String.format("QORT amount (INCLUDING FEES): %s", qortAmount.toPlainString()));
System.out.println(String.format("QORT redeem amount: %s", redeemAmount.toPlainString()));
if (fundingAmount == null)
fundingAmount = redeemAmount.add(atFundingExtra);
System.out.println(String.format("AT funding amount: %s", fundingAmount.toPlainString()));
System.out.println(String.format("HASH160 of secret: %s", HashCode.fromBytes(secretHash)));
@@ -117,7 +131,7 @@ public class DeployAT {
final int BLOCK_TIME = 60; // seconds
final int refundTimeout = (lockTime - (int) (System.currentTimeMillis() / 1000L)) / BLOCK_TIME;
byte[] creationBytes = BTCACCT.buildQortalAT(secretHash, redeemAddress, refundTimeout, initialPayout);
byte[] creationBytes = BTCACCT.buildQortalAT(secretHash, redeemAddress, refundTimeout, initialPayout, fundingAmount);
System.out.println("CIYAM AT creation bytes: " + HashCode.fromBytes(creationBytes).toString());
long txTimestamp = System.currentTimeMillis();
@@ -135,7 +149,7 @@ public class DeployAT {
String tags = "QORT-BTC ACCT";
BaseTransactionData baseTransactionData = new BaseTransactionData(txTimestamp, Group.NO_GROUP, lastReference, refundAccount.getPublicKey(), fee, null);
TransactionData deployAtTransactionData = new DeployAtTransactionData(baseTransactionData, name, description, atType, tags, creationBytes, qortAmount, Asset.QORT);
TransactionData deployAtTransactionData = new DeployAtTransactionData(baseTransactionData, name, description, atType, tags, creationBytes, redeemAmount, Asset.QORT);
Transaction deployAtTransaction = new DeployAtTransaction(repository, deployAtTransactionData);

View File

@@ -44,7 +44,7 @@ public class Redeem {
+ "2NEZboTLhBDPPQciR7sExBhy3TsDi7wV3Cv \\\n"
+ "\tmrTDPdM15cFWJC4g223BXX5snicfVJBx6M \\\n"
+ "\tec199a4abc9d3bf024349e397535dfee9d287e174aeabae94237eb03a0118c03 \\\n"
+ "\t736563726574 \\\n"
+ "\t5468697320737472696e672069732065786163746c7920333220627974657321 \\\n"
+ "\t1585920000"));
System.exit(1);
}

View File

@@ -44,7 +44,7 @@ public class Refund {
+ "2NEZboTLhBDPPQciR7sExBhy3TsDi7wV3Cv \\\n"
+ "\tef027fb5828c5e201eaf6de4cd3b0b340d16a191ef848cd691f35ef8f727358c9c01b576fb7e \\\n"
+ "\tn2N5VKrzq39nmuefZwp3wBiF4icdXX2B6o \\\n"
+ "\td1b64100879ad93ceaa3c15929b6fe8550f54967 \\\n"
+ "\tdaf59884b4d1aec8c1b17102530909ee43c0151a \\\n"
+ "\t1585920000"));
System.exit(1);
}

View File

@@ -17,9 +17,9 @@ public class BlockUtils {
private static final Logger LOGGER = LogManager.getLogger(BlockUtils.class);
/** Mints a new block using "alice-reward-share" test account. */
public static void mintBlock(Repository repository) throws DataException {
public static Block mintBlock(Repository repository) throws DataException {
PrivateKeyAccount mintingAccount = Common.getTestAccount(repository, "alice-reward-share");
BlockMinter.mintTestingBlock(repository, mintingAccount);
return BlockMinter.mintTestingBlock(repository, mintingAccount);
}
public static BigDecimal getNextBlockReward(Repository repository) throws DataException {

View File

@@ -29,6 +29,12 @@
"blockTimingsByHeight": [
{ "height": 1, "target": 60000, "deviation": 30000, "power": 0.2 }
],
"ciyamAtSettings": {
"feePerStep": "0.0001",
"maxStepsPerRound": 500,
"stepsPerFunctionCall": 10,
"minutesPerBlock": 1
},
"featureTriggers": {
"messageHeight": 0,
"atHeight": 0,

View File

@@ -29,6 +29,12 @@
"blockTimingsByHeight": [
{ "height": 1, "target": 60000, "deviation": 30000, "power": 0.2 }
],
"ciyamAtSettings": {
"feePerStep": "0.0001",
"maxStepsPerRound": 500,
"stepsPerFunctionCall": 10,
"minutesPerBlock": 1
},
"featureTriggers": {
"messageHeight": 0,
"atHeight": 0,

View File

@@ -29,6 +29,12 @@
"blockTimingsByHeight": [
{ "height": 1, "target": 60000, "deviation": 30000, "power": 0.2 }
],
"ciyamAtSettings": {
"feePerStep": "0.0001",
"maxStepsPerRound": 500,
"stepsPerFunctionCall": 10,
"minutesPerBlock": 1
},
"featureTriggers": {
"messageHeight": 0,
"atHeight": 0,

View File

@@ -29,6 +29,12 @@
"blockTimingsByHeight": [
{ "height": 1, "target": 60000, "deviation": 30000, "power": 0.2 }
],
"ciyamAtSettings": {
"feePerStep": "0.0001",
"maxStepsPerRound": 500,
"stepsPerFunctionCall": 10,
"minutesPerBlock": 1
},
"featureTriggers": {
"messageHeight": 0,
"atHeight": 0,

View File

@@ -29,6 +29,12 @@
"blockTimingsByHeight": [
{ "height": 1, "target": 60000, "deviation": 30000, "power": 0.2 }
],
"ciyamAtSettings": {
"feePerStep": "0.0001",
"maxStepsPerRound": 500,
"stepsPerFunctionCall": 10,
"minutesPerBlock": 1
},
"featureTriggers": {
"messageHeight": 0,
"atHeight": 0,

View File

@@ -29,6 +29,12 @@
"blockTimingsByHeight": [
{ "height": 1, "target": 60000, "deviation": 30000, "power": 0.2 }
],
"ciyamAtSettings": {
"feePerStep": "0.0001",
"maxStepsPerRound": 500,
"stepsPerFunctionCall": 10,
"minutesPerBlock": 1
},
"featureTriggers": {
"messageHeight": 0,
"atHeight": 0,

View File

@@ -2,5 +2,6 @@
"restrictedApi": false,
"blockchainConfig": "src/test/resources/test-chain-old-asset.json",
"wipeUnconfirmedOnStart": false,
"testNtpOffset": 0,
"minPeers": 0
}

View File

@@ -2,5 +2,6 @@
"restrictedApi": false,
"blockchainConfig": "src/test/resources/test-chain-v1.json",
"wipeUnconfirmedOnStart": false,
"testNtpOffset": 0,
"minPeers": 0
}

View File

@@ -2,5 +2,6 @@
"restrictedApi": false,
"blockchainConfig": "src/test/resources/test-chain-v2-founder-rewards.json",
"wipeUnconfirmedOnStart": false,
"testNtpOffset": 0,
"minPeers": 0
}

View File

@@ -2,5 +2,6 @@
"restrictedApi": false,
"blockchainConfig": "src/test/resources/test-chain-v2-minting.json",
"wipeUnconfirmedOnStart": false,
"testNtpOffset": 0,
"minPeers": 0
}

View File

@@ -2,5 +2,6 @@
"restrictedApi": false,
"blockchainConfig": "src/test/resources/test-chain-v2-qora-holder.json",
"wipeUnconfirmedOnStart": false,
"testNtpOffset": 0,
"minPeers": 0
}

View File

@@ -2,5 +2,6 @@
"restrictedApi": false,
"blockchainConfig": "src/test/resources/test-chain-v2.json",
"wipeUnconfirmedOnStart": false,
"testNtpOffset": 0,
"minPeers": 0
}