1use crate::{Index, NodeCount, NodeIndex, NodeMap};
2use codec::{Codec, Decode, Encode};
3use log::warn;
4use std::{fmt::Debug, hash::Hash};
5
6pub trait Signature: Debug + Clone + Codec + Send + Sync + Eq + 'static {}
10
11impl<T: Debug + Clone + Codec + Send + Sync + Eq + 'static> Signature for T {}
12
13pub trait Keychain: Index + Clone + Send + Sync + 'static {
21 type Signature: Signature;
22
23 fn node_count(&self) -> NodeCount;
25 fn sign(&self, msg: &[u8]) -> Self::Signature;
27 fn verify(&self, msg: &[u8], sgn: &Self::Signature, index: NodeIndex) -> bool;
30}
31
32pub trait PartialMultisignature: Signature {
40 type Signature: Signature;
41 #[must_use = "consumes the original and returns the aggregated signature which should be used"]
43 fn add_signature(self, signature: &Self::Signature, index: NodeIndex) -> Self;
44}
45
46pub trait MultiKeychain: Keychain {
51 type PartialMultisignature: PartialMultisignature<Signature = Self::Signature>;
52 fn bootstrap_multi(
54 &self,
55 signature: &Self::Signature,
56 index: NodeIndex,
57 ) -> Self::PartialMultisignature;
58 fn is_complete(&self, msg: &[u8], partial: &Self::PartialMultisignature) -> bool;
60}
61
62pub type SignatureSet<S> = NodeMap<S>;
64
65impl<S: Signature> PartialMultisignature for SignatureSet<S> {
66 type Signature = S;
67
68 #[must_use = "consumes the original and returns the aggregated signature which should be used"]
69 fn add_signature(mut self, signature: &Self::Signature, index: NodeIndex) -> Self {
70 self.insert(index, signature.clone());
71 self
72 }
73}
74
75pub trait Signable {
81 type Hash: AsRef<[u8]>;
82 fn hash(&self) -> Self::Hash;
84}
85
86impl<T: AsRef<[u8]> + Clone> Signable for T {
87 type Hash = T;
88 fn hash(&self) -> Self::Hash {
89 self.clone()
90 }
91}
92
93#[derive(Clone, Eq, PartialEq, Hash, Debug, Decode, Encode)]
98pub struct UncheckedSigned<T: Signable, S: Signature> {
99 signable: T,
100 signature: S,
101}
102
103impl<T: Signable, S: Signature> UncheckedSigned<T, S> {
104 pub fn as_signable(&self) -> &T {
105 &self.signable
106 }
107
108 pub fn into_signable(self) -> T {
109 self.signable
110 }
111
112 pub fn signature(&self) -> S {
113 self.signature.clone()
114 }
115}
116
117impl<T: Signable, S: Signature> UncheckedSigned<Indexed<T>, S> {
118 pub fn as_signable_strip_index(&self) -> &T {
119 &self.signable.signable
120 }
121}
122
123#[derive(Clone, Eq, PartialEq, Hash, Debug, Decode, Encode)]
125pub struct SignatureError<T: Signable, S: Signature> {
126 pub unchecked: UncheckedSigned<T, S>,
127}
128
129impl<T: Signable + Index, S: Signature> UncheckedSigned<T, S> {
130 pub fn check<K: Keychain<Signature = S>>(
132 self,
133 keychain: &K,
134 ) -> Result<Signed<T, K>, SignatureError<T, S>> {
135 let index = self.signable.index();
136 if !keychain.verify(self.signable.hash().as_ref(), &self.signature, index) {
137 return Err(SignatureError { unchecked: self });
138 }
139 Ok(Signed { unchecked: self })
140 }
141}
142
143impl<T: Signable + Index, S: Signature> Index for UncheckedSigned<T, S> {
144 fn index(&self) -> NodeIndex {
145 self.signable.index()
146 }
147}
148
149impl<T: Signable, S: PartialMultisignature> UncheckedSigned<T, S> {
150 pub fn check_multi<MK: MultiKeychain<PartialMultisignature = S>>(
152 self,
153 keychain: &MK,
154 ) -> Result<Multisigned<T, MK>, SignatureError<T, S>> {
155 if !(keychain.is_complete(self.signable.hash().as_ref(), &self.signature)) {
156 return Err(SignatureError { unchecked: self });
157 }
158 Ok(Multisigned { unchecked: self })
159 }
160}
161
162impl<T: Signable, S: Signature> UncheckedSigned<Indexed<T>, S> {
163 fn strip_index(self) -> UncheckedSigned<T, S> {
164 UncheckedSigned {
165 signable: self.signable.strip_index(),
166 signature: self.signature,
167 }
168 }
169}
170
171impl<T: Signable, S: Signature> From<UncheckedSigned<Indexed<T>, S>> for UncheckedSigned<T, S> {
172 fn from(us: UncheckedSigned<Indexed<T>, S>) -> Self {
173 us.strip_index()
174 }
175}
176
177#[derive(Eq, PartialEq, Hash, Debug, Decode, Encode)]
179pub struct Signed<T: Signable + Index, K: Keychain> {
180 unchecked: UncheckedSigned<T, K::Signature>,
181}
182
183impl<T: Signable + Clone + Index, K: Keychain> Clone for Signed<T, K> {
184 fn clone(&self) -> Self {
185 Signed {
186 unchecked: self.unchecked.clone(),
187 }
188 }
189}
190
191impl<T: Signable + Index, K: Keychain> Signed<T, K> {
192 pub fn sign(signable: T, keychain: &K) -> Signed<T, K> {
194 assert_eq!(signable.index(), keychain.index());
195 let signature = keychain.sign(signable.hash().as_ref());
196 Signed {
197 unchecked: UncheckedSigned {
198 signable,
199 signature,
200 },
201 }
202 }
203
204 pub fn as_signable(&self) -> &T {
206 &self.unchecked.signable
207 }
208
209 pub fn into_signable(self) -> T {
210 self.unchecked.signable
211 }
212
213 pub fn into_unchecked(self) -> UncheckedSigned<T, K::Signature> {
214 self.unchecked
215 }
216}
217
218impl<T: Signable, K: Keychain> Signed<Indexed<T>, K> {
219 pub fn sign_with_index(signable: T, keychain: &K) -> Signed<Indexed<T>, K> {
221 Signed::sign(Indexed::new(signable, keychain.index()), keychain)
222 }
223}
224
225impl<T: Signable, MK: MultiKeychain> Signed<Indexed<T>, MK> {
226 pub fn into_partially_multisigned(self, keychain: &MK) -> PartiallyMultisigned<T, MK> {
229 let multisignature =
230 keychain.bootstrap_multi(&self.unchecked.signature, self.unchecked.signable.index);
231 let unchecked = UncheckedSigned {
232 signable: self.unchecked.signable.strip_index(),
233 signature: multisignature,
234 };
235 if keychain.is_complete(unchecked.signable.hash().as_ref(), &unchecked.signature) {
236 PartiallyMultisigned::Complete {
237 multisigned: Multisigned { unchecked },
238 }
239 } else {
240 PartiallyMultisigned::Incomplete { unchecked }
241 }
242 }
243}
244
245impl<T: Signable + Index, K: Keychain> From<Signed<T, K>> for UncheckedSigned<T, K::Signature> {
246 fn from(signed: Signed<T, K>) -> Self {
247 signed.into_unchecked()
248 }
249}
250
251#[derive(Clone, Eq, PartialEq, Hash, Debug, Decode, Encode)]
260pub struct Indexed<T: Signable> {
261 signable: T,
262 index: NodeIndex,
263}
264
265impl<T: Signable> Indexed<T> {
266 fn new(signable: T, index: NodeIndex) -> Self {
267 Indexed { signable, index }
268 }
269
270 fn strip_index(self) -> T {
271 self.signable
272 }
273
274 pub fn as_signable(&self) -> &T {
275 &self.signable
276 }
277}
278
279impl<T: Signable> Signable for Indexed<T> {
280 type Hash = T::Hash;
281
282 fn hash(&self) -> Self::Hash {
283 self.signable.hash()
284 }
285}
286
287impl<T: Signable> Index for Indexed<T> {
288 fn index(&self) -> NodeIndex {
289 self.index
290 }
291}
292
293#[derive(Eq, PartialEq, Hash, Debug, Decode, Encode)]
299pub struct Multisigned<T: Signable, MK: MultiKeychain> {
300 unchecked: UncheckedSigned<T, MK::PartialMultisignature>,
301}
302
303impl<T: Signable, MK: MultiKeychain> Multisigned<T, MK> {
304 pub fn as_signable(&self) -> &T {
306 &self.unchecked.signable
307 }
308
309 pub fn into_unchecked(self) -> UncheckedSigned<T, MK::PartialMultisignature> {
310 self.unchecked
311 }
312}
313
314impl<T: Signable, MK: MultiKeychain> From<Multisigned<T, MK>>
315 for UncheckedSigned<T, MK::PartialMultisignature>
316{
317 fn from(signed: Multisigned<T, MK>) -> Self {
318 signed.into_unchecked()
319 }
320}
321
322impl<T: Signable + Clone, MK: MultiKeychain> Clone for Multisigned<T, MK> {
323 fn clone(&self) -> Self {
324 Multisigned {
325 unchecked: self.unchecked.clone(),
326 }
327 }
328}
329
330#[derive(Clone, Eq, PartialEq, Debug, Decode, Encode)]
351pub struct IncompleteMultisignatureError<T: Signable, MK: MultiKeychain> {
352 pub partial: PartiallyMultisigned<T, MK>,
353}
354
355#[derive(Clone, Eq, PartialEq, Hash, Debug, Decode, Encode)]
361pub enum PartiallyMultisigned<T: Signable, MK: MultiKeychain> {
362 Incomplete {
363 unchecked: UncheckedSigned<T, MK::PartialMultisignature>,
364 },
365 Complete {
366 multisigned: Multisigned<T, MK>,
367 },
368}
369
370impl<T: Signable, MK: MultiKeychain> PartiallyMultisigned<T, MK> {
371 pub fn sign(signable: T, keychain: &MK) -> PartiallyMultisigned<T, MK> {
373 Signed::sign_with_index(signable, keychain).into_partially_multisigned(keychain)
374 }
375
376 pub fn is_complete(&self) -> bool {
378 match self {
379 PartiallyMultisigned::Incomplete { .. } => false,
380 PartiallyMultisigned::Complete { .. } => true,
381 }
382 }
383
384 pub fn as_signable(&self) -> &T {
386 match self {
387 PartiallyMultisigned::Incomplete { unchecked } => unchecked.as_signable(),
388 PartiallyMultisigned::Complete { multisigned } => multisigned.as_signable(),
389 }
390 }
391
392 pub fn into_unchecked(self) -> UncheckedSigned<T, MK::PartialMultisignature> {
394 match self {
395 PartiallyMultisigned::Incomplete { unchecked } => unchecked,
396 PartiallyMultisigned::Complete { multisigned } => multisigned.unchecked,
397 }
398 }
399
400 #[must_use = "consumes the original and returns the aggregated signature which should be used"]
402 pub fn add_signature(self, signed: Signed<Indexed<T>, MK>, keychain: &MK) -> Self {
403 if self.as_signable().hash().as_ref() != signed.as_signable().hash().as_ref() {
404 warn!(target: "AlephBFT-signed", "Tried to add a signature of a different object");
405 return self;
406 }
407 match self {
408 PartiallyMultisigned::Incomplete { mut unchecked } => {
409 unchecked.signature = unchecked
410 .signature
411 .add_signature(&signed.unchecked.signature, signed.unchecked.signable.index);
412 if keychain.is_complete(unchecked.signable.hash().as_ref(), &unchecked.signature) {
413 PartiallyMultisigned::Complete {
414 multisigned: Multisigned { unchecked },
415 }
416 } else {
417 PartiallyMultisigned::Incomplete { unchecked }
418 }
419 }
420 PartiallyMultisigned::Complete { .. } => self,
421 }
422 }
423}
424
425#[cfg(test)]
426mod tests {
427
428 use crate::{
429 Index, Keychain, MultiKeychain, NodeCount, NodeIndex, PartialMultisignature,
430 PartiallyMultisigned, Signable, SignatureSet, Signed,
431 };
432 use codec::{Decode, Encode};
433 use std::fmt::Debug;
434
435 #[derive(Debug, Clone)]
440 struct DefaultMultiKeychain<K: Keychain> {
441 keychain: K,
442 }
443
444 impl<K: Keychain> DefaultMultiKeychain<K> {
445 fn new(keychain: K) -> Self {
447 DefaultMultiKeychain { keychain }
448 }
449 }
450
451 impl<K: Keychain> Index for DefaultMultiKeychain<K> {
452 fn index(&self) -> NodeIndex {
453 self.keychain.index()
454 }
455 }
456
457 impl<K: Keychain> Keychain for DefaultMultiKeychain<K> {
458 type Signature = K::Signature;
459
460 fn node_count(&self) -> NodeCount {
461 self.keychain.node_count()
462 }
463
464 fn sign(&self, msg: &[u8]) -> Self::Signature {
465 self.keychain.sign(msg)
466 }
467
468 fn verify(&self, msg: &[u8], sgn: &Self::Signature, index: NodeIndex) -> bool {
469 self.keychain.verify(msg, sgn, index)
470 }
471 }
472
473 impl<K: Keychain> MultiKeychain for DefaultMultiKeychain<K> {
474 type PartialMultisignature = SignatureSet<K::Signature>;
475
476 fn bootstrap_multi(
477 &self,
478 signature: &Self::Signature,
479 index: NodeIndex,
480 ) -> Self::PartialMultisignature {
481 SignatureSet::add_signature(
482 SignatureSet::with_size(self.node_count()),
483 signature,
484 index,
485 )
486 }
487
488 fn is_complete(&self, msg: &[u8], partial: &Self::PartialMultisignature) -> bool {
489 let signature_count = partial.iter().count();
490 if signature_count < self.node_count().consensus_threshold().0 {
491 return false;
492 }
493 partial
494 .iter()
495 .all(|(i, sgn)| self.keychain.verify(msg, sgn, i))
496 }
497 }
498
499 #[derive(Clone, Debug, Default, PartialEq, Eq)]
500 struct TestMessage {
501 msg: Vec<u8>,
502 }
503
504 impl Signable for TestMessage {
505 type Hash = Vec<u8>;
506 fn hash(&self) -> Self::Hash {
507 self.msg.clone()
508 }
509 }
510
511 fn test_message() -> TestMessage {
512 TestMessage {
513 msg: "Hello".as_bytes().to_vec(),
514 }
515 }
516
517 #[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)]
518 struct TestSignature {
519 msg: Vec<u8>,
520 index: NodeIndex,
521 }
522
523 #[derive(Clone, Debug)]
524 struct TestKeychain {
525 count: NodeCount,
526 index: NodeIndex,
527 }
528
529 impl TestKeychain {
530 fn new(count: NodeCount, index: NodeIndex) -> Self {
531 TestKeychain { count, index }
532 }
533 }
534
535 impl Index for TestKeychain {
536 fn index(&self) -> NodeIndex {
537 self.index
538 }
539 }
540
541 impl Keychain for TestKeychain {
542 type Signature = TestSignature;
543
544 fn node_count(&self) -> NodeCount {
545 self.count
546 }
547
548 fn sign(&self, msg: &[u8]) -> Self::Signature {
549 TestSignature {
550 msg: msg.to_vec(),
551 index: self.index,
552 }
553 }
554
555 fn verify(&self, msg: &[u8], sgn: &Self::Signature, index: NodeIndex) -> bool {
556 index == sgn.index && msg == sgn.msg
557 }
558 }
559
560 type TestMultiKeychain = DefaultMultiKeychain<TestKeychain>;
561
562 fn test_multi_keychain(node_count: NodeCount, index: NodeIndex) -> TestMultiKeychain {
563 let keychain = TestKeychain::new(node_count, index);
564 DefaultMultiKeychain::new(keychain)
565 }
566
567 #[test]
568 fn test_valid_signatures() {
569 let node_count: NodeCount = 7.into();
570 let keychains: Vec<TestMultiKeychain> = (0_usize..node_count.0)
571 .map(|i| test_multi_keychain(node_count, i.into()))
572 .collect();
573 for i in 0..node_count.0 {
574 for j in 0..node_count.0 {
575 let msg = test_message();
576 let signed_msg = Signed::sign_with_index(msg.clone(), &keychains[i]);
577 let unchecked_msg = signed_msg.into_unchecked();
578 assert!(
579 unchecked_msg.check(&keychains[j]).is_ok(),
580 "Signed message should be valid"
581 );
582 }
583 }
584 }
585
586 #[test]
587 fn test_invalid_signatures() {
588 let node_count: NodeCount = 1.into();
589 let index: NodeIndex = 0.into();
590 let keychain = test_multi_keychain(node_count, index);
591 let msg = test_message();
592 let signed_msg = Signed::sign_with_index(msg, &keychain);
593 let mut unchecked_msg = signed_msg.into_unchecked();
594 unchecked_msg.signature.index = 1.into();
595
596 assert!(
597 unchecked_msg.check(&keychain).is_err(),
598 "wrong index makes wrong signature"
599 );
600 }
601
602 #[test]
603 fn test_incomplete_multisignature() {
604 let msg = test_message();
605 let index: NodeIndex = 0.into();
606 let node_count: NodeCount = 2.into();
607 let keychain = test_multi_keychain(node_count, index);
608
609 let partial = PartiallyMultisigned::sign(msg, &keychain);
610 assert!(
611 !partial.is_complete(),
612 "One signature does not form a complete multisignature",
613 );
614 }
615
616 #[test]
617 fn test_multisignatures() {
618 let msg = test_message();
619 let node_count: NodeCount = 7.into();
620 let keychains: Vec<TestMultiKeychain> = (0..node_count.0)
621 .map(|i| test_multi_keychain(node_count, i.into()))
622 .collect();
623
624 let mut partial = PartiallyMultisigned::sign(msg.clone(), &keychains[0]);
625 for keychain in keychains.iter().skip(1).take(4) {
626 assert!(!partial.is_complete());
627 let signed = Signed::sign_with_index(msg.clone(), keychain);
628 partial = partial.add_signature(signed, keychain);
629 }
630 assert!(
631 partial.is_complete(),
632 "5 signatures should form a complete signature {:?}",
633 partial
634 );
635 }
636}