@@ -25,7 +25,6 @@ use std::collections::HashSet;
25
25
use std:: time:: { Duration , SystemTime , UNIX_EPOCH } ;
26
26
27
27
use bytes:: Bytes ;
28
- use ethereum_types:: H256 ;
29
28
use hash:: keccak;
30
29
use heapsize:: HeapSizeOf ;
31
30
use rlp:: Rlp ;
@@ -37,15 +36,17 @@ use client::{BlockInfo, CallContract};
37
36
use engines:: EthEngine ;
38
37
use error:: { BlockError , Error } ;
39
38
use header:: { BlockNumber , Header } ;
40
- use transaction:: { SignedTransaction , UnverifiedTransaction } ;
41
- use views :: BlockView ;
39
+ use transaction:: SignedTransaction ;
40
+ use verification :: queue :: kind :: blocks :: Unverified ;
42
41
43
42
/// Preprocessed block data gathered in `verify_block_unordered` call
44
43
pub struct PreverifiedBlock {
45
44
/// Populated block header
46
45
pub header : Header ,
47
46
/// Populated block transactions
48
47
pub transactions : Vec < SignedTransaction > ,
48
+ /// Populated block uncles
49
+ pub uncles : Vec < Header > ,
49
50
/// Block bytes
50
51
pub bytes : Bytes ,
51
52
}
@@ -59,63 +60,66 @@ impl HeapSizeOf for PreverifiedBlock {
59
60
}
60
61
61
62
/// Phase 1 quick block verification. Only does checks that are cheap. Operates on a single block
62
- pub fn verify_block_basic ( header : & Header , bytes : & [ u8 ] , engine : & EthEngine ) -> Result < ( ) , Error > {
63
- verify_header_params ( & header, engine, true ) ?;
64
- verify_block_integrity ( bytes , & header . transactions_root ( ) , & header . uncles_hash ( ) ) ?;
65
- engine. verify_block_basic ( & header) ?;
66
- for u in Rlp :: new ( bytes ) . at ( 2 ) ? . iter ( ) . map ( |rlp| rlp . as_val :: < Header > ( ) ) {
67
- let u = u? ;
68
- verify_header_params ( & u , engine, false ) ?;
69
- engine. verify_block_basic ( & u ) ?;
63
+ pub fn verify_block_basic ( block : & Unverified , engine : & EthEngine ) -> Result < ( ) , Error > {
64
+ verify_header_params ( & block . header , engine, true ) ?;
65
+ verify_block_integrity ( block ) ?;
66
+ engine. verify_block_basic ( & block . header ) ?;
67
+
68
+ for uncle in & block . uncles {
69
+ verify_header_params ( uncle , engine, false ) ?;
70
+ engine. verify_block_basic ( uncle ) ?;
70
71
}
71
72
72
- for t in Rlp :: new ( bytes ) . at ( 1 ) ? . iter ( ) . map ( |rlp| rlp . as_val :: < UnverifiedTransaction > ( ) ) {
73
- engine. verify_transaction_basic ( & t? , & header) ?;
73
+ for t in & block . transactions {
74
+ engine. verify_transaction_basic ( t , & block . header ) ?;
74
75
}
76
+
75
77
Ok ( ( ) )
76
78
}
77
79
78
80
/// Phase 2 verification. Perform costly checks such as transaction signatures and block nonce for ethash.
79
81
/// Still operates on a individual block
80
82
/// Returns a `PreverifiedBlock` structure populated with transactions
81
- pub fn verify_block_unordered ( header : Header , bytes : Bytes , engine : & EthEngine , check_seal : bool ) -> Result < PreverifiedBlock , Error > {
83
+ pub fn verify_block_unordered ( block : Unverified , engine : & EthEngine , check_seal : bool ) -> Result < PreverifiedBlock , Error > {
84
+ let header = block. header ;
82
85
if check_seal {
83
86
engine. verify_block_unordered ( & header) ?;
84
- for u in Rlp :: new ( & bytes ) . at ( 2 ) ? . iter ( ) . map ( |rlp| rlp . as_val :: < Header > ( ) ) {
85
- engine. verify_block_unordered ( & u? ) ?;
87
+ for uncle in & block . uncles {
88
+ engine. verify_block_unordered ( uncle ) ?;
86
89
}
87
90
}
88
91
// Verify transactions.
89
- let mut transactions = Vec :: new ( ) ;
90
92
let nonce_cap = if header. number ( ) >= engine. params ( ) . dust_protection_transition {
91
93
Some ( ( engine. params ( ) . nonce_cap_increment * header. number ( ) ) . into ( ) )
92
- } else { None } ;
93
- {
94
- let v = view ! ( BlockView , & bytes) ;
95
- for t in v. transactions ( ) {
94
+ } else {
95
+ None
96
+ } ;
97
+
98
+ let transactions = block. transactions
99
+ . into_iter ( )
100
+ . map ( |t| {
96
101
let t = engine. verify_transaction_unordered ( t, & header) ?;
97
102
if let Some ( max_nonce) = nonce_cap {
98
103
if t. nonce >= max_nonce {
99
104
return Err ( BlockError :: TooManyTransactions ( t. sender ( ) ) . into ( ) ) ;
100
105
}
101
106
}
102
- transactions. push ( t) ;
103
- }
104
- }
107
+ Ok ( t)
108
+ } )
109
+ . collect :: < Result < Vec < _ > , Error > > ( ) ?;
110
+
105
111
Ok ( PreverifiedBlock {
106
- header : header,
107
- transactions : transactions,
108
- bytes : bytes,
112
+ header,
113
+ transactions,
114
+ uncles : block. uncles ,
115
+ bytes : block. bytes ,
109
116
} )
110
117
}
111
118
112
119
/// Parameters for full verification of block family
113
120
pub struct FullFamilyParams < ' a , C : BlockInfo + CallContract + ' a > {
114
- /// Serialized block bytes
115
- pub block_bytes : & ' a [ u8 ] ,
116
-
117
- /// Signed transactions
118
- pub transactions : & ' a [ SignedTransaction ] ,
121
+ /// Preverified block
122
+ pub block : & ' a PreverifiedBlock ,
119
123
120
124
/// Block provider to use during verification
121
125
pub block_provider : & ' a BlockProvider ,
@@ -135,17 +139,18 @@ pub fn verify_block_family<C: BlockInfo + CallContract>(header: &Header, parent:
135
139
None => return Ok ( ( ) ) ,
136
140
} ;
137
141
138
- verify_uncles ( header , params. block_bytes , params. block_provider , engine) ?;
142
+ verify_uncles ( params. block , params. block_provider , engine) ?;
139
143
140
- for transaction in params. transactions {
141
- engine. machine ( ) . verify_transaction ( transaction , header, params. client ) ?;
144
+ for tx in & params. block . transactions {
145
+ engine. machine ( ) . verify_transaction ( tx , header, params. client ) ?;
142
146
}
143
147
144
148
Ok ( ( ) )
145
149
}
146
150
147
- fn verify_uncles ( header : & Header , bytes : & [ u8 ] , bc : & BlockProvider , engine : & EthEngine ) -> Result < ( ) , Error > {
148
- let num_uncles = Rlp :: new ( bytes) . at ( 2 ) ?. item_count ( ) ?;
151
+ fn verify_uncles ( block : & PreverifiedBlock , bc : & BlockProvider , engine : & EthEngine ) -> Result < ( ) , Error > {
152
+ let header = & block. header ;
153
+ let num_uncles = block. uncles . len ( ) ;
149
154
let max_uncles = engine. maximum_uncle_count ( header. number ( ) ) ;
150
155
if num_uncles != 0 {
151
156
if num_uncles > max_uncles {
@@ -174,8 +179,7 @@ fn verify_uncles(header: &Header, bytes: &[u8], bc: &BlockProvider, engine: &Eth
174
179
}
175
180
176
181
let mut verified = HashSet :: new ( ) ;
177
- for uncle in Rlp :: new ( bytes) . at ( 2 ) ?. iter ( ) . map ( |rlp| rlp. as_val :: < Header > ( ) ) {
178
- let uncle = uncle?;
182
+ for uncle in & block. uncles {
179
183
if excluded. contains ( & uncle. hash ( ) ) {
180
184
return Err ( From :: from ( BlockError :: UncleInChain ( uncle. hash ( ) ) ) )
181
185
}
@@ -332,16 +336,22 @@ fn verify_parent(header: &Header, parent: &Header, engine: &EthEngine) -> Result
332
336
}
333
337
334
338
/// Verify block data against header: transactions root and uncles hash.
335
- fn verify_block_integrity ( block : & [ u8 ] , transactions_root : & H256 , uncles_hash : & H256 ) -> Result < ( ) , Error > {
336
- let block = Rlp :: new ( block) ;
337
- let tx = block. at ( 1 ) ?;
338
- let expected_root = & ordered_trie_root ( tx. iter ( ) . map ( |r| r. as_raw ( ) ) ) ;
339
- if expected_root != transactions_root {
340
- return Err ( From :: from ( BlockError :: InvalidTransactionsRoot ( Mismatch { expected : expected_root. clone ( ) , found : transactions_root. clone ( ) } ) ) )
341
- }
342
- let expected_uncles = & keccak ( block. at ( 2 ) ?. as_raw ( ) ) ;
343
- if expected_uncles != uncles_hash {
344
- return Err ( From :: from ( BlockError :: InvalidUnclesHash ( Mismatch { expected : expected_uncles. clone ( ) , found : uncles_hash. clone ( ) } ) ) )
339
+ fn verify_block_integrity ( block : & Unverified ) -> Result < ( ) , Error > {
340
+ let block_rlp = Rlp :: new ( & block. bytes ) ;
341
+ let tx = block_rlp. at ( 1 ) ?;
342
+ let expected_root = ordered_trie_root ( tx. iter ( ) . map ( |r| r. as_raw ( ) ) ) ;
343
+ if & expected_root != block. header . transactions_root ( ) {
344
+ bail ! ( BlockError :: InvalidTransactionsRoot ( Mismatch {
345
+ expected: expected_root,
346
+ found: * block. header. transactions_root( ) ,
347
+ } ) ) ;
348
+ }
349
+ let expected_uncles = keccak ( block_rlp. at ( 2 ) ?. as_raw ( ) ) ;
350
+ if & expected_uncles != block. header . uncles_hash ( ) {
351
+ bail ! ( BlockError :: InvalidUnclesHash ( Mismatch {
352
+ expected: expected_uncles,
353
+ found: * block. header. uncles_hash( ) ,
354
+ } ) ) ;
345
355
}
346
356
Ok ( ( ) )
347
357
}
@@ -366,6 +376,7 @@ mod tests {
366
376
use types:: log_entry:: { LogEntry , LocalizedLogEntry } ;
367
377
use rlp;
368
378
use triehash:: ordered_trie_root;
379
+ use views:: BlockView ;
369
380
370
381
fn check_ok ( result : Result < ( ) , Error > ) {
371
382
result. unwrap_or_else ( |e| panic ! ( "Block verification failed: {:?}" , e) ) ;
@@ -486,8 +497,8 @@ mod tests {
486
497
}
487
498
488
499
fn basic_test ( bytes : & [ u8 ] , engine : & EthEngine ) -> Result < ( ) , Error > {
489
- let header = view ! ( BlockView , bytes) . header ( ) ;
490
- verify_block_basic ( & header , bytes , engine)
500
+ let unverified = Unverified :: from_rlp ( bytes. to_vec ( ) ) ? ;
501
+ verify_block_basic ( & unverified , engine)
491
502
}
492
503
493
504
fn family_test < BC > ( bytes : & [ u8 ] , engine : & EthEngine , bc : & BC ) -> Result < ( ) , Error > where BC : BlockProvider {
@@ -507,18 +518,25 @@ mod tests {
507
518
. ok_or ( BlockError :: UnknownParent ( header. parent_hash ( ) . clone ( ) ) ) ?
508
519
. decode ( ) ?;
509
520
521
+ let block = PreverifiedBlock {
522
+ header,
523
+ transactions,
524
+ uncles : view. uncles ( ) ,
525
+ bytes : bytes. to_vec ( ) ,
526
+ } ;
527
+
510
528
let full_params = FullFamilyParams {
511
- block_bytes : bytes,
512
- transactions : & transactions[ ..] ,
529
+ block : & block,
513
530
block_provider : bc as & BlockProvider ,
514
531
client : & client,
515
532
} ;
516
- verify_block_family ( & header, & parent, engine, Some ( full_params) )
533
+ verify_block_family ( & block . header , & parent, engine, Some ( full_params) )
517
534
}
518
535
519
536
fn unordered_test ( bytes : & [ u8 ] , engine : & EthEngine ) -> Result < ( ) , Error > {
520
- let header = view ! ( BlockView , bytes) . header ( ) ;
521
- verify_block_unordered ( header, bytes. to_vec ( ) , engine, false ) ?;
537
+ use verification:: queue:: kind:: blocks:: Unverified ;
538
+ let un = Unverified :: from_rlp ( bytes. to_vec ( ) ) ?;
539
+ verify_block_unordered ( un, engine, false ) ?;
522
540
Ok ( ( ) )
523
541
}
524
542
0 commit comments