11package io .iohk .ethereum .blockchain .data
22
33import java .io .FileNotFoundException
4-
54import akka .util .ByteString
6- import io .iohk .ethereum .blockchain .data .GenesisDataLoader .JsonSerializers .ByteStringJsonSerializer
5+ import io .iohk .ethereum .blockchain .data .GenesisDataLoader .JsonSerializers .{
6+ ByteStringJsonSerializer ,
7+ UInt256JsonSerializer
8+ }
9+ import io .iohk .ethereum .db .storage .MptStorage
710import io .iohk .ethereum .db .storage .StateStorage .GenesisDataLoad
811import io .iohk .ethereum .rlp .RLPList
912import io .iohk .ethereum .utils .BlockchainConfig
1013import io .iohk .ethereum .utils .Logger
1114import io .iohk .ethereum .{crypto , rlp }
1215import io .iohk .ethereum .domain ._
16+ import io .iohk .ethereum .jsonrpc .JsonMethodsImplicits
1317import io .iohk .ethereum .mpt .MerklePatriciaTrie
1418import io .iohk .ethereum .rlp .RLPImplicits ._
1519import org .json4s .{CustomSerializer , DefaultFormats , Formats , JString , JValue }
@@ -75,7 +79,7 @@ class GenesisDataLoader(blockchain: Blockchain, blockchainConfig: BlockchainConf
7579
7680 private def loadGenesisData (genesisJson : String ): Try [Unit ] = {
7781 import org .json4s .native .JsonMethods .parse
78- implicit val formats : Formats = DefaultFormats + ByteStringJsonSerializer
82+ implicit val formats : Formats = DefaultFormats + ByteStringJsonSerializer + UInt256JsonSerializer
7983 for {
8084 genesisData <- Try (parse(genesisJson).extract[GenesisData ])
8185 _ <- loadGenesisData(genesisData)
@@ -89,19 +93,7 @@ class GenesisDataLoader(blockchain: Blockchain, blockchainConfig: BlockchainConf
8993 val storage = stateStorage.getReadOnlyStorage
9094 val initalRootHash = MerklePatriciaTrie .EmptyRootHash
9195
92- val stateMptRootHash = genesisData.alloc.zipWithIndex.foldLeft(initalRootHash) {
93- case (rootHash, (((address, AllocAccount (balance)), idx))) =>
94- val mpt = MerklePatriciaTrie [Array [Byte ], Account ](rootHash, storage)
95- val paddedAddress = address.reverse.padTo(addressLength, " 0" ).reverse.mkString
96- val stateRoot = mpt
97- .put(
98- crypto.kec256(Hex .decode(paddedAddress)),
99- Account (blockchainConfig.accountStartNonce, UInt256 (BigInt (balance)), emptyTrieRootHash, emptyEvmHash)
100- )
101- .getRootHash
102- stateRoot
103- }
104-
96+ val stateMptRootHash = getGenesisStateRoot(genesisData, initalRootHash, storage)
10597 val header : BlockHeader = prepareHeader(genesisData, stateMptRootHash)
10698
10799 log.debug(s " Prepared genesis header: $header" )
@@ -130,6 +122,27 @@ class GenesisDataLoader(blockchain: Blockchain, blockchainConfig: BlockchainConf
130122 }
131123 }
132124
125+ private def getGenesisStateRoot (genesisData : GenesisData , initalRootHash : Array [Byte ], storage : MptStorage ) = {
126+ import MerklePatriciaTrie .defaultByteArraySerializable
127+
128+ genesisData.alloc.zipWithIndex.foldLeft(initalRootHash) { case (rootHash, ((address, genesisAccount), _)) =>
129+ val mpt = MerklePatriciaTrie [Array [Byte ], Account ](rootHash, storage)
130+ val paddedAddress = address.reverse.padTo(addressLength, " 0" ).reverse.mkString
131+ val stateRoot = mpt
132+ .put(
133+ crypto.kec256(Hex .decode(paddedAddress)),
134+ Account (
135+ nonce = genesisAccount.nonce
136+ .getOrElse(blockchainConfig.accountStartNonce),
137+ balance = genesisAccount.balance,
138+ codeHash = genesisAccount.code.map(codeValue => crypto.kec256(codeValue)).getOrElse(Account .EmptyCodeHash )
139+ )
140+ )
141+ .getRootHash
142+ stateRoot
143+ }
144+ }
145+
133146 private def prepareHeader (genesisData : GenesisData , stateMptRootHash : Array [Byte ]) =
134147 BlockHeader (
135148 parentHash = zeros(hashLength),
@@ -178,5 +191,23 @@ object GenesisDataLoader {
178191 )
179192 )
180193
194+ def deserializeUint256String (jv : JValue ): UInt256 = jv match {
195+ case JString (s) =>
196+ Try (UInt256 (BigInt (s))) match {
197+ case Failure (_) => throw new RuntimeException (" Cannot parse hex string: " + s)
198+ case Success (value) => value
199+ }
200+ case other => throw new RuntimeException (" Expected hex string, but got: " + other)
201+ }
202+
203+ object UInt256JsonSerializer
204+ extends CustomSerializer [UInt256 ](formats =>
205+ (
206+ { case jv => deserializeUint256String(jv) },
207+ PartialFunction .empty
208+ )
209+ )
181210 }
182211}
212+
213+ object Implicits extends JsonMethodsImplicits
0 commit comments