cli_commands/
address_association_signatures.rs1use crate::key_params::StakeSigningKeyParam;
2use anyhow::Ok;
3use byte_string::ByteString;
4use clap::Parser;
5use pallet_address_associations::AddressAssociationSignedMessage;
6use parity_scale_codec::Encode;
7use serde::Serialize;
8use serde_json::json;
9use sidechain_domain::*;
10
11#[derive(Clone, Debug, Parser)]
14#[command(author, version, about, long_about = None)]
15pub struct AddressAssociationSignaturesCmd<
16 PartnerchainAddress: Clone + Sync + Send + FromStrStdErr + 'static,
17> {
18 #[arg(long)]
20 pub genesis_utxo: UtxoId,
21 #[arg(long)]
23 pub partnerchain_address: PartnerchainAddress,
24 #[arg(long)]
26 pub signing_key: StakeSigningKeyParam,
27}
28
29impl<PartnerchainAddress> AddressAssociationSignaturesCmd<PartnerchainAddress>
30where
31 PartnerchainAddress: Serialize + Clone + Sync + Send + FromStrStdErr + Encode + 'static,
32{
33 pub fn execute(&self) -> anyhow::Result<()> {
35 let signature = self.sign();
36 let output = json!({
37 "partnerchain_address": self.partnerchain_address,
38 "signature": signature,
39 "stake_public_key": self.signing_key.vkey()
40
41 });
42 println!("{}", serde_json::to_string_pretty(&output)?);
43 Ok(())
44 }
45
46 fn sign(&self) -> ByteString {
48 let msg = AddressAssociationSignedMessage {
49 stake_public_key: self.signing_key.vkey(),
50 partnerchain_address: self.partnerchain_address.clone(),
51 genesis_utxo: self.genesis_utxo,
52 };
53 let encoded = msg.encode();
54 self.signing_key.0.sign(&encoded).to_bytes().to_vec().into()
55 }
56}
57
58#[cfg(test)]
59mod test {
60 use super::*;
61 use hex::FromHexError;
62 use hex_literal::hex;
63 use sidechain_domain::byte_string::ByteString;
64 use std::str::FromStr;
65
66 #[derive(Clone, Encode, Serialize)]
67 struct AccountId32(pub [u8; 32]);
68
69 impl FromStr for AccountId32 {
70 type Err = anyhow::Error;
71
72 fn from_str(s: &str) -> Result<Self, Self::Err> {
73 let bytes =
74 hex::decode(s)?.try_into().map_err(|_| FromHexError::InvalidStringLength)?;
75
76 Ok(Self(bytes))
77 }
78 }
79
80 #[test]
82 fn signature_test() {
83 let cmd = AddressAssociationSignaturesCmd {
84 genesis_utxo: UtxoId::new(
85 hex!("59104061ffa0d66f9ba0135d6fc6a884a395b10f8ae9cb276fc2c3bfdfedc260"),
86 1,
87 ),
88 partnerchain_address:
89 AccountId32(hex!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d")),
91 signing_key: StakeSigningKeyParam::from_str(
92 "d75c630516c33a66b11b3444a70b65083aeb21353bd919cc5e3daa02c9732a84"
94 ).unwrap(),
95 };
96
97 assert_eq!(
98 cmd.sign(),
99 ByteString(hex!("1aa8c1b363a207ddadf0c6242a0632f5a557690a327d0245f9d473b983b3d8e1c95a3dd804cab41123c36ddbcb7137b8261c35d5c8ef04ce9d0f8d5c4b3ca607").into())
100 );
101 }
102}