@@ -112,7 +112,7 @@ defmodule Blockchain.Block do
112
112
113
113
@ doc """
114
114
Computes hash of a block, which is simply the hash of the serialized
115
- block after apply RLP.
115
+ block after applying RLP encoding .
116
116
117
117
This is defined in Eq.(37) of the Yellow Paper.
118
118
@@ -128,7 +128,7 @@ defmodule Blockchain.Block do
128
128
"""
129
129
@ spec hash ( t ) :: EVM . hash
130
130
def hash ( block ) do
131
- block . header |> Header . serialize ( ) |> ExRLP . encode |> BitHelper . kec
131
+ block . header |> Header . hash
132
132
end
133
133
134
134
@ doc """
@@ -191,6 +191,84 @@ defmodule Blockchain.Block do
191
191
end
192
192
end
193
193
194
+ @ doc """
195
+ Returns a given block from the database, if the hash
196
+ exists in the database.
197
+
198
+ See `Blockchain.Block.put_block/2` for details.
199
+
200
+ ## Examples
201
+
202
+ # Legit, current block
203
+ iex> db = MerklePatriciaTree.Test.random_ets_db()
204
+ iex> block = %Blockchain.Block{
205
+ ...> transactions: [%Blockchain.Transaction{nonce: 5, gas_price: 6, gas_limit: 7, to: <<1::160>>, value: 8, v: 27, r: 9, s: 10, data: "hi"}],
206
+ ...> header: %Block.Header{number: 5, parent_hash: <<1, 2, 3>>, beneficiary: <<2, 3, 4>>, difficulty: 100, timestamp: 11, mix_hash: <<1>>, nonce: <<2>>}
207
+ ...> }
208
+ iex> Blockchain.Block.put_block(block, db)
209
+ iex> Blockchain.Block.get_block_hash_by_steps(block |> Blockchain.Block.hash, 0, db)
210
+ {:ok, <<78, 28, 127, 10, 192, 253, 127, 239, 254, 179, 39, 34, 245, 44,
211
+ 152, 98, 128, 71, 238, 155, 100, 161, 199, 71, 243, 223, 172, 191,
212
+ 74, 99, 128, 63>>}
213
+
214
+ # Bad, in the future
215
+ iex> db = MerklePatriciaTree.Test.random_ets_db()
216
+ iex> block = %Blockchain.Block{
217
+ ...> transactions: [%Blockchain.Transaction{nonce: 5, gas_price: 6, gas_limit: 7, to: <<1::160>>, value: 8, v: 27, r: 9, s: 10, data: "hi"}],
218
+ ...> header: %Block.Header{number: 5, parent_hash: <<1, 2, 3>>, beneficiary: <<2, 3, 4>>, difficulty: 100, timestamp: 11, mix_hash: <<1>>, nonce: <<2>>}
219
+ ...> }
220
+ iex> Blockchain.Block.put_block(block, db)
221
+ iex> Blockchain.Block.get_block_hash_by_steps(block |> Blockchain.Block.hash, -1, db)
222
+ :not_found
223
+
224
+ # Bad, before the dawn of time
225
+ iex> db = MerklePatriciaTree.Test.random_ets_db()
226
+ iex> block = %Blockchain.Block{
227
+ ...> transactions: [%Blockchain.Transaction{nonce: 5, gas_price: 6, gas_limit: 7, to: <<1::160>>, value: 8, v: 27, r: 9, s: 10, data: "hi"}],
228
+ ...> header: %Block.Header{number: 5, parent_hash: <<1, 2, 3>>, beneficiary: <<2, 3, 4>>, difficulty: 100, timestamp: 11, mix_hash: <<1>>, nonce: <<2>>}
229
+ ...> }
230
+ iex> Blockchain.Block.put_block(block, db)
231
+ iex> Blockchain.Block.get_block_hash_by_steps(block |> Blockchain.Block.hash, 6, db)
232
+ :not_found
233
+
234
+ iex> Blockchain.Block.get_block_hash_by_steps(<<1, 2, 3>>, 0, nil)
235
+ {:ok, <<1, 2, 3>>}
236
+
237
+ # Legit, back zero and one
238
+ iex> db = MerklePatriciaTree.Test.random_ets_db()
239
+ iex> block_1 = %Blockchain.Block{
240
+ ...> transactions: [%Blockchain.Transaction{nonce: 5, gas_price: 6, gas_limit: 7, to: <<1::160>>, value: 8, v: 27, r: 9, s: 10, data: "hi"}],
241
+ ...> header: %Block.Header{number: 5, parent_hash: <<1, 2, 3>>, beneficiary: <<2, 3, 4>>, difficulty: 100, timestamp: 11, mix_hash: <<1>>, nonce: <<2>>}
242
+ ...> }
243
+ iex> {:ok, block_1_hash} = Blockchain.Block.put_block(block_1, db)
244
+ iex> block_2 = %Blockchain.Block{
245
+ ...> transactions: [%Blockchain.Transaction{nonce: 5, gas_price: 6, gas_limit: 7, to: <<1::160>>, value: 8, v: 27, r: 9, s: 10, data: "hi"}],
246
+ ...> header: %Block.Header{number: 6, parent_hash: block_1_hash, beneficiary: <<2, 3, 4>>, difficulty: 100, timestamp: 11, mix_hash: <<1>>, nonce: <<2>>}
247
+ ...> }
248
+ iex> Blockchain.Block.put_block(block_2, db)
249
+ iex> Blockchain.Block.get_block_hash_by_steps(block_2 |> Blockchain.Block.hash, 0, db)
250
+ {:ok, <<203, 210, 109, 46, 207, 246, 94, 33, 247, 97, 60, 56, 65, 134,
251
+ 203, 120, 62, 64, 59, 64, 101, 190, 181, 7, 242, 215, 247, 212,
252
+ 107, 12, 92, 9>>}
253
+ iex> Blockchain.Block.get_block_hash_by_steps(block_2 |> Blockchain.Block.hash, 1, db)
254
+ {:ok, <<78, 28, 127, 10, 192, 253, 127, 239, 254, 179, 39, 34, 245, 44,
255
+ 152, 98, 128, 71, 238, 155, 100, 161, 199, 71, 243, 223, 172, 191,
256
+ 74, 99, 128, 63>>}
257
+ """
258
+ @ spec get_block_hash_by_steps ( EVM . hash , non_neg_integer ( ) , DB . db ) :: { :ok , EVM . hash } | :not_found
259
+ def get_block_hash_by_steps ( curr_block_hash , steps , db ) do
260
+ do_get_block_hash_by_steps ( curr_block_hash , steps , db )
261
+ end
262
+
263
+ @ spec get_block_hash_by_steps ( EVM . hash , non_neg_integer ( ) , DB . db ) :: { :ok , EVM . hash } | :not_found
264
+ defp do_get_block_hash_by_steps ( block_hash , 0 , _db ) , do: { :ok , block_hash }
265
+ defp do_get_block_hash_by_steps ( _block_hash , steps , _db ) when steps < 0 or steps > 256 , do: :not_found
266
+ defp do_get_block_hash_by_steps ( block_hash , steps , db ) do
267
+ with { :ok , block } <- get_block ( block_hash , db ) do
268
+ do_get_block_hash_by_steps ( block . header . parent_hash , steps - 1 , db )
269
+ end
270
+ end
271
+
194
272
@ doc """
195
273
Returns the parent node for a given block,
196
274
if it exists.
0 commit comments