1#![cfg_attr(not(feature = "std"), no_std)]
2
3use core::fmt;
5use ink_prelude::vec::Vec;
6use ink_storage::traits::{PackedLayout, SpreadAllocate, SpreadLayout};
7use pink::chain_extension::{signing, SigType};
8use pink_extension as pink;
9use scale::{Decode, Encode};
10
11#[derive(Clone, Encode, Decode, Debug, PartialEq, Eq)]
13#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
14pub struct Attestation {
15 pub data: Vec<u8>,
16 pub signature: Vec<u8>,
17 }
19
20#[derive(Debug, Encode, Decode, Clone, SpreadLayout, PackedLayout, SpreadAllocate)]
22#[cfg_attr(
23 feature = "std",
24 derive(scale_info::TypeInfo, ink_storage::traits::StorageLayout,)
25)]
26pub struct Verifier {
27 pub pubkey: Vec<u8>,
28}
29
30impl Verifier {
31 pub fn verify(&self, attestation: &Attestation) -> bool {
33 signing::verify(
34 &attestation.data,
35 &self.pubkey,
36 &attestation.signature,
37 SigType::Sr25519,
38 )
39 }
40
41 pub fn verify_as<T: Decode>(&self, attestation: &Attestation) -> Option<T> {
43 if !self.verify(&attestation) {
44 return None;
45 }
46 Decode::decode(&mut &attestation.data[..]).ok()
47 }
48}
49
50#[derive(Encode, Decode, Clone, SpreadLayout, PackedLayout, SpreadAllocate)]
52#[cfg_attr(
53 feature = "std",
54 derive(scale_info::TypeInfo, ink_storage::traits::StorageLayout,)
55)]
56pub struct Generator {
57 pub privkey: Vec<u8>,
58}
59
60impl Generator {
61 pub fn sign<T: Clone + Encode + Decode>(&self, data: T) -> Attestation {
63 let encoded = Encode::encode(&data);
64 let signature = signing::sign(&encoded, &self.privkey, SigType::Sr25519);
65 Attestation {
66 data: encoded,
67 signature,
68 }
69 }
70}
71
72impl fmt::Debug for Generator {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 write!(f, "Generator")
76 }
77}
78
79pub fn create(salt: &[u8]) -> (Generator, Verifier) {
81 let privkey = signing::derive_sr25519_key(salt);
82 let pubkey = signing::get_public_key(&privkey, SigType::Sr25519);
83 (Generator { privkey }, Verifier { pubkey })
84}
85
86#[cfg(test)]
87mod test {
88 use super::*;
89 use ink_lang as ink;
90
91 #[ink::test]
92 fn it_works() {
93 pink_extension_runtime::mock_ext::mock_all_ext();
94
95 #[derive(Clone, Encode, Decode, scale_info::TypeInfo)]
97 struct SomeData {
98 x: u32,
99 }
100
101 let (generator, verifier) = create(b"salt");
102 let attestation = generator.sign(SomeData { x: 123 });
103 assert!(verifier.verify(&attestation));
104 }
105}