forked from Qortal/qortal
WIP: PRESENCE - TradeBot support, moved PresenceType enum, added Presence-only transaction deadline override
This commit is contained in:
parent
cfacddcb36
commit
e093520696
@ -3,7 +3,10 @@ package org.qortal.controller;
|
||||
import java.awt.TrayIcon.MessageType;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@ -32,6 +35,7 @@ import org.qortal.data.crosschain.TradeBotData;
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.DeployAtTransactionData;
|
||||
import org.qortal.data.transaction.MessageTransactionData;
|
||||
import org.qortal.data.transaction.PresenceTransactionData;
|
||||
import org.qortal.event.Event;
|
||||
import org.qortal.event.EventBus;
|
||||
import org.qortal.event.Listener;
|
||||
@ -43,13 +47,18 @@ import org.qortal.repository.RepositoryManager;
|
||||
import org.qortal.settings.Settings;
|
||||
import org.qortal.transaction.DeployAtTransaction;
|
||||
import org.qortal.transaction.MessageTransaction;
|
||||
import org.qortal.transaction.PresenceTransaction;
|
||||
import org.qortal.transaction.PresenceTransaction.PresenceType;
|
||||
import org.qortal.transaction.Transaction.ValidationResult;
|
||||
import org.qortal.transform.TransformationException;
|
||||
import org.qortal.transform.transaction.DeployAtTransactionTransformer;
|
||||
import org.qortal.transform.transaction.TransactionTransformer;
|
||||
import org.qortal.utils.Amounts;
|
||||
import org.qortal.utils.Base58;
|
||||
import org.qortal.utils.NTP;
|
||||
|
||||
import com.google.common.primitives.Longs;
|
||||
|
||||
/**
|
||||
* Performing cross-chain trading steps on behalf of user.
|
||||
* <p>
|
||||
@ -86,6 +95,8 @@ public class TradeBot implements Listener {
|
||||
|
||||
private static TradeBot instance;
|
||||
|
||||
private final Map<String, Long> presenceTimestampsByAtAddress = Collections.synchronizedMap(new HashMap<>());
|
||||
|
||||
private TradeBot() {
|
||||
EventBus.INSTANCE.addListener(event -> TradeBot.getInstance().listen(event));
|
||||
}
|
||||
@ -348,26 +359,32 @@ public class TradeBot implements Listener {
|
||||
break;
|
||||
|
||||
case ALICE_WAITING_FOR_P2SH_A:
|
||||
updatePresence(repository, tradeBotData);
|
||||
handleAliceWaitingForP2shA(repository, tradeBotData);
|
||||
break;
|
||||
|
||||
case BOB_WAITING_FOR_MESSAGE:
|
||||
updatePresence(repository, tradeBotData);
|
||||
handleBobWaitingForMessage(repository, tradeBotData);
|
||||
break;
|
||||
|
||||
case ALICE_WAITING_FOR_AT_LOCK:
|
||||
updatePresence(repository, tradeBotData);
|
||||
handleAliceWaitingForAtLock(repository, tradeBotData);
|
||||
break;
|
||||
|
||||
case BOB_WAITING_FOR_P2SH_B:
|
||||
updatePresence(repository, tradeBotData);
|
||||
handleBobWaitingForP2shB(repository, tradeBotData);
|
||||
break;
|
||||
|
||||
case ALICE_WATCH_P2SH_B:
|
||||
updatePresence(repository, tradeBotData);
|
||||
handleAliceWatchingP2shB(repository, tradeBotData);
|
||||
break;
|
||||
|
||||
case BOB_WAITING_FOR_AT_REDEEM:
|
||||
updatePresence(repository, tradeBotData);
|
||||
handleBobWaitingForAtRedeem(repository, tradeBotData);
|
||||
break;
|
||||
|
||||
@ -376,10 +393,12 @@ public class TradeBot implements Listener {
|
||||
break;
|
||||
|
||||
case ALICE_REFUNDING_B:
|
||||
updatePresence(repository, tradeBotData);
|
||||
handleAliceRefundingP2shB(repository, tradeBotData);
|
||||
break;
|
||||
|
||||
case ALICE_REFUNDING_A:
|
||||
updatePresence(repository, tradeBotData);
|
||||
handleAliceRefundingP2shA(repository, tradeBotData);
|
||||
break;
|
||||
|
||||
@ -1249,4 +1268,41 @@ public class TradeBot implements Listener {
|
||||
EventBus.INSTANCE.notify(stateChangeEvent);
|
||||
}
|
||||
|
||||
// PRESENCE-related
|
||||
private void updatePresence(Repository repository, TradeBotData tradeBotData) throws DataException {
|
||||
String key = tradeBotData.getAtAddress();
|
||||
|
||||
long now = NTP.getTime();
|
||||
long threshold = now - PresenceType.TRADE_BOT.getLifetime();
|
||||
|
||||
long timestamp = presenceTimestampsByAtAddress.compute(key, (k, v) -> (v == null || v < threshold) ? now : v);
|
||||
|
||||
// If timestamp hasn't been updated then nothing to do
|
||||
if (timestamp != now)
|
||||
return;
|
||||
|
||||
PrivateKeyAccount tradeNativeAccount = new PrivateKeyAccount(repository, tradeBotData.getTradePrivateKey());
|
||||
|
||||
int txGroupId = Group.NO_GROUP;
|
||||
byte[] reference = new byte[TransactionTransformer.SIGNATURE_LENGTH];
|
||||
byte[] creatorPublicKey = tradeNativeAccount.getPublicKey();
|
||||
long fee = 0L;
|
||||
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, creatorPublicKey, fee, null);
|
||||
|
||||
int nonce = 0;
|
||||
byte[] timestampSignature = tradeNativeAccount.sign(Longs.toByteArray(timestamp));
|
||||
|
||||
PresenceTransactionData transactionData = new PresenceTransactionData(baseTransactionData, nonce, PresenceType.TRADE_BOT, timestampSignature);
|
||||
|
||||
PresenceTransaction presenceTransaction = new PresenceTransaction(repository, transactionData);
|
||||
presenceTransaction.computeNonce();
|
||||
|
||||
presenceTransaction.sign(tradeNativeAccount);
|
||||
|
||||
ValidationResult result = presenceTransaction.importAsUnconfirmed();
|
||||
if (result != ValidationResult.OK)
|
||||
LOGGER.debug(() -> String.format("Unable to build trade-bot PRESENCE transaction for %s: %s", tradeBotData.getAtAddress(), result.name()));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,14 +1,10 @@
|
||||
package org.qortal.data.transaction;
|
||||
|
||||
import static java.util.Arrays.stream;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
|
||||
import org.qortal.transaction.PresenceTransaction.PresenceType;
|
||||
import org.qortal.transaction.Transaction.TransactionType;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
@ -26,20 +22,6 @@ public class PresenceTransactionData extends TransactionData {
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
private int nonce;
|
||||
|
||||
public enum PresenceType {
|
||||
REWARD_SHARE(0), TRADE_BOT(1);
|
||||
|
||||
public final int value;
|
||||
private static final Map<Integer, PresenceType> map = stream(PresenceType.values()).collect(toMap(type -> type.value, type -> type));
|
||||
|
||||
PresenceType(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static PresenceType valueOf(int value) {
|
||||
return map.get(value);
|
||||
}
|
||||
}
|
||||
private PresenceType presenceType;
|
||||
|
||||
@Schema(description = "timestamp signature", example = "2yGEbwRFyhPZZckKA")
|
||||
|
@ -40,7 +40,7 @@ import io.swagger.v3.oas.annotations.media.Schema.AccessMode;
|
||||
GroupApprovalTransactionData.class, SetGroupTransactionData.class,
|
||||
UpdateAssetTransactionData.class,
|
||||
AccountFlagsTransactionData.class, RewardShareTransactionData.class,
|
||||
AccountLevelTransactionData.class, ChatTransactionData.class
|
||||
AccountLevelTransactionData.class, ChatTransactionData.class, PresenceTransactionData.class
|
||||
})
|
||||
//All properties to be converted to JSON via JAXB
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
|
@ -5,11 +5,11 @@ import java.sql.SQLException;
|
||||
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.PresenceTransactionData;
|
||||
import org.qortal.data.transaction.PresenceTransactionData.PresenceType;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.hsqldb.HSQLDBRepository;
|
||||
import org.qortal.repository.hsqldb.HSQLDBSaver;
|
||||
import org.qortal.transaction.PresenceTransaction.PresenceType;
|
||||
|
||||
public class HSQLDBPresenceTransactionRepository extends HSQLDBTransactionRepository {
|
||||
|
||||
|
@ -1,11 +1,16 @@
|
||||
package org.qortal.transaction;
|
||||
|
||||
import static java.util.Arrays.stream;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.qortal.account.Account;
|
||||
import org.qortal.controller.Controller;
|
||||
import org.qortal.crosschain.BTCACCT;
|
||||
import org.qortal.crypto.Crypto;
|
||||
import org.qortal.crypto.MemoryPoW;
|
||||
@ -13,7 +18,6 @@ import org.qortal.data.at.ATData;
|
||||
import org.qortal.data.crosschain.CrossChainTradeData;
|
||||
import org.qortal.data.transaction.PresenceTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.data.transaction.PresenceTransactionData.PresenceType;
|
||||
import org.qortal.group.Group;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
@ -35,6 +39,34 @@ public class PresenceTransaction extends Transaction {
|
||||
public static final int POW_BUFFER_SIZE = 8 * 1024 * 1024; // bytes
|
||||
public static final int POW_DIFFICULTY = 8; // leading zero bits
|
||||
|
||||
public enum PresenceType {
|
||||
REWARD_SHARE(0) {
|
||||
@Override
|
||||
public long getLifetime() {
|
||||
return Controller.ONLINE_TIMESTAMP_MODULUS;
|
||||
}
|
||||
},
|
||||
TRADE_BOT(1) {
|
||||
@Override
|
||||
public long getLifetime() {
|
||||
return 30 * 60 * 1000L; // 30 minutes in milliseconds
|
||||
}
|
||||
};
|
||||
|
||||
public final int value;
|
||||
private static final Map<Integer, PresenceType> map = stream(PresenceType.values()).collect(toMap(type -> type.value, type -> type));
|
||||
|
||||
PresenceType(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public abstract long getLifetime();
|
||||
|
||||
public static PresenceType valueOf(int value) {
|
||||
return map.get(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Constructors
|
||||
|
||||
public PresenceTransaction(Repository repository, TransactionData transactionData) {
|
||||
@ -45,6 +77,11 @@ public class PresenceTransaction extends Transaction {
|
||||
|
||||
// More information
|
||||
|
||||
@Override
|
||||
public long getDeadline() {
|
||||
return this.transactionData.getTimestamp() + this.presenceTransactionData.getPresenceType().getLifetime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRecipientAddresses() throws DataException {
|
||||
return Collections.emptyList();
|
||||
|
@ -6,8 +6,8 @@ import java.nio.ByteBuffer;
|
||||
|
||||
import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.PresenceTransactionData;
|
||||
import org.qortal.data.transaction.PresenceTransactionData.PresenceType;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.transaction.PresenceTransaction.PresenceType;
|
||||
import org.qortal.transaction.Transaction.TransactionType;
|
||||
import org.qortal.transform.TransformationException;
|
||||
import org.qortal.utils.Serialization;
|
||||
|
@ -10,7 +10,6 @@ import org.qortal.data.transaction.BaseTransactionData;
|
||||
import org.qortal.data.transaction.DeployAtTransactionData;
|
||||
import org.qortal.data.transaction.PresenceTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.data.transaction.PresenceTransactionData.PresenceType;
|
||||
import org.qortal.group.Group;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
@ -20,6 +19,7 @@ import org.qortal.test.common.Common;
|
||||
import org.qortal.test.common.TransactionUtils;
|
||||
import org.qortal.transaction.DeployAtTransaction;
|
||||
import org.qortal.transaction.PresenceTransaction;
|
||||
import org.qortal.transaction.PresenceTransaction.PresenceType;
|
||||
import org.qortal.transaction.Transaction;
|
||||
import org.qortal.transaction.Transaction.ValidationResult;
|
||||
import org.qortal.utils.NTP;
|
||||
|
Loading…
x
Reference in New Issue
Block a user