19
19
// See the License for the specific language governing permissions and
20
20
// limitations under the License.
21
21
22
- // Coding conventions
23
- #![ deny(
24
- non_upper_case_globals,
25
- non_camel_case_types,
26
- non_snake_case,
27
- unused_mut,
28
- unused_imports,
29
- dead_code,
30
- missing_docs
31
- ) ]
32
22
#![ cfg_attr( docsrs, feature( doc_auto_cfg) ) ]
33
23
34
24
//! # Single-use-seals
113
103
//! <https://petertodd.org/2017/scalable-single-use-seal-asset-transfer>
114
104
115
105
use core:: borrow:: Borrow ;
106
+ use core:: convert:: Infallible ;
107
+ use core:: error:: Error ;
108
+ use core:: fmt:: { self , Debug , Display , Formatter } ;
109
+ use core:: marker:: PhantomData ;
116
110
117
111
/// Trait for proof-of-publication medium on which the seals are defined,
118
112
/// closed, verified and which can be used for convenience operations related to
@@ -132,52 +126,153 @@ use core::borrow::Borrow;
132
126
///
133
127
/// To read more on proof-of-publication please check
134
128
/// <https://petertodd.org/2014/setting-the-record-proof-of-publication>
135
- pub trait Seal : Sized {
129
+ pub trait SingleUseSeal : Clone + Debug + Display {
136
130
/// Single-use seal parameters, which allow to differentiate alternative
137
131
/// forms of single-use seals from each other.
138
132
type Params ;
139
133
140
134
/// Seal parameters which the type commits to.
141
135
const PARAMS : Self :: Params ;
142
136
143
- /// Associated type for the witness produced by the single-use-seal close
144
- /// procedure
145
- type Witness : SealWitness < Self > ;
137
+ /// Message type that is supported by the current single-use-seal.
138
+ type Message : Copy ;
146
139
147
- /// Message type that is supported by the current single-use-seal
148
- type Message ;
140
+ type PubWitness : PublishedWitness < Self > ;
141
+ type CliWitness : ClientSideWitness < Seal = Self > ;
142
+ }
143
+
144
+ pub trait ClientSideWitness {
145
+ type Seal : SingleUseSeal ;
146
+ type Error : Clone + Error ;
147
+
148
+ fn includes_seal ( & self , seal : impl Borrow < Self :: Seal > ) -> bool ;
149
+ fn convolve_commit (
150
+ & self ,
151
+ msg : <Self :: Seal as SingleUseSeal >:: Message ,
152
+ ) -> Result < <Self :: Seal as SingleUseSeal >:: Message , Self :: Error > ;
153
+ }
154
+
155
+ #[ derive( Copy , Clone , Ord , PartialOrd , Eq , PartialEq , Hash , Debug , Default ) ]
156
+ pub struct NoWitness < Seal : SingleUseSeal > ( PhantomData < Seal > ) ;
157
+ impl < Seal : SingleUseSeal > ClientSideWitness for NoWitness < Seal > {
158
+ type Seal = Seal ;
159
+ type Error = Infallible ;
160
+
161
+ fn includes_seal ( & self , _: impl Borrow < Self :: Seal > ) -> bool { false }
162
+
163
+ fn convolve_commit (
164
+ & self ,
165
+ msg : <Self :: Seal as SingleUseSeal >:: Message ,
166
+ ) -> Result < <Self :: Seal as SingleUseSeal >:: Message , Self :: Error > {
167
+ Ok ( msg)
168
+ }
169
+ }
149
170
171
+ pub trait PublishedWitness < Seal : SingleUseSeal > {
150
172
/// Publication id that may be used for referencing publication of
151
173
/// witness data in the medium. By default, set `()`, so [`SealProtocol`]
152
- /// may not implement publication id and related functions
153
- type PublicationId ;
174
+ /// may not implement publication id and related functions.
175
+ type PubId : Copy + Ord + Debug + Display ;
176
+
177
+ type Error : Clone + Error ;
178
+
179
+ fn pub_id ( & self ) -> Self :: PubId ;
180
+ fn includes_seal ( & self , seal : impl Borrow < Seal > ) -> bool ;
181
+ fn verify_commitment ( & self , msg : Seal :: Message ) -> Result < ( ) , Self :: Error > ;
154
182
}
155
183
156
- /// Seal witness which can verify seal or multiple seals.
157
- pub trait SealWitness < S : Seal < Witness = Self > > {
158
- /// Message type that is supported by the current single-use-seal
159
- type Message ;
184
+ /// Seal closing witness.
185
+ #[ derive( Clone , Copy ) ]
186
+ pub struct SealWitness < Seal >
187
+ where Seal : SingleUseSeal
188
+ {
189
+ pub published : Seal :: PubWitness ,
190
+ pub client : Seal :: CliWitness ,
191
+ _phantom : PhantomData < Seal > ,
192
+ }
160
193
161
- /// Error type that contains reasons of medium access failure
162
- type Error : std:: error:: Error ;
194
+ impl < Seal > SealWitness < Seal >
195
+ where Seal : SingleUseSeal
196
+ {
197
+ pub fn includes_seal ( & self , seal : impl Borrow < Seal > ) -> bool {
198
+ self . published . borrow ( ) . includes_seal ( seal. borrow ( ) ) ||
199
+ self . client . borrow ( ) . includes_seal ( seal)
200
+ }
163
201
164
- /// Verifies that the seal was indeed closed over the message with the
165
- /// provided seal closure witness.
166
- fn verify_seal ( & self , seal : impl Borrow < S > , msg : & Self :: Message ) -> Result < ( ) , Self :: Error > ;
202
+ pub fn verify_seal_closing (
203
+ & self ,
204
+ seal : impl Borrow < Seal > ,
205
+ message : Seal :: Message ,
206
+ ) -> Result < ( ) , SealError < Seal > > {
207
+ self . verify_seals_closing ( [ seal] , message)
208
+ }
167
209
168
- /// Performs batch verification of the seals.
169
- ///
170
- /// Default implementation iterates through the seals and calls
171
- /// [`Self::verify_seal`] for each of them, returning `false` on first
172
- /// failure (not verifying the rest of seals).
173
- fn verify_many_seals (
210
+ pub fn verify_seals_closing (
174
211
& self ,
175
- seals : impl IntoIterator < Item = impl Borrow < S > > ,
176
- msg : & Self :: Message ,
177
- ) -> Result < ( ) , Self :: Error > {
212
+ seals : impl IntoIterator < Item = impl Borrow < Seal > > ,
213
+ message : Seal :: Message ,
214
+ ) -> Result < ( ) , SealError < Seal > > {
215
+ // ensure that witness includes all seals
178
216
for seal in seals {
179
- self . verify_seal ( seal, msg) ?;
217
+ self . includes_seal ( seal. borrow ( ) )
218
+ . then_some ( ( ) )
219
+ . ok_or ( SealError :: NotIncluded ( seal. borrow ( ) . clone ( ) , self . published . pub_id ( ) ) ) ?;
220
+ }
221
+ // ensure that published witness contains the commitment to the
222
+ // f(message), where `f` is defined in the client-side witness
223
+ let f_msg = self
224
+ . client
225
+ . convolve_commit ( message)
226
+ . map_err ( SealError :: Client ) ?;
227
+ self . published
228
+ . verify_commitment ( f_msg)
229
+ . map_err ( SealError :: Published )
230
+ }
231
+ }
232
+
233
+ #[ derive( Clone ) ]
234
+ pub enum SealError < Seal : SingleUseSeal > {
235
+ NotIncluded ( Seal , <Seal :: PubWitness as PublishedWitness < Seal > >:: PubId ) ,
236
+ Published ( <Seal :: PubWitness as PublishedWitness < Seal > >:: Error ) ,
237
+ Client ( <Seal :: CliWitness as ClientSideWitness >:: Error ) ,
238
+ }
239
+
240
+ impl < Seal : SingleUseSeal > Debug for SealError < Seal > {
241
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
242
+ match self {
243
+ SealError :: NotIncluded ( seal, pub_id) => f
244
+ . debug_tuple ( "SealError::NotIncluded" )
245
+ . field ( seal)
246
+ . field ( pub_id)
247
+ . finish ( ) ,
248
+ SealError :: Published ( err) => f. debug_tuple ( "SealError::Published" ) . field ( err) . finish ( ) ,
249
+ SealError :: Client ( err) => f. debug_tuple ( "SealError::Client(err" ) . field ( err) . finish ( ) ,
250
+ }
251
+ }
252
+ }
253
+
254
+ impl < Seal : SingleUseSeal > Display for SealError < Seal > {
255
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
256
+ match self {
257
+ SealError :: NotIncluded ( seal, pub_id) => {
258
+ write ! ( f, "seal {seal} is not included in the witness {pub_id}" )
259
+ }
260
+ SealError :: Published ( err) => Display :: fmt ( err, f) ,
261
+ SealError :: Client ( err) => Display :: fmt ( err, f) ,
262
+ }
263
+ }
264
+ }
265
+
266
+ impl < Seal : SingleUseSeal > Error for SealError < Seal >
267
+ where
268
+ <<Seal as SingleUseSeal >:: PubWitness as PublishedWitness < Seal > >:: Error : ' static ,
269
+ <<Seal as SingleUseSeal >:: CliWitness as ClientSideWitness >:: Error : ' static ,
270
+ {
271
+ fn source ( & self ) -> Option < & ( dyn Error + ' static ) > {
272
+ match self {
273
+ SealError :: NotIncluded ( ..) => None ,
274
+ SealError :: Published ( e) => Some ( e) ,
275
+ SealError :: Client ( e) => Some ( e) ,
180
276
}
181
- Ok ( ( ) )
182
277
}
183
278
}
0 commit comments