Merge pull request #332 from seansu4you87/signed_root_annotations
Adding annotation capabilities to SignedRoot macro
This commit is contained in:
		
						commit
						09d216c992
					
				| @ -25,6 +25,7 @@ pub struct Attestation { | ||||
|     pub aggregation_bitfield: Bitfield, | ||||
|     pub data: AttestationData, | ||||
|     pub custody_bitfield: Bitfield, | ||||
|     #[signed_root(skip_hashing)] | ||||
|     pub aggregate_signature: AggregateSignature, | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -27,6 +27,7 @@ pub struct BeaconBlock { | ||||
|     pub previous_block_root: Hash256, | ||||
|     pub state_root: Hash256, | ||||
|     pub body: BeaconBlockBody, | ||||
|     #[signed_root(skip_hashing)] | ||||
|     pub signature: Signature, | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -27,6 +27,7 @@ pub struct BeaconBlockHeader { | ||||
|     pub previous_block_root: Hash256, | ||||
|     pub state_root: Hash256, | ||||
|     pub block_body_root: Hash256, | ||||
|     #[signed_root(skip_hashing)] | ||||
|     pub signature: Signature, | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -25,6 +25,7 @@ use test_random_derive::TestRandom; | ||||
| pub struct DepositInput { | ||||
|     pub pubkey: PublicKey, | ||||
|     pub withdrawal_credentials: Hash256, | ||||
|     #[signed_root(skip_hashing)] | ||||
|     pub proof_of_possession: Signature, | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -27,6 +27,7 @@ pub struct SlashableAttestation { | ||||
|     pub validator_indices: Vec<u64>, | ||||
|     pub data: AttestationData, | ||||
|     pub custody_bitfield: Bitfield, | ||||
|     #[signed_root(skip_hashing)] | ||||
|     pub aggregate_signature: AggregateSignature, | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -32,6 +32,7 @@ pub struct Transfer { | ||||
|     pub slot: Slot, | ||||
|     pub pubkey: PublicKey, | ||||
|     #[derivative(Hash = "ignore")] | ||||
|     #[signed_root(skip_hashing)] | ||||
|     pub signature: Signature, | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -24,6 +24,7 @@ use test_random_derive::TestRandom; | ||||
| pub struct VoluntaryExit { | ||||
|     pub epoch: Epoch, | ||||
|     pub validator_index: u64, | ||||
|     #[signed_root(skip_hashing)] | ||||
|     pub signature: Signature, | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -38,7 +38,7 @@ | ||||
| extern crate proc_macro; | ||||
| 
 | ||||
| use proc_macro::TokenStream; | ||||
| use quote::quote; | ||||
| use quote::{quote, ToTokens}; | ||||
| use syn::{parse_macro_input, DeriveInput}; | ||||
| 
 | ||||
| /// Returns a Vec of `syn::Ident` for each named field in the struct.
 | ||||
| @ -218,7 +218,7 @@ fn get_tree_hashable_named_field_idents<'a>( | ||||
| /// The field attribute is: `#[tree_hash(skip_hashing)]`
 | ||||
| fn should_skip_tree_hash(field: &syn::Field) -> bool { | ||||
|     for attr in &field.attrs { | ||||
|         if attr.tts.to_string() == "( skip_hashing )" { | ||||
|         if attr.into_token_stream().to_string() == "# [ tree_hash ( skip_hashing ) ]" { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
| @ -289,7 +289,7 @@ fn final_type_ident(field: &syn::Field) -> &syn::Ident { | ||||
| /// If you can think of a better way to do this, please make an issue!
 | ||||
| ///
 | ||||
| /// Fields are processed in the order they are defined.
 | ||||
| #[proc_macro_derive(SignedRoot)] | ||||
| #[proc_macro_derive(SignedRoot, attributes(signed_root))] | ||||
| pub fn ssz_signed_root_derive(input: TokenStream) -> TokenStream { | ||||
|     let item = parse_macro_input!(input as DeriveInput); | ||||
| 
 | ||||
| @ -302,19 +302,7 @@ pub fn ssz_signed_root_derive(input: TokenStream) -> TokenStream { | ||||
| 
 | ||||
|     let mut field_idents: Vec<&syn::Ident> = vec![]; | ||||
| 
 | ||||
|     for field in struct_data.fields.iter() { | ||||
|         let final_type_ident = final_type_ident(&field); | ||||
| 
 | ||||
|         if type_ident_is_signature(final_type_ident) { | ||||
|             break; | ||||
|         } else { | ||||
|             let ident = field | ||||
|                 .ident | ||||
|                 .as_ref() | ||||
|                 .expect("ssz_derive only supports named_struct fields."); | ||||
|             field_idents.push(ident); | ||||
|         } | ||||
|     } | ||||
|     let field_idents = get_signed_root_named_field_idents(&struct_data); | ||||
| 
 | ||||
|     let output = quote! { | ||||
|         impl ssz::SignedRoot for #name { | ||||
| @ -330,3 +318,27 @@ pub fn ssz_signed_root_derive(input: TokenStream) -> TokenStream { | ||||
|     }; | ||||
|     output.into() | ||||
| } | ||||
| 
 | ||||
| fn get_signed_root_named_field_idents(struct_data: &syn::DataStruct) -> Vec<&syn::Ident> { | ||||
|     struct_data | ||||
|         .fields | ||||
|         .iter() | ||||
|         .filter_map(|f| { | ||||
|             if should_skip_signed_root(&f) { | ||||
|                 None | ||||
|             } else { | ||||
|                 Some(match &f.ident { | ||||
|                     Some(ref ident) => ident, | ||||
|                     _ => panic!("ssz_derive only supports named struct fields"), | ||||
|                 }) | ||||
|             } | ||||
|         }) | ||||
|         .collect() | ||||
| } | ||||
| 
 | ||||
| fn should_skip_signed_root(field: &syn::Field) -> bool { | ||||
|     field | ||||
|         .attrs | ||||
|         .iter() | ||||
|         .any(|attr| attr.into_token_stream().to_string() == "# [ signed_root ( skip_hashing ) ]") | ||||
| } | ||||
|  | ||||
							
								
								
									
										94
									
								
								eth2/utils/ssz_derive/tests/test_derives.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								eth2/utils/ssz_derive/tests/test_derives.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,94 @@ | ||||
| use ssz::{SignedRoot, TreeHash}; | ||||
| use ssz_derive::{SignedRoot, TreeHash}; | ||||
| 
 | ||||
| #[derive(TreeHash, SignedRoot)] | ||||
| struct CryptoKitties { | ||||
|     best_kitty: u64, | ||||
|     worst_kitty: u8, | ||||
|     kitties: Vec<u32>, | ||||
| } | ||||
| 
 | ||||
| impl CryptoKitties { | ||||
|     fn new() -> Self { | ||||
|         CryptoKitties { | ||||
|             best_kitty: 9999, | ||||
|             worst_kitty: 1, | ||||
|             kitties: vec![2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43], | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn hash(&self) -> Vec<u8> { | ||||
|         let mut list: Vec<Vec<u8>> = Vec::new(); | ||||
|         list.push(self.best_kitty.hash_tree_root()); | ||||
|         list.push(self.worst_kitty.hash_tree_root()); | ||||
|         list.push(self.kitties.hash_tree_root()); | ||||
|         ssz::merkle_hash(&mut list) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn test_cryptokitties_hash() { | ||||
|     let kitties = CryptoKitties::new(); | ||||
|     let expected_hash = vec![ | ||||
|         201, 9, 139, 14, 24, 247, 21, 55, 132, 211, 51, 125, 183, 186, 177, 33, 147, 210, 42, 108, | ||||
|         174, 162, 221, 227, 157, 179, 15, 7, 97, 239, 82, 220, | ||||
|     ]; | ||||
|     assert_eq!(kitties.hash(), expected_hash); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn test_simple_tree_hash_derive() { | ||||
|     let kitties = CryptoKitties::new(); | ||||
|     assert_eq!(kitties.hash_tree_root(), kitties.hash()); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn test_simple_signed_root_derive() { | ||||
|     let kitties = CryptoKitties::new(); | ||||
|     assert_eq!(kitties.signed_root(), kitties.hash()); | ||||
| } | ||||
| 
 | ||||
| #[derive(TreeHash, SignedRoot)] | ||||
| struct Casper { | ||||
|     friendly: bool, | ||||
|     #[tree_hash(skip_hashing)] | ||||
|     friends: Vec<u32>, | ||||
|     #[signed_root(skip_hashing)] | ||||
|     dead: bool, | ||||
| } | ||||
| 
 | ||||
| impl Casper { | ||||
|     fn new() -> Self { | ||||
|         Casper { | ||||
|             friendly: true, | ||||
|             friends: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10], | ||||
|             dead: true, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn expected_signed_hash(&self) -> Vec<u8> { | ||||
|         let mut list = Vec::new(); | ||||
|         list.push(self.friendly.hash_tree_root()); | ||||
|         list.push(self.friends.hash_tree_root()); | ||||
|         ssz::merkle_hash(&mut list) | ||||
|     } | ||||
| 
 | ||||
|     fn expected_tree_hash(&self) -> Vec<u8> { | ||||
|         let mut list = Vec::new(); | ||||
|         list.push(self.friendly.hash_tree_root()); | ||||
|         list.push(self.dead.hash_tree_root()); | ||||
|         ssz::merkle_hash(&mut list) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn test_annotated_tree_hash_derive() { | ||||
|     let casper = Casper::new(); | ||||
|     assert_eq!(casper.hash_tree_root(), casper.expected_tree_hash()); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn test_annotated_signed_root_derive() { | ||||
|     let casper = Casper::new(); | ||||
|     assert_eq!(casper.signed_root(), casper.expected_signed_hash()); | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user