Coverage Summary for Class: BootstrapFileHandler (co.rsk.db.importer.provider)

Class Class, % Method, % Line, %
BootstrapFileHandler 0% (0/1) 0% (0/9) 0% (0/41)


1 /* 2  * This file is part of RskJ 3  * Copyright (C) 2019 RSK Labs Ltd. 4  * 5  * This program is free software: you can redistribute it and/or modify 6  * it under the terms of the GNU Lesser General Public License as published by 7  * the Free Software Foundation, either version 3 of the License, or 8  * (at your option) any later version. 9  * 10  * This program is distributed in the hope that it will be useful, 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13  * GNU Lesser General Public License for more details. 14  * 15  * You should have received a copy of the GNU Lesser General Public License 16  * along with this program. If not, see <http://www.gnu.org/licenses/>. 17  */ 18  19 package co.rsk.db.importer.provider; 20  21 import co.rsk.db.importer.BootstrapImportException; 22 import co.rsk.db.importer.BootstrapURLProvider; 23 import co.rsk.db.importer.provider.index.data.BootstrapDataEntry; 24 import org.bouncycastle.util.encoders.Hex; 25 import org.ethereum.crypto.HashUtil; 26 import org.slf4j.Logger; 27 import org.slf4j.LoggerFactory; 28  29 import java.io.*; 30 import java.net.URL; 31 import java.nio.file.Files; 32 import java.nio.file.Path; 33 import java.nio.file.StandardCopyOption; 34 import java.security.SecureRandom; 35 import java.util.*; 36  37 public class BootstrapFileHandler { 38  39  private static final Logger logger = LoggerFactory.getLogger(BootstrapFileHandler.class); 40  private static final String BOOTSTRAP_DATA_NAME = "bootstrap-data.zip"; 41  private static final String EXTRACTED_PATH = "bootstrap-data.bin"; 42  43  private final BootstrapURLProvider bootstrapUrlProvider; 44  private final Unzipper unzipper; 45  private Path tempPath; 46  47  public BootstrapFileHandler( 48  BootstrapURLProvider bootstrapUrlProvider, 49  Unzipper unzipper) { 50  this.bootstrapUrlProvider = bootstrapUrlProvider; 51  this.unzipper = unzipper; 52  } 53  54  // for testing purposes these 3 methods are splitted into 3 public items 55  public void setTempDirectory() { 56  this.tempPath = getTempDirectory(); 57  } 58  59  public byte[] getBootstrapData() { 60  Path bootstrapPath = tempPath.resolve(EXTRACTED_PATH); 61  try { 62  return Files.readAllBytes(bootstrapPath); 63  } catch (IOException e) { 64  throw new BootstrapImportException(String.format( 65  "Failed reading data after decompression %s", bootstrapPath), e); 66  67  } 68  } 69  70  public void retrieveAndUnpack(Map<String, BootstrapDataEntry> selectedEntries) { 71  Path zipPath = tempPath.resolve(BOOTSTRAP_DATA_NAME); 72  73  List<String> publicKeys = new ArrayList<>(selectedEntries.keySet()); 74  String publicKey = publicKeys.get(new SecureRandom().nextInt(publicKeys.size())); 75  String expectedHash = selectedEntries.get(publicKey).getHash(); 76  77  String dbSuffix = selectedEntries.get(publicKey).getDb(); 78  URL dbURL = bootstrapUrlProvider.getFullURL(dbSuffix); 79  80  downloadFile(zipPath, dbURL); 81  checkFileHash(zipPath, expectedHash); 82  unzipFile(zipPath, tempPath); 83  } 84  85  private void checkFileHash(Path databasePath, String expectedHash) { 86  try { 87  byte[] fileContent = Files.readAllBytes(databasePath); 88  byte[] hash = HashUtil.sha256(fileContent); 89  if (!Arrays.equals(hash, Hex.decode(expectedHash))) { 90  throw new BootstrapImportException(String.format( 91  "File: %s does not match with expected hash: %s", databasePath, expectedHash)); 92  } 93  logger.info("Bootstrap data hash checked"); 94  } catch (IOException e) { 95  throw new BootstrapImportException( 96  "Error trying to read bootstrap data contents. Please start again the import process", e); 97  } 98  } 99  100  private void unzipFile(Path sourcePath, Path destinationPath) { 101  try (InputStream inputStream = Files.newInputStream(sourcePath)){ 102  unzipper.unzip(inputStream, destinationPath); 103  logger.info("Bootstrap data extracted"); 104  } catch (IOException e) { 105  throw new BootstrapImportException( 106  "The file is corrupted or incomplete. Please start again the import process", e); 107  } 108  } 109  110  private Path getTempDirectory() { 111  try { 112  return Files.createTempDirectory("import"); 113  } catch (IOException e) { 114  throw new BootstrapImportException( 115  "Failed to create a temporary directory. Please start again the import process", e); 116  } 117  } 118  119  private void downloadFile(Path downloadPath, URL url) { 120  try (InputStream is = url.openStream()) { 121  Files.copy(is, downloadPath, StandardCopyOption.REPLACE_EXISTING); 122  logger.info("Bootstrap data downloaded"); 123  } catch (IOException e) { 124  throw new BootstrapImportException(String.format( 125  "Error downloading bootstrap data from %s. Please start again the import process", url 126  ), e); 127  } 128  } 129 }