mirror of
https://github.com/bisq-network/bisq.git
synced 2025-03-26 20:30:55 +01:00
Add signature to request to limit the feature to requests from trusted nodes (monitor)
This commit is contained in:
parent
9dab186086
commit
ca7fe94c06
7 changed files with 208 additions and 88 deletions
|
@ -40,12 +40,18 @@ import bisq.common.util.MathUtils;
|
|||
import bisq.common.util.Profiler;
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import org.bitcoinj.core.ECKey;
|
||||
import org.bitcoinj.core.Sha256Hash;
|
||||
import org.bitcoinj.core.SignatureDecodeException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.RuntimeMXBean;
|
||||
|
@ -61,6 +67,7 @@ public class GetInventoryRequestHandler implements MessageListener {
|
|||
private final DaoStateMonitoringService daoStateMonitoringService;
|
||||
private final ProposalStateMonitoringService proposalStateMonitoringService;
|
||||
private final BlindVoteStateMonitoringService blindVoteStateMonitoringService;
|
||||
private final Set<String> permittedRequestersPubKey = new HashSet<>();
|
||||
|
||||
@Inject
|
||||
public GetInventoryRequestHandler(NetworkNode networkNode,
|
||||
|
@ -84,93 +91,121 @@ public class GetInventoryRequestHandler implements MessageListener {
|
|||
@Override
|
||||
public void onMessage(NetworkEnvelope networkEnvelope, Connection connection) {
|
||||
if (networkEnvelope instanceof GetInventoryRequest) {
|
||||
if (permittedRequestersPubKey.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GetInventoryRequest getInventoryRequest = (GetInventoryRequest) networkEnvelope;
|
||||
if (isPermitted(getInventoryRequest)) {
|
||||
Map<String, Integer> dataObjects = new HashMap<>();
|
||||
p2PDataStorage.getMapForDataResponse(getInventoryRequest.getVersion()).values().stream()
|
||||
.map(e -> e.getClass().getSimpleName())
|
||||
.forEach(className -> {
|
||||
dataObjects.putIfAbsent(className, 0);
|
||||
int prev = dataObjects.get(className);
|
||||
dataObjects.put(className, prev + 1);
|
||||
});
|
||||
p2PDataStorage.getMap().values().stream()
|
||||
.map(ProtectedStorageEntry::getProtectedStoragePayload)
|
||||
.filter(Objects::nonNull)
|
||||
.map(e -> e.getClass().getSimpleName())
|
||||
.forEach(className -> {
|
||||
dataObjects.putIfAbsent(className, 0);
|
||||
int prev = dataObjects.get(className);
|
||||
dataObjects.put(className, prev + 1);
|
||||
});
|
||||
Map<String, String> inventory = new HashMap<>();
|
||||
dataObjects.forEach((key, value) -> inventory.put(key, String.valueOf(value)));
|
||||
|
||||
Map<String, Integer> dataObjects = new HashMap<>();
|
||||
p2PDataStorage.getMapForDataResponse(getInventoryRequest.getVersion()).values().stream()
|
||||
.map(e -> e.getClass().getSimpleName())
|
||||
.forEach(className -> {
|
||||
dataObjects.putIfAbsent(className, 0);
|
||||
int prev = dataObjects.get(className);
|
||||
dataObjects.put(className, prev + 1);
|
||||
});
|
||||
p2PDataStorage.getMap().values().stream()
|
||||
.map(ProtectedStorageEntry::getProtectedStoragePayload)
|
||||
.filter(Objects::nonNull)
|
||||
.map(e -> e.getClass().getSimpleName())
|
||||
.forEach(className -> {
|
||||
dataObjects.putIfAbsent(className, 0);
|
||||
int prev = dataObjects.get(className);
|
||||
dataObjects.put(className, prev + 1);
|
||||
});
|
||||
Map<String, String> inventory = new HashMap<>();
|
||||
dataObjects.forEach((key, value) -> inventory.put(key, String.valueOf(value)));
|
||||
// DAO data
|
||||
int numBsqBlocks = daoStateService.getBlocks().size();
|
||||
inventory.put("numBsqBlocks", String.valueOf(numBsqBlocks));
|
||||
|
||||
// DAO data
|
||||
int numBsqBlocks = daoStateService.getBlocks().size();
|
||||
inventory.put("numBsqBlocks", String.valueOf(numBsqBlocks));
|
||||
int daoStateChainHeight = daoStateService.getChainHeight();
|
||||
inventory.put("daoStateChainHeight", String.valueOf(daoStateChainHeight));
|
||||
|
||||
int daoStateChainHeight = daoStateService.getChainHeight();
|
||||
inventory.put("daoStateChainHeight", String.valueOf(daoStateChainHeight));
|
||||
int walletChainHeight = btcWalletService.getBestChainHeight();
|
||||
inventory.put("walletChainHeight", String.valueOf(walletChainHeight));
|
||||
|
||||
int walletChainHeight = btcWalletService.getBestChainHeight();
|
||||
inventory.put("walletChainHeight", String.valueOf(walletChainHeight));
|
||||
LinkedList<DaoStateBlock> daoStateBlockChain = daoStateMonitoringService.getDaoStateBlockChain();
|
||||
if (!daoStateBlockChain.isEmpty()) {
|
||||
String daoStateHash = Utilities.bytesAsHexString(daoStateBlockChain.getLast().getMyStateHash().getHash());
|
||||
inventory.put("daoStateHash", daoStateHash);
|
||||
} else {
|
||||
inventory.put("daoStateHash", "n/a");
|
||||
}
|
||||
|
||||
LinkedList<DaoStateBlock> daoStateBlockChain = daoStateMonitoringService.getDaoStateBlockChain();
|
||||
if (!daoStateBlockChain.isEmpty()) {
|
||||
String daoStateHash = Utilities.bytesAsHexString(daoStateBlockChain.getLast().getMyStateHash().getHash());
|
||||
inventory.put("daoStateHash", daoStateHash);
|
||||
} else {
|
||||
inventory.put("daoStateHash", "n/a");
|
||||
LinkedList<ProposalStateBlock> proposalStateBlockChain = proposalStateMonitoringService.getProposalStateBlockChain();
|
||||
if (!proposalStateBlockChain.isEmpty()) {
|
||||
String proposalHash = Utilities.bytesAsHexString(proposalStateBlockChain.getLast().getMyStateHash().getHash());
|
||||
inventory.put("proposalHash", proposalHash);
|
||||
} else {
|
||||
inventory.put("proposalHash", "n/a");
|
||||
}
|
||||
|
||||
LinkedList<BlindVoteStateBlock> blindVoteStateBlockChain = blindVoteStateMonitoringService.getBlindVoteStateBlockChain();
|
||||
if (!blindVoteStateBlockChain.isEmpty()) {
|
||||
String blindVoteHash = Utilities.bytesAsHexString(blindVoteStateBlockChain.getLast().getMyStateHash().getHash());
|
||||
inventory.put("blindVoteHash", blindVoteHash);
|
||||
} else {
|
||||
inventory.put("blindVoteHash", "n/a");
|
||||
}
|
||||
|
||||
// P2P network data
|
||||
int numConnections = networkNode.getAllConnections().size();
|
||||
inventory.put("numConnections", String.valueOf(numConnections));
|
||||
|
||||
long sentBytes = Statistic.totalSentBytesProperty().get();
|
||||
inventory.put("sentBytes", String.valueOf(sentBytes));
|
||||
|
||||
long receivedBytes = Statistic.totalReceivedBytesProperty().get();
|
||||
inventory.put("receivedBytes", String.valueOf(receivedBytes));
|
||||
|
||||
double receivedMessagesPerSec = MathUtils.roundDouble(Statistic.numTotalReceivedMessagesPerSecProperty().get(), 2);
|
||||
inventory.put("receivedMessagesPerSec", String.valueOf(receivedMessagesPerSec));
|
||||
|
||||
double sentMessagesPerSec = MathUtils.roundDouble(Statistic.numTotalSentMessagesPerSecProperty().get(), 2);
|
||||
inventory.put("sentMessagesPerSec", String.valueOf(sentMessagesPerSec));
|
||||
|
||||
// JVM info
|
||||
long usedMemory = Profiler.getUsedMemoryInMB();
|
||||
inventory.put("usedMemory", String.valueOf(usedMemory));
|
||||
|
||||
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
|
||||
long startTime = runtimeBean.getStartTime();
|
||||
inventory.put("jvmStartTime", String.valueOf(startTime));
|
||||
|
||||
log.info("Send inventory {} to {}", inventory, connection.getPeersNodeAddressOptional());
|
||||
GetInventoryResponse getInventoryResponse = new GetInventoryResponse(inventory);
|
||||
networkNode.sendMessage(connection, getInventoryResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LinkedList<ProposalStateBlock> proposalStateBlockChain = proposalStateMonitoringService.getProposalStateBlockChain();
|
||||
if (!proposalStateBlockChain.isEmpty()) {
|
||||
String proposalHash = Utilities.bytesAsHexString(proposalStateBlockChain.getLast().getMyStateHash().getHash());
|
||||
inventory.put("proposalHash", proposalHash);
|
||||
} else {
|
||||
inventory.put("proposalHash", "n/a");
|
||||
}
|
||||
|
||||
LinkedList<BlindVoteStateBlock> blindVoteStateBlockChain = blindVoteStateMonitoringService.getBlindVoteStateBlockChain();
|
||||
if (!blindVoteStateBlockChain.isEmpty()) {
|
||||
String blindVoteHash = Utilities.bytesAsHexString(blindVoteStateBlockChain.getLast().getMyStateHash().getHash());
|
||||
inventory.put("blindVoteHash", blindVoteHash);
|
||||
} else {
|
||||
inventory.put("blindVoteHash", "n/a");
|
||||
}
|
||||
|
||||
// P2P network data
|
||||
int numConnections = networkNode.getAllConnections().size();
|
||||
inventory.put("numConnections", String.valueOf(numConnections));
|
||||
|
||||
long sentBytes = Statistic.totalSentBytesProperty().get();
|
||||
inventory.put("sentBytes", String.valueOf(sentBytes));
|
||||
|
||||
long receivedBytes = Statistic.totalReceivedBytesProperty().get();
|
||||
inventory.put("receivedBytes", String.valueOf(receivedBytes));
|
||||
|
||||
double receivedMessagesPerSec = MathUtils.roundDouble(Statistic.numTotalReceivedMessagesPerSecProperty().get(), 2);
|
||||
inventory.put("receivedMessagesPerSec", String.valueOf(receivedMessagesPerSec));
|
||||
|
||||
double sentMessagesPerSec = MathUtils.roundDouble(Statistic.numTotalSentMessagesPerSecProperty().get(), 2);
|
||||
inventory.put("sentMessagesPerSec", String.valueOf(sentMessagesPerSec));
|
||||
|
||||
// JVM info
|
||||
long usedMemory = Profiler.getUsedMemoryInMB();
|
||||
inventory.put("usedMemory", String.valueOf(usedMemory));
|
||||
|
||||
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
|
||||
long startTime = runtimeBean.getStartTime();
|
||||
inventory.put("jvmStartTime", String.valueOf(startTime));
|
||||
|
||||
log.info("Send inventory {} to {}", inventory, connection.getPeersNodeAddressOptional());
|
||||
GetInventoryResponse getInventoryResponse = new GetInventoryResponse(inventory);
|
||||
networkNode.sendMessage(connection, getInventoryResponse);
|
||||
private boolean isPermitted(GetInventoryRequest getInventoryRequest) {
|
||||
ECKey pubKey = ECKey.fromPublicOnly(getInventoryRequest.getPubKey());
|
||||
String pubKeyAsHex = pubKey.getPublicKeyAsHex();
|
||||
if (!permittedRequestersPubKey.contains(pubKeyAsHex)) {
|
||||
return false;
|
||||
}
|
||||
byte[] nonce = getInventoryRequest.getNonce();
|
||||
byte[] signature = getInventoryRequest.getSignature();
|
||||
try {
|
||||
ECKey.ECDSASignature ecdsaSignature = ECKey.ECDSASignature.decodeFromDER(signature).toCanonicalised();
|
||||
Sha256Hash hash = Sha256Hash.of(nonce);
|
||||
return pubKey.verify(hash, ecdsaSignature);
|
||||
} catch (SignatureDecodeException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void shutDown() {
|
||||
networkNode.removeMessageListener(this);
|
||||
}
|
||||
|
||||
public void addPermittedRequestersPubKey(String pubKey) {
|
||||
permittedRequestersPubKey.add(pubKey);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ import bisq.network.p2p.network.NetworkNode;
|
|||
|
||||
import bisq.common.handlers.ErrorMessageHandler;
|
||||
|
||||
import org.bitcoinj.core.ECKey;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -33,11 +35,13 @@ import lombok.extern.slf4j.Slf4j;
|
|||
@Slf4j
|
||||
public class GetInventoryRequestManager {
|
||||
private final NetworkNode networkNode;
|
||||
private final ECKey sigKey;
|
||||
private final Map<NodeAddress, GetInventoryRequester> requesterMap = new HashMap<>();
|
||||
|
||||
@Inject
|
||||
public GetInventoryRequestManager(NetworkNode networkNode) {
|
||||
public GetInventoryRequestManager(NetworkNode networkNode, ECKey sigKey) {
|
||||
this.networkNode = networkNode;
|
||||
this.sigKey = sigKey;
|
||||
}
|
||||
|
||||
public void request(NodeAddress nodeAddress,
|
||||
|
@ -50,6 +54,7 @@ public class GetInventoryRequestManager {
|
|||
|
||||
GetInventoryRequester getInventoryRequester = new GetInventoryRequester(networkNode,
|
||||
nodeAddress,
|
||||
sigKey,
|
||||
resultMap -> {
|
||||
requesterMap.remove(nodeAddress);
|
||||
resultHandler.accept(resultMap);
|
||||
|
|
|
@ -28,9 +28,13 @@ import bisq.network.p2p.network.NetworkNode;
|
|||
import bisq.common.Timer;
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.app.Version;
|
||||
import bisq.common.crypto.CryptoUtils;
|
||||
import bisq.common.handlers.ErrorMessageHandler;
|
||||
import bisq.common.proto.network.NetworkEnvelope;
|
||||
|
||||
import org.bitcoinj.core.ECKey;
|
||||
import org.bitcoinj.core.Sha256Hash;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
@ -42,16 +46,19 @@ public class GetInventoryRequester implements MessageListener {
|
|||
|
||||
private final NetworkNode networkNode;
|
||||
private final NodeAddress nodeAddress;
|
||||
private final ECKey sigKey;
|
||||
private final Consumer<Map<String, String>> resultHandler;
|
||||
private final ErrorMessageHandler errorMessageHandler;
|
||||
private Timer timer;
|
||||
|
||||
public GetInventoryRequester(NetworkNode networkNode,
|
||||
NodeAddress nodeAddress,
|
||||
ECKey sigKey,
|
||||
Consumer<Map<String, String>> resultHandler,
|
||||
ErrorMessageHandler errorMessageHandler) {
|
||||
this.networkNode = networkNode;
|
||||
this.nodeAddress = nodeAddress;
|
||||
this.sigKey = sigKey;
|
||||
this.resultHandler = resultHandler;
|
||||
this.errorMessageHandler = errorMessageHandler;
|
||||
}
|
||||
|
@ -59,7 +66,11 @@ public class GetInventoryRequester implements MessageListener {
|
|||
public void request() {
|
||||
networkNode.addMessageListener(this);
|
||||
timer = UserThread.runAfter(this::onTimeOut, TIMEOUT_SEC);
|
||||
networkNode.sendMessage(nodeAddress, new GetInventoryRequest(Version.VERSION));
|
||||
byte[] nonce = CryptoUtils.getRandomBytes(32);
|
||||
byte[] signature = sigKey.sign(Sha256Hash.of(nonce)).encodeToDER();
|
||||
byte[] pubKey = sigKey.getPubKey();
|
||||
GetInventoryRequest getInventoryRequest = new GetInventoryRequest(Version.VERSION, nonce, signature, pubKey);
|
||||
networkNode.sendMessage(nodeAddress, getInventoryRequest);
|
||||
}
|
||||
|
||||
private void onTimeOut() {
|
||||
|
|
|
@ -21,35 +21,58 @@ package bisq.core.network.p2p.inventory.messages;
|
|||
import bisq.common.app.Version;
|
||||
import bisq.common.proto.network.NetworkEnvelope;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
public class GetInventoryRequest extends NetworkEnvelope {
|
||||
private final String version;
|
||||
private final byte[] nonce;
|
||||
private final byte[] signature;
|
||||
// The Sig key (DSA)
|
||||
private final byte[] pubKey;
|
||||
|
||||
public GetInventoryRequest(String version) {
|
||||
this(version, Version.getP2PMessageVersion());
|
||||
public GetInventoryRequest(String version,
|
||||
byte[] nonce,
|
||||
byte[] signature,
|
||||
byte[] pubKey) {
|
||||
this(version, nonce, signature, pubKey, Version.getP2PMessageVersion());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PROTO BUFFER
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private GetInventoryRequest(String version, int messageVersion) {
|
||||
private GetInventoryRequest(String version,
|
||||
byte[] nonce,
|
||||
byte[] signature,
|
||||
byte[] pubKey,
|
||||
int messageVersion) {
|
||||
super(messageVersion);
|
||||
|
||||
this.version = version;
|
||||
this.nonce = nonce;
|
||||
this.signature = signature;
|
||||
this.pubKey = pubKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
|
||||
return getNetworkEnvelopeBuilder()
|
||||
.setGetInventoryRequest(protobuf.GetInventoryRequest.newBuilder()
|
||||
.setVersion(version))
|
||||
.setVersion(version)
|
||||
.setNonce(ByteString.copyFrom(nonce))
|
||||
.setSignature(ByteString.copyFrom(signature))
|
||||
.setPubKey(ByteString.copyFrom(pubKey)))
|
||||
.build();
|
||||
}
|
||||
|
||||
public static GetInventoryRequest fromProto(protobuf.GetInventoryRequest proto, int messageVersion) {
|
||||
return new GetInventoryRequest(proto.getVersion(), messageVersion);
|
||||
return new GetInventoryRequest(proto.getVersion(),
|
||||
proto.getNonce().toByteArray(),
|
||||
proto.getSignature().toByteArray(),
|
||||
proto.getPubKey().toByteArray(),
|
||||
messageVersion);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,21 +34,25 @@ import bisq.common.config.BaseCurrencyNetwork;
|
|||
import bisq.common.file.JsonFileManager;
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import org.bitcoinj.core.ECKey;
|
||||
|
||||
import java.time.Clock;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@Slf4j
|
||||
public class InventoryMonitor {
|
||||
|
||||
|
@ -83,11 +87,13 @@ public class InventoryMonitor {
|
|||
Capability.RECEIVE_BSQ_BLOCK
|
||||
);
|
||||
|
||||
networkNode = new NetworkNodeProvider(new CoreNetworkProtoResolver(Clock.systemDefaultZone()),
|
||||
File torDir = new File(appDir, "tor");
|
||||
CoreNetworkProtoResolver networkProtoResolver = new CoreNetworkProtoResolver(Clock.systemDefaultZone());
|
||||
networkNode = new NetworkNodeProvider(networkProtoResolver,
|
||||
ArrayList::new,
|
||||
useLocalhostForP2P,
|
||||
9999,
|
||||
new File(appDir, "tor"),
|
||||
torDir,
|
||||
null,
|
||||
"",
|
||||
-1,
|
||||
|
@ -95,7 +101,17 @@ public class InventoryMonitor {
|
|||
null,
|
||||
false,
|
||||
false).get();
|
||||
getInventoryRequestManager = new GetInventoryRequestManager(networkNode);
|
||||
|
||||
File keyFile = new File(appDir, "sigKey");
|
||||
ECKey ecKey = getPersistedSigKey(keyFile).orElseGet(() -> {
|
||||
ECKey key = new ECKey();
|
||||
log.info("No persisted key found. We create a new EC key");
|
||||
persistSigKey(keyFile, key);
|
||||
return key;
|
||||
});
|
||||
log.info("EC key: " + ecKey.getPublicKeyAsHex());
|
||||
|
||||
getInventoryRequestManager = new GetInventoryRequestManager(networkNode, ecKey);
|
||||
|
||||
seedNodes.addAll(DefaultSeedNodeRepository.getSeedNodeAddressesFromPropertyFile(network));
|
||||
|
||||
|
@ -128,7 +144,31 @@ public class InventoryMonitor {
|
|||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private void persistSigKey(File keyFile, ECKey ecKey) {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(keyFile.getAbsolutePath())) {
|
||||
fileOutputStream.write(ecKey.getPrivKeyBytes());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<ECKey> getPersistedSigKey(File keyFile) {
|
||||
if (!keyFile.exists()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
try (FileInputStream fis = new FileInputStream(keyFile.getAbsolutePath())) {
|
||||
byte[] keyBytes = new byte[(int) keyFile.length()];
|
||||
fis.read(keyBytes);
|
||||
return Optional.of(ECKey.fromPrivate(keyBytes));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.toString());
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private String getShortAddress(NodeAddress nodeAddress, boolean useLocalhostForP2P) {
|
||||
return useLocalhostForP2P ?
|
||||
nodeAddress.getFullAddress().replace(":", "_") :
|
||||
|
|
|
@ -144,6 +144,9 @@ message Pong {
|
|||
|
||||
message GetInventoryRequest {
|
||||
string version = 1;
|
||||
bytes nonce = 2;
|
||||
bytes signature = 3;
|
||||
bytes pub_key = 4;
|
||||
}
|
||||
|
||||
message GetInventoryResponse {
|
||||
|
|
|
@ -41,6 +41,9 @@ public class SeedNode {
|
|||
appSetup.start();
|
||||
|
||||
getInventoryRequestHandler = injector.getInstance(GetInventoryRequestHandler.class);
|
||||
|
||||
// TODO dev test key
|
||||
getInventoryRequestHandler.addPermittedRequestersPubKey("035243719433b154a86329fd23a8389bee6369698be809f7e27f003f5b5aa9eb42");
|
||||
}
|
||||
|
||||
public void shutDown() {
|
||||
|
|
Loading…
Add table
Reference in a new issue