Add creatorAddress, qortAmount and (last updated) timestamp to trade-bot entries

This commit is contained in:
catbref 2020-08-05 16:00:40 +01:00
parent cac68ccc14
commit c89de7adfb
5 changed files with 129 additions and 36 deletions

View File

@ -1011,6 +1011,9 @@ public class CrossChainResource {
if (tradeBotCreateRequest.tradeTimeout < 60)
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA);
if (tradeBotCreateRequest.bitcoinAmount <= 0 || tradeBotCreateRequest.qortAmount <= 0 || tradeBotCreateRequest.fundingQortAmount <= 0)
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA);
try (final Repository repository = RepositoryManager.getRepository()) {
// Do some simple checking first
Account creator = new PublicKeyAccount(repository, tradeBotCreateRequest.creatorPublicKey);

View File

@ -163,7 +163,7 @@ public class TradeBot {
String atAddress = deployAtTransactionData.getAtAddress();
TradeBotData tradeBotData = new TradeBotData(tradePrivateKey, TradeBotData.State.BOB_WAITING_FOR_AT_CONFIRM,
atAddress,
creator.getAddress(), atAddress, timestamp, tradeBotCreateRequest.qortAmount,
tradeNativePublicKey, tradeNativePublicKeyHash, tradeNativeAddress,
secretB, hashOfSecretB,
tradeForeignPublicKey, tradeForeignPublicKeyHash,
@ -237,7 +237,7 @@ public class TradeBot {
int lockTimeA = crossChainTradeData.tradeTimeout * 60 + (int) (NTP.getTime() / 1000L);
TradeBotData tradeBotData = new TradeBotData(tradePrivateKey, TradeBotData.State.ALICE_WAITING_FOR_P2SH_A,
crossChainTradeData.qortalAtAddress,
receivingAddress, crossChainTradeData.qortalAtAddress, NTP.getTime(), crossChainTradeData.qortAmount,
tradeNativePublicKey, tradeNativePublicKeyHash, tradeNativeAddress,
secretA, hashOfSecretA,
tradeForeignPublicKey, tradeForeignPublicKeyHash,
@ -380,6 +380,7 @@ public class TradeBot {
return;
tradeBotData.setState(TradeBotData.State.BOB_WAITING_FOR_MESSAGE);
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();
@ -418,6 +419,7 @@ public class TradeBot {
if (atData.getIsFinished()) {
// No point sending MESSAGE - might as well wait for refund
tradeBotData.setState(TradeBotData.State.ALICE_REFUNDING_A);
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();
@ -456,6 +458,7 @@ public class TradeBot {
}
tradeBotData.setState(TradeBotData.State.ALICE_WAITING_FOR_AT_LOCK);
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();
@ -493,6 +496,7 @@ public class TradeBot {
// If AT has finished then Bob likely cancelled his trade offer
if (atData.getIsFinished()) {
tradeBotData.setState(TradeBotData.State.BOB_REFUNDED);
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();
@ -563,6 +567,7 @@ public class TradeBot {
}
tradeBotData.setState(TradeBotData.State.BOB_WAITING_FOR_P2SH_B);
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();
@ -577,6 +582,7 @@ public class TradeBot {
// Don't resave if we don't need to
if (tradeBotData.getLastTransactionSignature() != originalLastTransactionSignature) {
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();
notifyStateChange(tradeBotData);
@ -608,6 +614,7 @@ public class TradeBot {
// Refund P2SH-A if AT finished (i.e. Bob cancelled trade) or we've passed lockTime-A
if (atData.getIsFinished() || NTP.getTime() >= tradeBotData.getLockTimeA() * 1000L) {
tradeBotData.setState(TradeBotData.State.ALICE_REFUNDING_A);
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();
@ -643,6 +650,7 @@ public class TradeBot {
// There's no P2SH-B at this point, so jump straight to refunding P2SH-A
tradeBotData.setState(TradeBotData.State.ALICE_REFUNDING_A);
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();
@ -700,6 +708,7 @@ public class TradeBot {
// P2SH-B funded, now we wait for Bob to redeem it
tradeBotData.setState(TradeBotData.State.ALICE_WATCH_P2SH_B);
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();
@ -730,6 +739,7 @@ public class TradeBot {
// If we've passed AT refund timestamp then AT will have finished after auto-refunding
if (atData.getIsFinished()) {
tradeBotData.setState(TradeBotData.State.BOB_REFUNDED);
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();
@ -771,6 +781,7 @@ public class TradeBot {
// P2SH-B redeemed, now we wait for Alice to use secret-A to redeem AT
tradeBotData.setState(TradeBotData.State.BOB_WAITING_FOR_AT_REDEEM);
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();
@ -808,6 +819,7 @@ public class TradeBot {
// Refund P2SH-B if we've passed lockTime-B
if (NTP.getTime() >= crossChainTradeData.lockTimeB * 1000L) {
tradeBotData.setState(TradeBotData.State.ALICE_REFUNDING_B);
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();
@ -849,6 +861,7 @@ public class TradeBot {
}
tradeBotData.setState(TradeBotData.State.ALICE_DONE);
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();
@ -896,6 +909,7 @@ public class TradeBot {
// We check variable in AT that is set when trade successfully completes
if (crossChainTradeData.mode != BTCACCT.Mode.REDEEMED) {
tradeBotData.setState(TradeBotData.State.BOB_REFUNDED);
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();
@ -930,6 +944,7 @@ public class TradeBot {
}
tradeBotData.setState(TradeBotData.State.BOB_DONE);
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();
@ -973,7 +988,7 @@ public class TradeBot {
}
tradeBotData.setState(TradeBotData.State.ALICE_REFUNDING_A);
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();
@ -1018,7 +1033,7 @@ public class TradeBot {
}
tradeBotData.setState(TradeBotData.State.ALICE_REFUNDED);
tradeBotData.setTimestamp(NTP.getTime());
repository.getCrossChainRepository().save(tradeBotData);
repository.saveChanges();

View File

@ -35,8 +35,14 @@ public class TradeBotData {
}
private State tradeState;
private String creatorAddress;
private String atAddress;
private long timestamp;
@XmlJavaTypeAdapter(value = org.qortal.api.AmountTypeAdapter.class)
private long qortAmount;
private byte[] tradeNativePublicKey;
private byte[] tradeNativePublicKeyHash;
String tradeNativeAddress;
@ -66,14 +72,18 @@ public class TradeBotData {
/* JAXB */
}
public TradeBotData(byte[] tradePrivateKey, State tradeState, String atAddress,
public TradeBotData(byte[] tradePrivateKey, State tradeState, String creatorAddress, String atAddress,
long timestamp, long qortAmount,
byte[] tradeNativePublicKey, byte[] tradeNativePublicKeyHash, String tradeNativeAddress,
byte[] secret, byte[] hashOfSecret,
byte[] tradeForeignPublicKey, byte[] tradeForeignPublicKeyHash,
long bitcoinAmount, String xprv58, byte[] lastTransactionSignature, Integer lockTimeA, byte[] receivingAccountInfo) {
this.tradePrivateKey = tradePrivateKey;
this.tradeState = tradeState;
this.creatorAddress = creatorAddress;
this.atAddress = atAddress;
this.timestamp = timestamp;
this.qortAmount = qortAmount;
this.tradeNativePublicKey = tradeNativePublicKey;
this.tradeNativePublicKeyHash = tradeNativePublicKeyHash;
this.tradeNativeAddress = tradeNativeAddress;
@ -100,6 +110,10 @@ public class TradeBotData {
this.tradeState = state;
}
public String getCreatorAddress() {
return this.creatorAddress;
}
public String getAtAddress() {
return this.atAddress;
}
@ -108,6 +122,18 @@ public class TradeBotData {
this.atAddress = atAddress;
}
public long getTimestamp() {
return this.timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public long getQortAmount() {
return this.qortAmount;
}
public byte[] getTradeNativePublicKey() {
return this.tradeNativePublicKey;
}

View File

@ -19,7 +19,8 @@ public class HSQLDBCrossChainRepository implements CrossChainRepository {
@Override
public TradeBotData getTradeBotData(byte[] tradePrivateKey) throws DataException {
String sql = "SELECT trade_state, at_address, "
String sql = "SELECT trade_state, creator_address, at_address, "
+ "updated_when, qort_amount, "
+ "trade_native_public_key, trade_native_public_key_hash, "
+ "trade_native_address, secret, hash_of_secret, "
+ "trade_foreign_public_key, trade_foreign_public_key_hash, "
@ -36,24 +37,27 @@ public class HSQLDBCrossChainRepository implements CrossChainRepository {
if (tradeState == null)
throw new DataException("Illegal trade-bot trade-state fetched from repository");
String atAddress = resultSet.getString(2);
byte[] tradeNativePublicKey = resultSet.getBytes(3);
byte[] tradeNativePublicKeyHash = resultSet.getBytes(4);
String tradeNativeAddress = resultSet.getString(5);
byte[] secret = resultSet.getBytes(6);
byte[] hashOfSecret = resultSet.getBytes(7);
byte[] tradeForeignPublicKey = resultSet.getBytes(8);
byte[] tradeForeignPublicKeyHash = resultSet.getBytes(9);
long bitcoinAmount = resultSet.getLong(10);
String xprv58 = resultSet.getString(11);
byte[] lastTransactionSignature = resultSet.getBytes(12);
Integer lockTimeA = resultSet.getInt(13);
String creatorAddress = resultSet.getString(2);
String atAddress = resultSet.getString(3);
long timestamp = resultSet.getLong(4);
long qortAmount = resultSet.getLong(5);
byte[] tradeNativePublicKey = resultSet.getBytes(6);
byte[] tradeNativePublicKeyHash = resultSet.getBytes(7);
String tradeNativeAddress = resultSet.getString(8);
byte[] secret = resultSet.getBytes(9);
byte[] hashOfSecret = resultSet.getBytes(10);
byte[] tradeForeignPublicKey = resultSet.getBytes(11);
byte[] tradeForeignPublicKeyHash = resultSet.getBytes(12);
long bitcoinAmount = resultSet.getLong(13);
String xprv58 = resultSet.getString(14);
byte[] lastTransactionSignature = resultSet.getBytes(15);
Integer lockTimeA = resultSet.getInt(16);
if (lockTimeA == 0 && resultSet.wasNull())
lockTimeA = null;
byte[] receivingAccountInfo = resultSet.getBytes(14);
byte[] receivingAccountInfo = resultSet.getBytes(17);
return new TradeBotData(tradePrivateKey, tradeState,
atAddress,
creatorAddress, atAddress, timestamp, qortAmount,
tradeNativePublicKey, tradeNativePublicKeyHash, tradeNativeAddress,
secret, hashOfSecret,
tradeForeignPublicKey, tradeForeignPublicKeyHash,
@ -65,7 +69,8 @@ public class HSQLDBCrossChainRepository implements CrossChainRepository {
@Override
public List<TradeBotData> getAllTradeBotData() throws DataException {
String sql = "SELECT trade_private_key, trade_state, at_address, "
String sql = "SELECT trade_private_key, trade_state, creator_address, at_address, "
+ "updated_when, qort_amount, "
+ "trade_native_public_key, trade_native_public_key_hash, "
+ "trade_native_address, secret, hash_of_secret, "
+ "trade_foreign_public_key, trade_foreign_public_key_hash, "
@ -85,24 +90,27 @@ public class HSQLDBCrossChainRepository implements CrossChainRepository {
if (tradeState == null)
throw new DataException("Illegal trade-bot trade-state fetched from repository");
String atAddress = resultSet.getString(3);
byte[] tradeNativePublicKey = resultSet.getBytes(4);
byte[] tradeNativePublicKeyHash = resultSet.getBytes(5);
String tradeNativeAddress = resultSet.getString(6);
byte[] secret = resultSet.getBytes(7);
byte[] hashOfSecret = resultSet.getBytes(8);
byte[] tradeForeignPublicKey = resultSet.getBytes(9);
byte[] tradeForeignPublicKeyHash = resultSet.getBytes(10);
long bitcoinAmount = resultSet.getLong(11);
String xprv58 = resultSet.getString(12);
byte[] lastTransactionSignature = resultSet.getBytes(13);
Integer lockTimeA = resultSet.getInt(14);
String creatorAddress = resultSet.getString(3);
String atAddress = resultSet.getString(4);
long timestamp = resultSet.getLong(5);
long qortAmount = resultSet.getLong(6);
byte[] tradeNativePublicKey = resultSet.getBytes(7);
byte[] tradeNativePublicKeyHash = resultSet.getBytes(8);
String tradeNativeAddress = resultSet.getString(9);
byte[] secret = resultSet.getBytes(10);
byte[] hashOfSecret = resultSet.getBytes(11);
byte[] tradeForeignPublicKey = resultSet.getBytes(12);
byte[] tradeForeignPublicKeyHash = resultSet.getBytes(13);
long bitcoinAmount = resultSet.getLong(14);
String xprv58 = resultSet.getString(15);
byte[] lastTransactionSignature = resultSet.getBytes(16);
Integer lockTimeA = resultSet.getInt(17);
if (lockTimeA == 0 && resultSet.wasNull())
lockTimeA = null;
byte[] receivingAccountInfo = resultSet.getBytes(15);
byte[] receivingAccountInfo = resultSet.getBytes(18);
TradeBotData tradeBotData = new TradeBotData(tradePrivateKey, tradeState,
atAddress,
creatorAddress, atAddress, timestamp, qortAmount,
tradeNativePublicKey, tradeNativePublicKeyHash, tradeNativeAddress,
secret, hashOfSecret,
tradeForeignPublicKey, tradeForeignPublicKeyHash,
@ -122,7 +130,10 @@ public class HSQLDBCrossChainRepository implements CrossChainRepository {
saveHelper.bind("trade_private_key", tradeBotData.getTradePrivateKey())
.bind("trade_state", tradeBotData.getState().value)
.bind("creator_address", tradeBotData.getCreatorAddress())
.bind("at_address", tradeBotData.getAtAddress())
.bind("updated_when", tradeBotData.getTimestamp())
.bind("qort_amount", tradeBotData.getQortAmount())
.bind("trade_native_public_key", tradeBotData.getTradeNativePublicKey())
.bind("trade_native_public_key_hash", tradeBotData.getTradeNativePublicKeyHash())
.bind("trade_native_address", tradeBotData.getTradeNativeAddress())

View File

@ -4,9 +4,14 @@ import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.qortal.utils.Base58;
import com.google.common.hash.HashCode;
public class HSQLDBDatabaseUpdates {
@ -621,7 +626,7 @@ public class HSQLDBDatabaseUpdates {
case 20:
// Trade bot
stmt.execute("CREATE TABLE TradeBotStates (trade_private_key QortalKeySeed NOT NULL, trade_state TINYINT NOT NULL, "
+ "at_address QortalAddress, "
+ "creator_address QortalAddress NOT NULL, at_address QortalAddress, updated_when BIGINT NOT NULL, qort_amount QortalAmount NOT NULL, "
+ "trade_native_public_key QortalPublicKey NOT NULL, trade_native_public_key_hash VARBINARY(32) NOT NULL, "
+ "trade_native_address QortalAddress NOT NULL, secret VARBINARY(32) NOT NULL, hash_of_secret VARBINARY(32) NOT NULL, "
+ "trade_foreign_public_key VARBINARY(33) NOT NULL, trade_foreign_public_key_hash VARBINARY(32) NOT NULL, "
@ -641,6 +646,39 @@ public class HSQLDBDatabaseUpdates {
stmt.execute("ALTER TABLE TradeBotStates ADD COLUMN IF NOT EXISTS receiving_account_info VARBINARY(32)");
break;
case 23:
// XXX for testing/dev only - do not merge into 'master'
stmt.execute("ALTER TABLE TradeBotStates ADD COLUMN IF NOT EXISTS creator_address QortalAddress BEFORE at_address");
// Update Bob bot entries
stmt.execute("UPDATE TradeBotStates AS StatesToUpdate "
+ "SET (trade_private_key, creator_address) = ("
+ "SELECT trade_private_key, accounts.account "
+ "FROM TradeBotStates "
+ "JOIN ATs USING (at_address) "
+ "JOIN Accounts ON Accounts.public_key = ATs.creator "
+ "WHERE tradebotstates.trade_private_key = StatesToUpdate.trade_private_key"
+ ") WHERE trade_state < 90");
stmt.execute("SELECT trade_private_key, receiving_account_info FROM TradeBotStates WHERE trade_state >= 90");
Map<String, String> aliceAddresses = new HashMap<>();
try (ResultSet resultSet = stmt.getResultSet()) {
while (resultSet.next()) {
byte[] tradePrivateKey = resultSet.getBytes(1);
byte[] receivingAccountInfo = resultSet.getBytes(2);
aliceAddresses.put(HashCode.fromBytes(tradePrivateKey).toString(), Base58.encode(receivingAccountInfo));
}
}
for (Map.Entry<String, String> entry : aliceAddresses.entrySet())
stmt.execute("UPDATE TradeBotStates SET creator_address = '" + entry.getValue() + "' WHERE trade_private_key = HEXTORAW('" + entry.getKey() + "')");
stmt.execute("COMMIT");
stmt.execute("ALTER TABLE TradeBotStates ADD COLUMN IF NOT EXISTS updated_when BIGINT BEFORE trade_native_public_key");
stmt.execute("UPDATE TradeBotStates SET updated_when = UNIX_TIMESTAMP() * 1000");
stmt.execute("ALTER TABLE TradeBotStates ADD COLUMN IF NOT EXISTS qort_amount QortalAmount NOT NULL DEFAULT 12345678 BEFORE trade_native_public_key");
break;
default:
// nothing to do
return false;