com.scalar.dl.client.service.DefaultClientServiceHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scalardl-java-client-sdk Show documentation
Show all versions of scalardl-java-client-sdk Show documentation
A client-side Java library to interact with Scalar DL network.
The newest version!
package com.scalar.dl.client.service;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.scalar.dl.client.error.ClientError;
import com.scalar.dl.client.exception.ClientException;
import com.scalar.dl.ledger.exception.ValidationException;
import com.scalar.dl.ledger.model.ContractExecutionResult;
import com.scalar.dl.ledger.model.LedgerValidationResult;
import com.scalar.dl.ledger.service.StatusCode;
import com.scalar.dl.rpc.AssetProof;
import com.scalar.dl.rpc.CertificateRegistrationRequest;
import com.scalar.dl.rpc.ContractExecutionRequest;
import com.scalar.dl.rpc.ContractExecutionResponse;
import com.scalar.dl.rpc.ContractRegistrationRequest;
import com.scalar.dl.rpc.ContractsListingRequest;
import com.scalar.dl.rpc.ExecutionOrderingResponse;
import com.scalar.dl.rpc.ExecutionValidationRequest;
import com.scalar.dl.rpc.FunctionRegistrationRequest;
import com.scalar.dl.rpc.LedgerValidationRequest;
import com.scalar.dl.rpc.SecretRegistrationRequest;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import javax.json.JsonObject;
public class DefaultClientServiceHandler implements ClientServiceHandler {
private final AbstractLedgerClient client;
private final AbstractAuditorClient auditorClient;
/**
* Constructs a {@code BaseClientService} with the specified {@link AbstractLedgerClient} and
* {@link AbstractAuditorClient}.
*
* @param client a client for the ledger server
* @param auditorClient a client for the auditor server
*/
@Inject
public DefaultClientServiceHandler(
AbstractLedgerClient client, @Nullable AbstractAuditorClient auditorClient) {
this.client = client;
this.auditorClient = auditorClient;
}
/**
* Registers the certificate with the specified {@code CertificateRegistrationRequest} for digital
* signature authentication.
*
* @param request a {@code CertificateRegistrationRequest}.
* @throws ClientException if a request fails for some reason
*/
@Override
public void registerCertificate(CertificateRegistrationRequest request) {
registerToAuditor(request);
client.register(request);
}
/**
* Registers the secret key with the specified {@code SecretRegistrationRequest} for HMAC
* authentication.
*
* @param request a {@code SecretRegistrationRequest}.
* @throws ClientException if a request fails for some reason
*/
@Override
public void registerSecret(SecretRegistrationRequest request) {
registerToAuditor(request);
client.register(request);
}
/**
* Registers the function with the specified {@code FunctionRegistrationRequest}.
*
* @param request a {@code FunctionRegistrationRequest}.
* @throws ClientException if a request fails for some reason
*/
@Override
public void registerFunction(FunctionRegistrationRequest request) {
client.register(request);
}
/**
* Registers the contract with the specified {@code ContractRegistrationRequest}.
*
* @param request a {@code ContractRegistrationRequest}.
* @throws ClientException if a request fails for some reason
*/
@Override
public void registerContract(ContractRegistrationRequest request) {
registerToAuditor(request);
client.register(request);
}
/**
* Retrieves a list of contracts with the specified {@code ContractsListingRequest}.
*
* @param request a {@code ContractsListingRequest}.
* @return {@link JsonObject}
* @throws ClientException if a request fails for some reason
*/
@Override
public JsonObject listContracts(ContractsListingRequest request) {
return client.list(request);
}
/**
* Executes the specified contract with the specified {@code ContractExecutionRequest}.
*
* @param request a {@code ContractExecutionRequest}.
* @return {@link ContractExecutionResult}
* @throws ClientException if a request fails for some reason
*/
@Override
public ContractExecutionResult executeContract(ContractExecutionRequest request) {
ContractExecutionRequest ordered = order(request);
return client.execute(ordered, r -> validate(ordered, r));
}
/**
* Validates the specified asset in the ledger with the specified {@code LedgerValidationRequest}.
*
* @param request a {@code LedgerValidationRequest}.
* @return {@link LedgerValidationResult}
* @throws ClientException if a request fails for some reason
*/
@Override
public LedgerValidationResult validateLedger(LedgerValidationRequest request) {
return client.validate(request);
}
private void registerToAuditor(CertificateRegistrationRequest request) {
if (auditorClient == null) {
return;
}
try {
auditorClient.register(request);
} catch (ClientException e) {
if (!e.getStatusCode().equals(StatusCode.CERTIFICATE_ALREADY_REGISTERED)) {
throw e;
}
}
}
private void registerToAuditor(SecretRegistrationRequest request) {
if (auditorClient == null) {
return;
}
try {
auditorClient.register(request);
} catch (ClientException e) {
if (!e.getStatusCode().equals(StatusCode.SECRET_ALREADY_REGISTERED)) {
throw e;
}
}
}
private void registerToAuditor(ContractRegistrationRequest request) {
if (auditorClient == null) {
return;
}
try {
auditorClient.register(request);
} catch (ClientException e) {
if (!e.getStatusCode().equals(StatusCode.CONTRACT_ALREADY_REGISTERED)) {
throw e;
}
}
}
private ContractExecutionRequest order(ContractExecutionRequest request) {
if (auditorClient == null) {
return request;
}
ExecutionOrderingResponse response = auditorClient.order(request);
return ContractExecutionRequest.newBuilder(request)
.setAuditorSignature(response.getSignature())
.build();
}
private ContractExecutionResponse validate(
ContractExecutionRequest request, ContractExecutionResponse ledgerResponse) {
if (auditorClient == null) {
return null;
}
ExecutionValidationRequest req =
ExecutionValidationRequest.newBuilder()
.setRequest(request)
.addAllProofs(ledgerResponse.getProofsList())
.build();
ContractExecutionResponse auditorResponse = auditorClient.validate(req);
validateResponses(ledgerResponse, auditorResponse);
return auditorResponse;
}
private void validateResponses(
ContractExecutionResponse ledgerResponse, ContractExecutionResponse auditorResponse) {
Runnable throwError =
() -> {
throw new ValidationException(ClientError.INCONSISTENT_RESULTS);
};
if (!ledgerResponse.getContractResult().equals(auditorResponse.getContractResult())
|| ledgerResponse.getProofsCount() != auditorResponse.getProofsCount()) {
throwError.run();
}
Map map = new HashMap<>();
ledgerResponse.getProofsList().forEach(p -> map.put(p.getAssetId(), p));
auditorResponse
.getProofsList()
.forEach(
p2 -> {
AssetProof p1 = map.get(p2.getAssetId());
if (p1 == null || p1.getAge() != p2.getAge() || !p1.getHash().equals(p2.getHash())) {
throwError.run();
}
});
}
@VisibleForTesting
AbstractLedgerClient getLedgerClient() {
return client;
}
@VisibleForTesting
AbstractAuditorClient getAuditorClient() {
return auditorClient;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy