Advertisement
Guest User

Untitled

a guest
Jan 17th, 2017
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.17 KB | None | 0 0
  1. package io.iohk.ethereum.mpt
  2.  
  3. import java.io.File
  4.  
  5. import akka.util.ByteString
  6. import io.iohk.ethereum.crypto._
  7. import io.iohk.ethereum.network.p2p.messages.CommonMessages.{Transaction, TransactionData}
  8. import io.iohk.ethereum.rlp.RLPImplicits._
  9. import io.iohk.ethereum.rlp.{decode => rlpDecode, encode => rlpEncode}
  10. import io.iohk.iodb.LSMStore
  11. import org.spongycastle.util.encoders.Hex
  12.  
  13. object TestPatriciaTrie {
  14.  
  15. implicit val intByteArraySerializable = new ByteArraySerializable[Int] {
  16. override def toBytes(input: Int): Array[Byte] = rlpEncode(input)
  17.  
  18. override def fromBytes(bytes: Array[Byte]): Int = rlpDecode[Int](bytes)
  19. }
  20.  
  21. implicit val txByteArraySerializable = new ByteArraySerializable[Transaction] {
  22. override def toBytes(input: Transaction): Array[Byte] = rlpEncode(input)
  23.  
  24. override def fromBytes(bytes: Array[Byte]): Transaction = rlpDecode[Transaction](bytes)
  25. }
  26.  
  27. case class HashMapDataSource(storage: Map[ByteString, Array[Byte]]) extends DataSource {
  28.  
  29. override def get(key: Array[Byte]): Option[Array[Byte]] = storage.get(ByteString(key))
  30.  
  31. override def update(rootHash: Array[Byte], toRemove: Seq[Key], toUpdate: Seq[(Key, Value)]): DataSource = {
  32. val afterUpdate = toUpdate.foldLeft(storage)((storage, toUpdate) => storage + (ByteString(toUpdate._1) -> toUpdate._2))
  33. HashMapDataSource(afterUpdate)
  34. }
  35. }
  36.  
  37.  
  38. def main(args: Array[String]): Unit = {
  39. val dir = File.createTempFile("iodb", "iodb")
  40. dir.delete()
  41. dir.mkdir()
  42.  
  43. //open new store
  44. val dataSource = new IodbDataSource(new LSMStore(dir = dir, keySize = 32))
  45. val emptyTrie = MerklePatriciaTrie[Int, Transaction](dataSource, (input: Array[Byte]) => sha3(input))
  46.  
  47. // Get the same hash as Geth
  48. val tx = Transaction(
  49. nonce = 0,
  50. gasPrice = BigInt(20000000000l),
  51. gasLimit = BigInt(90000),
  52. receivingAddress = ByteString(Hex.decode("4dcc858fe9a8048bc778b7170ac29faccd116a4c")),
  53. value = BigInt(50000000000000000l),
  54. payload = Right(TransactionData(ByteString.empty)),
  55. pointSign = 28,
  56. signatureRandom = ByteString(Hex.decode("5663dbcb92cefdbca6907ed5bef9f5134fbde571726364da691f37462e2c4751")),
  57. signature = ByteString(Hex.decode("0300f72c91529304101e362913dbaf4ae03caee2fb84ba7d52f5362c103db8a1"))
  58. )
  59.  
  60. val afterInsert = emptyTrie.put(0, tx)
  61. val hexRoothash = Hex.toHexString(afterInsert.getRootHash)
  62. println(s"Single root hash: $hexRoothash \n")
  63. assert(hexRoothash == "98de664ac20c6eb730c0f0eff02e1e1300ecbe907e19dd54b65f3859306190f3")
  64.  
  65. // We can create a new trie using the same root and data source
  66. val sameAsEmptyTrie = MerklePatriciaTrie[Int, Transaction](afterInsert.getRootHash, dataSource, (input: Array[Byte]) => sha3(input))
  67. println(s"Let's grab the stored tx => ${sameAsEmptyTrie.get(0).get} \n")
  68.  
  69. // And you can configure which datasource you would like to use, for example, an inmemory one
  70. val txs = Seq(
  71. Transaction(
  72. nonce = 1,
  73. gasPrice = BigInt(20000000000l),
  74. gasLimit = BigInt(90000),
  75. receivingAddress = ByteString(Hex.decode("4dcc858fe9a8048bc778b7170ac29faccd116a4c")),
  76. value = BigInt(100000000000000000l),
  77. payload = Right(TransactionData(ByteString.empty)),
  78. pointSign = 28,
  79. signatureRandom = ByteString(Hex.decode("f39a27210ef18b03bea91d6d722db71437d26ad6c85069ade674dba593dd2fe3")),
  80. signature = ByteString(Hex.decode("644d064f9774c05e51858e33f4bdd440819cc7d278075fb233538047ac9f0e5a"))
  81. ),
  82. Transaction(
  83. nonce = 2,
  84. gasPrice = BigInt(20000000000l),
  85. gasLimit = BigInt(90000),
  86. receivingAddress = ByteString(Hex.decode("4dcc858fe9a8048bc778b7170ac29faccd116a4c")),
  87. value = BigInt(200000000000000000l),
  88. payload = Right(TransactionData(ByteString.empty)),
  89. pointSign = 27,
  90. signatureRandom = ByteString(Hex.decode("301f8200f4d250cda6ea00701ae339ee73296b9ab1315d1402fcd249aaa0024d")),
  91. signature = ByteString(Hex.decode("344bd35299031441b984d3a6e3b8884ea2c08483a2aeab69edf9e5c5401edbfa"))
  92. ), Transaction(
  93. nonce = 3,
  94. gasPrice = BigInt(20000000000l),
  95. gasLimit = BigInt(90000),
  96. receivingAddress = ByteString(Hex.decode("4dcc858fe9a8048bc778b7170ac29faccd116a4c")),
  97. value = BigInt(300000000000000000l),
  98. payload = Right(TransactionData(ByteString.empty)),
  99. pointSign = 27,
  100. signatureRandom = ByteString(Hex.decode("9c4df5bf829fecfa6c5932ac30a402898e565f6b45107cb0fd1cd7738f210049")),
  101. signature = ByteString(Hex.decode("4681d880ebed7b3cfa477023d8ce94314705ed2826a0beac52b121b7d8706b69"))
  102. )
  103. )
  104. val ephemeralDS = HashMapDataSource(Map())
  105. val trie2 = MerklePatriciaTrie[Int, Transaction](ephemeralDS, (input: Array[Byte]) => sha3(input))
  106.  
  107. val toInsert = txs.zipWithIndex
  108.  
  109. val trieAfterAllInserts = toInsert.foldLeft(trie2) { (result: MerklePatriciaTrie[Int, Transaction], value) =>
  110. result.put(value._2, value._1)
  111. }
  112.  
  113. val trieAfterAllInsertsRootHash = Hex.toHexString(trieAfterAllInserts.getRootHash)
  114. println(s"Trie root hash => ${trieAfterAllInsertsRootHash} \n")
  115. assert(trieAfterAllInsertsRootHash == "3cf268d513153a048d21ea425412038120f9e60dfd13372c20a5d045dcfbf1e7")
  116. }
  117.  
  118. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement