1717//! This is part of the Substrate runtime.
1818
1919use sp_core:: { ed25519, sr25519, crypto:: Pair } ;
20+ use std:: sync:: { Arc , atomic:: { AtomicBool , AtomicUsize , Ordering as AtomicOrdering } } ;
2021
2122#[ derive( Debug , Clone ) ]
2223struct Ed25519BatchItem {
@@ -32,15 +33,31 @@ struct Sr25519BatchItem {
3233 message : Vec < u8 > ,
3334}
3435
35- #[ derive( Debug , Default ) ]
36+ #[ derive( Debug ) ]
3637pub struct BatchVerifier {
37- ed25519_items : Vec < Ed25519BatchItem > ,
3838 sr25519_items : Vec < Sr25519BatchItem > ,
39+ invalid : Arc < AtomicBool > ,
40+ left : Arc < AtomicUsize > ,
41+ }
42+
43+
44+ lazy_static:: lazy_static! {
45+ static ref LOCAL_POOL : futures:: executor:: ThreadPool = {
46+ futures:: executor:: ThreadPool :: builder( )
47+ . stack_size( 16 * 1024 )
48+ . name_prefix( "io-background" )
49+ . create( )
50+ . expect( "failed to create background thread pool" )
51+ } ;
3952}
4053
4154impl BatchVerifier {
4255 pub fn new ( ) -> Self {
43- Self :: default ( )
56+ BatchVerifier {
57+ sr25519_items : Default :: default ( ) ,
58+ invalid : Arc :: new ( false . into ( ) ) ,
59+ left : Arc :: new ( 0 . into ( ) ) ,
60+ }
4461 }
4562
4663 pub fn push_ed25519 (
@@ -49,7 +66,18 @@ impl BatchVerifier {
4966 pub_key : ed25519:: Public ,
5067 message : Vec < u8 > ,
5168 ) {
52- self . ed25519_items . push ( Ed25519BatchItem { signature, pub_key, message } ) ;
69+ if self . invalid . load ( AtomicOrdering :: Relaxed ) { return ; } // there is already invalid transaction encountered
70+
71+ let invalid_clone = self . invalid . clone ( ) ;
72+ let left_clone = self . left . clone ( ) ;
73+ self . left . fetch_add ( 1 , AtomicOrdering :: SeqCst ) ;
74+
75+ LOCAL_POOL . spawn_ok ( async move {
76+ if !ed25519:: Pair :: verify ( & signature, & message, & pub_key) {
77+ invalid_clone. store ( true , AtomicOrdering :: Relaxed ) ;
78+ }
79+ left_clone. fetch_sub ( 1 , AtomicOrdering :: SeqCst ) ;
80+ } ) ;
5381 }
5482
5583 pub fn push_sr25519 (
@@ -62,13 +90,16 @@ impl BatchVerifier {
6290 }
6391
6492 pub fn verify_and_clear ( & mut self ) -> bool {
65- // TODO: parallel
66- for ed25519_item in self . ed25519_items . drain ( ..) {
67- if !ed25519:: Pair :: verify ( & ed25519_item. signature , & ed25519_item. message , & ed25519_item. pub_key ) {
68- return false ;
69- }
93+ while self . left . load ( AtomicOrdering :: SeqCst ) != 0 {
94+ std:: thread:: park_timeout ( std:: time:: Duration :: from_micros ( 50 ) ) ;
7095 }
7196
97+ if self . invalid . load ( AtomicOrdering :: Relaxed ) {
98+ self . invalid . store ( false , AtomicOrdering :: Relaxed ) ;
99+ return false ;
100+ }
101+
102+
72103 let sr25519_batch_result = {
73104 let messages = self . sr25519_items . iter ( ) . map ( |item| & item. message [ ..] ) . collect ( ) ;
74105 let signatures = self . sr25519_items . iter ( ) . map ( |item| & item. signature ) . collect ( ) ;
0 commit comments