Search in sources :

Example 1 with IonStruct

use of com.amazon.ion.IonStruct in project amazon-qldb-dmv-sample-java by aws-samples.

the class GetRevision method queryRegistrationsByVin.

/**
 * Query the registration history for the given VIN.
 *
 * @param txn
 *              The {@link TransactionExecutor} for lambda execute.
 * @param vin
 *              The unique VIN to query.
 * @return a list of {@link IonStruct} representing the registration history.
 * @throws IllegalStateException if failed to convert parameters into {@link IonValue}
 */
public static List<IonStruct> queryRegistrationsByVin(final TransactionExecutor txn, final String vin) {
    log.info(String.format("Let's query the 'VehicleRegistration' table for VIN: %s...", vin));
    log.info("Let's query the 'VehicleRegistration' table for VIN: {}...", vin);
    final String query = String.format("SELECT * FROM _ql_committed_%s WHERE data.VIN = ?", Constants.VEHICLE_REGISTRATION_TABLE_NAME);
    try {
        final List<IonValue> parameters = Collections.singletonList(Constants.MAPPER.writeValueAsIonValue(vin));
        final Result result = txn.execute(query, parameters);
        List<IonStruct> list = ScanTable.toIonStructs(result);
        log.info(String.format("Found %d document(s)!", list.size()));
        return list;
    } catch (IOException ioe) {
        throw new IllegalStateException(ioe);
    }
}
Also used : IonValue(com.amazon.ion.IonValue) IonStruct(com.amazon.ion.IonStruct) IOException(java.io.IOException) GetRevisionResult(com.amazonaws.services.qldb.model.GetRevisionResult) Result(software.amazon.qldb.Result) GetDigestResult(com.amazonaws.services.qldb.model.GetDigestResult)

Example 2 with IonStruct

use of com.amazon.ion.IonStruct in project amazon-qldb-dmv-sample-java by aws-samples.

the class GetRevision method verifyRegistration.

/**
 * Verify each version of the registration for the given VIN.
 *
 * @param driver
 *              A QLDB driver.
 * @param ledgerName
 *              The ledger to get digest from.
 * @param vin
 *              VIN to query the revision history of a specific registration with.
 * @throws Exception if failed to verify digests.
 * @throws AssertionError if document revision verification failed.
 */
public static void verifyRegistration(final QldbDriver driver, final String ledgerName, final String vin) throws Exception {
    log.info(String.format("Let's verify the registration with VIN=%s, in ledger=%s.", vin, ledgerName));
    try {
        log.info("First, let's get a digest.");
        GetDigestResult digestResult = GetDigest.getDigest(ledgerName);
        ValueHolder digestTipAddress = digestResult.getDigestTipAddress();
        byte[] digestBytes = Verifier.convertByteBufferToByteArray(digestResult.getDigest());
        log.info("Got a ledger digest. Digest end address={}, digest={}.", QldbStringUtils.toUnredactedString(digestTipAddress), Verifier.toBase64(digestBytes));
        log.info(String.format("Next, let's query the registration with VIN=%s. " + "Then we can verify each version of the registration.", vin));
        List<IonStruct> documentsWithMetadataList = new ArrayList<>();
        driver.execute(txn -> {
            documentsWithMetadataList.addAll(queryRegistrationsByVin(txn, vin));
        });
        log.info("Registrations queried successfully!");
        log.info(String.format("Found %s revisions of the registration with VIN=%s.", documentsWithMetadataList.size(), vin));
        for (IonStruct ionStruct : documentsWithMetadataList) {
            QldbRevision document = QldbRevision.fromIon(ionStruct);
            log.info(String.format("Let's verify the document: %s", document));
            log.info("Let's get a proof for the document.");
            GetRevisionResult proofResult = getRevision(ledgerName, document.getMetadata().getId(), digestTipAddress, document.getBlockAddress());
            final IonValue proof = Constants.MAPPER.writeValueAsIonValue(proofResult.getProof());
            final IonReader reader = IonReaderBuilder.standard().build(proof);
            reader.next();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            IonWriter writer = SYSTEM.newBinaryWriter(baos);
            writer.writeValue(reader);
            writer.close();
            baos.flush();
            baos.close();
            byte[] byteProof = baos.toByteArray();
            log.info(String.format("Got back a proof: %s", Verifier.toBase64(byteProof)));
            boolean verified = Verifier.verify(document.getHash(), digestBytes, proofResult.getProof().getIonText());
            if (!verified) {
                throw new AssertionError("Document revision is not verified!");
            } else {
                log.info("Success! The document is verified");
            }
            byte[] alteredDigest = Verifier.flipRandomBit(digestBytes);
            log.info(String.format("Flipping one bit in the digest and assert that the document is NOT verified. " + "The altered digest is: %s", Verifier.toBase64(alteredDigest)));
            verified = Verifier.verify(document.getHash(), alteredDigest, proofResult.getProof().getIonText());
            if (verified) {
                throw new AssertionError("Expected document to not be verified against altered digest.");
            } else {
                log.info("Success! As expected flipping a bit in the digest causes verification to fail.");
            }
            byte[] alteredDocumentHash = Verifier.flipRandomBit(document.getHash());
            log.info(String.format("Flipping one bit in the document's hash and assert that it is NOT verified. " + "The altered document hash is: %s.", Verifier.toBase64(alteredDocumentHash)));
            verified = Verifier.verify(alteredDocumentHash, digestBytes, proofResult.getProof().getIonText());
            if (verified) {
                throw new AssertionError("Expected altered document hash to not be verified against digest.");
            } else {
                log.info("Success! As expected flipping a bit in the document hash causes verification to fail.");
            }
        }
    } catch (Exception e) {
        log.error("Failed to verify digests.", e);
        throw e;
    }
    log.info(String.format("Finished verifying the registration with VIN=%s in ledger=%s.", vin, ledgerName));
}
Also used : IonValue(com.amazon.ion.IonValue) GetDigestResult(com.amazonaws.services.qldb.model.GetDigestResult) ArrayList(java.util.ArrayList) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ValueHolder(com.amazonaws.services.qldb.model.ValueHolder) IOException(java.io.IOException) IonStruct(com.amazon.ion.IonStruct) QldbRevision(software.amazon.qldb.tutorial.qldb.QldbRevision) IonReader(com.amazon.ion.IonReader) IonWriter(com.amazon.ion.IonWriter) GetRevisionResult(com.amazonaws.services.qldb.model.GetRevisionResult)

Example 3 with IonStruct

use of com.amazon.ion.IonStruct in project amazon-qldb-dmv-sample-java by aws-samples.

the class JournalS3ExportReader method getDataFileKeysFromManifest.

/**
 * Given the S3Object to the completed manifest file, return the keys
 * which are part of this export request.
 *
 * @param s3Object
 *              A {@link S3Object}.
 * @return a list of data file keys containing the chunk of {@link JournalBlock}.
 */
private static List<String> getDataFileKeysFromManifest(final S3Object s3Object) {
    IonReader ionReader = IonReaderBuilder.standard().build(s3Object.getObjectContent());
    // Read the data
    ionReader.next();
    List<String> keys = new ArrayList<>();
    IonStruct ionStruct = (IonStruct) SYSTEM.newValue(ionReader);
    IonList ionKeysList = (IonList) ionStruct.get("keys");
    ionKeysList.forEach(key -> keys.add(((IonString) key).stringValue()));
    return keys;
}
Also used : IonStruct(com.amazon.ion.IonStruct) IonString(com.amazon.ion.IonString) IonList(com.amazon.ion.IonList) IonReader(com.amazon.ion.IonReader) ArrayList(java.util.ArrayList) IonString(com.amazon.ion.IonString)

Example 4 with IonStruct

use of com.amazon.ion.IonStruct in project amazon-qldb-dmv-sample-java by aws-samples.

the class QldbRevision method fromIon.

/**
 * Constructs a new {@link QldbRevision} from an {@link IonStruct}.
 *
 * The specified {@link IonStruct} must include the following fields
 *
 * - blockAddress -- a {@link BlockAddress},
 * - metadata -- a {@link RevisionMetadata},
 * - hash -- the document's hash calculated by QLDB,
 * - data -- an {@link IonStruct} containing user data in the document.
 *
 * If any of these fields are missing or are malformed, then throws {@link IllegalArgumentException}.
 *
 * If the document hash calculated from the members of the specified {@link IonStruct} does not match
 * the hash member of the {@link IonStruct} then throws {@link IllegalArgumentException}.
 *
 * @param ionStruct
 *              The {@link IonStruct} that contains a {@link QldbRevision} object.
 * @return the converted {@link QldbRevision} object.
 * @throws IOException if failed to parse parameter {@link IonStruct}.
 */
public static QldbRevision fromIon(final IonStruct ionStruct) throws IOException {
    try {
        BlockAddress blockAddress = Constants.MAPPER.readValue(ionStruct.get("blockAddress"), BlockAddress.class);
        IonBlob hash = (IonBlob) ionStruct.get("hash");
        IonStruct metadataStruct = (IonStruct) ionStruct.get("metadata");
        IonStruct data = (IonStruct) ionStruct.get("data");
        if (hash == null || data == null) {
            throw new IllegalArgumentException("Document is missing required fields");
        }
        verifyRevisionHash(metadataStruct, data, hash.getBytes());
        RevisionMetadata metadata = RevisionMetadata.fromIon(metadataStruct);
        return new QldbRevision(blockAddress, metadata, hash.getBytes(), data);
    } catch (ClassCastException e) {
        log.error("Failed to parse ion document");
        throw new IllegalArgumentException("Document members are not of the correct type", e);
    }
}
Also used : IonStruct(com.amazon.ion.IonStruct) IonBlob(com.amazon.ion.IonBlob)

Example 5 with IonStruct

use of com.amazon.ion.IonStruct in project amazon-qldb-dmv-sample-java by aws-samples.

the class StreamJournal method streamRecordsToJournalBlocks.

private static List<JournalBlock> streamRecordsToJournalBlocks() {
    Map<ByteBuffer, QldbRevision> revisionsByHash = new HashMap<>();
    recordBuffer.stream().filter(record -> record.getRecordType().equals("REVISION_DETAILS")).forEach(record -> {
        try {
            Revision revision = ((RevisionDetailsRecord) record.getPayload()).getRevision();
            byte[] revisionHash = revision.getHash();
            revisionsByHash.put(wrap(revisionHash).asReadOnlyBuffer(), QldbRevision.fromIon((IonStruct) Constants.MAPPER.writeValueAsIonValue(revision)));
        } catch (IOException e) {
            throw new IllegalArgumentException("Could not map RevisionDetailsRecord to QldbRevision.", e);
        }
    });
    return recordBuffer.stream().filter(streamRecord -> streamRecord.getRecordType().equals("BLOCK_SUMMARY")).map(streamRecord -> (BlockSummaryRecord) streamRecord.getPayload()).distinct().map(blockSummaryRecord -> blockSummaryRecordToJournalBlock(blockSummaryRecord, revisionsByHash)).sorted(Comparator.comparingLong(o -> o.getBlockAddress().getSequenceNo())).collect(Collectors.toList());
}
Also used : DefaultAWSCredentialsProviderChain(com.amazonaws.auth.DefaultAWSCredentialsProviderChain) Date(java.util.Date) JournalKinesisStreamDescription(com.amazonaws.services.qldb.model.JournalKinesisStreamDescription) LoggerFactory(org.slf4j.LoggerFactory) ByteBuffer(java.nio.ByteBuffer) CreateTable(software.amazon.qldb.tutorial.CreateTable) ObjectReader(com.fasterxml.jackson.databind.ObjectReader) AmazonIdentityManagementClientBuilder(com.amazonaws.services.identitymanagement.AmazonIdentityManagementClientBuilder) DescribeStreamResult(com.amazonaws.services.kinesis.model.DescribeStreamResult) RevisionDetailsRecord(software.amazon.qldb.tutorial.model.streams.RevisionDetailsRecord) StreamRecord(software.amazon.qldb.tutorial.model.streams.StreamRecord) StreamJournalToKinesisRequest(com.amazonaws.services.qldb.model.StreamJournalToKinesisRequest) Duration(java.time.Duration) Map(java.util.Map) ListJournalKinesisStreamsForLedgerResult(com.amazonaws.services.qldb.model.ListJournalKinesisStreamsForLedgerResult) AmazonIdentityManagement(com.amazonaws.services.identitymanagement.AmazonIdentityManagement) LEDGER_NAME(software.amazon.qldb.tutorial.Constants.LEDGER_NAME) CreateRoleRequest(com.amazonaws.services.identitymanagement.model.CreateRoleRequest) AmazonKinesis(com.amazonaws.services.kinesis.AmazonKinesis) ListJournalKinesisStreamsForLedgerRequest(com.amazonaws.services.qldb.model.ListJournalKinesisStreamsForLedgerRequest) AmazonQLDBClientBuilder(com.amazonaws.services.qldb.AmazonQLDBClientBuilder) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) PutRolePolicyRequest(com.amazonaws.services.identitymanagement.model.PutRolePolicyRequest) Executors(java.util.concurrent.Executors) IonTextWriterBuilder(com.amazon.ion.system.IonTextWriterBuilder) List(java.util.List) IonReader(com.amazon.ion.IonReader) NoSuchEntityException(com.amazonaws.services.identitymanagement.model.NoSuchEntityException) GetRoleRequest(com.amazonaws.services.identitymanagement.model.GetRoleRequest) JournalBlock(software.amazon.qldb.tutorial.qldb.JournalBlock) Record(com.amazonaws.services.kinesis.model.Record) IonWriter(com.amazon.ion.IonWriter) ByteBuffer.wrap(java.nio.ByteBuffer.wrap) InsertDocument(software.amazon.qldb.tutorial.InsertDocument) IRecordProcessorCheckpointer(com.amazonaws.services.kinesis.clientlibrary.interfaces.IRecordProcessorCheckpointer) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) Function(java.util.function.Function) QldbRevision(software.amazon.qldb.tutorial.qldb.QldbRevision) STREAM_NAME(software.amazon.qldb.tutorial.Constants.STREAM_NAME) ArrayList(java.util.ArrayList) IonStruct(com.amazon.ion.IonStruct) Worker(com.amazonaws.services.kinesis.clientlibrary.lib.worker.Worker) ValidateQldbHashChain(software.amazon.qldb.tutorial.ValidateQldbHashChain) DescribeStreamRequest(com.amazonaws.services.kinesis.model.DescribeStreamRequest) IRecordProcessorFactory(com.amazonaws.services.kinesis.clientlibrary.interfaces.IRecordProcessorFactory) DescribeJournalKinesisStreamRequest(com.amazonaws.services.qldb.model.DescribeJournalKinesisStreamRequest) AWSCredentialsProvider(com.amazonaws.auth.AWSCredentialsProvider) ResourceNotFoundException(com.amazonaws.services.kinesis.model.ResourceNotFoundException) CreateLedger(software.amazon.qldb.tutorial.CreateLedger) BlockSummaryRecord(software.amazon.qldb.tutorial.model.streams.BlockSummaryRecord) IRecordProcessor(com.amazonaws.services.kinesis.clientlibrary.interfaces.IRecordProcessor) Logger(org.slf4j.Logger) StreamJournalToKinesisResult(com.amazonaws.services.qldb.model.StreamJournalToKinesisResult) AmazonQLDB(com.amazonaws.services.qldb.AmazonQLDB) SampleData(software.amazon.qldb.tutorial.model.SampleData) IonReaderBuilder(com.amazon.ion.system.IonReaderBuilder) CancelJournalKinesisStreamRequest(com.amazonaws.services.qldb.model.CancelJournalKinesisStreamRequest) GetRolePolicyRequest(com.amazonaws.services.identitymanagement.model.GetRolePolicyRequest) KinesisConfiguration(com.amazonaws.services.qldb.model.KinesisConfiguration) IOException(java.io.IOException) DescribeJournalKinesisStreamResult(com.amazonaws.services.qldb.model.DescribeJournalKinesisStreamResult) TRIM_HORIZON(com.amazonaws.services.kinesis.clientlibrary.lib.worker.InitialPositionInStream.TRIM_HORIZON) TimeUnit(java.util.concurrent.TimeUnit) Revision(software.amazon.qldb.tutorial.model.streams.Revision) DeleteLedger(software.amazon.qldb.tutorial.DeleteLedger) AmazonKinesisClientBuilder(com.amazonaws.services.kinesis.AmazonKinesisClientBuilder) ShutdownReason(com.amazonaws.services.kinesis.clientlibrary.lib.worker.ShutdownReason) Constants(software.amazon.qldb.tutorial.Constants) DeletionProtection(software.amazon.qldb.tutorial.DeletionProtection) Comparator(java.util.Comparator) KinesisClientLibConfiguration(com.amazonaws.services.kinesis.clientlibrary.lib.worker.KinesisClientLibConfiguration) RevisionDetailsRecord(software.amazon.qldb.tutorial.model.streams.RevisionDetailsRecord) IonStruct(com.amazon.ion.IonStruct) QldbRevision(software.amazon.qldb.tutorial.qldb.QldbRevision) Revision(software.amazon.qldb.tutorial.model.streams.Revision) HashMap(java.util.HashMap) QldbRevision(software.amazon.qldb.tutorial.qldb.QldbRevision) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer)

Aggregations

IonStruct (com.amazon.ion.IonStruct)68 Test (org.junit.Test)28 IonValue (com.amazon.ion.IonValue)18 IonDatagram (com.amazon.ion.IonDatagram)13 IonList (com.amazon.ion.IonList)13 IonReader (com.amazon.ion.IonReader)13 SymbolTable (com.amazon.ion.SymbolTable)13 IOException (java.io.IOException)8 IonString (com.amazon.ion.IonString)7 IonSystem (com.amazon.ion.IonSystem)6 IonException (com.amazon.ion.IonException)5 IonSequence (com.amazon.ion.IonSequence)5 IonType (com.amazon.ion.IonType)5 IonFloat (com.amazon.ion.IonFloat)4 IonSymbol (com.amazon.ion.IonSymbol)4 IonTimestamp (com.amazon.ion.IonTimestamp)4 IonWriter (com.amazon.ion.IonWriter)4 SymbolToken (com.amazon.ion.SymbolToken)4 ArrayList (java.util.ArrayList)4 IonBlob (com.amazon.ion.IonBlob)3