1
1
package io .iohk .ethereum .jsonrpc
2
2
3
3
import akka .actor .ActorSystem
4
- import akka .testkit .{ TestKit , TestProbe }
4
+ import akka .testkit .TestKit
5
5
import akka .util .ByteString
6
6
import com .softwaremill .diffx .scalatest .DiffMatcher
7
+ import io .iohk .ethereum ._
7
8
import io .iohk .ethereum .blockchain .sync .EphemBlockchainTestSetup
8
- import io .iohk .ethereum .consensus ._
9
9
import io .iohk .ethereum .consensus .ethash .blocks .EthashBlockGenerator
10
- import io .iohk .ethereum .domain .{ Account , Address , Block , EthereumUInt256Mpt , UInt256 }
11
- import io .iohk .ethereum .jsonrpc .server . controllers . JsonRpcBaseController . JsonRpcConfig
12
- import io .iohk .ethereum .keystore . KeyStore
13
- import io .iohk .ethereum .ledger .{ Ledger , StxLedger }
10
+ import io .iohk .ethereum .domain ._
11
+ import io .iohk .ethereum .jsonrpc .EthUserService .{ GetBalanceRequest , GetBalanceResponse , GetStorageAtRequest , GetTransactionCountRequest }
12
+ import io .iohk .ethereum .jsonrpc . ProofService .{ GetProofRequest , StorageProofKey }
13
+ import io .iohk .ethereum .ledger .Ledger
14
14
import io .iohk .ethereum .mpt .MerklePatriciaTrie
15
15
import io .iohk .ethereum .nodebuilder .ApisBuilder
16
- import io .iohk .ethereum .utils ._
17
- import io .iohk .ethereum ._
18
- import io .iohk .ethereum .jsonrpc .ProofService .{GetProofRequest , StorageProofKey }
19
16
import monix .execution .Scheduler .Implicits .global
20
17
import org .bouncycastle .util .encoders .Hex
21
18
import org .scalactic .TypeCheckedTripleEquals
@@ -24,11 +21,7 @@ import org.scalatest.OptionValues
24
21
import org .scalatest .concurrent .ScalaFutures
25
22
import org .scalatest .flatspec .AnyFlatSpecLike
26
23
import org .scalatest .matchers .should .Matchers
27
-
28
- import io .iohk .ethereum .jsonrpc .EthUserService .GetBalanceResponse
29
- import io .iohk .ethereum .jsonrpc .EthUserService .GetBalanceRequest
30
- import io .iohk .ethereum .jsonrpc .EthUserService .GetTransactionCountRequest
31
- import io .iohk .ethereum .jsonrpc .EthUserService .GetStorageAtRequest
24
+ import io .iohk .ethereum .mpt .MerklePatriciaTrie .defaultByteArraySerializable
32
25
33
26
class EthProofServiceSpec
34
27
extends TestKit (ActorSystem (" EthGetProofSpec_ActorSystem" ))
@@ -43,49 +36,9 @@ class EthProofServiceSpec
43
36
with DiffMatcher {
44
37
45
38
" EthProofService" should " handle getStorageAt request" in new TestSetup {
46
- // given
47
- val address = Address (ByteString (Hex .decode(" abbb6bebfa05aa13e908eaa492bd7a8343760477" )))
48
-
49
- val key = 333
50
- val value = 123
51
-
52
- val storageMpt = EthereumUInt256Mpt
53
- .storageMpt(
54
- ByteString (MerklePatriciaTrie .EmptyRootHash ),
55
- storagesInstance.storages.stateStorage.getBackingStorage(0 )
56
- )
57
- .put(UInt256 (key), UInt256 (value))
58
-
59
- val account = Account (
60
- nonce = 0 ,
61
- balance = UInt256 (0 ),
62
- storageRoot = ByteString (storageMpt.getRootHash),
63
- codeHash = ByteString (" " )
64
- )
65
-
66
- import MerklePatriciaTrie .defaultByteArraySerializable
67
- val mpt =
68
- MerklePatriciaTrie [Array [Byte ], Account ](storagesInstance.storages.stateStorage.getBackingStorage(0 ))
69
- .put(
70
- crypto.kec256(address.bytes.toArray[Byte ]),
71
- account
72
- )
73
-
74
- val blockToRequest = Block (Fixtures .Blocks .Block3125369 .header, Fixtures .Blocks .Block3125369 .body)
75
- val newBlockHeader = blockToRequest.header.copy(stateRoot = ByteString (mpt.getRootHash))
76
- val newblock = blockToRequest.copy(header = newBlockHeader)
77
- blockchain.storeBlock(newblock).commit()
78
- blockchain.saveBestKnownBlocks(newblock.header.number)
79
-
80
- val ethGetProof = new EthProofService (blockchain, blockGenerator, blockchainConfig.ethCompatibleStorage)
81
- val storageKeys = Seq (StorageProofKey (key))
82
- val blockNumber = BlockParam .Latest
83
39
val request = GetProofRequest (address, storageKeys, blockNumber)
84
-
85
- // when
86
40
val result = ethGetProof.getProof(request)
87
41
88
- // then
89
42
val balanceResponse : GetBalanceResponse = ethUserService
90
43
.getBalance(GetBalanceRequest (address, BlockParam .Latest ))
91
44
.runSyncUnsafe()
@@ -125,18 +78,113 @@ class EthProofServiceSpec
125
78
}
126
79
127
80
" EthProofService" should " return an error when the proof is requested for non-existing account" in new TestSetup {
128
- val ethGetProof = new EthProofService (blockchain, blockGenerator, blockchainConfig.ethCompatibleStorage)
129
- val key = 999
130
- val storageKeys = Seq (StorageProofKey (key))
131
- val blockNumber = BlockParam .Latest
132
81
val wrongAddress = Address (666 )
133
82
val request = GetProofRequest (wrongAddress, storageKeys, blockNumber)
134
83
val retrievedAccountProofWrong : ServiceResponse [ProofService .GetProofResponse ] = ethGetProof.getProof(request)
135
- retrievedAccountProofWrong.runSyncUnsafe().isLeft shouldBe true
84
+ val result = retrievedAccountProofWrong.runSyncUnsafe()
85
+
86
+ result.isLeft shouldBe true
87
+ result.fold(l => l.message should include(" No account found for Address" ), r => r)
88
+ }
89
+
90
+ " EthProofService" should " return the proof with empty value for non-existing storage key" in new TestSetup {
91
+ val wrongStorageKey = Seq (StorageProofKey (321 ))
92
+ val request = GetProofRequest (address, wrongStorageKey, blockNumber)
93
+ val retrievedAccountProofWrong : ServiceResponse [ProofService .GetProofResponse ] = ethGetProof.getProof(request)
94
+ val result = retrievedAccountProofWrong.runSyncUnsafe()
95
+ result.isRight shouldBe true
96
+ result.fold(l => l, r => r.proofAccount.storageProof.map(v => {
97
+ v.proof.nonEmpty shouldBe true
98
+ v.value shouldBe BigInt (0 )
99
+ }))
100
+ }
101
+
102
+ " EthProofService" should " return the proof and value for existing storage key" in new TestSetup {
103
+ val storageKey = Seq (StorageProofKey (key))
104
+ val request = GetProofRequest (address, storageKey, blockNumber)
105
+ val retrievedAccountProofWrong : ServiceResponse [ProofService .GetProofResponse ] = ethGetProof.getProof(request)
106
+ val result = retrievedAccountProofWrong.runSyncUnsafe()
107
+ result.isRight shouldBe true
108
+ result.fold(l => l, r => r.proofAccount.storageProof.map(v => {
109
+ v.proof.nonEmpty shouldBe true
110
+ v.value shouldBe BigInt (value)
111
+ }))
112
+ }
113
+
114
+ " EthProofService" should " return the proof and value for multiple existing storage keys" in new TestSetup {
115
+ val storageKey = Seq (StorageProofKey (key), StorageProofKey (key2))
116
+ val expectedValueStorageKey = Seq (BigInt (value), BigInt (value2))
117
+ val request = GetProofRequest (address, storageKey, blockNumber)
118
+ val retrievedAccountProofWrong : ServiceResponse [ProofService .GetProofResponse ] = ethGetProof.getProof(request)
119
+ val result = retrievedAccountProofWrong.runSyncUnsafe()
120
+ result.isRight shouldBe true
121
+ result.fold(l => l, r => {
122
+ r.proofAccount.storageProof.size shouldBe 2
123
+ r.proofAccount.storageProof.map(v => {
124
+ v.proof.nonEmpty shouldBe true
125
+ expectedValueStorageKey should contain(v.value)
126
+ })
127
+ })
128
+ }
129
+
130
+ " EthProofService" should " return the proof for all storage keys provided, but value should be returned only for the existing ones" in new TestSetup {
131
+ val wrongStorageKey = StorageProofKey (321 )
132
+ val storageKey = Seq (StorageProofKey (key), StorageProofKey (key2)) :+ wrongStorageKey
133
+ val expectedValueStorageKey = Seq (BigInt (value), BigInt (value2), BigInt (0 ))
134
+ val request = GetProofRequest (address, storageKey, blockNumber)
135
+ val retrievedAccountProofWrong : ServiceResponse [ProofService .GetProofResponse ] = ethGetProof.getProof(request)
136
+ val result = retrievedAccountProofWrong.runSyncUnsafe()
137
+ result.isRight shouldBe true
138
+ result.fold(l => l, r => {
139
+ r.proofAccount.storageProof.size shouldBe 3
140
+ expectedValueStorageKey.forall(r.proofAccount.storageProof.map(_.value).contains) shouldBe true
141
+ })
136
142
}
137
143
138
144
class TestSetup (implicit system : ActorSystem ) extends MockFactory with EphemBlockchainTestSetup with ApisBuilder {
145
+
139
146
val blockGenerator = mock[EthashBlockGenerator ]
147
+ val address = Address (ByteString (Hex .decode(" abbb6bebfa05aa13e908eaa492bd7a8343760477" )))
148
+
149
+ val key = 333
150
+ val value = 123
151
+ val key1 = 334
152
+ val value1 = 124
153
+ val key2 = 335
154
+ val value2 = 125
155
+
156
+ val storageMpt = EthereumUInt256Mpt
157
+ .storageMpt(
158
+ ByteString (MerklePatriciaTrie .EmptyRootHash ),
159
+ storagesInstance.storages.stateStorage.getBackingStorage(0 )
160
+ )
161
+ .put(UInt256 (key), UInt256 (value))
162
+ .put(UInt256 (key1), UInt256 (value1))
163
+ .put(UInt256 (key2), UInt256 (value2))
164
+
165
+ val account = Account (
166
+ nonce = 0 ,
167
+ balance = UInt256 (0 ),
168
+ storageRoot = ByteString (storageMpt.getRootHash)
169
+ )
170
+
171
+ val mpt =
172
+ MerklePatriciaTrie [Array [Byte ], Account ](storagesInstance.storages.stateStorage.getBackingStorage(0 ))
173
+ .put(
174
+ crypto.kec256(address.bytes.toArray[Byte ]),
175
+ account
176
+ )
177
+
178
+ val blockToRequest = Block (Fixtures .Blocks .Block3125369 .header, Fixtures .Blocks .Block3125369 .body)
179
+ val newBlockHeader = blockToRequest.header.copy(stateRoot = ByteString (mpt.getRootHash))
180
+ val newblock = blockToRequest.copy(header = newBlockHeader)
181
+ blockchain.storeBlock(newblock).commit()
182
+ blockchain.saveBestKnownBlocks(newblock.header.number)
183
+
184
+ val ethGetProof = new EthProofService (blockchain, blockGenerator, blockchainConfig.ethCompatibleStorage)
185
+
186
+ val storageKeys = Seq (StorageProofKey (key))
187
+ val blockNumber = BlockParam .Latest
140
188
141
189
override lazy val ledger = mock[Ledger ]
142
190
0 commit comments