1use crate::common::{ADDR_BYTES_LEN, HASH_BYTES_LEN};
15use cita_cloud_proto::blockchain::BlockHeader;
16use cita_cloud_proto::client::{CryptoClientTrait, InterceptedSvc};
17use cita_cloud_proto::crypto::crypto_service_client::CryptoServiceClient;
18use cita_cloud_proto::crypto::{HashDataRequest, RecoverSignatureRequest, SignMessageRequest};
19use cita_cloud_proto::retry::RetryClient;
20use cita_cloud_proto::status_code::StatusCodeEnum;
21use prost::Message;
22
23pub async fn hash_data(
24 client: RetryClient<CryptoServiceClient<InterceptedSvc>>,
25 data: &[u8],
26) -> Result<Vec<u8>, StatusCodeEnum> {
27 let data = data.to_vec();
28 match client.hash_data(HashDataRequest { data }).await {
29 Ok(hash_respond) => {
30 let status_code = StatusCodeEnum::from(
31 hash_respond
32 .status
33 .ok_or(StatusCodeEnum::NoneStatusCode)?
34 .code,
35 );
36
37 if status_code != StatusCodeEnum::Success {
38 Err(status_code)
39 } else {
40 Ok(hash_respond
41 .hash
42 .ok_or(StatusCodeEnum::NoneHashResult)?
43 .hash)
44 }
45 }
46 Err(status) => {
47 warn!("hash_data error: {}", status.to_string());
48 Err(StatusCodeEnum::CryptoServerNotReady)
49 }
50 }
51}
52
53pub async fn get_block_hash(
54 client: RetryClient<CryptoServiceClient<InterceptedSvc>>,
55 header: Option<&BlockHeader>,
56) -> Result<Vec<u8>, StatusCodeEnum> {
57 match header {
58 Some(header) => {
59 let mut block_header_bytes = Vec::with_capacity(header.encoded_len());
60 header.encode(&mut block_header_bytes).map_err(|_| {
61 warn!("get_block_hash: encode block header failed");
62 StatusCodeEnum::EncodeError
63 })?;
64 let block_hash = hash_data(client, &block_header_bytes).await?;
65 Ok(block_hash)
66 }
67 None => Err(StatusCodeEnum::NoneBlockHeader),
68 }
69}
70
71pub async fn pk2address(
72 client: RetryClient<CryptoServiceClient<InterceptedSvc>>,
73 pk: &[u8],
74) -> Result<Vec<u8>, StatusCodeEnum> {
75 Ok(hash_data(client, pk).await?[HASH_BYTES_LEN - ADDR_BYTES_LEN..].to_vec())
76}
77
78pub async fn sign_message(
79 client: RetryClient<CryptoServiceClient<InterceptedSvc>>,
80 msg: &[u8],
81) -> Result<Vec<u8>, StatusCodeEnum> {
82 let smr = client
83 .sign_message(SignMessageRequest { msg: msg.to_vec() })
84 .await
85 .map_err(|e| {
86 warn!("sign_message failed: {}", e.to_string());
87 StatusCodeEnum::CryptoServerNotReady
88 })?;
89
90 let status = StatusCodeEnum::from(smr.status.ok_or(StatusCodeEnum::NoneStatusCode)?);
91 if status != StatusCodeEnum::Success {
92 Err(status)
93 } else {
94 Ok(smr.signature)
95 }
96}
97
98pub async fn recover_signature(
99 client: RetryClient<CryptoServiceClient<InterceptedSvc>>,
100 signature: &[u8],
101 msg: &[u8],
102) -> Result<Vec<u8>, StatusCodeEnum> {
103 let rsr = client
104 .recover_signature(RecoverSignatureRequest {
105 msg: msg.to_vec(),
106 signature: signature.to_vec(),
107 })
108 .await
109 .map_err(|e| {
110 warn!("recover_signature failed: {}", e.to_string());
111 StatusCodeEnum::CryptoServerNotReady
112 })?;
113
114 let status = StatusCodeEnum::from(rsr.status.ok_or(StatusCodeEnum::NoneStatusCode)?);
115 if status != StatusCodeEnum::Success {
116 Err(status)
117 } else {
118 Ok(rsr.address)
119 }
120}