mirror of
https://github.com/Qortal/qortal.git
synced 2025-07-23 04:36:50 +00:00
WIP: split P2SH from BTCACCT, add more fields to TradeBotData, remove initial QORT payout
This commit is contained in:
@@ -47,7 +47,6 @@ public class AtTests extends Common {
|
||||
public static final byte[] bitcoinPublicKeyHash = new byte[20]; // not used in tests
|
||||
public static final byte[] secretHash = Crypto.hash160(secret); // daf59884b4d1aec8c1b17102530909ee43c0151a
|
||||
public static final int refundTimeout = 10; // blocks
|
||||
public static final long initialPayout = 100000L;
|
||||
public static final long redeemAmount = 80_40200000L;
|
||||
public static final long fundingAmount = 123_45600000L;
|
||||
public static final long bitcoinAmount = 864200L;
|
||||
@@ -61,7 +60,7 @@ public class AtTests extends Common {
|
||||
public void testCompile() {
|
||||
Account deployer = Common.getTestAccount(null, "chloe");
|
||||
|
||||
byte[] creationBytes = BTCACCT.buildQortalAT(deployer.getAddress(), bitcoinPublicKeyHash, secretHash, refundTimeout, initialPayout, redeemAmount, bitcoinAmount);
|
||||
byte[] creationBytes = BTCACCT.buildQortalAT(deployer.getAddress(), bitcoinPublicKeyHash, secretHash, refundTimeout, redeemAmount, bitcoinAmount);
|
||||
System.out.println("CIYAM AT creation bytes: " + HashCode.fromBytes(creationBytes).toString());
|
||||
}
|
||||
|
||||
@@ -156,44 +155,6 @@ public class AtTests extends Common {
|
||||
}
|
||||
}
|
||||
|
||||
@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");
|
||||
|
||||
long deployersInitialBalance = deployer.getConfirmedBalance(Asset.QORT);
|
||||
long recipientsInitialBalance = recipient.getConfirmedBalance(Asset.QORT);
|
||||
|
||||
DeployAtTransaction deployAtTransaction = doDeploy(repository, deployer);
|
||||
Account at = deployAtTransaction.getATAccount();
|
||||
String atAddress = at.getAddress();
|
||||
|
||||
// Send recipient's address to AT
|
||||
byte[] recipientAddressBytes = Bytes.ensureCapacity(Base58.decode(recipient.getAddress()), 32, 0);
|
||||
MessageTransaction messageTransaction = sendMessage(repository, deployer, recipientAddressBytes, atAddress);
|
||||
|
||||
// Initial payment should happen 1st block after receiving recipient address
|
||||
BlockUtils.mintBlock(repository);
|
||||
|
||||
long expectedBalance = recipientsInitialBalance + initialPayout;
|
||||
long actualBalance = recipient.getConfirmedBalance(Asset.QORT);
|
||||
|
||||
assertEquals("Recipient's post-initial-payout balance incorrect", expectedBalance, actualBalance);
|
||||
|
||||
describeAt(repository, atAddress);
|
||||
|
||||
// Test orphaning
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
expectedBalance = recipientsInitialBalance;
|
||||
actualBalance = recipient.getConfirmedBalance(Asset.QORT);
|
||||
|
||||
assertEquals("Recipient's pre-initial-payout balance incorrect", expectedBalance, actualBalance);
|
||||
}
|
||||
}
|
||||
|
||||
// TEST SENDING RECIPIENT ADDRESS BUT NOT FROM AT CREATOR (SHOULD BE IGNORED)
|
||||
@SuppressWarnings("unused")
|
||||
@Test
|
||||
@@ -294,7 +255,7 @@ public class AtTests extends Common {
|
||||
ATStateData preRedeemAtStateData = repository.getATRepository().getLatestATState(atAddress);
|
||||
BlockUtils.mintBlock(repository);
|
||||
|
||||
long expectedBalance = recipientsInitialBalance + initialPayout - messageTransaction.getTransactionData().getFee() + redeemAmount;
|
||||
long expectedBalance = recipientsInitialBalance - messageTransaction.getTransactionData().getFee() + redeemAmount;
|
||||
long actualBalance = recipient.getConfirmedBalance(Asset.QORT);
|
||||
|
||||
assertEquals("Recipent's post-redeem balance incorrect", expectedBalance, actualBalance);
|
||||
@@ -304,7 +265,7 @@ public class AtTests extends Common {
|
||||
// Orphan redeem
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
expectedBalance = recipientsInitialBalance + initialPayout - messageTransaction.getTransactionData().getFee();
|
||||
expectedBalance = recipientsInitialBalance - messageTransaction.getTransactionData().getFee();
|
||||
actualBalance = recipient.getConfirmedBalance(Asset.QORT);
|
||||
|
||||
assertEquals("Recipent's post-orphan/pre-redeem balance incorrect", expectedBalance, actualBalance);
|
||||
@@ -347,7 +308,7 @@ public class AtTests extends Common {
|
||||
ATStateData preRedeemAtStateData = repository.getATRepository().getLatestATState(atAddress);
|
||||
BlockUtils.mintBlock(repository);
|
||||
|
||||
long expectedBalance = recipientsInitialBalance + initialPayout;
|
||||
long expectedBalance = recipientsInitialBalance;
|
||||
long actualBalance = recipient.getConfirmedBalance(Asset.QORT);
|
||||
|
||||
assertEquals("Recipent's balance incorrect", expectedBalance, actualBalance);
|
||||
@@ -389,7 +350,7 @@ public class AtTests extends Common {
|
||||
ATStateData preRedeemAtStateData = repository.getATRepository().getLatestATState(atAddress);
|
||||
BlockUtils.mintBlock(repository);
|
||||
|
||||
long expectedBalance = recipientsInitialBalance + initialPayout - messageTransaction.getTransactionData().getFee();
|
||||
long expectedBalance = recipientsInitialBalance - messageTransaction.getTransactionData().getFee();
|
||||
long actualBalance = recipient.getConfirmedBalance(Asset.QORT);
|
||||
|
||||
assertEquals("Recipent's balance incorrect", expectedBalance, actualBalance);
|
||||
@@ -435,7 +396,7 @@ public class AtTests extends Common {
|
||||
}
|
||||
|
||||
private DeployAtTransaction doDeploy(Repository repository, PrivateKeyAccount deployer) throws DataException {
|
||||
byte[] creationBytes = BTCACCT.buildQortalAT(deployer.getAddress(), bitcoinPublicKeyHash, secretHash, refundTimeout, initialPayout, redeemAmount, bitcoinAmount);
|
||||
byte[] creationBytes = BTCACCT.buildQortalAT(deployer.getAddress(), bitcoinPublicKeyHash, secretHash, refundTimeout, redeemAmount, bitcoinAmount);
|
||||
|
||||
long txTimestamp = System.currentTimeMillis();
|
||||
byte[] lastReference = deployer.getLastReference();
|
||||
@@ -501,7 +462,7 @@ public class AtTests extends Common {
|
||||
|
||||
// We don't bother to exactly calculate QORT spent running AT for several blocks, but we do know the expected range
|
||||
long expectedMinimumBalance = deployersPostDeploymentBalance;
|
||||
long expectedMaximumBalance = deployersInitialBalance - deployAtFee - initialPayout;
|
||||
long expectedMaximumBalance = deployersInitialBalance - deployAtFee;
|
||||
|
||||
long actualBalance = deployer.getConfirmedBalance(Asset.QORT);
|
||||
|
||||
@@ -521,7 +482,6 @@ public class AtTests extends Common {
|
||||
+ "\tcreation timestamp: %s,\n"
|
||||
+ "\tcurrent balance: %s QORT,\n"
|
||||
+ "\tHASH160 of secret: %s,\n"
|
||||
+ "\tinitial payout: %s QORT,\n"
|
||||
+ "\tredeem payout: %s QORT,\n"
|
||||
+ "\texpected bitcoin: %s BTC,\n"
|
||||
+ "\ttrade timeout: %d minutes (from trade start),\n"
|
||||
@@ -531,10 +491,9 @@ public class AtTests extends Common {
|
||||
epochMilliFormatter.apply(tradeData.creationTimestamp),
|
||||
Amounts.prettyAmount(tradeData.qortBalance),
|
||||
HashCode.fromBytes(tradeData.secretHash).toString().substring(0, 40),
|
||||
Amounts.prettyAmount(tradeData.initialPayout),
|
||||
Amounts.prettyAmount(tradeData.redeemPayout),
|
||||
Amounts.prettyAmount(tradeData.qortAmount),
|
||||
Amounts.prettyAmount(tradeData.expectedBitcoin),
|
||||
tradeData.tradeRefundTimeout,
|
||||
tradeData.tradeTimeout,
|
||||
currentBlockHeight));
|
||||
|
||||
// Are we in 'offer' or 'trade' stage?
|
||||
|
@@ -10,7 +10,7 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.qortal.crosschain.BTC;
|
||||
import org.qortal.crosschain.BTCACCT;
|
||||
import org.qortal.crosschain.BTCP2SH;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.test.common.Common;
|
||||
|
||||
@@ -56,7 +56,7 @@ public class BtcTests extends Common {
|
||||
List<byte[]> rawTransactions = BTC.getInstance().getAddressTransactions(p2shAddress);
|
||||
|
||||
byte[] expectedSecret = AtTests.secret;
|
||||
byte[] secret = BTCACCT.findP2shSecret(p2shAddress, rawTransactions);
|
||||
byte[] secret = BTCP2SH.findP2shSecret(p2shAddress, rawTransactions);
|
||||
|
||||
assertNotNull(secret);
|
||||
assertTrue("secret incorrect", Arrays.equals(expectedSecret, secret));
|
||||
|
@@ -13,7 +13,7 @@ import org.bitcoinj.script.Script.ScriptType;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.qortal.controller.Controller;
|
||||
import org.qortal.crosschain.BTC;
|
||||
import org.qortal.crosschain.BTCACCT;
|
||||
import org.qortal.crosschain.BTCP2SH;
|
||||
import org.qortal.crypto.Crypto;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
@@ -103,7 +103,7 @@ public class BuildP2SH {
|
||||
System.out.println(String.format("Redeem script lockTime: %s (%d)", LocalDateTime.ofInstant(Instant.ofEpochSecond(lockTime), ZoneOffset.UTC), lockTime));
|
||||
System.out.println(String.format("Hash of secret: %s", HashCode.fromBytes(secretHash)));
|
||||
|
||||
byte[] redeemScriptBytes = BTCACCT.buildScript(refundBitcoinAddress.getHash(), lockTime, redeemBitcoinAddress.getHash(), secretHash);
|
||||
byte[] redeemScriptBytes = BTCP2SH.buildScript(refundBitcoinAddress.getHash(), lockTime, redeemBitcoinAddress.getHash(), secretHash);
|
||||
System.out.println(String.format("Redeem script: %s", HashCode.fromBytes(redeemScriptBytes)));
|
||||
|
||||
byte[] redeemScriptHash = Crypto.hash160(redeemScriptBytes);
|
||||
|
@@ -15,7 +15,7 @@ import org.bitcoinj.script.Script.ScriptType;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.qortal.controller.Controller;
|
||||
import org.qortal.crosschain.BTC;
|
||||
import org.qortal.crosschain.BTCACCT;
|
||||
import org.qortal.crosschain.BTCP2SH;
|
||||
import org.qortal.crypto.Crypto;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
@@ -113,7 +113,7 @@ public class CheckP2SH {
|
||||
|
||||
System.out.println(String.format("P2SH address: %s", p2shAddress));
|
||||
|
||||
byte[] redeemScriptBytes = BTCACCT.buildScript(refundBitcoinAddress.getHash(), lockTime, redeemBitcoinAddress.getHash(), secretHash);
|
||||
byte[] redeemScriptBytes = BTCP2SH.buildScript(refundBitcoinAddress.getHash(), lockTime, redeemBitcoinAddress.getHash(), secretHash);
|
||||
System.out.println(String.format("Redeem script: %s", HashCode.fromBytes(redeemScriptBytes)));
|
||||
|
||||
byte[] redeemScriptHash = Crypto.hash160(redeemScriptBytes);
|
||||
|
@@ -34,21 +34,20 @@ public class DeployAT {
|
||||
if (error != null)
|
||||
System.err.println(error);
|
||||
|
||||
System.err.println(String.format("usage: DeployAT <your Qortal PRIVATE key> <QORT amount> <BTC amount> <your Bitcoin PKH> <HASH160-of-secret> <initial QORT payout> <AT funding amount> <AT trade timeout>"));
|
||||
System.err.println(String.format("usage: DeployAT <your Qortal PRIVATE key> <QORT amount> <BTC amount> <your Bitcoin PKH> <HASH160-of-secret> <AT funding amount> <AT trade timeout>"));
|
||||
System.err.println(String.format("example: DeployAT "
|
||||
+ "AdTd9SUEYSdTW8mgK3Gu72K97bCHGdUwi2VvLNjUohot \\\n"
|
||||
+ "\t80.4020 \\\n"
|
||||
+ "\t0.00864200 \\\n"
|
||||
+ "\t750b06757a2448b8a4abebaa6e4662833fd5ddbb \\\n"
|
||||
+ "\tdaf59884b4d1aec8c1b17102530909ee43c0151a \\\n"
|
||||
+ "\t0.0001 \\\n"
|
||||
+ "\t123.456 \\\n"
|
||||
+ "\t10"));
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
if (args.length != 8)
|
||||
if (args.length != 7)
|
||||
usage(null);
|
||||
|
||||
Security.insertProviderAt(new BouncyCastleProvider(), 0);
|
||||
@@ -59,7 +58,6 @@ public class DeployAT {
|
||||
long expectedBitcoin = 0;
|
||||
byte[] bitcoinPublicKeyHash = null;
|
||||
byte[] secretHash = null;
|
||||
long initialPayout = 0;
|
||||
long fundingAmount = 0;
|
||||
int tradeTimeout = 0;
|
||||
|
||||
@@ -85,10 +83,6 @@ public class DeployAT {
|
||||
if (secretHash.length != 20)
|
||||
usage("Hash of secret must be 20 bytes");
|
||||
|
||||
initialPayout = Long.parseLong(args[argIndex++]);
|
||||
if (initialPayout < 0)
|
||||
usage("Initial QORT payout must be positive");
|
||||
|
||||
fundingAmount = Long.parseLong(args[argIndex++]);
|
||||
if (fundingAmount <= redeemAmount)
|
||||
usage("AT funding amount must be greater than QORT redeem amount");
|
||||
@@ -120,7 +114,7 @@ public class DeployAT {
|
||||
System.out.println(String.format("HASH160 of secret: %s", HashCode.fromBytes(secretHash)));
|
||||
|
||||
// Deploy AT
|
||||
byte[] creationBytes = BTCACCT.buildQortalAT(refundAccount.getAddress(), bitcoinPublicKeyHash, secretHash, tradeTimeout, initialPayout, redeemAmount, expectedBitcoin);
|
||||
byte[] creationBytes = BTCACCT.buildQortalAT(refundAccount.getAddress(), bitcoinPublicKeyHash, secretHash, tradeTimeout, redeemAmount, expectedBitcoin);
|
||||
System.out.println("CIYAM AT creation bytes: " + HashCode.fromBytes(creationBytes).toString());
|
||||
|
||||
long txTimestamp = System.currentTimeMillis();
|
||||
|
@@ -18,7 +18,7 @@ import org.bitcoinj.script.Script.ScriptType;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.qortal.controller.Controller;
|
||||
import org.qortal.crosschain.BTC;
|
||||
import org.qortal.crosschain.BTCACCT;
|
||||
import org.qortal.crosschain.BTCP2SH;
|
||||
import org.qortal.crypto.Crypto;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
@@ -121,7 +121,7 @@ public class Redeem {
|
||||
|
||||
System.out.println(String.format("P2SH address: %s", p2shAddress));
|
||||
|
||||
byte[] redeemScriptBytes = BTCACCT.buildScript(refundBitcoinAddress.getHash(), lockTime, redeemAddress.getHash(), secretHash);
|
||||
byte[] redeemScriptBytes = BTCP2SH.buildScript(refundBitcoinAddress.getHash(), lockTime, redeemAddress.getHash(), secretHash);
|
||||
System.out.println(String.format("Redeem script: %s", HashCode.fromBytes(redeemScriptBytes)));
|
||||
|
||||
byte[] redeemScriptHash = Crypto.hash160(redeemScriptBytes);
|
||||
@@ -182,7 +182,7 @@ public class Redeem {
|
||||
Coin redeemAmount = Coin.valueOf(p2shBalance).subtract(bitcoinFee);
|
||||
System.out.println(String.format("Spending %s of output, with %s as mining fee", BTC.format(redeemAmount), BTC.format(bitcoinFee)));
|
||||
|
||||
Transaction redeemTransaction = BTCACCT.buildRedeemTransaction(redeemAmount, redeemKey, fundingOutputs, redeemScriptBytes, secret);
|
||||
Transaction redeemTransaction = BTCP2SH.buildRedeemTransaction(redeemAmount, redeemKey, fundingOutputs, redeemScriptBytes, secret);
|
||||
|
||||
byte[] redeemBytes = redeemTransaction.bitcoinSerialize();
|
||||
|
||||
|
@@ -18,7 +18,7 @@ import org.bitcoinj.script.Script.ScriptType;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.qortal.controller.Controller;
|
||||
import org.qortal.crosschain.BTC;
|
||||
import org.qortal.crosschain.BTCACCT;
|
||||
import org.qortal.crosschain.BTCP2SH;
|
||||
import org.qortal.crypto.Crypto;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
@@ -120,7 +120,7 @@ public class Refund {
|
||||
Address refundAddress = Address.fromKey(params, refundKey, ScriptType.P2PKH);
|
||||
System.out.println(String.format("Refund recipient (PKH): %s (%s)", refundAddress, HashCode.fromBytes(refundAddress.getHash())));
|
||||
|
||||
byte[] redeemScriptBytes = BTCACCT.buildScript(refundAddress.getHash(), lockTime, redeemBitcoinAddress.getHash(), secretHash);
|
||||
byte[] redeemScriptBytes = BTCP2SH.buildScript(refundAddress.getHash(), lockTime, redeemBitcoinAddress.getHash(), secretHash);
|
||||
System.out.println(String.format("Redeem script: %s", HashCode.fromBytes(redeemScriptBytes)));
|
||||
|
||||
byte[] redeemScriptHash = Crypto.hash160(redeemScriptBytes);
|
||||
@@ -186,7 +186,7 @@ public class Refund {
|
||||
Coin refundAmount = Coin.valueOf(p2shBalance).subtract(bitcoinFee);
|
||||
System.out.println(String.format("Spending %s of output, with %s as mining fee", BTC.format(refundAmount), BTC.format(bitcoinFee)));
|
||||
|
||||
Transaction redeemTransaction = BTCACCT.buildRefundTransaction(refundAmount, refundKey, fundingOutputs, redeemScriptBytes, lockTime);
|
||||
Transaction redeemTransaction = BTCP2SH.buildRefundTransaction(refundAmount, refundKey, fundingOutputs, redeemScriptBytes, lockTime);
|
||||
|
||||
byte[] redeemBytes = redeemTransaction.bitcoinSerialize();
|
||||
|
||||
|
Reference in New Issue
Block a user