11// @todo: remove this
22#![ allow( dead_code) ]
3- use mithril_aggregator:: entities;
43
54use ark_bls12_377:: Bls12_377 ;
5+ use hex:: { FromHex , ToHex } ;
6+ use std:: io:: Cursor ;
7+ use thiserror:: Error ;
8+
69use mithril:: key_reg:: KeyReg ;
710use mithril:: merkle_tree:: MTHashLeaf ;
811use mithril:: mithril_proof:: concat_proofs:: { ConcatProof , TrivialEnv } ;
@@ -11,7 +14,7 @@ use mithril::stm::{
1114 Index , MTValue , PartyId , Stake , StmClerk , StmInitializer , StmMultiSig , StmParameters , StmSig ,
1215 StmSigner ,
1316} ;
14- use thiserror :: Error ;
17+ use mithril_aggregator :: entities ;
1518
1619pub type Bytes = Vec < u8 > ;
1720
@@ -36,6 +39,9 @@ pub type ProtocolSignerSecretKey = MspSk<Bls12_377>;
3639use mithril_aggregator:: entities:: { SignerWithStake , SingleSignature } ;
3740#[ cfg( test) ]
3841use mockall:: automock;
42+ use rand_chacha:: ChaCha20Rng ;
43+ use rand_core:: SeedableRng ;
44+ use slog_scope:: { trace, warn} ;
3945
4046#[ cfg_attr( test, automock) ]
4147pub trait SingleSigner {
@@ -49,38 +55,163 @@ pub trait SingleSigner {
4955
5056#[ derive( Error , Debug , PartialEq ) ]
5157pub enum SingleSignerError {
52- #[ error( "the signer is not registered in the stake distribution" ) ]
58+ #[ error( "the signer verification key is not registered in the stake distribution" ) ]
5359 UnregisteredVerificationKey ( ) ,
60+
61+ #[ error( "the signer party id is not registered in the stake distribution" ) ]
62+ UnregisteredPartyId ( ) ,
63+
64+ #[ error( "the protocol signer creation failed: `{0}`" ) ]
65+ ProtocolSignerCreationFailure ( String ) ,
5466}
5567
56- pub struct MithrilSingleSigner { }
68+ pub struct MithrilSingleSigner {
69+ party_id : u64 ,
70+ secret_key : ProtocolSignerSecretKey ,
71+ }
5772
5873impl MithrilSingleSigner {
59- pub fn new ( ) -> Self {
60- Self { }
74+ pub fn new ( party_id : u64 , secret_key : ProtocolSignerSecretKey ) -> Self {
75+ Self {
76+ party_id,
77+ secret_key,
78+ }
79+ }
80+
81+ pub fn create_protocol_signer (
82+ & self ,
83+ current_player_stake : ProtocolStake ,
84+ stake_distribution : & [ SignerWithStake ] , // @todo : use a hmap to prevent party id duplication
85+ protocol_parameters : & entities:: ProtocolParameters ,
86+ ) -> Result < ProtocolSigner , String > {
87+ let players = stake_distribution
88+ . into_iter ( )
89+ . map ( |s| ( s. party_id as ProtocolPartyId , s. stake as ProtocolStake ) )
90+ . collect :: < Vec < _ > > ( ) ;
91+ let protocol_parameters = ProtocolParameters {
92+ k : protocol_parameters. k ,
93+ m : protocol_parameters. m ,
94+ phi_f : protocol_parameters. phi_f as f64 ,
95+ } ;
96+
97+ let mut key_reg = KeyReg :: new ( & players) ;
98+ for s in stake_distribution {
99+ let decoded_key = key_decode_hex ( & s. verification_key ) ?;
100+ key_reg
101+ . register ( s. party_id as ProtocolPartyId , decoded_key)
102+ . unwrap ( ) ;
103+ }
104+ let closed_reg = key_reg. close ( ) ;
105+
106+ let seed = [ 0u8 ; 32 ] ;
107+ let mut rng = ChaCha20Rng :: from_seed ( seed) ;
108+ let p = StmInitializer :: setup (
109+ protocol_parameters,
110+ self . party_id as ProtocolPartyId ,
111+ current_player_stake,
112+ & mut rng,
113+ ) ;
114+ Ok ( p. new_signer ( closed_reg) )
61115 }
62116}
63117
64118impl SingleSigner for MithrilSingleSigner {
65119 fn compute_single_signatures (
66120 & self ,
67- _message : Bytes ,
68- _stake_distribution : Vec < SignerWithStake > ,
69- _protocol_parameters : & entities:: ProtocolParameters ,
121+ message : Bytes ,
122+ stake_distribution : Vec < SignerWithStake > , // @todo : use a hmap to prevent party id duplication
123+ protocol_parameters : & entities:: ProtocolParameters ,
70124 ) -> Result < Vec < SingleSignature > , SingleSignerError > {
71- Err ( SingleSignerError :: UnregisteredVerificationKey ( ) )
125+ let current_signer_with_stake = stake_distribution
126+ . iter ( )
127+ . find ( |s| s. party_id == self . party_id )
128+ . ok_or ( SingleSignerError :: UnregisteredPartyId ( ) ) ?;
129+
130+ if current_signer_with_stake. verification_key . is_empty ( ) {
131+ Err ( SingleSignerError :: UnregisteredVerificationKey ( ) )
132+ } else {
133+ let protocol_signer = self
134+ . create_protocol_signer (
135+ current_signer_with_stake. stake ,
136+ & stake_distribution,
137+ protocol_parameters,
138+ )
139+ . map_err ( SingleSignerError :: ProtocolSignerCreationFailure ) ?;
140+
141+ trace ! (
142+ "Party #{}: sign message {}" ,
143+ self . party_id,
144+ message. encode_hex:: <String >( )
145+ ) ;
146+
147+ let mut signatures = Vec :: new ( ) ;
148+ for i in 1 ..=protocol_parameters. m {
149+ if let Some ( signature) = protocol_signer. sign ( & message, i) {
150+ trace ! ( "Party #{}: lottery #{} won" , self . party_id, i, ) ;
151+ let encoded_signature = key_encode_hex ( signature) ;
152+
153+ if encoded_signature. is_err ( ) {
154+ warn ! ( "couldn't compute signature: `{:?}`" , encoded_signature) ; // @todo: structured log
155+ continue ;
156+ }
157+
158+ signatures. push ( SingleSignature :: new (
159+ self . party_id ,
160+ i,
161+ encoded_signature. unwrap ( ) ,
162+ ) ) ;
163+ }
164+ }
165+ Ok ( signatures)
166+ }
72167 }
73168}
74169
170+ /// Encode key to hex helper
171+ pub fn key_encode_hex < T : ark_ff:: ToBytes > ( from : T ) -> Result < String , String > {
172+ Ok ( ark_ff:: to_bytes!( from)
173+ . map_err ( |e| format ! ( "can't convert to hex: {}" , e) ) ?
174+ . encode_hex :: < String > ( ) )
175+ }
176+
177+ /// Decode key from hex helper
178+ pub fn key_decode_hex < T : ark_ff:: FromBytes > ( from : & str ) -> Result < T , String > {
179+ ark_ff:: FromBytes :: read ( Cursor :: new (
180+ Vec :: from_hex ( from) . map_err ( |e| format ! ( "can't parse from hex: {}" , e) ) ?,
181+ ) )
182+ . map_err ( |e| format ! ( "can't convert to bytes: {}" , e) )
183+ }
184+
75185#[ cfg( test) ]
76186mod tests {
77187 use super :: * ;
78188 use mithril_aggregator:: fake_data;
79189
190+ fn create_clerk ( signer : & ProtocolSigner ) -> ProtocolClerk {
191+ StmClerk :: from_signer ( signer, TrivialEnv )
192+ }
193+
80194 #[ test]
81195 fn cant_compute_if_signer_verification_key_is_not_registered ( ) {
82- let single_signer = MithrilSingleSigner :: new ( ) ;
83- let stake_distribution = fake_data:: signers_with_stakes ( 5 ) ;
196+ let signer_with_keys = fake_data:: signer_keys ( 0 ) . unwrap ( ) ;
197+ let single_signer = MithrilSingleSigner :: new (
198+ signer_with_keys. party_id ,
199+ key_decode_hex ( & signer_with_keys. secret_key ) . unwrap ( ) ,
200+ ) ;
201+ let stake_distribution = fake_data:: signers_with_stakes ( 5 )
202+ . into_iter ( )
203+ . map ( |s| {
204+ if s. party_id == signer_with_keys. party_id {
205+ SignerWithStake {
206+ party_id : s. party_id ,
207+ verification_key : "" . to_string ( ) ,
208+ stake : s. stake ,
209+ }
210+ } else {
211+ s
212+ }
213+ } )
214+ . collect ( ) ;
84215 let protocol_parameters = fake_data:: protocol_parameters ( ) ;
85216
86217 let sign_result = single_signer. compute_single_signatures (
@@ -94,4 +225,36 @@ mod tests {
94225 sign_result. unwrap_err( )
95226 )
96227 }
228+
229+ #[ test]
230+ fn should_produce_a_single_signature ( ) {
231+ let signer_with_keys = fake_data:: signer_keys ( 0 ) . unwrap ( ) ;
232+ let single_signer = MithrilSingleSigner :: new (
233+ signer_with_keys. party_id ,
234+ key_decode_hex ( & signer_with_keys. secret_key ) . unwrap ( ) ,
235+ ) ;
236+ let stake_distribution = fake_data:: signers_with_stakes ( 5 ) ;
237+ let protocol_parameters = fake_data:: protocol_parameters ( ) ;
238+ let protocol_signer: ProtocolSigner = single_signer
239+ . create_protocol_signer (
240+ signer_with_keys. stake ,
241+ & stake_distribution,
242+ & protocol_parameters,
243+ )
244+ . unwrap ( ) ;
245+ let clerk = StmClerk :: from_signer ( & protocol_signer, TrivialEnv ) ;
246+
247+ let message = "message" . as_bytes ( ) ;
248+ let sign_result = single_signer. compute_single_signatures (
249+ message. to_vec ( ) ,
250+ stake_distribution,
251+ & protocol_parameters,
252+ ) ;
253+
254+ assert ! ( !sign_result. as_ref( ) . unwrap( ) . is_empty( ) ) ;
255+ for sig in sign_result. unwrap ( ) {
256+ let decoded_sig = key_decode_hex ( & sig. signature ) . unwrap ( ) ;
257+ assert ! ( clerk. verify_sig( & decoded_sig, sig. index, message) . is_ok( ) ) ;
258+ }
259+ }
97260}
0 commit comments