@@ -73,21 +73,82 @@ pub fn aggregate(_: TokenStream, body: TokenStream) -> TokenStream {
73
73
pub fn tuxedo_verifier ( _: TokenStream , body : TokenStream ) -> TokenStream {
74
74
let ast = parse_macro_input ! ( body as ItemEnum ) ;
75
75
let original_code = ast. clone ( ) ;
76
+ let vis = ast. vis ;
76
77
77
78
let outer_type = ast. ident ;
78
- let variants = ast. variants . into_iter ( ) . map ( |v| v. ident ) ;
79
+ let variant_type_pairs = ast. variants . iter ( ) . map ( |variant| {
80
+ // Make sure there is only a single field, and if not, give a helpful error
81
+ assert ! (
82
+ variant. fields. len( ) == 1 ,
83
+ "Each variant must have a single unnamed field"
84
+ ) ;
85
+ (
86
+ variant. ident . clone ( ) ,
87
+ variant
88
+ . fields
89
+ . iter ( )
90
+ . next ( )
91
+ . expect ( "exactly one field per variant" )
92
+ . ty
93
+ . clone ( ) ,
94
+ )
95
+ } ) ;
96
+ let variants = variant_type_pairs. clone ( ) . map ( |( v, _t) | v) ;
97
+ let inner_types = variant_type_pairs. map ( |( _v, t) | t) ;
98
+
99
+ // Set up the name of the new associated type.
100
+ let mut redeemer_type_name = outer_type. to_string ( ) ;
101
+ redeemer_type_name. push_str ( "Redeemer" ) ;
102
+ let redeemer_type = Ident :: new ( & redeemer_type_name, outer_type. span ( ) ) ;
103
+
104
+ // TODO there must be a better way to do this, right?
105
+ let inner_types2 = inner_types. clone ( ) ;
106
+ let variants2 = variants. clone ( ) ;
107
+ let variants3 = variants. clone ( ) ;
108
+ let variants4 = variants. clone ( ) ;
79
109
80
110
let output = quote ! {
81
111
82
112
// Preserve the original enum, and write the From impls
83
113
#[ tuxedo_core:: aggregate]
84
114
#original_code
85
115
116
+ /// This type is generated by the `#[tuxedo_verifier]` macro.
117
+ /// It is a combined redeemer type for the redeemers of each individual verifier.
118
+ ///
119
+ /// This type is accessible downstream as `<OuterVerifier as Verifier>::Redeemer`
120
+ #[ derive( Debug , Decode ) ]
121
+ #vis enum #redeemer_type {
122
+ #(
123
+ #variants( <#inner_types as tuxedo_core:: Verifier >:: Redeemer ) ,
124
+ ) *
125
+ }
126
+
127
+ // Put a bunch of methods like `.as_variant1()` on the aggregate redeemer type
128
+ // These are necessary when unwrapping the onion.
129
+ // Might be that we should have a helper macro for this as well
130
+ impl #redeemer_type {
131
+ #(
132
+ //TODO I would rather the function be called as_variant2,
133
+ // but my macro n00b skills can't figure it out.
134
+ #[ allow( non_snake_case) ]
135
+ pub fn #variants2( & self ) -> Option <& <#inner_types2 as tuxedo_core:: Verifier >:: Redeemer > {
136
+ match self {
137
+ Self :: #variants3( inner) => Some ( inner) ,
138
+ _ => None ,
139
+ }
140
+ }
141
+ ) *
142
+ }
143
+
86
144
impl tuxedo_core:: Verifier for #outer_type {
87
- fn verify( & self , simplified_tx: & [ u8 ] , redeemer: & [ u8 ] ) -> bool {
145
+
146
+ type Redeemer = #redeemer_type;
147
+
148
+ fn verify( & self , simplified_tx: & [ u8 ] , block_number: u32 , redeemer: & Self :: Redeemer ) -> bool {
88
149
match self {
89
150
#(
90
- Self :: #variants ( inner) => inner. verify( simplified_tx, redeemer) ,
151
+ Self :: #variants4 ( inner) => inner. verify( simplified_tx, block_number , redeemer. #variants4 ( ) . expect ( "redeemer variant exists because the macro constructed that type." ) ) ,
91
152
) *
92
153
}
93
154
}
0 commit comments