Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add core support for registration of regtest dispute agents via API #4524

Merged
merged 6 commits into from
Sep 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cli/src/main/java/bisq/cli/GrpcStubs.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package bisq.cli;

import bisq.proto.grpc.DisputeAgentsGrpc;
import bisq.proto.grpc.GetVersionGrpc;
import bisq.proto.grpc.OffersGrpc;
import bisq.proto.grpc.PaymentAccountsGrpc;
Expand All @@ -29,6 +30,7 @@

public class GrpcStubs {

public final DisputeAgentsGrpc.DisputeAgentsBlockingStub disputeAgentsService;
public final GetVersionGrpc.GetVersionBlockingStub versionService;
public final OffersGrpc.OffersBlockingStub offersService;
public final PaymentAccountsGrpc.PaymentAccountsBlockingStub paymentAccountsService;
Expand All @@ -46,6 +48,7 @@ public GrpcStubs(String apiHost, int apiPort, String apiPassword) {
}
}));

this.disputeAgentsService = DisputeAgentsGrpc.newBlockingStub(channel).withCallCredentials(credentials);
this.versionService = GetVersionGrpc.newBlockingStub(channel).withCallCredentials(credentials);
this.offersService = OffersGrpc.newBlockingStub(channel).withCallCredentials(credentials);
this.paymentAccountsService = PaymentAccountsGrpc.newBlockingStub(channel).withCallCredentials(credentials);
Expand Down
14 changes: 13 additions & 1 deletion core/src/main/java/bisq/core/api/CoreApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,26 +47,38 @@
@Slf4j
public class CoreApi {

private final CoreDisputeAgentsService coreDisputeAgentsService;
private final CoreOffersService coreOffersService;
private final CorePaymentAccountsService paymentAccountsService;
private final CoreWalletsService walletsService;
private final TradeStatisticsManager tradeStatisticsManager;

@Inject
public CoreApi(CoreOffersService coreOffersService,
public CoreApi(CoreDisputeAgentsService coreDisputeAgentsService,
CoreOffersService coreOffersService,
CorePaymentAccountsService paymentAccountsService,
CoreWalletsService walletsService,
TradeStatisticsManager tradeStatisticsManager) {
this.coreDisputeAgentsService = coreDisputeAgentsService;
this.coreOffersService = coreOffersService;
this.paymentAccountsService = paymentAccountsService;
this.walletsService = walletsService;
this.tradeStatisticsManager = tradeStatisticsManager;
}

@SuppressWarnings("SameReturnValue")
public String getVersion() {
return Version.VERSION;
}

///////////////////////////////////////////////////////////////////////////////////////////
// Dispute Agents
///////////////////////////////////////////////////////////////////////////////////////////

public void registerDisputeAgent(String disputeAgentType, String registrationKey) {
coreDisputeAgentsService.registerDisputeAgent(disputeAgentType, registrationKey);
}

///////////////////////////////////////////////////////////////////////////////////////////
// Offers
///////////////////////////////////////////////////////////////////////////////////////////
Expand Down
144 changes: 144 additions & 0 deletions core/src/main/java/bisq/core/api/CoreDisputeAgentsService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/

package bisq.core.api;

import bisq.core.support.dispute.mediation.mediator.Mediator;
import bisq.core.support.dispute.mediation.mediator.MediatorManager;
import bisq.core.support.dispute.refund.refundagent.RefundAgent;
import bisq.core.support.dispute.refund.refundagent.RefundAgentManager;

import bisq.network.p2p.NodeAddress;
import bisq.network.p2p.P2PService;

import bisq.common.config.Config;
import bisq.common.crypto.KeyRing;

import org.bitcoinj.core.ECKey;

import javax.inject.Inject;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import lombok.extern.slf4j.Slf4j;

import static bisq.common.app.DevEnv.DEV_PRIVILEGE_PRIV_KEY;
import static java.net.InetAddress.getLoopbackAddress;

@Slf4j
class CoreDisputeAgentsService {

private final Config config;
private final KeyRing keyRing;
private final MediatorManager mediatorManager;
private final RefundAgentManager refundAgentManager;
private final P2PService p2PService;
private final NodeAddress nodeAddress;
private final List<String> languageCodes;

@Inject
public CoreDisputeAgentsService(Config config,
KeyRing keyRing,
MediatorManager mediatorManager,
RefundAgentManager refundAgentManager,
P2PService p2PService) {
this.config = config;
this.keyRing = keyRing;
this.mediatorManager = mediatorManager;
this.refundAgentManager = refundAgentManager;
this.p2PService = p2PService;
this.nodeAddress = new NodeAddress(getLoopbackAddress().getHostAddress(), config.nodePort);
this.languageCodes = Arrays.asList("de", "en", "es", "fr");
}

public void registerDisputeAgent(String disputeAgentType, String registrationKey) {
if (!p2PService.isBootstrapped())
throw new IllegalStateException("p2p service is not bootstrapped yet");

if (config.baseCurrencyNetwork.isMainnet()
|| config.baseCurrencyNetwork.isDaoBetaNet()
|| !config.useLocalhostForP2P)
throw new IllegalStateException("dispute agents must be registered in a Bisq UI");

if (!registrationKey.equals(DEV_PRIVILEGE_PRIV_KEY))
throw new IllegalArgumentException("invalid registration key");

ECKey ecKey;
String signature;
switch (disputeAgentType) {
case "arbitrator":
throw new IllegalArgumentException("arbitrators must be registered in a Bisq UI");
case "mediator":
ecKey = mediatorManager.getRegistrationKey(registrationKey);
signature = mediatorManager.signStorageSignaturePubKey(Objects.requireNonNull(ecKey));
registerMediator(nodeAddress, languageCodes, ecKey, signature);
return;
case "refundagent":
ecKey = refundAgentManager.getRegistrationKey(registrationKey);
signature = refundAgentManager.signStorageSignaturePubKey(Objects.requireNonNull(ecKey));
registerRefundAgent(nodeAddress, languageCodes, ecKey, signature);
return;
default:
throw new IllegalArgumentException("unknown dispute agent type " + disputeAgentType);
}
}

private void registerMediator(NodeAddress nodeAddress,
List<String> languageCodes,
ECKey ecKey,
String signature) {
Mediator mediator = new Mediator(nodeAddress,
keyRing.getPubKeyRing(),
languageCodes,
new Date().getTime(),
ecKey.getPubKey(),
signature,
null,
null,
null
);
mediatorManager.addDisputeAgent(mediator, () -> {
}, errorMessage -> {
ghubstan marked this conversation as resolved.
Show resolved Hide resolved
});
mediatorManager.getDisputeAgentByNodeAddress(nodeAddress).orElseThrow(() ->
new IllegalStateException("could not register mediator"));
}

private void registerRefundAgent(NodeAddress nodeAddress,
List<String> languageCodes,
ECKey ecKey,
String signature) {
RefundAgent refundAgent = new RefundAgent(nodeAddress,
keyRing.getPubKeyRing(),
languageCodes,
new Date().getTime(),
ecKey.getPubKey(),
signature,
null,
null,
null
);
refundAgentManager.addDisputeAgent(refundAgent, () -> {
}, errorMessage -> {
});
refundAgentManager.getDisputeAgentByNodeAddress(nodeAddress).orElseThrow(() ->
new IllegalStateException("could not register refund agent"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package bisq.daemon.grpc;

import bisq.core.api.CoreApi;

import bisq.proto.grpc.DisputeAgentsGrpc;
import bisq.proto.grpc.RegisterDisputeAgentReply;
import bisq.proto.grpc.RegisterDisputeAgentRequest;

import io.grpc.Status;
import io.grpc.StatusRuntimeException;
import io.grpc.stub.StreamObserver;

import javax.inject.Inject;

import lombok.extern.slf4j.Slf4j;

@Slf4j
class GrpcDisputeAgentsService extends DisputeAgentsGrpc.DisputeAgentsImplBase {

private final CoreApi coreApi;

@Inject
public GrpcDisputeAgentsService(CoreApi coreApi) {
this.coreApi = coreApi;
}

@Override
public void registerDisputeAgent(RegisterDisputeAgentRequest req,
StreamObserver<RegisterDisputeAgentReply> responseObserver) {
try {
coreApi.registerDisputeAgent(req.getDisputeAgentType(), req.getRegistrationKey());
var reply = RegisterDisputeAgentReply.newBuilder().build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
} catch (IllegalArgumentException cause) {
var ex = new StatusRuntimeException(Status.INVALID_ARGUMENT.withDescription(cause.getMessage()));
responseObserver.onError(ex);
throw ex;
} catch (IllegalStateException cause) {
var ex = new StatusRuntimeException(Status.UNKNOWN.withDescription(cause.getMessage()));
responseObserver.onError(ex);
throw ex;
}
}
}
2 changes: 2 additions & 0 deletions daemon/src/main/java/bisq/daemon/grpc/GrpcServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,13 @@ public class GrpcServer {
@Inject
public GrpcServer(Config config,
CoreApi coreApi,
GrpcDisputeAgentsService disputeAgentsService,
GrpcOffersService offersService,
GrpcPaymentAccountsService paymentAccountsService,
GrpcWalletsService walletsService) {
this.coreApi = coreApi;
this.server = ServerBuilder.forPort(config.apiPort)
.addService(disputeAgentsService)
.addService(new GetVersionService())
.addService(new GetTradeStatisticsService())
.addService(offersService)
Expand Down
30 changes: 24 additions & 6 deletions proto/src/main/proto/grpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,20 @@ option java_package = "bisq.proto.grpc";
option java_multiple_files = true;

///////////////////////////////////////////////////////////////////////////////////////////
// Version
// DisputeAgents
///////////////////////////////////////////////////////////////////////////////////////////

service GetVersion {
rpc GetVersion (GetVersionRequest) returns (GetVersionReply) {
service DisputeAgents {
rpc RegisterDisputeAgent (RegisterDisputeAgentRequest) returns (RegisterDisputeAgentReply) {
}
}

message GetVersionRequest {
message RegisterDisputeAgentRequest {
string disputeAgentType = 1;
string registrationKey = 2;
}

message GetVersionReply {
string version = 1;
message RegisterDisputeAgentReply {
}

///////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -214,3 +215,20 @@ message AddressBalanceInfo {
int64 balance = 2;
int64 numConfirmations = 3;
}

///////////////////////////////////////////////////////////////////////////////////////////
// Version
///////////////////////////////////////////////////////////////////////////////////////////

service GetVersion {
rpc GetVersion (GetVersionRequest) returns (GetVersionReply) {
}
}

message GetVersionRequest {
}

message GetVersionReply {
string version = 1;
}