forked from Qortal/qortal
Fix ALICE-based PRESENCE transactions.
PRESENCE transactions were previously validated using Bob's trade key (in address form). But as PRESENCE transactions are already emitted by Alice, her trade key is also used (if present in trade data by virtue of AT being locked to Alice). Similarly, Alice's trade-bot won't even try to build PRESENCE transactions if her trade key isn't publicly visible to other peers, i.e. after AT is locked to Alice.
This commit is contained in:
parent
35b0ac78b8
commit
332c917c94
@ -387,32 +387,32 @@ public class BitcoinACCTv1TradeBot implements AcctTradeBot {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ALICE_WAITING_FOR_P2SH_A:
|
case ALICE_WAITING_FOR_P2SH_A:
|
||||||
TradeBot.getInstance().updatePresence(repository, tradeBotData);
|
TradeBot.getInstance().updatePresence(repository, tradeBotData, tradeData);
|
||||||
handleAliceWaitingForP2shA(repository, tradeBotData, atData, tradeData);
|
handleAliceWaitingForP2shA(repository, tradeBotData, atData, tradeData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BOB_WAITING_FOR_MESSAGE:
|
case BOB_WAITING_FOR_MESSAGE:
|
||||||
TradeBot.getInstance().updatePresence(repository, tradeBotData);
|
TradeBot.getInstance().updatePresence(repository, tradeBotData, tradeData);
|
||||||
handleBobWaitingForMessage(repository, tradeBotData, atData, tradeData);
|
handleBobWaitingForMessage(repository, tradeBotData, atData, tradeData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ALICE_WAITING_FOR_AT_LOCK:
|
case ALICE_WAITING_FOR_AT_LOCK:
|
||||||
TradeBot.getInstance().updatePresence(repository, tradeBotData);
|
TradeBot.getInstance().updatePresence(repository, tradeBotData, tradeData);
|
||||||
handleAliceWaitingForAtLock(repository, tradeBotData, atData, tradeData);
|
handleAliceWaitingForAtLock(repository, tradeBotData, atData, tradeData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BOB_WAITING_FOR_P2SH_B:
|
case BOB_WAITING_FOR_P2SH_B:
|
||||||
TradeBot.getInstance().updatePresence(repository, tradeBotData);
|
TradeBot.getInstance().updatePresence(repository, tradeBotData, tradeData);
|
||||||
handleBobWaitingForP2shB(repository, tradeBotData, atData, tradeData);
|
handleBobWaitingForP2shB(repository, tradeBotData, atData, tradeData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ALICE_WATCH_P2SH_B:
|
case ALICE_WATCH_P2SH_B:
|
||||||
TradeBot.getInstance().updatePresence(repository, tradeBotData);
|
TradeBot.getInstance().updatePresence(repository, tradeBotData, tradeData);
|
||||||
handleAliceWatchingP2shB(repository, tradeBotData, atData, tradeData);
|
handleAliceWatchingP2shB(repository, tradeBotData, atData, tradeData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BOB_WAITING_FOR_AT_REDEEM:
|
case BOB_WAITING_FOR_AT_REDEEM:
|
||||||
TradeBot.getInstance().updatePresence(repository, tradeBotData);
|
TradeBot.getInstance().updatePresence(repository, tradeBotData, tradeData);
|
||||||
handleBobWaitingForAtRedeem(repository, tradeBotData, atData, tradeData);
|
handleBobWaitingForAtRedeem(repository, tradeBotData, atData, tradeData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -421,12 +421,12 @@ public class BitcoinACCTv1TradeBot implements AcctTradeBot {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ALICE_REFUNDING_B:
|
case ALICE_REFUNDING_B:
|
||||||
TradeBot.getInstance().updatePresence(repository, tradeBotData);
|
TradeBot.getInstance().updatePresence(repository, tradeBotData, tradeData);
|
||||||
handleAliceRefundingP2shB(repository, tradeBotData, atData, tradeData);
|
handleAliceRefundingP2shB(repository, tradeBotData, atData, tradeData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ALICE_REFUNDING_A:
|
case ALICE_REFUNDING_A:
|
||||||
TradeBot.getInstance().updatePresence(repository, tradeBotData);
|
TradeBot.getInstance().updatePresence(repository, tradeBotData, tradeData);
|
||||||
handleAliceRefundingP2shA(repository, tradeBotData, atData, tradeData);
|
handleAliceRefundingP2shA(repository, tradeBotData, atData, tradeData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -384,17 +384,17 @@ public class LitecoinACCTv1TradeBot implements AcctTradeBot {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BOB_WAITING_FOR_MESSAGE:
|
case BOB_WAITING_FOR_MESSAGE:
|
||||||
TradeBot.getInstance().updatePresence(repository, tradeBotData);
|
TradeBot.getInstance().updatePresence(repository, tradeBotData, tradeData);
|
||||||
handleBobWaitingForMessage(repository, tradeBotData, atData, tradeData);
|
handleBobWaitingForMessage(repository, tradeBotData, atData, tradeData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ALICE_WAITING_FOR_AT_LOCK:
|
case ALICE_WAITING_FOR_AT_LOCK:
|
||||||
TradeBot.getInstance().updatePresence(repository, tradeBotData);
|
TradeBot.getInstance().updatePresence(repository, tradeBotData, tradeData);
|
||||||
handleAliceWaitingForAtLock(repository, tradeBotData, atData, tradeData);
|
handleAliceWaitingForAtLock(repository, tradeBotData, atData, tradeData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BOB_WAITING_FOR_AT_REDEEM:
|
case BOB_WAITING_FOR_AT_REDEEM:
|
||||||
TradeBot.getInstance().updatePresence(repository, tradeBotData);
|
TradeBot.getInstance().updatePresence(repository, tradeBotData, tradeData);
|
||||||
handleBobWaitingForAtRedeem(repository, tradeBotData, atData, tradeData);
|
handleBobWaitingForAtRedeem(repository, tradeBotData, atData, tradeData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -403,7 +403,7 @@ public class LitecoinACCTv1TradeBot implements AcctTradeBot {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ALICE_REFUNDING_A:
|
case ALICE_REFUNDING_A:
|
||||||
TradeBot.getInstance().updatePresence(repository, tradeBotData);
|
TradeBot.getInstance().updatePresence(repository, tradeBotData, tradeData);
|
||||||
handleAliceRefundingP2shA(repository, tradeBotData, atData, tradeData);
|
handleAliceRefundingP2shA(repository, tradeBotData, atData, tradeData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -307,20 +307,32 @@ public class TradeBot implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PRESENCE-related
|
// PRESENCE-related
|
||||||
/*package*/ void updatePresence(Repository repository, TradeBotData tradeBotData) throws DataException {
|
/*package*/ void updatePresence(Repository repository, TradeBotData tradeBotData, CrossChainTradeData tradeData)
|
||||||
String key = tradeBotData.getAtAddress();
|
throws DataException {
|
||||||
|
String atAddress = tradeBotData.getAtAddress();
|
||||||
|
|
||||||
|
PrivateKeyAccount tradeNativeAccount = new PrivateKeyAccount(repository, tradeBotData.getTradePrivateKey());
|
||||||
|
String signerAddress = tradeNativeAccount.getAddress();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There's no point in Alice trying to build a PRESENCE transaction
|
||||||
|
* for an AT that isn't locked to her, as other peers won't be able
|
||||||
|
* to validate the PRESENCE transaction as signing public key won't
|
||||||
|
* be visible.
|
||||||
|
*/
|
||||||
|
if (!signerAddress.equals(tradeData.qortalCreatorTradeAddress) && !signerAddress.equals(tradeData.qortalPartnerAddress))
|
||||||
|
// Signer is neither Bob, nor Alice, or trade not yet locked to Alice
|
||||||
|
return;
|
||||||
|
|
||||||
long now = NTP.getTime();
|
long now = NTP.getTime();
|
||||||
long threshold = now - PresenceType.TRADE_BOT.getLifetime();
|
long threshold = now - PresenceType.TRADE_BOT.getLifetime();
|
||||||
|
|
||||||
long timestamp = presenceTimestampsByAtAddress.compute(key, (k, v) -> (v == null || v < threshold) ? now : v);
|
long timestamp = presenceTimestampsByAtAddress.compute(atAddress, (k, v) -> (v == null || v < threshold) ? now : v);
|
||||||
|
|
||||||
// If timestamp hasn't been updated then nothing to do
|
// If timestamp hasn't been updated then nothing to do
|
||||||
if (timestamp != now)
|
if (timestamp != now)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PrivateKeyAccount tradeNativeAccount = new PrivateKeyAccount(repository, tradeBotData.getTradePrivateKey());
|
|
||||||
|
|
||||||
int txGroupId = Group.NO_GROUP;
|
int txGroupId = Group.NO_GROUP;
|
||||||
byte[] reference = new byte[TransactionTransformer.SIGNATURE_LENGTH];
|
byte[] reference = new byte[TransactionTransformer.SIGNATURE_LENGTH];
|
||||||
byte[] creatorPublicKey = tradeNativeAccount.getPublicKey();
|
byte[] creatorPublicKey = tradeNativeAccount.getPublicKey();
|
||||||
|
@ -168,15 +168,15 @@ public class PresenceTransaction extends Transaction {
|
|||||||
if (!Crypto.verify(this.transactionData.getCreatorPublicKey(), timestampSignature, timestampBytes))
|
if (!Crypto.verify(this.transactionData.getCreatorPublicKey(), timestampSignature, timestampBytes))
|
||||||
return ValidationResult.INVALID_TIMESTAMP_SIGNATURE;
|
return ValidationResult.INVALID_TIMESTAMP_SIGNATURE;
|
||||||
|
|
||||||
// Check signer is known trade address
|
|
||||||
String signerAddress = Crypto.toAddress(this.transactionData.getCreatorPublicKey());
|
|
||||||
|
|
||||||
Map<ByteArray, Supplier<ACCT>> acctSuppliersByCodeHash = SupportedBlockchain.getAcctMap();
|
Map<ByteArray, Supplier<ACCT>> acctSuppliersByCodeHash = SupportedBlockchain.getAcctMap();
|
||||||
Set<ByteArray> codeHashes = acctSuppliersByCodeHash.keySet();
|
Set<ByteArray> codeHashes = acctSuppliersByCodeHash.keySet();
|
||||||
boolean isExecutable = true;
|
boolean isExecutable = true;
|
||||||
|
|
||||||
List<ATData> atsData = repository.getATRepository().getAllATsByFunctionality(codeHashes, isExecutable);
|
List<ATData> atsData = repository.getATRepository().getAllATsByFunctionality(codeHashes, isExecutable);
|
||||||
|
|
||||||
|
// Convert signer's public key to address form
|
||||||
|
String signerAddress = Crypto.toAddress(this.transactionData.getCreatorPublicKey());
|
||||||
|
|
||||||
for (ATData atData : atsData) {
|
for (ATData atData : atsData) {
|
||||||
ByteArray atCodeHash = new ByteArray(atData.getCodeHash());
|
ByteArray atCodeHash = new ByteArray(atData.getCodeHash());
|
||||||
Supplier<ACCT> acctSupplier = acctSuppliersByCodeHash.get(atCodeHash);
|
Supplier<ACCT> acctSupplier = acctSuppliersByCodeHash.get(atCodeHash);
|
||||||
@ -185,7 +185,12 @@ public class PresenceTransaction extends Transaction {
|
|||||||
|
|
||||||
CrossChainTradeData crossChainTradeData = acctSupplier.get().populateTradeData(repository, atData);
|
CrossChainTradeData crossChainTradeData = acctSupplier.get().populateTradeData(repository, atData);
|
||||||
|
|
||||||
if (crossChainTradeData.qortalCreatorTradeAddress.equals(signerAddress))
|
// OK if signer's public key (in address form) matches Bob's trade public key (in address form)
|
||||||
|
if (signerAddress.equals(crossChainTradeData.qortalCreatorTradeAddress))
|
||||||
|
return ValidationResult.OK;
|
||||||
|
|
||||||
|
// OK if signer's public key (in address form) matches Alice's trade public key (in address form)
|
||||||
|
if (signerAddress.equals(crossChainTradeData.qortalPartnerAddress))
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user