sp_block_producer_metadata/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
2
3use parity_scale_codec::{Decode, Encode};
4use sidechain_domain::*;
5use sp_api;
6extern crate alloc;
7
8#[derive(Debug, Clone, Encode)]
9pub struct MetadataSignedMessage<Metadata> {
10 pub cross_chain_pub_key: CrossChainPublicKey,
11 pub metadata: Metadata,
12 pub genesis_utxo: UtxoId,
13}
14
15impl<M: Encode> MetadataSignedMessage<M> {
16 #[cfg(feature = "std")]
17 pub fn sign_with_key(&self, skey: &k256::SecretKey) -> CrossChainSignature {
18 use k256::Secp256k1;
19 use k256::ecdsa::hazmat::DigestPrimitive;
20 use k256::ecdsa::*;
21 use k256::sha2::Digest;
22 let data = self.encode();
23 let digest = <Secp256k1 as DigestPrimitive>::Digest::new_with_prefix(data);
24
25 let (sig, _recid) = SigningKey::from(skey).sign_digest_recoverable(digest.clone()).unwrap();
26 CrossChainSignature(sig.to_vec())
27 }
28
29 pub fn verify_signature(
30 &self,
31 vkey: &CrossChainPublicKey,
32 signature: CrossChainSignature,
33 ) -> Result<(), k256::ecdsa::signature::Error> {
34 signature.verify(vkey, &self.encode())
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41 use hex_literal::hex;
42
43 #[test]
44 fn round_trip() {
45 let message = MetadataSignedMessage {
46 cross_chain_pub_key: CrossChainPublicKey(vec![1; 32]),
47 metadata: "metadata".to_string(),
48 genesis_utxo: UtxoId::new([2; 32], 0),
49 };
50
51 let skey = k256::SecretKey::from_slice(&hex!(
53 "cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854"
54 ))
55 .unwrap();
56 let vkey = skey.public_key();
57
58 let signature = message.sign_with_key(&skey);
59
60 assert!(message.verify_signature(&vkey.into(), signature).is_ok());
61 }
62}
63
64sp_api::decl_runtime_apis! {
65 pub trait BlockProducerMetadataApi<Metadata>
66 where Metadata:Decode
67 {
68 fn get_metadata_for(
70 cross_chain_pub_key: &CrossChainPublicKey,
71 ) -> Option<Metadata>;
72 }
73}