Search in sources :

Example 26 with StreamFileData

use of com.hedera.mirror.importer.domain.StreamFileData in project hedera-mirror-node by hashgraph.

the class Downloader method verifySigsAndDownloadDataFiles.

/**
 * For each group of signature files with the same file name: (1) verify that the signature files are signed by
 * corresponding node's PublicKey; (2) For valid signature files, we compare their Hashes to see if at least 1/3 of
 * hashes match. If they do, we download the corresponding data file from a node folder which has valid signature
 * file. (3) compare the hash of data file with Hash which has been agreed on by valid signatures, if match, move
 * the data file into `valid` directory; else download the data file from other valid node folder and compare the
 * hash until we find a match.
 *
 * @param sigFilesMap signature files grouped by filename
 */
private void verifySigsAndDownloadDataFiles(Multimap<String, FileStreamSignature> sigFilesMap) {
    Instant endDate = mirrorProperties.getEndDate();
    for (var sigFilenameIter = sigFilesMap.keySet().iterator(); sigFilenameIter.hasNext(); ) {
        if (ShutdownHelper.isStopping()) {
            return;
        }
        Instant startTime = Instant.now();
        String sigFilename = sigFilenameIter.next();
        Collection<FileStreamSignature> signatures = sigFilesMap.get(sigFilename);
        boolean valid = false;
        try {
            nodeSignatureVerifier.verify(signatures);
        } catch (SignatureVerificationException ex) {
            if (sigFilenameIter.hasNext()) {
                log.warn("Signature verification failed but still have files in the batch, try to process the " + "next group: {}", ex.getMessage());
                continue;
            }
            throw ex;
        }
        for (FileStreamSignature signature : signatures) {
            if (ShutdownHelper.isStopping()) {
                return;
            }
            // Ignore signatures that didn't validate or weren't in the majority
            if (signature.getStatus() != FileStreamSignature.SignatureStatus.CONSENSUS_REACHED) {
                continue;
            }
            try {
                PendingDownload pendingDownload = downloadSignedDataFile(signature);
                if (!pendingDownload.waitForCompletion()) {
                    continue;
                }
                StreamFilename dataFilename = pendingDownload.getStreamFilename();
                StreamFileData streamFileData = new StreamFileData(dataFilename, pendingDownload.getBytes());
                T streamFile = streamFileReader.read(streamFileData);
                streamFile.setNodeAccountId(signature.getNodeAccountId());
                verify(streamFile, signature);
                if (downloaderProperties.isWriteFiles()) {
                    Utility.archiveFile(streamFile.getName(), streamFile.getBytes(), downloaderProperties.getNodeStreamPath(signature.getNodeAccountIdString()));
                }
                if (downloaderProperties.isWriteSignatures()) {
                    signatures.forEach(s -> {
                        Path destination = downloaderProperties.getNodeStreamPath(s.getNodeAccountIdString());
                        Utility.archiveFile(s.getFilename(), s.getBytes(), destination);
                    });
                }
                if (!downloaderProperties.isPersistBytes()) {
                    streamFile.setBytes(null);
                }
                if (dataFilename.getInstant().isAfter(endDate)) {
                    downloaderProperties.setEnabled(false);
                    log.warn("Disabled polling after downloading all files <= endDate ({})", endDate);
                    return;
                }
                onVerified(pendingDownload, streamFile);
                valid = true;
                break;
            } catch (HashMismatchException e) {
                log.warn("Failed to verify data file from node {} corresponding to {}. Will retry another node", signature.getNodeAccountIdString(), sigFilename, e);
            } catch (InterruptedException e) {
                log.warn("Failed to download data file from node {} corresponding to {}", signature.getNodeAccountIdString(), sigFilename, e);
                Thread.currentThread().interrupt();
            } catch (Exception e) {
                log.error("Error downloading data file from node {} corresponding to {}. Will retry another node", signature.getNodeAccountIdString(), sigFilename, e);
            }
        }
        if (!valid) {
            log.error("None of the data files could be verified, signatures: {}", signatures);
        }
        streamVerificationMetric.tag("success", String.valueOf(valid)).register(meterRegistry).record(Duration.between(startTime, Instant.now()));
    }
}
Also used : Path(java.nio.file.Path) StreamFilename(com.hedera.mirror.importer.domain.StreamFilename) Instant(java.time.Instant) FileStreamSignature(com.hedera.mirror.importer.domain.FileStreamSignature) HashMismatchException(com.hedera.mirror.importer.exception.HashMismatchException) HashMismatchException(com.hedera.mirror.importer.exception.HashMismatchException) InvalidStreamFileException(com.hedera.mirror.importer.exception.InvalidStreamFileException) SignatureVerificationException(com.hedera.mirror.importer.exception.SignatureVerificationException) ExecutionException(java.util.concurrent.ExecutionException) StreamFileData(com.hedera.mirror.importer.domain.StreamFileData) SignatureVerificationException(com.hedera.mirror.importer.exception.SignatureVerificationException)

Example 27 with StreamFileData

use of com.hedera.mirror.importer.domain.StreamFileData in project hedera-mirror-node by hashgraph.

the class Downloader method parseSignatureFile.

private Optional<FileStreamSignature> parseSignatureFile(PendingDownload pendingDownload, EntityId nodeAccountId) throws InterruptedException, ExecutionException {
    String s3Key = pendingDownload.getS3key();
    Stopwatch stopwatch = pendingDownload.getStopwatch();
    if (!pendingDownload.waitForCompletion()) {
        log.warn("Failed downloading {} in {}", s3Key, stopwatch);
        return Optional.empty();
    }
    StreamFilename streamFilename = pendingDownload.getStreamFilename();
    StreamFileData streamFileData = new StreamFileData(streamFilename, pendingDownload.getBytes());
    FileStreamSignature fileStreamSignature = signatureFileReader.read(streamFileData);
    fileStreamSignature.setNodeAccountId(nodeAccountId);
    fileStreamSignature.setStreamType(streamType);
    return Optional.of(fileStreamSignature);
}
Also used : StreamFilename(com.hedera.mirror.importer.domain.StreamFilename) StreamFileData(com.hedera.mirror.importer.domain.StreamFileData) Stopwatch(com.google.common.base.Stopwatch) FileStreamSignature(com.hedera.mirror.importer.domain.FileStreamSignature)

Example 28 with StreamFileData

use of com.hedera.mirror.importer.domain.StreamFileData in project hedera-mirror-node by hashgraph.

the class CompositeBalanceFileReaderTest method usesVersion2Reader.

@Test
void usesVersion2Reader() {
    StreamFileData streamFileData = StreamFileData.from(BALANCE_FILENAME_PREFIX + ".csv", "# version:2");
    configMockReader(protoBalanceFileReader, streamFileData, false);
    configMockReader(readerImplV2, streamFileData, true);
    compositeBalanceFileReader.read(streamFileData);
    verify(readerImplV2, times(1)).read(streamFileData);
    verify(readerImplV1, never()).read(streamFileData);
    verify(protoBalanceFileReader, never()).read(streamFileData);
}
Also used : StreamFileData(com.hedera.mirror.importer.domain.StreamFileData) Test(org.junit.jupiter.api.Test)

Example 29 with StreamFileData

use of com.hedera.mirror.importer.domain.StreamFileData in project hedera-mirror-node by hashgraph.

the class CompositeBalanceFileReaderTest method usesProtoBalanceFileReader.

@Test
void usesProtoBalanceFileReader() {
    StreamFileData streamFileData = StreamFileData.from(BALANCE_FILENAME_PREFIX + ".pb.gz", "proto-based balance file");
    configMockReader(protoBalanceFileReader, streamFileData, true);
    compositeBalanceFileReader.read(streamFileData);
    verify(protoBalanceFileReader, times(1)).read(streamFileData);
    verify(readerImplV1, never()).read(streamFileData);
    verify(readerImplV2, never()).read(streamFileData);
}
Also used : StreamFileData(com.hedera.mirror.importer.domain.StreamFileData) Test(org.junit.jupiter.api.Test)

Example 30 with StreamFileData

use of com.hedera.mirror.importer.domain.StreamFileData in project hedera-mirror-node by hashgraph.

the class CsvBalanceFileReaderTest method readValidWhenFileHasLinesWithDifferentShardNum.

@Test
void readValidWhenFileHasLinesWithDifferentShardNum() throws IOException {
    List<String> lines = FileUtils.readLines(balanceFile, CsvBalanceFileReader.CHARSET);
    FileUtils.writeLines(testFile, lines);
    long otherShard = mirrorProperties.getShard() + 1;
    FileUtils.writeStringToFile(testFile, String.format("\n%d,0,3,340\n%d,0,4,340\n", otherShard, otherShard), CsvBalanceFileReader.CHARSET, true);
    StreamFileData streamFileData = StreamFileData.from(testFile);
    AccountBalanceFile accountBalanceFile = balanceFileReader.read(streamFileData);
    assertAccountBalanceFile(accountBalanceFile);
    verifySuccess(testFile, accountBalanceFile, 2);
}
Also used : AccountBalanceFile(com.hedera.mirror.common.domain.balance.AccountBalanceFile) StreamFileData(com.hedera.mirror.importer.domain.StreamFileData) Test(org.junit.jupiter.api.Test)

Aggregations

StreamFileData (com.hedera.mirror.importer.domain.StreamFileData)51 Test (org.junit.jupiter.api.Test)40 AccountBalanceFile (com.hedera.mirror.common.domain.balance.AccountBalanceFile)8 Path (java.nio.file.Path)6 TestFactory (org.junit.jupiter.api.TestFactory)6 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)6 FileStreamSignature (com.hedera.mirror.importer.domain.FileStreamSignature)4 AllAccountBalances (com.hedera.services.stream.proto.AllAccountBalances)4 UnknownFieldSet (com.google.protobuf.UnknownFieldSet)3 RecordFile (com.hedera.mirror.common.domain.transaction.RecordFile)3 RecordItem (com.hedera.mirror.common.domain.transaction.RecordItem)3 InvalidStreamFileException (com.hedera.mirror.importer.exception.InvalidStreamFileException)3 Instant (java.time.Instant)3 ValueSource (org.junit.jupiter.params.provider.ValueSource)3 AccountBalance (com.hedera.mirror.common.domain.balance.AccountBalance)2 TokenBalance (com.hedera.mirror.common.domain.balance.TokenBalance)2 EntityId (com.hedera.mirror.common.domain.entity.EntityId)2 EventFile (com.hedera.mirror.common.domain.event.EventFile)2 DomainUtils (com.hedera.mirror.common.util.DomainUtils)2 StreamFilename (com.hedera.mirror.importer.domain.StreamFilename)2