From 4eed44d35019ec3b3a1fde6df3a9b2c5fccd9270 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 22 Jan 2021 13:45:12 -0300 Subject: [PATCH 1/2] Define gRPC api call rate constraints The general rule is limit calls that change p2p data to 1/minute, others to 1/second. An exception is made to set/remove wallet password methods (1/5s), due to the latency of writing wallet changes to disk. This change may affect api testing in the future. If that happens, further changes to the call rate metering interceptor may be made to loosen the constraints when running in regtest/dev mode. --- .../daemon/grpc/GrpcDisputeAgentsService.java | 30 +++++++++++++ .../grpc/GrpcGetTradeStatisticsService.java | 27 ++++++++++++ .../bisq/daemon/grpc/GrpcHelpService.java | 28 ++++++++++++ .../bisq/daemon/grpc/GrpcOffersService.java | 32 ++++++++++++++ .../grpc/GrpcPaymentAccountsService.java | 31 +++++++++++++ .../bisq/daemon/grpc/GrpcPriceService.java | 28 ++++++++++++ .../java/bisq/daemon/grpc/GrpcServer.java | 16 +++---- .../bisq/daemon/grpc/GrpcTradesService.java | 33 ++++++++++++++ .../bisq/daemon/grpc/GrpcVersionService.java | 5 +-- .../bisq/daemon/grpc/GrpcWalletsService.java | 44 +++++++++++++++++++ .../GrpcServiceRateMeteringConfig.java | 1 + 11 files changed, 264 insertions(+), 11 deletions(-) diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcDisputeAgentsService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcDisputeAgentsService.java index cd336da436a..95fe347cacf 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcDisputeAgentsService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcDisputeAgentsService.java @@ -6,12 +6,24 @@ import bisq.proto.grpc.RegisterDisputeAgentReply; import bisq.proto.grpc.RegisterDisputeAgentRequest; +import io.grpc.ServerInterceptor; import io.grpc.stub.StreamObserver; import javax.inject.Inject; +import java.util.HashMap; +import java.util.Optional; + import lombok.extern.slf4j.Slf4j; +import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor; +import static java.util.concurrent.TimeUnit.SECONDS; + + + +import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor; +import bisq.daemon.grpc.interceptor.GrpcCallRateMeter; + @Slf4j class GrpcDisputeAgentsService extends DisputeAgentsGrpc.DisputeAgentsImplBase { @@ -36,4 +48,22 @@ public void registerDisputeAgent(RegisterDisputeAgentRequest req, exceptionHandler.handleException(cause, responseObserver); } } + + final ServerInterceptor[] interceptors() { + Optional rateMeteringInterceptor = rateMeteringInterceptor(); + return rateMeteringInterceptor.map(serverInterceptor -> + new ServerInterceptor[]{serverInterceptor}).orElseGet(() -> new ServerInterceptor[0]); + } + + final Optional rateMeteringInterceptor() { + CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = + new CallRateMeteringInterceptor(new HashMap<>() {{ + // You can only register mainnet dispute agents in the UI. + // Do not limit devs' ability to register test agents. + put("registerDisputeAgent", new GrpcCallRateMeter(1, SECONDS)); + }}); + + return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) + .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcGetTradeStatisticsService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcGetTradeStatisticsService.java index 18cd5ef1c7c..0245e488c29 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcGetTradeStatisticsService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcGetTradeStatisticsService.java @@ -7,12 +7,23 @@ import bisq.proto.grpc.GetTradeStatisticsReply; import bisq.proto.grpc.GetTradeStatisticsRequest; +import io.grpc.ServerInterceptor; import io.grpc.stub.StreamObserver; import javax.inject.Inject; +import java.util.HashMap; +import java.util.Optional; import java.util.stream.Collectors; +import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor; +import static java.util.concurrent.TimeUnit.SECONDS; + + + +import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor; +import bisq.daemon.grpc.interceptor.GrpcCallRateMeter; + class GrpcGetTradeStatisticsService extends GetTradeStatisticsGrpc.GetTradeStatisticsImplBase { private final CoreApi coreApi; @@ -39,4 +50,20 @@ public void getTradeStatistics(GetTradeStatisticsRequest req, exceptionHandler.handleException(cause, responseObserver); } } + + final ServerInterceptor[] interceptors() { + Optional rateMeteringInterceptor = rateMeteringInterceptor(); + return rateMeteringInterceptor.map(serverInterceptor -> + new ServerInterceptor[]{serverInterceptor}).orElseGet(() -> new ServerInterceptor[0]); + } + + final Optional rateMeteringInterceptor() { + CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = + new CallRateMeteringInterceptor(new HashMap<>() {{ + put("getTradeStatistics", new GrpcCallRateMeter(1, SECONDS)); + }}); + + return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) + .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcHelpService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcHelpService.java index 1a62ed6f9f6..81654dfa826 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcHelpService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcHelpService.java @@ -23,12 +23,24 @@ import bisq.proto.grpc.GetMethodHelpRequest; import bisq.proto.grpc.HelpGrpc; +import io.grpc.ServerInterceptor; import io.grpc.stub.StreamObserver; import javax.inject.Inject; +import java.util.HashMap; +import java.util.Optional; + import lombok.extern.slf4j.Slf4j; +import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor; +import static java.util.concurrent.TimeUnit.SECONDS; + + + +import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor; +import bisq.daemon.grpc.interceptor.GrpcCallRateMeter; + @Slf4j class GrpcHelpService extends HelpGrpc.HelpImplBase { @@ -53,4 +65,20 @@ public void getMethodHelp(GetMethodHelpRequest req, exceptionHandler.handleException(cause, responseObserver); } } + + final ServerInterceptor[] interceptors() { + Optional rateMeteringInterceptor = rateMeteringInterceptor(); + return rateMeteringInterceptor.map(serverInterceptor -> + new ServerInterceptor[]{serverInterceptor}).orElseGet(() -> new ServerInterceptor[0]); + } + + final Optional rateMeteringInterceptor() { + CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = + new CallRateMeteringInterceptor(new HashMap<>() {{ + put("getMethodHelp", new GrpcCallRateMeter(1, SECONDS)); + }}); + + return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) + .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java index a0bef9ee3b3..6f7f55b4106 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java @@ -36,16 +36,27 @@ import bisq.proto.grpc.GetOffersRequest; import bisq.proto.grpc.OffersGrpc; +import io.grpc.ServerInterceptor; import io.grpc.stub.StreamObserver; import javax.inject.Inject; +import java.util.HashMap; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import static bisq.core.api.model.OfferInfo.toOfferInfo; +import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor; +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.SECONDS; + + + +import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor; +import bisq.daemon.grpc.interceptor.GrpcCallRateMeter; @Slf4j class GrpcOffersService extends OffersGrpc.OffersImplBase { @@ -171,4 +182,25 @@ public void cancelOffer(CancelOfferRequest req, exceptionHandler.handleException(cause, responseObserver); } } + + final ServerInterceptor[] interceptors() { + Optional rateMeteringInterceptor = rateMeteringInterceptor(); + return rateMeteringInterceptor.map(serverInterceptor -> + new ServerInterceptor[]{serverInterceptor}).orElseGet(() -> new ServerInterceptor[0]); + } + + final Optional rateMeteringInterceptor() { + CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = + new CallRateMeteringInterceptor(new HashMap<>() {{ + put("getOffer", new GrpcCallRateMeter(1, SECONDS)); + put("getMyOffer", new GrpcCallRateMeter(1, SECONDS)); + put("getOffers", new GrpcCallRateMeter(1, SECONDS)); + put("getMyOffers", new GrpcCallRateMeter(1, SECONDS)); + put("createOffer", new GrpcCallRateMeter(1, MINUTES)); + put("cancelOffer", new GrpcCallRateMeter(1, MINUTES)); + }}); + + return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) + .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcPaymentAccountsService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcPaymentAccountsService.java index 4decb5b1bae..8d6ad768d31 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcPaymentAccountsService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcPaymentAccountsService.java @@ -31,12 +31,24 @@ import bisq.proto.grpc.GetPaymentMethodsRequest; import bisq.proto.grpc.PaymentAccountsGrpc; +import io.grpc.ServerInterceptor; import io.grpc.stub.StreamObserver; import javax.inject.Inject; +import java.util.HashMap; +import java.util.Optional; import java.util.stream.Collectors; +import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor; +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.SECONDS; + + + +import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor; +import bisq.daemon.grpc.interceptor.GrpcCallRateMeter; + class GrpcPaymentAccountsService extends PaymentAccountsGrpc.PaymentAccountsImplBase { @@ -110,4 +122,23 @@ public void getPaymentAccountForm(GetPaymentAccountFormRequest req, exceptionHandler.handleException(cause, responseObserver); } } + + final ServerInterceptor[] interceptors() { + Optional rateMeteringInterceptor = rateMeteringInterceptor(); + return rateMeteringInterceptor.map(serverInterceptor -> + new ServerInterceptor[]{serverInterceptor}).orElseGet(() -> new ServerInterceptor[0]); + } + + final Optional rateMeteringInterceptor() { + CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = + new CallRateMeteringInterceptor(new HashMap<>() {{ + put("createPaymentAccount", new GrpcCallRateMeter(1, MINUTES)); + put("getPaymentAccounts", new GrpcCallRateMeter(1, SECONDS)); + put("getPaymentMethods", new GrpcCallRateMeter(1, SECONDS)); + put("getPaymentAccountForm", new GrpcCallRateMeter(1, SECONDS)); + }}); + + return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) + .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcPriceService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcPriceService.java index 7930b7b300d..0dee3dae0ed 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcPriceService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcPriceService.java @@ -23,12 +23,24 @@ import bisq.proto.grpc.MarketPriceRequest; import bisq.proto.grpc.PriceGrpc; +import io.grpc.ServerInterceptor; import io.grpc.stub.StreamObserver; import javax.inject.Inject; +import java.util.HashMap; +import java.util.Optional; + import lombok.extern.slf4j.Slf4j; +import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor; +import static java.util.concurrent.TimeUnit.SECONDS; + + + +import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor; +import bisq.daemon.grpc.interceptor.GrpcCallRateMeter; + @Slf4j class GrpcPriceService extends PriceGrpc.PriceImplBase { @@ -55,4 +67,20 @@ public void getMarketPrice(MarketPriceRequest req, exceptionHandler.handleException(cause, responseObserver); } } + + final ServerInterceptor[] interceptors() { + Optional rateMeteringInterceptor = rateMeteringInterceptor(); + return rateMeteringInterceptor.map(serverInterceptor -> + new ServerInterceptor[]{serverInterceptor}).orElseGet(() -> new ServerInterceptor[0]); + } + + final Optional rateMeteringInterceptor() { + CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = + new CallRateMeteringInterceptor(new HashMap<>() {{ + put("getMarketPrice", new GrpcCallRateMeter(1, SECONDS)); + }}); + + return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) + .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcServer.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcServer.java index 8e50a98aa1f..540ac3071e8 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcServer.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcServer.java @@ -60,15 +60,15 @@ public GrpcServer(CoreContext coreContext, GrpcWalletsService walletsService) { this.server = ServerBuilder.forPort(config.apiPort) .executor(UserThread.getExecutor()) - .addService(disputeAgentsService) - .addService(helpService) - .addService(offersService) - .addService(paymentAccountsService) - .addService(priceService) - .addService(tradeStatisticsService) - .addService(tradesService) + .addService(interceptForward(disputeAgentsService, disputeAgentsService.interceptors())) + .addService(interceptForward(helpService, helpService.interceptors())) + .addService(interceptForward(offersService, offersService.interceptors())) + .addService(interceptForward(paymentAccountsService, paymentAccountsService.interceptors())) + .addService(interceptForward(priceService, priceService.interceptors())) + .addService(interceptForward(tradeStatisticsService, tradeStatisticsService.interceptors())) + .addService(interceptForward(tradesService, tradesService.interceptors())) .addService(interceptForward(versionService, versionService.interceptors())) - .addService(walletsService) + .addService(interceptForward(walletsService, walletsService.interceptors())) .intercept(passwordAuthInterceptor) .build(); coreContext.setApiUser(true); diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java index b862e04ac95..a87a180dedd 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java @@ -35,13 +35,25 @@ import bisq.proto.grpc.WithdrawFundsReply; import bisq.proto.grpc.WithdrawFundsRequest; +import io.grpc.ServerInterceptor; import io.grpc.stub.StreamObserver; import javax.inject.Inject; +import java.util.HashMap; +import java.util.Optional; + import lombok.extern.slf4j.Slf4j; import static bisq.core.api.model.TradeInfo.toTradeInfo; +import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor; +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.SECONDS; + + + +import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor; +import bisq.daemon.grpc.interceptor.GrpcCallRateMeter; @Slf4j class GrpcTradesService extends TradesGrpc.TradesImplBase { @@ -142,4 +154,25 @@ public void withdrawFunds(WithdrawFundsRequest req, exceptionHandler.handleException(cause, responseObserver); } } + + final ServerInterceptor[] interceptors() { + Optional rateMeteringInterceptor = rateMeteringInterceptor(); + return rateMeteringInterceptor.map(serverInterceptor -> + new ServerInterceptor[]{serverInterceptor}).orElseGet(() -> new ServerInterceptor[0]); + } + + final Optional rateMeteringInterceptor() { + CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = + new CallRateMeteringInterceptor(new HashMap<>() {{ + put("getTrade", new GrpcCallRateMeter(1, SECONDS)); + put("takeOffer", new GrpcCallRateMeter(1, MINUTES)); + put("confirmPaymentStarted", new GrpcCallRateMeter(1, MINUTES)); + put("confirmPaymentReceived", new GrpcCallRateMeter(1, MINUTES)); + put("keepFunds", new GrpcCallRateMeter(1, MINUTES)); + put("withdrawFunds", new GrpcCallRateMeter(1, MINUTES)); + }}); + + return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) + .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcVersionService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcVersionService.java index 9fdba3b1654..268c60b0236 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcVersionService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcVersionService.java @@ -74,13 +74,12 @@ final ServerInterceptor[] interceptors() { } final Optional rateMeteringInterceptor() { - @SuppressWarnings("unused") // Defined as a usage example. CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = new CallRateMeteringInterceptor(new HashMap<>() {{ - put("getVersion", new GrpcCallRateMeter(100, SECONDS)); + put("getVersion", new GrpcCallRateMeter(1, SECONDS)); }}); return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) - .or(Optional::empty /* Optional.of(defaultCallRateMeteringInterceptor) */); + .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java index f8b06758070..e7ba1086c82 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java @@ -53,6 +53,7 @@ import bisq.proto.grpc.UnsetTxFeeRatePreferenceRequest; import bisq.proto.grpc.WalletsGrpc; +import io.grpc.ServerInterceptor; import io.grpc.stub.StreamObserver; import org.bitcoinj.core.Transaction; @@ -61,7 +62,9 @@ import com.google.common.util.concurrent.FutureCallback; +import java.util.HashMap; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; @@ -69,6 +72,14 @@ import org.jetbrains.annotations.NotNull; import static bisq.core.api.model.TxInfo.toTxInfo; +import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor; +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.SECONDS; + + + +import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor; +import bisq.daemon.grpc.interceptor.GrpcCallRateMeter; @Slf4j class GrpcWalletsService extends WalletsGrpc.WalletsImplBase { @@ -330,4 +341,37 @@ public void unlockWallet(UnlockWalletRequest req, exceptionHandler.handleException(cause, responseObserver); } } + + final ServerInterceptor[] interceptors() { + Optional rateMeteringInterceptor = rateMeteringInterceptor(); + return rateMeteringInterceptor.map(serverInterceptor -> + new ServerInterceptor[]{serverInterceptor}).orElseGet(() -> new ServerInterceptor[0]); + } + + final Optional rateMeteringInterceptor() { + CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = + new CallRateMeteringInterceptor(new HashMap<>() {{ + put("getBalances", new GrpcCallRateMeter(1, SECONDS)); + put("getAddressBalance", new GrpcCallRateMeter(1, SECONDS)); + put("getFundingAddresses", new GrpcCallRateMeter(1, SECONDS)); + put("getUnusedBsqAddress", new GrpcCallRateMeter(1, SECONDS)); + put("sendBsq", new GrpcCallRateMeter(1, MINUTES)); + put("sendBtc", new GrpcCallRateMeter(1, MINUTES)); + put("getTxFeeRate", new GrpcCallRateMeter(1, SECONDS)); + put("setTxFeeRatePreference", new GrpcCallRateMeter(1, SECONDS)); + put("unsetTxFeeRatePreference", new GrpcCallRateMeter(1, SECONDS)); + put("getTransaction", new GrpcCallRateMeter(1, SECONDS)); + + // Trying to set or remove a wallet password several times before the 1st attempt has time to + // persist the change to disk may corrupt the wallet, so allow only 1 attempt per 5 seconds. + put("setWalletPassword", new GrpcCallRateMeter(1, SECONDS, 5)); + put("removeWalletPassword", new GrpcCallRateMeter(1, SECONDS, 5)); + + put("lockWallet", new GrpcCallRateMeter(1, SECONDS)); + put("unlockWallet", new GrpcCallRateMeter(1, SECONDS)); + }}); + + return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) + .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/interceptor/GrpcServiceRateMeteringConfig.java b/daemon/src/main/java/bisq/daemon/grpc/interceptor/GrpcServiceRateMeteringConfig.java index 8c6297022f9..b01ac176552 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/interceptor/GrpcServiceRateMeteringConfig.java +++ b/daemon/src/main/java/bisq/daemon/grpc/interceptor/GrpcServiceRateMeteringConfig.java @@ -76,6 +76,7 @@ public GrpcServiceRateMeteringConfig(String grpcServiceClassName, this.methodRateMeters = methodRateMeters; } + @SuppressWarnings("unused") public GrpcServiceRateMeteringConfig addMethodCallRateMeter(String methodName, int maxCalls, TimeUnit timeUnit) { From c99624015b1a9566d1f4e3533ae12ace570618b6 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Mon, 25 Jan 2021 14:38:53 -0300 Subject: [PATCH 2/2] Factor out repeated 'new CallRateMeteringInterceptor' calls Move this into a static CallRateMeteringInterceptor.valueOf(Map) method. --- .../daemon/grpc/GrpcDisputeAgentsService.java | 15 +++---- .../grpc/GrpcGetTradeStatisticsService.java | 11 +++-- .../bisq/daemon/grpc/GrpcHelpService.java | 11 +++-- .../bisq/daemon/grpc/GrpcOffersService.java | 21 +++++---- .../grpc/GrpcPaymentAccountsService.java | 17 ++++--- .../bisq/daemon/grpc/GrpcPriceService.java | 11 +++-- .../bisq/daemon/grpc/GrpcTradesService.java | 21 +++++---- .../bisq/daemon/grpc/GrpcVersionService.java | 11 +++-- .../bisq/daemon/grpc/GrpcWalletsService.java | 45 +++++++++---------- .../CallRateMeteringInterceptor.java | 7 +++ 10 files changed, 84 insertions(+), 86 deletions(-) diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcDisputeAgentsService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcDisputeAgentsService.java index 95fe347cacf..dfc7f7406a5 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcDisputeAgentsService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcDisputeAgentsService.java @@ -56,14 +56,13 @@ final ServerInterceptor[] interceptors() { } final Optional rateMeteringInterceptor() { - CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = - new CallRateMeteringInterceptor(new HashMap<>() {{ - // You can only register mainnet dispute agents in the UI. - // Do not limit devs' ability to register test agents. - put("registerDisputeAgent", new GrpcCallRateMeter(1, SECONDS)); - }}); - return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) - .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + .or(() -> Optional.of(CallRateMeteringInterceptor.valueOf( + new HashMap<>() {{ + // You can only register mainnet dispute agents in the UI. + // Do not limit devs' ability to register test agents. + put("registerDisputeAgent", new GrpcCallRateMeter(1, SECONDS)); + }} + ))); } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcGetTradeStatisticsService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcGetTradeStatisticsService.java index 0245e488c29..2fe205011b0 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcGetTradeStatisticsService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcGetTradeStatisticsService.java @@ -58,12 +58,11 @@ final ServerInterceptor[] interceptors() { } final Optional rateMeteringInterceptor() { - CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = - new CallRateMeteringInterceptor(new HashMap<>() {{ - put("getTradeStatistics", new GrpcCallRateMeter(1, SECONDS)); - }}); - return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) - .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + .or(() -> Optional.of(CallRateMeteringInterceptor.valueOf( + new HashMap<>() {{ + put("getTradeStatistics", new GrpcCallRateMeter(1, SECONDS)); + }} + ))); } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcHelpService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcHelpService.java index 81654dfa826..60cd051ae5a 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcHelpService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcHelpService.java @@ -73,12 +73,11 @@ final ServerInterceptor[] interceptors() { } final Optional rateMeteringInterceptor() { - CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = - new CallRateMeteringInterceptor(new HashMap<>() {{ - put("getMethodHelp", new GrpcCallRateMeter(1, SECONDS)); - }}); - return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) - .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + .or(() -> Optional.of(CallRateMeteringInterceptor.valueOf( + new HashMap<>() {{ + put("getMethodHelp", new GrpcCallRateMeter(1, SECONDS)); + }} + ))); } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java index 6f7f55b4106..784a366865b 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java @@ -190,17 +190,16 @@ final ServerInterceptor[] interceptors() { } final Optional rateMeteringInterceptor() { - CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = - new CallRateMeteringInterceptor(new HashMap<>() {{ - put("getOffer", new GrpcCallRateMeter(1, SECONDS)); - put("getMyOffer", new GrpcCallRateMeter(1, SECONDS)); - put("getOffers", new GrpcCallRateMeter(1, SECONDS)); - put("getMyOffers", new GrpcCallRateMeter(1, SECONDS)); - put("createOffer", new GrpcCallRateMeter(1, MINUTES)); - put("cancelOffer", new GrpcCallRateMeter(1, MINUTES)); - }}); - return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) - .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + .or(() -> Optional.of(CallRateMeteringInterceptor.valueOf( + new HashMap<>() {{ + put("getOffer", new GrpcCallRateMeter(1, SECONDS)); + put("getMyOffer", new GrpcCallRateMeter(1, SECONDS)); + put("getOffers", new GrpcCallRateMeter(1, SECONDS)); + put("getMyOffers", new GrpcCallRateMeter(1, SECONDS)); + put("createOffer", new GrpcCallRateMeter(1, MINUTES)); + put("cancelOffer", new GrpcCallRateMeter(1, MINUTES)); + }} + ))); } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcPaymentAccountsService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcPaymentAccountsService.java index 8d6ad768d31..d0d0c31cfa5 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcPaymentAccountsService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcPaymentAccountsService.java @@ -130,15 +130,14 @@ final ServerInterceptor[] interceptors() { } final Optional rateMeteringInterceptor() { - CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = - new CallRateMeteringInterceptor(new HashMap<>() {{ - put("createPaymentAccount", new GrpcCallRateMeter(1, MINUTES)); - put("getPaymentAccounts", new GrpcCallRateMeter(1, SECONDS)); - put("getPaymentMethods", new GrpcCallRateMeter(1, SECONDS)); - put("getPaymentAccountForm", new GrpcCallRateMeter(1, SECONDS)); - }}); - return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) - .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + .or(() -> Optional.of(CallRateMeteringInterceptor.valueOf( + new HashMap<>() {{ + put("createPaymentAccount", new GrpcCallRateMeter(1, MINUTES)); + put("getPaymentAccounts", new GrpcCallRateMeter(1, SECONDS)); + put("getPaymentMethods", new GrpcCallRateMeter(1, SECONDS)); + put("getPaymentAccountForm", new GrpcCallRateMeter(1, SECONDS)); + }} + ))); } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcPriceService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcPriceService.java index 0dee3dae0ed..55a0ebe2d0e 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcPriceService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcPriceService.java @@ -75,12 +75,11 @@ final ServerInterceptor[] interceptors() { } final Optional rateMeteringInterceptor() { - CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = - new CallRateMeteringInterceptor(new HashMap<>() {{ - put("getMarketPrice", new GrpcCallRateMeter(1, SECONDS)); - }}); - return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) - .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + .or(() -> Optional.of(CallRateMeteringInterceptor.valueOf( + new HashMap<>() {{ + put("getMarketPrice", new GrpcCallRateMeter(1, SECONDS)); + }} + ))); } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java index a87a180dedd..f6bcd3d97bd 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java @@ -162,17 +162,16 @@ final ServerInterceptor[] interceptors() { } final Optional rateMeteringInterceptor() { - CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = - new CallRateMeteringInterceptor(new HashMap<>() {{ - put("getTrade", new GrpcCallRateMeter(1, SECONDS)); - put("takeOffer", new GrpcCallRateMeter(1, MINUTES)); - put("confirmPaymentStarted", new GrpcCallRateMeter(1, MINUTES)); - put("confirmPaymentReceived", new GrpcCallRateMeter(1, MINUTES)); - put("keepFunds", new GrpcCallRateMeter(1, MINUTES)); - put("withdrawFunds", new GrpcCallRateMeter(1, MINUTES)); - }}); - return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) - .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + .or(() -> Optional.of(CallRateMeteringInterceptor.valueOf( + new HashMap<>() {{ + put("getTrade", new GrpcCallRateMeter(1, SECONDS)); + put("takeOffer", new GrpcCallRateMeter(1, MINUTES)); + put("confirmPaymentStarted", new GrpcCallRateMeter(1, MINUTES)); + put("confirmPaymentReceived", new GrpcCallRateMeter(1, MINUTES)); + put("keepFunds", new GrpcCallRateMeter(1, MINUTES)); + put("withdrawFunds", new GrpcCallRateMeter(1, MINUTES)); + }} + ))); } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcVersionService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcVersionService.java index 268c60b0236..24c114bc03f 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcVersionService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcVersionService.java @@ -74,12 +74,11 @@ final ServerInterceptor[] interceptors() { } final Optional rateMeteringInterceptor() { - CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = - new CallRateMeteringInterceptor(new HashMap<>() {{ - put("getVersion", new GrpcCallRateMeter(1, SECONDS)); - }}); - return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) - .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + .or(() -> Optional.of(CallRateMeteringInterceptor.valueOf( + new HashMap<>() {{ + put("getVersion", new GrpcCallRateMeter(1, SECONDS)); + }} + ))); } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java index e7ba1086c82..448957432cb 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java @@ -349,29 +349,28 @@ final ServerInterceptor[] interceptors() { } final Optional rateMeteringInterceptor() { - CallRateMeteringInterceptor defaultCallRateMeteringInterceptor = - new CallRateMeteringInterceptor(new HashMap<>() {{ - put("getBalances", new GrpcCallRateMeter(1, SECONDS)); - put("getAddressBalance", new GrpcCallRateMeter(1, SECONDS)); - put("getFundingAddresses", new GrpcCallRateMeter(1, SECONDS)); - put("getUnusedBsqAddress", new GrpcCallRateMeter(1, SECONDS)); - put("sendBsq", new GrpcCallRateMeter(1, MINUTES)); - put("sendBtc", new GrpcCallRateMeter(1, MINUTES)); - put("getTxFeeRate", new GrpcCallRateMeter(1, SECONDS)); - put("setTxFeeRatePreference", new GrpcCallRateMeter(1, SECONDS)); - put("unsetTxFeeRatePreference", new GrpcCallRateMeter(1, SECONDS)); - put("getTransaction", new GrpcCallRateMeter(1, SECONDS)); - - // Trying to set or remove a wallet password several times before the 1st attempt has time to - // persist the change to disk may corrupt the wallet, so allow only 1 attempt per 5 seconds. - put("setWalletPassword", new GrpcCallRateMeter(1, SECONDS, 5)); - put("removeWalletPassword", new GrpcCallRateMeter(1, SECONDS, 5)); - - put("lockWallet", new GrpcCallRateMeter(1, SECONDS)); - put("unlockWallet", new GrpcCallRateMeter(1, SECONDS)); - }}); - return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) - .or(() -> Optional.of(defaultCallRateMeteringInterceptor)); + .or(() -> Optional.of(CallRateMeteringInterceptor.valueOf( + new HashMap<>() {{ + put("getBalances", new GrpcCallRateMeter(1, SECONDS)); + put("getAddressBalance", new GrpcCallRateMeter(1, SECONDS)); + put("getFundingAddresses", new GrpcCallRateMeter(1, SECONDS)); + put("getUnusedBsqAddress", new GrpcCallRateMeter(1, SECONDS)); + put("sendBsq", new GrpcCallRateMeter(1, MINUTES)); + put("sendBtc", new GrpcCallRateMeter(1, MINUTES)); + put("getTxFeeRate", new GrpcCallRateMeter(1, SECONDS)); + put("setTxFeeRatePreference", new GrpcCallRateMeter(1, SECONDS)); + put("unsetTxFeeRatePreference", new GrpcCallRateMeter(1, SECONDS)); + put("getTransaction", new GrpcCallRateMeter(1, SECONDS)); + + // Trying to set or remove a wallet password several times before the 1st attempt has time to + // persist the change to disk may corrupt the wallet, so allow only 1 attempt per 5 seconds. + put("setWalletPassword", new GrpcCallRateMeter(1, SECONDS, 5)); + put("removeWalletPassword", new GrpcCallRateMeter(1, SECONDS, 5)); + + put("lockWallet", new GrpcCallRateMeter(1, SECONDS)); + put("unlockWallet", new GrpcCallRateMeter(1, SECONDS)); + }} + ))); } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/interceptor/CallRateMeteringInterceptor.java b/daemon/src/main/java/bisq/daemon/grpc/interceptor/CallRateMeteringInterceptor.java index 8cd7e1edeb0..429ed1e22c7 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/interceptor/CallRateMeteringInterceptor.java +++ b/daemon/src/main/java/bisq/daemon/grpc/interceptor/CallRateMeteringInterceptor.java @@ -25,6 +25,7 @@ import org.apache.commons.lang3.StringUtils; +import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -124,4 +125,10 @@ public String toString() { rateMetersString + "\n\t" + "}" + "\n" + "}"; } + + public static CallRateMeteringInterceptor valueOf(Map rateMeters) { + return new CallRateMeteringInterceptor(new HashMap<>() {{ + putAll(rateMeters); + }}); + } }