Guest User

Untitled

a guest
Dec 13th, 2017
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.22 KB | None | 0 0
  1. import java.io._
  2. import java.nio._
  3. import scala.collection.mutable.ArrayBuffer
  4. import org.apache.commons.io.FileUtils
  5. import org.bitcoinj.core._
  6. import org.bitcoinj.params._
  7. import scala.collection.JavaConversions._
  8.  
  9. object Utils {
  10.  
  11. // Used for closing files implicitly
  12. def using[A <: {def close(): Unit}, B](param: A)(f: A => B): B = try { f(param) } finally { param.close() }
  13.  
  14. // this is the method that actually parses the file
  15. def parseFile(name:String) = {
  16. System.gc // large files (around 140 GB, need to clear memory)
  17. using(new FileInputStream(name)) {fis =>
  18. using(new BufferedInputStream(fis)) {bis =>
  19. var currBlkByte = -1 // which byte of raw block are we reading?
  20. var currBlk = 0 // which block is currently being read?
  21. var currBlkSize = -1L // what is the size of block (in bytes)
  22. var endBlkByte = -1 // which is the ending byte of current block?
  23.  
  24. val blkSizeBytes = new ArrayBuffer[Byte] // stores bytes containing data about block size
  25. val blkBytes = new ArrayBuffer[Byte] // stores bytes of block
  26.  
  27. Stream.continually(bis.read).takeWhile(-1 !=).foreach{int =>
  28. currBlkByte += 1
  29. val byte = int.toByte
  30. // ignore first 4 bytes (magic bytes), next 4 bytes stores upcoming block's size in little endian
  31. if (currBlkByte >= 4 && currBlkByte < 8) blkSizeBytes += byte
  32. if (currBlkByte == 7) { // this byte is the last one encoding block's size
  33. currBlkSize = ByteBuffer.wrap(blkSizeBytes.toArray).order(ByteOrder.LITTLE_ENDIAN).getInt & 0xFFFFFFFFL;
  34. endBlkByte = currBlkSize.toInt + 7 // first 8 bytes for info, remaining encoding block
  35. blkSizeBytes.clear // clear for next block
  36. }
  37. if (currBlkByte > 7) blkBytes += byte // block data
  38. if (currBlkByte == endBlkByte) { // we have reached end of block
  39. // last block byte
  40. currBlk += 1 // increment block count
  41. currBlkByte = -1 // reset
  42. endBlkByte = -1 // reset
  43. parseBlk(blkBytes.toArray) // we have block in bytes, lets parse it
  44. blkBytes.clear // reset
  45. }
  46. }
  47. }
  48. }
  49. }
  50.  
  51. val context = new Context(MainNetParams.get) // needed for Bitcoinj v 0.13 and above
  52.  
  53. def parseBlk(bytes:Array[Byte]) = { // uses Bitcoinj
  54. new Block(MainNetParams.get, bytes).getTransactions.foreach {tx =>
  55. val hash = tx.getHashAsString
  56. val inputs = tx.getInputs
  57. val outputs = tx.getOutputs
  58. // do something with above
  59. }
  60. }
  61. def getAllFiles(dir:String, extensions:Array[String], recursive:Boolean) =
  62. FileUtils.listFiles(new File(dir), extensions, recursive).toArray.map(_.toString)
  63.  
  64. }
  65. import Utils._
  66.  
  67. object BlockParser {
  68. val dir = "/home/user/.bitcoin/blocks"
  69. //files have names like blk00000.dat, ..., blk01096.dat (last one at time of writing)
  70. val files = getAllFiles(dir, Array("dat"), false).collect {
  71. case name if name.contains("blk") => // collect only those file with names like "blkxxxxx.dat"
  72. val num = name.drop(s"$dir/blk".size).take(5).toInt // (take 5 is based on actual file names)
  73. (name, num)
  74. }.sortBy(_._2).unzip._1 // sort by file number
  75.  
  76. files.foreach(parseFile)
  77. }
Add Comment
Please, Sign In to add comment