1
// Copyright (C) Moondance Labs Ltd.
2
// This file is part of Tanssi.
3

            
4
// Tanssi is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Tanssi is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Tanssi.  If not, see <http://www.gnu.org/licenses/>
16

            
17
//! Crate containing various data structure used by both xcm-core-buyer pallet
18
//! as well as the client.
19

            
20
#![cfg_attr(not(feature = "std"), no_std)]
21

            
22
use {
23
    frame_support::{
24
        pallet_prelude::{Decode, Encode, TypeInfo},
25
        CloneNoBound, DebugNoBound,
26
    },
27
    sp_runtime::app_crypto::AppCrypto,
28
    sp_runtime::RuntimeAppPublic,
29
    sp_std::vec::Vec,
30
    tp_traits::ParaId,
31
};
32

            
33
#[cfg(feature = "std")]
34
use sp_keystore::{Keystore, KeystorePtr};
35

            
36
/// Proof that I am a collator, assigned to a para_id, and I can buy a core for that para_id
37
704
#[derive(Encode, Decode, CloneNoBound, PartialEq, Eq, DebugNoBound, TypeInfo)]
38
pub struct BuyCoreCollatorProof<PublicKey>
39
where
40
    PublicKey: RuntimeAppPublic + Clone + core::fmt::Debug,
41
{
42
    pub nonce: u64,
43
    pub public_key: PublicKey,
44
    pub signature: PublicKey::Signature,
45
}
46

            
47
#[cfg(feature = "std")]
48
#[derive(Debug)]
49
pub enum BuyCollatorProofCreationError {
50
    SignatureDecodingError(parity_scale_codec::Error),
51
    KeyStoreError(sp_keystore::Error),
52
}
53

            
54
#[cfg(feature = "std")]
55
impl From<parity_scale_codec::Error> for BuyCollatorProofCreationError {
56
    fn from(error: parity_scale_codec::Error) -> Self {
57
        BuyCollatorProofCreationError::SignatureDecodingError(error)
58
    }
59
}
60

            
61
#[cfg(feature = "std")]
62
impl From<sp_keystore::Error> for BuyCollatorProofCreationError {
63
    fn from(error: sp_keystore::Error) -> Self {
64
        BuyCollatorProofCreationError::KeyStoreError(error)
65
    }
66
}
67

            
68
impl<PublicKey> BuyCoreCollatorProof<PublicKey>
69
where
70
    PublicKey: AppCrypto + RuntimeAppPublic + Clone + core::fmt::Debug,
71
{
72
13
    pub fn prepare_payload(nonce: u64, para_id: ParaId) -> Vec<u8> {
73
13
        (nonce, para_id).encode()
74
13
    }
75

            
76
17
    pub fn verify_signature(&self, para_id: ParaId) -> bool {
77
17
        let payload = (self.nonce, para_id).encode();
78
17
        self.public_key.verify(&payload, &self.signature)
79
17
    }
80

            
81
13
    pub fn new(nonce: u64, para_id: ParaId, public_key: PublicKey) -> Option<Self> {
82
13
        let payload = Self::prepare_payload(nonce, para_id);
83
13
        public_key
84
13
            .sign(&payload)
85
13
            .map(|signature| BuyCoreCollatorProof {
86
13
                nonce,
87
13
                public_key,
88
13
                signature,
89
13
            })
90
13
    }
91

            
92
    #[cfg(feature = "std")]
93
    pub fn new_with_keystore(
94
        nonce: u64,
95
        para_id: ParaId,
96
        public_key: PublicKey,
97
        keystore: &KeystorePtr,
98
    ) -> Result<Option<Self>, BuyCollatorProofCreationError> {
99
        let payload = Self::prepare_payload(nonce, para_id);
100

            
101
        Ok(Keystore::sign_with(
102
            keystore,
103
            <PublicKey as AppCrypto>::ID,
104
            <PublicKey as AppCrypto>::CRYPTO_ID,
105
            &public_key.to_raw_vec(),
106
            payload.as_ref(),
107
        )?
108
        .map(|signature| Decode::decode(&mut signature.as_ref()))
109
        .transpose()?
110
        .map(|signature| BuyCoreCollatorProof {
111
            nonce,
112
            public_key,
113
            signature,
114
        }))
115
    }
116
}