Skip to content

Commit

Permalink
feat: vote verification adjustments for KERI.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mateusz Czeladka committed Sep 9, 2024
1 parent cff6711 commit 6435671
Show file tree
Hide file tree
Showing 14 changed files with 328 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,14 @@ public static Function<VoteRepository.CompactVote, byte[]> createSerialiserFunct
yield blake2bHash256(bytes);
}
case KERI -> {
val bytes = vote.getPayload().map(String::getBytes).orElse(new byte[0]);
val message = vote.getSignature().getBytes();
val payload = vote.getPayload().map(String::getBytes).orElse(new byte[0]);

yield blake2bHash256(bytes);
val result = new byte[message.length + payload.length];

System.arraycopy(message, 0, result, 0, payload.length);

yield blake2bHash256(result);
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.aot.hint.ExecutableMode;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.boot.CommandLineRunner;
Expand All @@ -18,7 +17,7 @@

import static org.springframework.aot.hint.ExecutableMode.INVOKE;

@SpringBootApplication(exclude = {SecurityAutoConfiguration.class, ErrorMvcAutoConfiguration.class})
@SpringBootApplication(exclude = { SecurityAutoConfiguration.class, ErrorMvcAutoConfiguration.class })
@ComponentScan(basePackages = {
"org.cardano.foundation.voting.client",
"org.cardano.foundation.voting.service",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import io.vavr.control.Either;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.cardano.foundation.voting.domain.CardanoNetwork;
import org.cardano.foundation.voting.domain.Network;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
Expand All @@ -25,7 +25,7 @@ public class ChainFollowerClient {

private final RestTemplate restTemplate;

private final CardanoNetwork network;
private final Network network;

@Value("${ledger.follower.app.base.url}")
private String ledgerFollowerBaseUrl;
Expand Down Expand Up @@ -88,6 +88,6 @@ public boolean isEventInactive() {

}

record MerkleRootHashResponse(boolean isPresent, CardanoNetwork network) { }
record MerkleRootHashResponse(boolean isPresent, Network network) { }

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package org.cardano.foundation.voting.client;

import io.vavr.control.Either;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.zalando.problem.Problem;
import org.zalando.problem.spring.common.HttpStatusAdapter;

import java.util.HashMap;
import java.util.Map;

import static org.springframework.http.HttpMethod.POST;

@RequiredArgsConstructor
@Component
@Slf4j
public class KeriVerificationClient {

private final RestTemplate restTemplate;

@Value("${keri.ballot.verifier.base.url}")
private String keriVerifierBaseUrl;

public Either<Problem, Boolean> verifySignature(String aid,
String signature,
String payload) {
val url = String.format("%s/verify", keriVerifierBaseUrl);

val headers = new HttpHeaders();
headers.add("Content-Type", "application/json");

val requestBody = new HashMap<String, String>();
requestBody.put("pre", aid);
requestBody.put("signature", signature);
requestBody.put("payload", payload);

val entity = new HttpEntity<Map<String, String>>(requestBody, headers);

try {
val response = restTemplate.exchange(url, POST, entity, String.class);

if (response.getStatusCode().is2xxSuccessful()) {
return Either.right(true);
}

return Either.left(Problem.builder()
.withTitle("KERI_VERIFICATION_FAILED")
.withDetail("The Keri-specific condition was not met.")
.withStatus(new HttpStatusAdapter(response.getStatusCode()))
.build());
} catch (HttpClientErrorException e) {
log.error("Unable to verify signature, reason: {}", e.getMessage());

return Either.left(Problem.builder()
.withTitle("KERI_VERIFICATION_ERROR")
.withDetail("Unable to verify signature, reason: " + e.getMessage())
.withStatus(new HttpStatusAdapter(e.getStatusCode()))
.build());
}
}

}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package org.cardano.foundation.voting.config;

import lombok.extern.slf4j.Slf4j;
import org.cardano.foundation.voting.domain.CardanoNetwork;
import org.cardano.foundation.voting.domain.Network;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@Slf4j
public class CardanoConfig {
public class NetworkConfig {

@Bean
public CardanoNetwork network(@Value("${cardano.network:main}") CardanoNetwork network) {
public Network network(@Value("${cardano.network:main}") Network network) {
log.info("Configured backend network:{}", network);

return network;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import io.swagger.v3.oas.annotations.media.Schema;

@Schema(description = "Cardano networks")
public enum CardanoNetwork {
public enum Network {

MAIN, // main-net
PREPROD, // preprod-net
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,22 @@ public class VoteVerificationRequest {
private String rootHash;

@NotBlank
@Schema(description = "COSE signature of the vote", required = true)
protected String voteCoseSignature;
@Schema(description = "Cardano or KERI", required = true)
private WalletType walletType;

@NotBlank
@Schema(description = "aid or stake address", required = true)
private String walletId;

@Schema(description = "payload")
protected Optional<String> payload;

@NotBlank
@Schema(description = "Signature of the vote", required = true)
protected String signature;

@Schema(description = "Public key for the vote")
protected Optional<@NotBlank String> voteCosePublicKey;
protected Optional<@NotBlank String> publicKey;

@Builder.Default
@Schema(description = "Merkle proof")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ public class VoteVerificationResult {
@Schema(description = "Indicates if the vote is verified or not", example = "true")
private boolean isVerified;

@Schema(description = "Cardano network ", required = true)
private CardanoNetwork network;
@Schema(description = "cardano or keri", required = true, example = "CARDANO")
private WalletType walletType;

@Schema(description = "Network ", required = true, example = "MAINNET")
private Network network;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.cardano.foundation.voting.domain;

public enum WalletType {

KERI, CARDANO

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.cardano.foundation.voting.domain;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

import java.util.Optional;

@Getter
@Builder
@AllArgsConstructor
public class WrappedVote {

private String walletId;

private WalletType walletType;

@Builder.Default
private Optional<String> payload = Optional.empty();

private String signature;

@Builder.Default
private Optional<String> publicKey = Optional.empty();

public static WrappedVote createCardanoVote(String walletId,
String signature,
Optional<String> publicKey) {
return WrappedVote.builder()
.walletId(walletId)
.walletType(WalletType.CARDANO)
.signature(signature)
.payload(Optional.empty())
.publicKey(publicKey)
.build();
}

public static WrappedVote createKERIVote(String walletId,
String signature,
String payload) {
return WrappedVote.builder()
.walletId(walletId)
.walletType(WalletType.KERI)
.signature(signature)
.payload(Optional.of(payload))
.publicKey(Optional.empty())
.build();
}

}
Loading

0 comments on commit 6435671

Please sign in to comment.