sign offers with random arbitrator, take trades with least used

This commit is contained in:
woodser 2023-05-16 11:38:50 -04:00
parent 0e0bd6b8c7
commit 654435d4dd
4 changed files with 63 additions and 8 deletions

View file

@ -145,6 +145,17 @@ arbitrator-desktop-local:
--apiPassword=apitest \
--apiPort=9998
arbitrator2-daemon-local:
# Arbitrator needs to be registered before making trades
./haveno-daemon$(APP_EXT) \
--baseCurrencyNetwork=XMR_LOCAL \
--useLocalhostForP2P=true \
--useDevPrivilegeKeys=true \
--nodePort=7777 \
--appName=haveno-XMR_LOCAL_arbitrator2 \
--apiPassword=apitest \
--apiPort=10001
arbitrator2-desktop-local:
# Arbitrator needs to be registered before making trades
./haveno-desktop$(APP_EXT) \

View file

@ -32,6 +32,7 @@ import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@ -47,7 +48,7 @@ public class DisputeAgentSelection {
return getLeastUsedDisputeAgent(tradeStatisticsManager,
disputeAgentManager,
null);
}
}
public static <T extends DisputeAgent> T getLeastUsedArbitrator(TradeStatisticsManager tradeStatisticsManager,
DisputeAgentManager<T> disputeAgentManager,
@ -109,4 +110,40 @@ public class DisputeAgentSelection {
disputeAgentTuples.sort(Comparator.comparingInt(e -> e.second.get()));
return disputeAgentTuples.get(0).first;
}
public static <T extends DisputeAgent> T getRandomArbitrator(DisputeAgentManager<T> disputeAgentManager) {
return getRandomArbitrator(disputeAgentManager, null);
}
public static <T extends DisputeAgent> T getRandomArbitrator(DisputeAgentManager<T> disputeAgentManager,
Set<NodeAddress> excludedArbitrator) {
return getRandomDisputeAgent(disputeAgentManager, excludedArbitrator);
}
private static <T extends DisputeAgent> T getRandomDisputeAgent(DisputeAgentManager<T> disputeAgentManager,
Set<NodeAddress> excludedDisputeAgents) {
// get all dispute agents
Set<String> disputeAgents = disputeAgentManager.getObservableMap().values().stream()
.map(disputeAgent -> disputeAgent.getNodeAddress().getFullAddress())
.collect(Collectors.toSet());
// remove excluded dispute agents
if (excludedDisputeAgents != null) disputeAgents.removeAll(excludedDisputeAgents.stream().map(NodeAddress::getFullAddress).collect(Collectors.toList()));
if (disputeAgents.isEmpty()) return null;
// get random dispute agent
String result = getRandomDisputeAgent(disputeAgents);
Optional<T> optionalDisputeAgent = disputeAgentManager.getObservableMap().values().stream()
.filter(e -> e.getNodeAddress().getFullAddress().equals(result))
.findAny();
checkArgument(optionalDisputeAgent.isPresent(), "optionalDisputeAgent has to be present");
return optionalDisputeAgent.get();
}
private static String getRandomDisputeAgent(Set<String> disputeAgents) {
int randomIndex = new Random().nextInt(disputeAgents.size());
List<String> elements = new ArrayList<String>(disputeAgents);
return elements.get(randomIndex);
}
}

View file

@ -92,12 +92,12 @@ public class MakerSendSignOfferRequest extends Task<PlaceOfferModel> {
}
private void sendSignOfferRequests(SignOfferRequest request, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
Arbitrator leastUsedArbitrator = DisputeAgentSelection.getLeastUsedArbitrator(model.getTradeStatisticsManager(), model.getArbitratorManager());
if (leastUsedArbitrator == null) {
errorMessageHandler.handleErrorMessage("Could not get least used arbitrator to send " + request.getClass().getSimpleName() + " for offer " + request.getOfferId());
Arbitrator randomArbitrator = DisputeAgentSelection.getRandomArbitrator(model.getArbitratorManager());
if (randomArbitrator == null) {
errorMessageHandler.handleErrorMessage("Could not get random arbitrator to send " + request.getClass().getSimpleName() + " for offer " + request.getOfferId());
return;
}
sendSignOfferRequests(request, leastUsedArbitrator.getNodeAddress(), new HashSet<NodeAddress>(), resultHandler, errorMessageHandler);
sendSignOfferRequests(request, randomArbitrator.getNodeAddress(), new HashSet<NodeAddress>(), resultHandler, errorMessageHandler);
}
private void sendSignOfferRequests(SignOfferRequest request, NodeAddress arbitratorNodeAddress, Set<NodeAddress> excludedArbitrators, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
@ -135,7 +135,7 @@ public class MakerSendSignOfferRequest extends Task<PlaceOfferModel> {
public void onFault(String errorMessage) {
log.warn("Arbitrator unavailable: {}", errorMessage);
excludedArbitrators.add(arbitratorNodeAddress);
Arbitrator altArbitrator = DisputeAgentSelection.getLeastUsedArbitrator(model.getTradeStatisticsManager(), model.getArbitratorManager(), excludedArbitrators);
Arbitrator altArbitrator = DisputeAgentSelection.getRandomArbitrator(model.getArbitratorManager(), excludedArbitrators);
if (altArbitrator == null) {
errorMessageHandler.handleErrorMessage("Offer " + request.getOfferId() + " could not be signed by any arbitrator");
return;

View file

@ -45,8 +45,15 @@ public class TakerSendInitTradeRequestToArbitrator extends TradeTask {
try {
runInterceptHook();
// send request to signing arbitrator then least used arbitrators until success
sendInitTradeRequests(trade.getOffer().getOfferPayload().getArbitratorSigner(), new HashSet<NodeAddress>(), () -> {
// get least used arbitrator
Arbitrator leastUsedArbitrator = DisputeAgentSelection.getLeastUsedArbitrator(processModel.getTradeStatisticsManager(), processModel.getArbitratorManager());
if (leastUsedArbitrator == null) {
failed("Could not get least used arbitrator to send " + InitTradeRequest.class.getSimpleName() + " for offer " + trade.getId());
return;
}
// send request to least used arbitrators until success
sendInitTradeRequests(leastUsedArbitrator.getNodeAddress(), new HashSet<NodeAddress>(), () -> {
trade.addInitProgressStep();
complete();
}, (errorMessage) -> {