mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 07:07:43 +01:00
Merge pull request #5250 from ghubstan/03-fix-interceptor-method-key-lookup
Fix call rate metering interceptor bug
This commit is contained in:
commit
6f0f0ef5fc
16 changed files with 149 additions and 125 deletions
|
@ -53,6 +53,8 @@
|
|||
}
|
||||
|
||||
@test "test getversion" {
|
||||
# Wait 1 second before calling getversion again.
|
||||
sleep 1
|
||||
load 'version-parser'
|
||||
run ./bisq-cli --password=xyz getversion
|
||||
[ "$status" -eq 0 ]
|
||||
|
@ -118,6 +120,8 @@
|
|||
}
|
||||
|
||||
@test "test setwalletpassword oldpwd newpwd" {
|
||||
# Wait 5 seconds before calling setwalletpassword again.
|
||||
sleep 5
|
||||
run ./bisq-cli --password=xyz setwalletpassword --wallet-password="a b c" --new-wallet-password="d e f"
|
||||
[ "$status" -eq 0 ]
|
||||
echo "actual output: $output" >&2
|
||||
|
@ -137,7 +141,7 @@
|
|||
[ "$status" -eq 0 ]
|
||||
echo "actual output: $output" >&2
|
||||
[ "$output" = "wallet decrypted" ]
|
||||
sleep 1
|
||||
sleep 3
|
||||
}
|
||||
|
||||
@test "test getbalance when wallet available & unlocked with 0 btc balance" {
|
||||
|
@ -151,7 +155,7 @@
|
|||
}
|
||||
|
||||
@test "test getunusedbsqaddress" {
|
||||
run ./bisq-cli --password=xyz getfundingaddresses
|
||||
run ./bisq-cli --password=xyz getunusedbsqaddress
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
|
@ -163,6 +167,8 @@
|
|||
}
|
||||
|
||||
@test "test getaddressbalance bogus address argument" {
|
||||
# Wait 1 second before calling getaddressbalance again.
|
||||
sleep 1
|
||||
run ./bisq-cli --password=xyz getaddressbalance --address=bogus
|
||||
[ "$status" -eq 1 ]
|
||||
echo "actual output: $output" >&2
|
||||
|
@ -187,16 +193,22 @@
|
|||
}
|
||||
|
||||
@test "test getoffers sell eur check return status" {
|
||||
# Wait 1 second before calling getoffers again.
|
||||
sleep 1
|
||||
run ./bisq-cli --password=xyz getoffers --direction=sell --currency-code=eur
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "test getoffers buy eur check return status" {
|
||||
# Wait 1 second before calling getoffers again.
|
||||
sleep 1
|
||||
run ./bisq-cli --password=xyz getoffers --direction=buy --currency-code=eur
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "test getoffers sell gbp check return status" {
|
||||
# Wait 1 second before calling getoffers again.
|
||||
sleep 1
|
||||
run ./bisq-cli --password=xyz getoffers --direction=sell --currency-code=gbp
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
@ -216,3 +228,9 @@
|
|||
[ "${lines[1]}" = "Usage: bisq-cli [options] <method> [params]" ]
|
||||
# TODO add asserts after help text is modified for new endpoints
|
||||
}
|
||||
|
||||
@test "test takeoffer method --help" {
|
||||
run ./bisq-cli --password=xyz takeoffer --help
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${lines[0]}" = "takeoffer" ]
|
||||
}
|
||||
|
|
|
@ -17,11 +17,14 @@
|
|||
|
||||
package bisq.apitest;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
|
@ -29,15 +32,20 @@ import org.junit.jupiter.api.TestInfo;
|
|||
import static bisq.apitest.config.BisqAppConfig.alicedaemon;
|
||||
import static bisq.apitest.config.BisqAppConfig.arbdaemon;
|
||||
import static bisq.apitest.config.BisqAppConfig.bobdaemon;
|
||||
import static bisq.proto.grpc.DisputeAgentsGrpc.getRegisterDisputeAgentMethod;
|
||||
import static bisq.proto.grpc.GetVersionGrpc.getGetVersionMethod;
|
||||
import static java.net.InetAddress.getLoopbackAddress;
|
||||
import static java.util.Arrays.stream;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
|
||||
|
||||
import bisq.apitest.config.ApiTestConfig;
|
||||
import bisq.apitest.method.BitcoinCliHelper;
|
||||
import bisq.cli.GrpcClient;
|
||||
import bisq.daemon.grpc.GrpcVersionService;
|
||||
import bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig;
|
||||
|
||||
/**
|
||||
* Base class for all test types: 'method', 'scenario' and 'e2e'.
|
||||
|
@ -64,6 +72,7 @@ import bisq.cli.GrpcClient;
|
|||
* <p>
|
||||
* Initial Bob balances & accounts: 10.0 BTC, 1500000.00 BSQ, USD PerfectMoney dummy
|
||||
*/
|
||||
@Slf4j
|
||||
public class ApiTestCase {
|
||||
|
||||
protected static Scaffold scaffold;
|
||||
|
@ -79,12 +88,12 @@ public class ApiTestCase {
|
|||
|
||||
public static void setUpScaffold(Enum<?>... supportingApps)
|
||||
throws InterruptedException, ExecutionException, IOException {
|
||||
scaffold = new Scaffold(stream(supportingApps).map(Enum::name)
|
||||
.collect(Collectors.joining(",")))
|
||||
.setUp();
|
||||
config = scaffold.config;
|
||||
bitcoinCli = new BitcoinCliHelper((config));
|
||||
createGrpcClients();
|
||||
String[] params = new String[]{
|
||||
"--supportingApps", stream(supportingApps).map(Enum::name).collect(Collectors.joining(",")),
|
||||
"--callRateMeteringConfigPath", defaultRateMeterInterceptorConfig().getAbsolutePath(),
|
||||
"--enableBisqDebugging", "false"
|
||||
};
|
||||
setUpScaffold(params);
|
||||
}
|
||||
|
||||
public static void setUpScaffold(String[] params)
|
||||
|
@ -139,4 +148,37 @@ public class ApiTestCase {
|
|||
? testInfo.getTestMethod().get().getName()
|
||||
: "unknown test name";
|
||||
}
|
||||
|
||||
protected static File defaultRateMeterInterceptorConfig() {
|
||||
GrpcServiceRateMeteringConfig.Builder builder = new GrpcServiceRateMeteringConfig.Builder();
|
||||
builder.addCallRateMeter(GrpcVersionService.class.getSimpleName(),
|
||||
getGetVersionMethod().getFullMethodName(),
|
||||
1,
|
||||
SECONDS);
|
||||
// Only GrpcVersionService is @VisibleForTesting, so we need to
|
||||
// hardcode other grpcServiceClassName parameter values used in
|
||||
// builder.addCallRateMeter(...).
|
||||
builder.addCallRateMeter("GrpcDisputeAgentsService",
|
||||
getRegisterDisputeAgentMethod().getFullMethodName(),
|
||||
10, // Same as default.
|
||||
SECONDS);
|
||||
// Define rate meters for non-existent method 'disabled', to override other grpc
|
||||
// services' default rate meters -- defined in their rateMeteringInterceptor()
|
||||
// methods.
|
||||
String[] serviceClassNames = new String[]{
|
||||
"GrpcGetTradeStatisticsService",
|
||||
"GrpcHelpService",
|
||||
"GrpcOffersService",
|
||||
"GrpcPaymentAccountsService",
|
||||
"GrpcPriceService",
|
||||
"GrpcTradesService",
|
||||
"GrpcWalletsService"
|
||||
};
|
||||
for (String service : serviceClassNames) {
|
||||
builder.addCallRateMeter(service, "disabled", 1, MILLISECONDS);
|
||||
}
|
||||
File file = builder.build();
|
||||
file.deleteOnExit();
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,9 +19,6 @@ package bisq.apitest.method;
|
|||
|
||||
import io.grpc.StatusRuntimeException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
|
@ -35,19 +32,9 @@ import org.junit.jupiter.api.TestMethodOrder;
|
|||
|
||||
import static bisq.apitest.Scaffold.BitcoinCoreApp.bitcoind;
|
||||
import static bisq.apitest.config.BisqAppConfig.alicedaemon;
|
||||
import static bisq.common.file.FileUtil.deleteFileIfExists;
|
||||
import static java.util.concurrent.TimeUnit.DAYS;
|
||||
import static java.util.concurrent.TimeUnit.HOURS;
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
|
||||
|
||||
import bisq.daemon.grpc.GrpcVersionService;
|
||||
import bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig;
|
||||
|
||||
@Disabled
|
||||
@Slf4j
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
|
@ -55,13 +42,9 @@ public class CallRateMeteringInterceptorTest extends MethodTest {
|
|||
|
||||
private static final GetVersionTest getVersionTest = new GetVersionTest();
|
||||
|
||||
private static File callRateMeteringConfigFile;
|
||||
|
||||
@BeforeAll
|
||||
public static void setUp() {
|
||||
callRateMeteringConfigFile = buildInterceptorConfigFile();
|
||||
startSupportingApps(callRateMeteringConfigFile,
|
||||
false,
|
||||
startSupportingApps(false,
|
||||
false,
|
||||
bitcoind, alicedaemon);
|
||||
}
|
||||
|
@ -102,37 +85,6 @@ public class CallRateMeteringInterceptorTest extends MethodTest {
|
|||
|
||||
@AfterAll
|
||||
public static void tearDown() {
|
||||
try {
|
||||
deleteFileIfExists(callRateMeteringConfigFile);
|
||||
} catch (IOException ex) {
|
||||
log.error(ex.getMessage());
|
||||
}
|
||||
tearDownScaffold();
|
||||
}
|
||||
|
||||
public static File buildInterceptorConfigFile() {
|
||||
GrpcServiceRateMeteringConfig.Builder builder = new GrpcServiceRateMeteringConfig.Builder();
|
||||
builder.addCallRateMeter(GrpcVersionService.class.getSimpleName(),
|
||||
"getVersion",
|
||||
1,
|
||||
SECONDS);
|
||||
builder.addCallRateMeter(GrpcVersionService.class.getSimpleName(),
|
||||
"shouldNotBreakAnything",
|
||||
1000,
|
||||
DAYS);
|
||||
// Only GrpcVersionService is @VisibleForTesting, so we hardcode the class names.
|
||||
builder.addCallRateMeter("GrpcOffersService",
|
||||
"createOffer",
|
||||
5,
|
||||
MINUTES);
|
||||
builder.addCallRateMeter("GrpcTradesService",
|
||||
"takeOffer",
|
||||
10,
|
||||
DAYS);
|
||||
builder.addCallRateMeter("GrpcTradesService",
|
||||
"withdrawFunds",
|
||||
3,
|
||||
HOURS);
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,8 +71,11 @@ public class MethodTest extends ApiTestCase {
|
|||
boolean generateBtcBlock,
|
||||
Enum<?>... supportingApps) {
|
||||
try {
|
||||
// Disable call rate metering where there is no callRateMeteringConfigFile.
|
||||
File callRateMeteringConfigFile = defaultRateMeterInterceptorConfig();
|
||||
setUpScaffold(new String[]{
|
||||
"--supportingApps", toNameList.apply(supportingApps),
|
||||
"--callRateMeteringConfigPath", callRateMeteringConfigFile.getAbsolutePath(),
|
||||
"--enableBisqDebugging", "false"
|
||||
});
|
||||
doPostStartup(registerDisputeAgents, generateBtcBlock);
|
||||
|
|
|
@ -33,7 +33,6 @@ import static bisq.apitest.Scaffold.BitcoinCoreApp.bitcoind;
|
|||
import static bisq.apitest.config.BisqAppConfig.alicedaemon;
|
||||
import static bisq.apitest.config.BisqAppConfig.arbdaemon;
|
||||
import static bisq.apitest.config.BisqAppConfig.seednode;
|
||||
import static bisq.apitest.method.CallRateMeteringInterceptorTest.buildInterceptorConfigFile;
|
||||
import static bisq.common.file.FileUtil.deleteFileIfExists;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
@ -55,7 +54,7 @@ public class StartupTest extends MethodTest {
|
|||
@BeforeAll
|
||||
public static void setUp() {
|
||||
try {
|
||||
callRateMeteringConfigFile = buildInterceptorConfigFile();
|
||||
callRateMeteringConfigFile = defaultRateMeterInterceptorConfig();
|
||||
startSupportingApps(callRateMeteringConfigFile,
|
||||
false,
|
||||
false,
|
||||
|
|
|
@ -2,7 +2,6 @@ package bisq.daemon.grpc;
|
|||
|
||||
import bisq.core.api.CoreApi;
|
||||
|
||||
import bisq.proto.grpc.DisputeAgentsGrpc;
|
||||
import bisq.proto.grpc.RegisterDisputeAgentReply;
|
||||
import bisq.proto.grpc.RegisterDisputeAgentRequest;
|
||||
|
||||
|
@ -17,6 +16,8 @@ import java.util.Optional;
|
|||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor;
|
||||
import static bisq.proto.grpc.DisputeAgentsGrpc.DisputeAgentsImplBase;
|
||||
import static bisq.proto.grpc.DisputeAgentsGrpc.getRegisterDisputeAgentMethod;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
|
||||
|
@ -25,7 +26,7 @@ import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor;
|
|||
import bisq.daemon.grpc.interceptor.GrpcCallRateMeter;
|
||||
|
||||
@Slf4j
|
||||
class GrpcDisputeAgentsService extends DisputeAgentsGrpc.DisputeAgentsImplBase {
|
||||
class GrpcDisputeAgentsService extends DisputeAgentsImplBase {
|
||||
|
||||
private final CoreApi coreApi;
|
||||
private final GrpcExceptionHandler exceptionHandler;
|
||||
|
@ -59,9 +60,9 @@ class GrpcDisputeAgentsService extends DisputeAgentsGrpc.DisputeAgentsImplBase {
|
|||
return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass())
|
||||
.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));
|
||||
// Do not limit devs' ability to test agent registration
|
||||
// and call validation in regtest arbitration daemons.
|
||||
put(getRegisterDisputeAgentMethod().getFullMethodName(), new GrpcCallRateMeter(10, SECONDS));
|
||||
}}
|
||||
)));
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package bisq.daemon.grpc;
|
|||
import bisq.core.api.CoreApi;
|
||||
import bisq.core.trade.statistics.TradeStatistics3;
|
||||
|
||||
import bisq.proto.grpc.GetTradeStatisticsGrpc;
|
||||
import bisq.proto.grpc.GetTradeStatisticsReply;
|
||||
import bisq.proto.grpc.GetTradeStatisticsRequest;
|
||||
|
||||
|
@ -19,6 +18,8 @@ import java.util.stream.Collectors;
|
|||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor;
|
||||
import static bisq.proto.grpc.GetTradeStatisticsGrpc.GetTradeStatisticsImplBase;
|
||||
import static bisq.proto.grpc.GetTradeStatisticsGrpc.getGetTradeStatisticsMethod;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
|
||||
|
@ -27,7 +28,7 @@ import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor;
|
|||
import bisq.daemon.grpc.interceptor.GrpcCallRateMeter;
|
||||
|
||||
@Slf4j
|
||||
class GrpcGetTradeStatisticsService extends GetTradeStatisticsGrpc.GetTradeStatisticsImplBase {
|
||||
class GrpcGetTradeStatisticsService extends GetTradeStatisticsImplBase {
|
||||
|
||||
private final CoreApi coreApi;
|
||||
private final GrpcExceptionHandler exceptionHandler;
|
||||
|
@ -64,7 +65,7 @@ class GrpcGetTradeStatisticsService extends GetTradeStatisticsGrpc.GetTradeStati
|
|||
return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass())
|
||||
.or(() -> Optional.of(CallRateMeteringInterceptor.valueOf(
|
||||
new HashMap<>() {{
|
||||
put("getTradeStatistics", new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getGetTradeStatisticsMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
}}
|
||||
)));
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import bisq.core.api.CoreApi;
|
|||
|
||||
import bisq.proto.grpc.GetMethodHelpReply;
|
||||
import bisq.proto.grpc.GetMethodHelpRequest;
|
||||
import bisq.proto.grpc.HelpGrpc;
|
||||
|
||||
import io.grpc.ServerInterceptor;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
|
@ -34,6 +33,8 @@ import java.util.Optional;
|
|||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor;
|
||||
import static bisq.proto.grpc.HelpGrpc.HelpImplBase;
|
||||
import static bisq.proto.grpc.HelpGrpc.getGetMethodHelpMethod;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
|
||||
|
@ -42,7 +43,7 @@ import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor;
|
|||
import bisq.daemon.grpc.interceptor.GrpcCallRateMeter;
|
||||
|
||||
@Slf4j
|
||||
class GrpcHelpService extends HelpGrpc.HelpImplBase {
|
||||
class GrpcHelpService extends HelpImplBase {
|
||||
|
||||
private final CoreApi coreApi;
|
||||
private final GrpcExceptionHandler exceptionHandler;
|
||||
|
@ -76,7 +77,7 @@ class GrpcHelpService extends HelpGrpc.HelpImplBase {
|
|||
return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass())
|
||||
.or(() -> Optional.of(CallRateMeteringInterceptor.valueOf(
|
||||
new HashMap<>() {{
|
||||
put("getMethodHelp", new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getGetMethodHelpMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
}}
|
||||
)));
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ import bisq.proto.grpc.GetOfferReply;
|
|||
import bisq.proto.grpc.GetOfferRequest;
|
||||
import bisq.proto.grpc.GetOffersReply;
|
||||
import bisq.proto.grpc.GetOffersRequest;
|
||||
import bisq.proto.grpc.OffersGrpc;
|
||||
|
||||
import io.grpc.ServerInterceptor;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
|
@ -50,6 +49,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||
|
||||
import static bisq.core.api.model.OfferInfo.toOfferInfo;
|
||||
import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor;
|
||||
import static bisq.proto.grpc.OffersGrpc.*;
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
|
@ -59,7 +59,7 @@ import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor;
|
|||
import bisq.daemon.grpc.interceptor.GrpcCallRateMeter;
|
||||
|
||||
@Slf4j
|
||||
class GrpcOffersService extends OffersGrpc.OffersImplBase {
|
||||
class GrpcOffersService extends OffersImplBase {
|
||||
|
||||
private final CoreApi coreApi;
|
||||
private final GrpcExceptionHandler exceptionHandler;
|
||||
|
@ -193,12 +193,12 @@ class GrpcOffersService extends OffersGrpc.OffersImplBase {
|
|||
return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass())
|
||||
.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));
|
||||
put(getGetOfferMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getGetMyOfferMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getGetOffersMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getGetMyOffersMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getCreateOfferMethod().getFullMethodName(), new GrpcCallRateMeter(1, MINUTES));
|
||||
put(getCancelOfferMethod().getFullMethodName(), new GrpcCallRateMeter(1, MINUTES));
|
||||
}}
|
||||
)));
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import bisq.proto.grpc.GetPaymentAccountsReply;
|
|||
import bisq.proto.grpc.GetPaymentAccountsRequest;
|
||||
import bisq.proto.grpc.GetPaymentMethodsReply;
|
||||
import bisq.proto.grpc.GetPaymentMethodsRequest;
|
||||
import bisq.proto.grpc.PaymentAccountsGrpc;
|
||||
|
||||
import io.grpc.ServerInterceptor;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
|
@ -43,6 +42,7 @@ import java.util.stream.Collectors;
|
|||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor;
|
||||
import static bisq.proto.grpc.PaymentAccountsGrpc.*;
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
|
@ -52,7 +52,7 @@ import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor;
|
|||
import bisq.daemon.grpc.interceptor.GrpcCallRateMeter;
|
||||
|
||||
@Slf4j
|
||||
class GrpcPaymentAccountsService extends PaymentAccountsGrpc.PaymentAccountsImplBase {
|
||||
class GrpcPaymentAccountsService extends PaymentAccountsImplBase {
|
||||
|
||||
private final CoreApi coreApi;
|
||||
private final GrpcExceptionHandler exceptionHandler;
|
||||
|
@ -135,10 +135,10 @@ class GrpcPaymentAccountsService extends PaymentAccountsGrpc.PaymentAccountsImpl
|
|||
return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass())
|
||||
.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));
|
||||
put(getCreatePaymentAccountMethod().getFullMethodName(), new GrpcCallRateMeter(1, MINUTES));
|
||||
put(getGetPaymentAccountsMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getGetPaymentMethodsMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getGetPaymentAccountFormMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
}}
|
||||
)));
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import bisq.core.api.CoreApi;
|
|||
|
||||
import bisq.proto.grpc.MarketPriceReply;
|
||||
import bisq.proto.grpc.MarketPriceRequest;
|
||||
import bisq.proto.grpc.PriceGrpc;
|
||||
|
||||
import io.grpc.ServerInterceptor;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
|
@ -34,6 +33,8 @@ import java.util.Optional;
|
|||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor;
|
||||
import static bisq.proto.grpc.PriceGrpc.PriceImplBase;
|
||||
import static bisq.proto.grpc.PriceGrpc.getGetMarketPriceMethod;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
|
||||
|
@ -42,7 +43,7 @@ import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor;
|
|||
import bisq.daemon.grpc.interceptor.GrpcCallRateMeter;
|
||||
|
||||
@Slf4j
|
||||
class GrpcPriceService extends PriceGrpc.PriceImplBase {
|
||||
class GrpcPriceService extends PriceImplBase {
|
||||
|
||||
private final CoreApi coreApi;
|
||||
private final GrpcExceptionHandler exceptionHandler;
|
||||
|
@ -78,7 +79,7 @@ class GrpcPriceService extends PriceGrpc.PriceImplBase {
|
|||
return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass())
|
||||
.or(() -> Optional.of(CallRateMeteringInterceptor.valueOf(
|
||||
new HashMap<>() {{
|
||||
put("getMarketPrice", new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getGetMarketPriceMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
}}
|
||||
)));
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ import bisq.proto.grpc.KeepFundsReply;
|
|||
import bisq.proto.grpc.KeepFundsRequest;
|
||||
import bisq.proto.grpc.TakeOfferReply;
|
||||
import bisq.proto.grpc.TakeOfferRequest;
|
||||
import bisq.proto.grpc.TradesGrpc;
|
||||
import bisq.proto.grpc.WithdrawFundsReply;
|
||||
import bisq.proto.grpc.WithdrawFundsRequest;
|
||||
|
||||
|
@ -47,6 +46,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||
|
||||
import static bisq.core.api.model.TradeInfo.toTradeInfo;
|
||||
import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor;
|
||||
import static bisq.proto.grpc.TradesGrpc.*;
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
|
@ -56,7 +56,7 @@ import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor;
|
|||
import bisq.daemon.grpc.interceptor.GrpcCallRateMeter;
|
||||
|
||||
@Slf4j
|
||||
class GrpcTradesService extends TradesGrpc.TradesImplBase {
|
||||
class GrpcTradesService extends TradesImplBase {
|
||||
|
||||
private final CoreApi coreApi;
|
||||
private final GrpcExceptionHandler exceptionHandler;
|
||||
|
@ -169,12 +169,12 @@ class GrpcTradesService extends TradesGrpc.TradesImplBase {
|
|||
return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass())
|
||||
.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));
|
||||
put(getGetTradeMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getTakeOfferMethod().getFullMethodName(), new GrpcCallRateMeter(1, MINUTES));
|
||||
put(getConfirmPaymentStartedMethod().getFullMethodName(), new GrpcCallRateMeter(1, MINUTES));
|
||||
put(getConfirmPaymentReceivedMethod().getFullMethodName(), new GrpcCallRateMeter(1, MINUTES));
|
||||
put(getKeepFundsMethod().getFullMethodName(), new GrpcCallRateMeter(1, MINUTES));
|
||||
put(getWithdrawFundsMethod().getFullMethodName(), new GrpcCallRateMeter(1, MINUTES));
|
||||
}}
|
||||
)));
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ package bisq.daemon.grpc;
|
|||
|
||||
import bisq.core.api.CoreApi;
|
||||
|
||||
import bisq.proto.grpc.GetVersionGrpc;
|
||||
import bisq.proto.grpc.GetVersionReply;
|
||||
import bisq.proto.grpc.GetVersionRequest;
|
||||
|
||||
|
@ -36,6 +35,8 @@ import java.util.Optional;
|
|||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor;
|
||||
import static bisq.proto.grpc.GetVersionGrpc.GetVersionImplBase;
|
||||
import static bisq.proto.grpc.GetVersionGrpc.getGetVersionMethod;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
|
||||
|
@ -45,7 +46,7 @@ import bisq.daemon.grpc.interceptor.GrpcCallRateMeter;
|
|||
|
||||
@VisibleForTesting
|
||||
@Slf4j
|
||||
public class GrpcVersionService extends GetVersionGrpc.GetVersionImplBase {
|
||||
public class GrpcVersionService extends GetVersionImplBase {
|
||||
|
||||
private final CoreApi coreApi;
|
||||
private final GrpcExceptionHandler exceptionHandler;
|
||||
|
@ -77,7 +78,7 @@ public class GrpcVersionService extends GetVersionGrpc.GetVersionImplBase {
|
|||
return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass())
|
||||
.or(() -> Optional.of(CallRateMeteringInterceptor.valueOf(
|
||||
new HashMap<>() {{
|
||||
put("getVersion", new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getGetVersionMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
}}
|
||||
)));
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@ import bisq.proto.grpc.UnlockWalletReply;
|
|||
import bisq.proto.grpc.UnlockWalletRequest;
|
||||
import bisq.proto.grpc.UnsetTxFeeRatePreferenceReply;
|
||||
import bisq.proto.grpc.UnsetTxFeeRatePreferenceRequest;
|
||||
import bisq.proto.grpc.WalletsGrpc;
|
||||
|
||||
import io.grpc.ServerInterceptor;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
|
@ -73,6 +72,7 @@ import org.jetbrains.annotations.NotNull;
|
|||
|
||||
import static bisq.core.api.model.TxInfo.toTxInfo;
|
||||
import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor;
|
||||
import static bisq.proto.grpc.WalletsGrpc.*;
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
|
@ -82,7 +82,7 @@ import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor;
|
|||
import bisq.daemon.grpc.interceptor.GrpcCallRateMeter;
|
||||
|
||||
@Slf4j
|
||||
class GrpcWalletsService extends WalletsGrpc.WalletsImplBase {
|
||||
class GrpcWalletsService extends WalletsImplBase {
|
||||
|
||||
private final CoreApi coreApi;
|
||||
private final GrpcExceptionHandler exceptionHandler;
|
||||
|
@ -352,24 +352,24 @@ class GrpcWalletsService extends WalletsGrpc.WalletsImplBase {
|
|||
return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass())
|
||||
.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));
|
||||
put(getGetBalancesMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getGetAddressBalanceMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getGetFundingAddressesMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getGetUnusedBsqAddressMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getSendBsqMethod().getFullMethodName(), new GrpcCallRateMeter(1, MINUTES));
|
||||
put(getSendBtcMethod().getFullMethodName(), new GrpcCallRateMeter(1, MINUTES));
|
||||
put(getGetTxFeeRateMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getSetTxFeeRatePreferenceMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getUnsetTxFeeRatePreferenceMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getGetTransactionMethod().getFullMethodName(), 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(getSetWalletPasswordMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS, 5));
|
||||
put(getRemoveWalletPasswordMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS, 5));
|
||||
|
||||
put("lockWallet", new GrpcCallRateMeter(1, SECONDS));
|
||||
put("unlockWallet", new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getLockWalletMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
put(getUnlockWalletMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS));
|
||||
}}
|
||||
)));
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.apache.commons.lang3.StringUtils;
|
|||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -85,16 +84,19 @@ public final class CallRateMeteringInterceptor implements ServerInterceptor {
|
|||
ServerCall<?, ?> serverCall)
|
||||
throws StatusRuntimeException {
|
||||
String msg = getDefaultRateExceededError(methodName, rateMeter);
|
||||
log.warn(StringUtils.capitalize(msg) + ".");
|
||||
serverCall.close(PERMISSION_DENIED.withDescription(msg), new Metadata());
|
||||
log.warn(msg + ".");
|
||||
serverCall.close(PERMISSION_DENIED.withDescription(msg.toLowerCase()), new Metadata());
|
||||
}
|
||||
|
||||
private String getDefaultRateExceededError(String methodName,
|
||||
GrpcCallRateMeter rateMeter) {
|
||||
// The derived method name may not be an exact match to CLI's method name.
|
||||
String timeUnitName = StringUtils.chop(rateMeter.getTimeUnit().name().toLowerCase());
|
||||
return format("the maximum allowed number of %s calls (%d/%s) has been exceeded",
|
||||
methodName.toLowerCase(),
|
||||
// Just print 'getversion', not the grpc method descriptor's
|
||||
// full-method-name: 'io.bisq.protobuffer.getversion/getversion'.
|
||||
String loggedMethodName = methodName.split("/")[1];
|
||||
return format("The maximum allowed number of %s calls (%d/%s) has been exceeded",
|
||||
loggedMethodName,
|
||||
rateMeter.getAllowedCallsPerTimeWindow(),
|
||||
timeUnitName);
|
||||
}
|
||||
|
@ -106,11 +108,11 @@ public final class CallRateMeteringInterceptor implements ServerInterceptor {
|
|||
}
|
||||
|
||||
private String getRateMeterKey(ServerCall<?, ?> serverCall) {
|
||||
// Get the rate meter map key from the full rpc service name. The key name
|
||||
// is hard coded in the Grpc*Service interceptors() method.
|
||||
String fullServiceName = serverCall.getMethodDescriptor().getServiceName();
|
||||
return StringUtils.uncapitalize(Objects.requireNonNull(fullServiceName)
|
||||
.substring("io.bisq.protobuffer.".length()));
|
||||
// Get the rate meter map key from the server call method descriptor. The
|
||||
// returned String (e.g., 'io.bisq.protobuffer.Offers/CreateOffer') will match
|
||||
// a map entry key in the 'serviceCallRateMeters' constructor argument, if it
|
||||
// was defined in the Grpc*Service class' rateMeteringInterceptor method.
|
||||
return serverCall.getMethodDescriptor().getFullMethodName();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -55,8 +55,11 @@ public class GrpcCallRateMeter {
|
|||
|
||||
public String getCallsCountProgress(String calledMethodName) {
|
||||
String shortTimeUnitName = StringUtils.chop(timeUnit.name().toLowerCase());
|
||||
// Just print 'GetVersion has been called N times...',
|
||||
// not 'io.bisq.protobuffer.GetVersion/GetVersion has been called N times...'
|
||||
String loggedMethodName = calledMethodName.split("/")[1];
|
||||
return format("%s has been called %d time%s in the last %s, rate limit is %d/%s",
|
||||
calledMethodName,
|
||||
loggedMethodName,
|
||||
callTimestamps.size(),
|
||||
callTimestamps.size() == 1 ? "" : "s",
|
||||
shortTimeUnitName,
|
||||
|
|
Loading…
Add table
Reference in a new issue