Skip to content

Commit

Permalink
Implemented priv_getLogs
Browse files Browse the repository at this point in the history
Signed-off-by: Lucas Saldanha <lucas.saldanha@consensys.net>
  • Loading branch information
lucassaldanha committed Apr 8, 2020
1 parent cb5244d commit 4af9d1c
Show file tree
Hide file tree
Showing 17 changed files with 923 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public enum RpcMethod {
PRIV_DISTRIBUTE_RAW_TRANSACTION("priv_distributeRawTransaction"),
PRIV_GET_EEA_TRANSACTION_COUNT("priv_getEeaTransactionCount"),
PRIV_GET_CODE("priv_getCode"),
PRIV_GET_LOGS("priv_getLogs"),
PRIVX_FIND_PRIVACY_GROUP("privx_findOnChainPrivacyGroup"),
EEA_SEND_RAW_TRANSACTION("eea_sendRawTransaction"),
ETH_ACCOUNTS("eth_accounts"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ public Hash getBlockhash() {
return blockhash;
}

public boolean isValid() {
if (!getFromBlock().isLatest() && !getToBlock().isLatest() && getBlockhash() != null) {
return false;
}

return true;
}

@Override
public String toString() {
return MoreObjects.toStringHelper(this)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;

import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.FilterParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.LogsResult;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.LogsQuery;
import org.hyperledger.besu.ethereum.api.query.PrivacyQueries;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;

public class PrivGetLogs implements JsonRpcMethod {

private final BlockchainQueries blockchainQueries;
private final PrivacyQueries privacyQueries;
private final PrivacyController privacyController;
private final EnclavePublicKeyProvider enclavePublicKeyProvider;

public PrivGetLogs(
final BlockchainQueries blockchainQueries,
final PrivacyQueries privacyQueries,
final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider) {
this.blockchainQueries = blockchainQueries;
this.privacyQueries = privacyQueries;
this.privacyController = privacyController;
this.enclavePublicKeyProvider = enclavePublicKeyProvider;
}

@Override
public String getName() {
return RpcMethod.PRIV_GET_LOGS.getMethodName();
}

@Override
public JsonRpcResponse response(final JsonRpcRequestContext request) {
final String privacyGroupId = request.getRequiredParameter(0, String.class);
final FilterParameter filter = request.getRequiredParameter(1, FilterParameter.class);

checkIfPrivacyGroupMatchesAuthenticatedEnclaveKey(request, privacyGroupId);

final LogsQuery query =
new LogsQuery.Builder().addresses(filter.getAddresses()).topics(filter.getTopics()).build();

if (!filter.isValid()) {
return new JsonRpcErrorResponse(request.getRequest().getId(), JsonRpcError.INVALID_PARAMS);
}

if (filter.getBlockhash() != null) {
return new JsonRpcSuccessResponse(
request.getRequest().getId(),
new LogsResult(
privacyQueries.matchingLogs(privacyGroupId, filter.getBlockhash(), query)));
}

final long fromBlockNumber = filter.getFromBlock().getNumber().orElse(0);
final long toBlockNumber =
filter.getToBlock().getNumber().orElse(blockchainQueries.headBlockNumber());

return new JsonRpcSuccessResponse(
request.getRequest().getId(),
new LogsResult(
privacyQueries.matchingLogs(privacyGroupId, fromBlockNumber, toBlockNumber, query)));
}

private void checkIfPrivacyGroupMatchesAuthenticatedEnclaveKey(
final JsonRpcRequestContext request, final String privacyGroupId) {
final String enclavePublicKey = enclavePublicKeyProvider.getEnclaveKey(request.getUser());
privacyController.verifyPrivacyGroupContainsEnclavePublicKey(privacyGroupId, enclavePublicKey);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.PrivDistributeRawTransaction;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.PrivFindPrivacyGroup;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.PrivGetCode;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.PrivGetLogs;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.PrivGetPrivacyPrecompileAddress;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.PrivGetPrivateTransaction;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.PrivGetTransactionCount;
Expand Down Expand Up @@ -74,7 +75,12 @@ protected Map<String, JsonRpcMethod> create(
enclavePublicKeyProvider,
getPrivacyParameters().isOnchainPrivacyGroupsEnabled()),
new PrivCall(getBlockchainQueries(), privacyController, enclavePublicKeyProvider),
new PrivGetCode(getBlockchainQueries(), privacyController, enclavePublicKeyProvider));
new PrivGetCode(getBlockchainQueries(), privacyController, enclavePublicKeyProvider),
new PrivGetLogs(
getBlockchainQueries(),
getPrivacyQueries(),
privacyController,
enclavePublicKeyProvider));
} else {
return mapOf(
new PrivGetTransactionReceipt(
Expand All @@ -97,7 +103,12 @@ protected Map<String, JsonRpcMethod> create(
enclavePublicKeyProvider,
getPrivacyParameters().isOnchainPrivacyGroupsEnabled()),
new PrivCall(getBlockchainQueries(), privacyController, enclavePublicKeyProvider),
new PrivGetCode(getBlockchainQueries(), privacyController, enclavePublicKeyProvider));
new PrivGetCode(getBlockchainQueries(), privacyController, enclavePublicKeyProvider),
new PrivGetLogs(
getBlockchainQueries(),
getPrivacyQueries(),
privacyController,
enclavePublicKeyProvider));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.MultiTenancyRpcMethodDecorator;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.PrivacyQueries;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
Expand Down Expand Up @@ -53,6 +54,7 @@ public abstract class PrivacyApiGroupJsonRpcMethods extends ApiGroupJsonRpcMetho
private final PrivacyParameters privacyParameters;
private final PrivateNonceProvider privateNonceProvider;
private final PrivateWorldStateReader privateWorldStateReader;
private final PrivacyQueries privacyQueries;

public PrivacyApiGroupJsonRpcMethods(
final BlockchainQueries blockchainQueries,
Expand All @@ -74,7 +76,12 @@ public PrivacyApiGroupJsonRpcMethods(

this.privateWorldStateReader =
new PrivateWorldStateReader(
privateStateRootResolver, privacyParameters.getPrivateWorldStateArchive());
privateStateRootResolver,
privacyParameters.getPrivateWorldStateArchive(),
privacyParameters.getPrivateStateStorage());

this.privacyQueries =
new PrivacyQueries(blockchainQueries.getBlockchain(), this.privateWorldStateReader);
}

public BlockchainQueries getBlockchainQueries() {
Expand Down Expand Up @@ -162,6 +169,14 @@ private PrivacyController createPrivacyController(
: defaultPrivacyController;
}

public PrivateWorldStateReader getPrivateWorldStateReader() {
return privateWorldStateReader;
}

PrivacyQueries getPrivacyQueries() {
return privacyQueries;
}

private JsonRpcMethod createPrivacyMethod(
final PrivacyParameters privacyParameters, final JsonRpcMethod rpcMethod) {
if (privacyParameters.isEnabled() && privacyParameters.isMultiTenancyEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.api.query;

import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.LogWithMetadata;
import org.hyperledger.besu.ethereum.privacy.PrivateTransactionReceipt;
import org.hyperledger.besu.ethereum.privacy.PrivateWorldStateReader;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateTransactionMetadata;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.LongStream;

public class PrivacyQueries {

private final Blockchain blockchain;
private final PrivateWorldStateReader privateWorldStateReader;

public PrivacyQueries(
final Blockchain blockchain, final PrivateWorldStateReader privateWorldStateReader) {
this.blockchain = blockchain;
this.privateWorldStateReader = privateWorldStateReader;
}

public List<LogWithMetadata> matchingLogs(
final String privacyGroupId,
final long fromBlockNumber,
final long toBlockNumber,
final LogsQuery query) {

return LongStream.rangeClosed(fromBlockNumber, toBlockNumber)
.mapToObj(blockchain::getBlockHashByNumber)
.takeWhile(Optional::isPresent)
.map(Optional::get)
.map(hash -> matchingLogs(privacyGroupId, hash, query))
.flatMap(List::stream)
.collect(Collectors.toList());
}

public List<LogWithMetadata> matchingLogs(
final String privacyGroupId, final Hash blockHash, final LogsQuery query) {

final Optional<BlockHeader> blockHeader = blockchain.getBlockHeader(blockHash);
if (blockHeader.isEmpty()) {
return Collections.emptyList();
}

final List<PrivateTransactionMetadata> privateTransactionMetadatas =
privateWorldStateReader.getPrivateTransactionsMetadata(privacyGroupId, blockHash);

final List<PrivateTransactionReceipt> privateTransactionReceipts =
privateTransactionMetadatas.stream()
.map(PrivateTransactionMetadata::getPrivacyMarkerTransactionHash)
.map(
pmtHash -> privateWorldStateReader.getPrivateTransactionReceipt(blockHash, pmtHash))
.flatMap(Optional::stream)
.collect(Collectors.toList());

final long number = blockHeader.get().getNumber();
final boolean removed = !blockchain.blockIsOnCanonicalChain(blockHash);

return IntStream.range(0, privateTransactionReceipts.size())
.mapToObj(
i ->
LogWithMetadata.generate(
privateTransactionReceipts.get(i),
number,
blockHash,
privateTransactionMetadatas.get(i).getPrivacyMarkerTransactionHash(),
i,
removed))
.flatMap(Collection::stream)
.filter(query::matches)
.collect(Collectors.toList());
}
}
Loading

0 comments on commit 4af9d1c

Please sign in to comment.