Skip to content

Commit

Permalink
feat: json metadata checker.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mateusz Czeladka committed Aug 14, 2024
1 parent 46d0029 commit 37cdc18
Show file tree
Hide file tree
Showing 12 changed files with 445 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ public static List<Either<IdentifiableProblem, TransactionItemEntity>> transacti
}).toList();
}

public static Either<IdentifiableProblem, TransactionItemEntity> transactionItemCannotRejectAlreadyApprovedResponse(String transactionId,
String txItemId) {
public static Either<IdentifiableProblem, TransactionItemEntity> transactionItemCannotRejectAlreadyApprovedForDispatchResponse(String transactionId,
String txItemId) {
val problem = Problem.builder()
.withTitle("TX_ALREADY_APPROVED_CANNOT_REJECT_TX_ITEM")
.withDetail(STR."Cannot reject transaction item \{txItemId} because transaction \{transactionId} has already been approved for dispatch")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ public List<Either<IdentifiableProblem, TransactionItemEntity>> rejectTransactio

val txItem = txItemM.orElseThrow();
if (tx.getLedgerDispatchApproved()) {
transactionItemEntitiesE.add(transactionItemCannotRejectAlreadyApprovedResponse(transactionId, txItemId));
transactionItemEntitiesE.add(transactionItemCannotRejectAlreadyApprovedForDispatchResponse(transactionId, txItemId));
continue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import jakarta.persistence.Embeddable;
import jakarta.persistence.Embedded;
import lombok.*;
import lombok.experimental.Accessors;

import javax.annotation.Nullable;
import java.util.Optional;
Expand Down Expand Up @@ -38,4 +37,8 @@ public Optional<Counterparty> getCounterparty() {
return Optional.ofNullable(counterparty);
}

public void setCounterparty(Optional<Counterparty> counterparty) {
this.counterparty = counterparty.orElse(null);
}

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package org.cardanofoundation.lob.app.blockchain_publisher.service;

import co.nstant.in.cbor.CborException;
import com.bloxbean.cardano.client.common.cbor.CborSerializationUtil;
import com.bloxbean.cardano.client.metadata.MetadataMap;
import com.bloxbean.cardano.client.metadata.helper.MetadataToJsonNoSchemaConverter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.networknt.schema.JsonSchemaFactory;
import jakarta.annotation.PostConstruct;
Expand All @@ -23,39 +19,31 @@
@RequiredArgsConstructor
public class JsonSchemaMetadataChecker implements MetadataChecker {

private final ObjectMapper objectMapper;

@Value("classpath:blockchain_transaction_metadata_schema.json")
private Resource metatdataSchemaResource;
protected Resource metatdataSchemaResource;

@Value("${lob.l1.transaction.metadata.validation.enable:true}")
private boolean enableChecker;

private final ObjectMapper objectMapper;
protected boolean enableChecker;

@PostConstruct
public void init() {
log.info("JsonSchemaMetadataChecker, metadata validation enabled: {}, schema found:{}", enableChecker, metatdataSchemaResource.exists());
}

@Override
public boolean checkTransactionMetadata(MetadataMap metadata) {
public boolean checkTransactionMetadata(String json) {
if (!enableChecker) {
//log.warn("Metadata validation is disabled, not recommended!");
log.warn("Metadata validation is disabled, not recommended in production / mainnet!");

return true;
}

try {
val data = metadata.getMap();
val bytes = CborSerializationUtil.serialize(data);

val json = MetadataToJsonNoSchemaConverter.cborBytesToJson(bytes);

val jsonObject = objectMapper.readTree(json);

val jsonSchemaFactory = JsonSchemaFactory.getInstance(V7);

val schema = jsonSchemaFactory.getSchema(metatdataSchemaResource.getInputStream());

val validationResult = schema.validate(jsonObject);

if (!validationResult.isEmpty()) {
Expand All @@ -65,7 +53,7 @@ public boolean checkTransactionMetadata(MetadataMap metadata) {
}

return true;
} catch (CborException | IOException e) {
} catch (IOException e) {
log.error("Error serializing metadata to cbor", e);
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import com.bloxbean.cardano.client.account.Account;
import com.bloxbean.cardano.client.api.model.Amount;
import com.bloxbean.cardano.client.backend.api.BackendService;
import com.bloxbean.cardano.client.common.cbor.CborSerializationUtil;
import com.bloxbean.cardano.client.function.helper.SignerProviders;
import com.bloxbean.cardano.client.metadata.Metadata;
import com.bloxbean.cardano.client.metadata.MetadataBuilder;
import com.bloxbean.cardano.client.metadata.helper.MetadataToJsonNoSchemaConverter;
import com.bloxbean.cardano.client.quicktx.QuickTxBuilder;
import com.bloxbean.cardano.client.quicktx.Tx;
import com.bloxbean.cardano.client.transaction.util.TransactionUtil;
Expand Down Expand Up @@ -129,29 +131,37 @@ private static Set<TransactionEntity> calculateRemainingTransactionLines(
private Either<Problem, byte[]> serialiseTransactionChunk(String organisationId,
Set<TransactionEntity> transactionsBatch,
long creationSlot) {
val metadataMap =
metadataSerialiser.serialiseToMetadataMap(organisationId, transactionsBatch, creationSlot);
try {
val metadataMap =
metadataSerialiser.serialiseToMetadataMap(organisationId, transactionsBatch, creationSlot);

// try {
// System.out.println(metadataMap.toJson());
// } catch (CborException e) {
// throw new RuntimeException(e);
// }
val data = metadataMap.getMap();
val bytes = CborSerializationUtil.serialize(data);

val metadata = MetadataBuilder.createMetadata();
metadata.put(metadataLabel, metadataMap);
val json = MetadataToJsonNoSchemaConverter.cborBytesToJson(bytes);

val isValid = jsonSchemaMetadataChecker.checkTransactionMetadata(metadataMap);
val metadata = MetadataBuilder.createMetadata();
metadata.put(metadataLabel, metadataMap);

if (!isValid) {
val isValid = jsonSchemaMetadataChecker.checkTransactionMetadata(json);

if (!isValid) {
return Either.left(Problem.builder()
.withTitle("INVALID_TRANSACTION_METADATA")
.withDetail("Metadata is not valid according to the transaction schema, we will not create a transaction!")
.build()
);
}

return Either.right(serialiseTransaction(metadata));
} catch (Exception e) {
log.error("Error serialising metadata to cbor", e);
return Either.left(Problem.builder()
.withTitle("INVALID_TRANSACTION_METADATA")
.withDetail("Metadata is not valid according to the transaction schema!")
.withTitle("ERROR_SERIALISING_METADATA")
.withDetail("Error serialising metadata to cbor")
.build()
);
}

return Either.right(serialiseTransaction(metadata));
}

@SneakyThrows
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package org.cardanofoundation.lob.app.blockchain_publisher.service;

import com.bloxbean.cardano.client.metadata.MetadataMap;

public interface MetadataChecker {

boolean checkTransactionMetadata(MetadataMap metadata);
boolean checkTransactionMetadata(String json);

class Noop implements MetadataChecker {
@Override
public boolean checkTransactionMetadata(MetadataMap metadata) {
public boolean checkTransactionMetadata(String json) {
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import org.cardanofoundation.lob.app.blockchain_publisher.domain.entity.*;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.time.Clock;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
Expand Down Expand Up @@ -51,7 +50,7 @@ private MetadataMap createMetadataSection(long creationSlot) {

val now = Instant.now(clock);

metadataMap.put("creation_slot", BigInteger.valueOf(creationSlot));
metadataMap.put("creation_slot", String.valueOf(creationSlot));
metadataMap.put("timestamp", DateTimeFormatter.ISO_INSTANT.format(now));
metadataMap.put("version", VERSION);

Expand Down
Loading

0 comments on commit 37cdc18

Please sign in to comment.