1#![cfg_attr(not(test), deny(clippy::expect_used,))]
2use std::convert::TryFrom;
3
4use bip39::{Language, MnemonicType, Seed};
5use bls_signatures::Serialize;
6use fvm_shared::crypto::signature::{Signature, SignatureType};
7use fvm_shared::message::Message;
8use libsecp256k1::util::{COMPRESSED_PUBLIC_KEY_SIZE, SECRET_KEY_SIZE, SIGNATURE_SIZE};
9use num_traits::FromPrimitive;
10use rayon::prelude::*;
11use zx_bip44::BIP44Path;
12
13use fil_actor_init::{ExecParams, Method as MethodInit};
14use fil_actor_multisig as multisig;
15use fil_actor_paych as paych;
16use fvm_ipld_encoding::{from_slice, to_vec, RawBytes};
17use fvm_shared::address::{Address, Network, Protocol};
18
19use bls_signatures::PublicKey as BLSPublicKey;
20use libsecp256k1::PublicKey as SECP256K1PublicKey;
21
22use extras::signed_message::ref_fvm::SignedMessage;
23
24use cid::multihash::MultihashDigest;
25use fvm_ipld_encoding::DAG_CBOR;
26use fvm_shared::econ::TokenAmount;
27use fvm_shared::MethodNum;
28
29use crate::api::{MessageParams, MessageTx, MessageTxAPI, MessageTxNetwork};
30use crate::error::SignerError;
31use crate::extended_key::ExtendedSecretKey;
32use crate::multisig_deprecated::ConstructorParamsV1;
33
34pub mod api;
35pub mod error;
36pub mod extended_key;
37pub mod multisig_deprecated;
38pub mod utils;
39
40pub struct Mnemonic(pub String);
42
43pub const SIGNATURE_RECOVERY_SIZE: usize = SIGNATURE_SIZE + 1;
44
45pub struct PrivateKey(pub [u8; SECRET_KEY_SIZE]);
47
48pub enum PublicKey {
49 SECP256K1PublicKey(SECP256K1PublicKey),
50 BLSPublicKey(BLSPublicKey),
51}
52
53impl PublicKey {
54 pub fn to_vec(&self) -> Vec<u8> {
55 match self {
56 PublicKey::SECP256K1PublicKey(pk) => pk.serialize().to_vec(),
58 PublicKey::BLSPublicKey(pk) => pk.as_bytes(),
59 }
60 }
61}
62
63pub struct PublicKeyCompressed(pub [u8; COMPRESSED_PUBLIC_KEY_SIZE]);
65
66pub struct ExtendedKey {
68 pub private_key: PrivateKey,
69 pub public_key: PublicKey,
70 pub address: String,
71}
72
73#[cfg(feature = "with-ffi-support")]
74ffi_support::implement_into_ffi_by_pointer!(ExtendedKey);
75
76impl TryFrom<String> for PrivateKey {
77 type Error = SignerError;
78
79 fn try_from(s: String) -> Result<PrivateKey, Self::Error> {
80 let v = base64::decode(&s)?;
81
82 PrivateKey::try_from(v)
83 }
84}
85
86impl TryFrom<Vec<u8>> for PrivateKey {
87 type Error = SignerError;
88
89 fn try_from(v: Vec<u8>) -> Result<PrivateKey, Self::Error> {
90 if v.len() != SECRET_KEY_SIZE {
91 return Err(SignerError::GenericString("Invalid Key Length".to_string()));
92 }
93 let mut sk = PrivateKey([0; SECRET_KEY_SIZE]);
94 sk.0.copy_from_slice(&v[..SECRET_KEY_SIZE]);
95 Ok(sk)
96 }
97}
98
99#[derive(serde::Serialize, serde::Deserialize)]
100#[serde(rename_all = "PascalCase")]
101pub struct ProposalHashDataAPI {
102 #[serde(with = "extras::json::option_address")]
103 pub requester: Option<Address>,
104 #[serde(with = "extras::json::address")]
105 pub to: Address,
106 #[serde(with = "extras::json::tokenamount")]
107 pub value: TokenAmount,
108 pub method: MethodNum,
109 #[serde(with = "extras::json::rawbytes")]
110 pub params: RawBytes,
111}
112
113#[derive(serde::Serialize, serde::Deserialize)]
114#[serde(transparent)]
115pub struct SignedVoucherWrapper(
116 #[serde(with = "extras::paych::SignedVoucherAPI")] paych::SignedVoucher,
117);
118
119pub fn key_generate_mnemonic() -> Result<Mnemonic, SignerError> {
121 let mnemonic = bip39::Mnemonic::new(MnemonicType::Words24, Language::English);
122 Ok(Mnemonic(mnemonic.to_string()))
123}
124
125fn derive_extended_secret_key(seed: &[u8], path: &str) -> Result<ExtendedSecretKey, SignerError> {
126 let master = ExtendedSecretKey::try_from(seed)?;
127 let bip44_path = BIP44Path::from_string(path)?;
128 let esk = master.derive_bip44(&bip44_path)?;
129
130 Ok(esk)
131}
132
133fn derive_extended_secret_key_from_mnemonic(
134 mnemonic: &str,
135 path: &str,
136 password: &str,
137 language_code: &str,
138) -> Result<ExtendedSecretKey, SignerError> {
139 let lang = Language::from_language_code(language_code);
140
141 match lang {
142 Some(l) => {
143 let mnemonic = bip39::Mnemonic::from_phrase(mnemonic, l)
144 .map_err(|err| SignerError::GenericString(err.to_string()))?;
145
146 let seed = Seed::new(&mnemonic, password);
147
148 derive_extended_secret_key(seed.as_bytes(), path)
149 }
150 None => Err(SignerError::GenericString(
151 "Unknown language code".to_string(),
152 )),
153 }
154}
155
156pub fn key_derive(
165 mnemonic: &str,
166 path: &str,
167 password: &str,
168 language_code: &str,
169) -> Result<ExtendedKey, SignerError> {
170 let esk = derive_extended_secret_key_from_mnemonic(mnemonic, path, password, language_code)?;
171
172 let address = Address::new_secp256k1(esk.public_key().as_ref())?;
173
174 let bip44_path = BIP44Path::from_string(path)?;
175
176 let mut network_str = "f".to_owned();
177 if bip44_path.is_testnet() {
178 network_str = "t".to_owned();
179 }
180
181 let address = network_str + &address.to_string()[1..];
182
183 Ok(ExtendedKey {
184 private_key: PrivateKey(esk.secret_key()),
185 public_key: PublicKey::SECP256K1PublicKey(SECP256K1PublicKey::parse(&esk.public_key())?),
186 address,
187 })
188}
189
190pub fn key_derive_from_seed(seed: &[u8], path: &str) -> Result<ExtendedKey, SignerError> {
198 let esk = derive_extended_secret_key(seed, path)?;
199
200 let address = Address::new_secp256k1(esk.public_key().as_ref())?;
201
202 let bip44_path = BIP44Path::from_string(path)?;
203
204 let mut network_str = "f".to_owned();
205 if bip44_path.is_testnet() {
206 network_str = "t".to_owned();
207 }
208
209 let address = network_str + &address.to_string()[1..];
210
211 Ok(ExtendedKey {
212 private_key: PrivateKey(esk.secret_key()),
213 public_key: PublicKey::SECP256K1PublicKey(SECP256K1PublicKey::parse(&esk.public_key())?),
214 address,
215 })
216}
217
218pub fn key_recover(private_key: &PrivateKey, testnet: bool) -> Result<ExtendedKey, SignerError> {
226 let secret_key = libsecp256k1::SecretKey::parse_slice(&private_key.0)?;
227 let public_key = libsecp256k1::PublicKey::from_secret_key(&secret_key);
228 let address = Address::new_secp256k1(&public_key.serialize())?;
229
230 let mut network_str = "f".to_owned();
231 if testnet {
232 network_str = "t".to_owned();
233 }
234
235 let address = network_str + &address.to_string()[1..];
236
237 Ok(ExtendedKey {
238 private_key: PrivateKey(secret_key.serialize()),
239 public_key: PublicKey::SECP256K1PublicKey(public_key),
240 address: address,
241 })
242}
243
244pub fn key_recover_bls(
252 private_key: &PrivateKey,
253 testnet: bool,
254) -> Result<ExtendedKey, SignerError> {
255 let sk = bls_signatures::PrivateKey::from_bytes(&private_key.0)?;
256
257 let address = Address::new_bls(&sk.public_key().as_bytes())?;
258
259 let mut network_str = "f".to_owned();
260 if testnet {
261 network_str = "t".to_owned();
262 }
263
264 let address = network_str + &address.to_string()[1..];
265
266 let mut secret_key = PrivateKey([0; SECRET_KEY_SIZE]);
267 secret_key.0.copy_from_slice(&sk.as_bytes());
268
269 Ok(ExtendedKey {
270 private_key: secret_key,
271 public_key: PublicKey::BLSPublicKey(sk.public_key()),
272 address,
273 })
274}
275
276pub fn transaction_serialize(message: &Message) -> Result<Vec<u8>, SignerError> {
283 let message_cbor = to_vec(message)?;
284 Ok(message_cbor)
285}
286
287pub fn transaction_parse(cbor: &[u8], testnet: bool) -> Result<MessageTxAPI, SignerError> {
295 let message: MessageTx = from_slice(cbor)?;
296
297 let message_tx_with_network = MessageTxNetwork {
298 message_tx: MessageTxAPI::from(message),
299 testnet,
300 };
301
302 let parsed_message = MessageTxAPI::try_from(message_tx_with_network)?;
303
304 Ok(parsed_message)
305}
306
307fn transaction_sign_secp56k1_raw(
308 message: &Message,
309 private_key: &PrivateKey,
310) -> Result<Signature, SignerError> {
311 let secret_key = libsecp256k1::SecretKey::parse_slice(&private_key.0)?;
312 let message_ser = to_vec(message)?;
313 let hash = cid::multihash::Code::Blake2b256.digest(&message_ser);
314 let message_cid = cid::Cid::new_v1(DAG_CBOR, hash);
315 let message_digest =
316 libsecp256k1::Message::parse_slice(&utils::blake2b_256(&message_cid.to_bytes()))?;
317
318 let (signature_rs, recovery_id) = libsecp256k1::sign(&message_digest, &secret_key);
319
320 let mut sig = [0; 65];
321 sig[..64].copy_from_slice(&signature_rs.serialize().to_vec());
322 sig[64] = recovery_id.serialize();
323
324 let signature = Signature::new_secp256k1(sig.to_vec());
325
326 Ok(signature)
327}
328
329fn transaction_sign_bls_raw(
330 message: &Message,
331 private_key: &PrivateKey,
332) -> Result<Signature, SignerError> {
333 let sk = bls_signatures::PrivateKey::from_bytes(&private_key.0)?;
334 let message_ser = to_vec(message)?;
335 let hash = cid::multihash::Code::Blake2b256.digest(&message_ser);
336 let message_cid = cid::Cid::new_v1(DAG_CBOR, hash);
337 let sig = sk.sign(&message_cid.to_bytes());
338 let signature = Signature::new_bls(sig.as_bytes());
339
340 Ok(signature)
341}
342
343pub fn transaction_sign_raw(
351 message: &Message,
352 private_key: &PrivateKey,
353) -> Result<Signature, SignerError> {
354 let signature = match message.from.protocol() {
356 fvm_shared::address::Protocol::Secp256k1 => {
357 transaction_sign_secp56k1_raw(message, private_key)?
358 }
359 fvm_shared::address::Protocol::BLS => transaction_sign_bls_raw(message, private_key)?,
360 _ => {
361 return Err(SignerError::GenericString(
362 "Unknown signing protocol".to_string(),
363 ));
364 }
365 };
366
367 Ok(signature)
368}
369
370pub fn transaction_sign(
378 message: &Message,
379 private_key: &PrivateKey,
380) -> Result<SignedMessage, SignerError> {
381 let signature = transaction_sign_raw(message, private_key)?;
382
383 let signed_message = SignedMessage {
384 message: message.to_owned(),
385 signature,
386 };
387
388 Ok(signed_message)
389}
390
391fn verify_secp256k1_signature(signature: &Signature, cbor: &Vec<u8>) -> Result<bool, SignerError> {
392 let network = Network::Testnet;
393
394 let signature_rs = libsecp256k1::Signature::parse_standard_slice(&signature.bytes[..64])?;
395 let recovery_id = libsecp256k1::RecoveryId::parse(signature.bytes[64])?;
396
397 let tx = transaction_parse(cbor, network == Network::Testnet)?;
401
402 let message_digest = utils::get_digest(cbor.as_ref())?;
404
405 let blob_to_sign = libsecp256k1::Message::parse_slice(&message_digest)?;
406
407 let public_key = libsecp256k1::recover(&blob_to_sign, &signature_rs, &recovery_id)?;
408 let from = Address::new_secp256k1(public_key.serialize().as_ref())?;
409
410 let tx_from = match tx {
411 MessageTxAPI::Message(tx) => tx.from,
412 MessageTxAPI::SignedMessage(tx) => tx.message.from,
413 };
414 let expected_from = from.to_string();
415
416 if tx_from.to_string() != expected_from {
418 return Ok(false);
419 }
420
421 Ok(libsecp256k1::verify(
422 &blob_to_sign,
423 &signature_rs,
424 &public_key,
425 ))
426}
427
428fn verify_bls_signature(signature: &Signature, cbor: &Vec<u8>) -> Result<bool, SignerError> {
429 let message = transaction_parse(cbor, true)?;
431 let message = message.get_message();
432
433 let pk = bls_signatures::PublicKey::from_bytes(&message.from.payload_bytes())?;
434
435 let sig = bls_signatures::Signature::from_bytes(signature.bytes())?;
436
437 let message_ser = to_vec(&message)?;
438 let hash = cid::multihash::Code::Blake2b256.digest(&message_ser);
439 let message_cid = cid::Cid::new_v1(DAG_CBOR, hash);
440 let signing_bytes = message_cid.to_bytes();
441
442 let result = pk.verify(sig, signing_bytes);
443
444 Ok(result)
445}
446
447pub fn verify_signature(signature: &Signature, cbor: &Vec<u8>) -> Result<bool, SignerError> {
455 let result = match signature.sig_type {
457 SignatureType::Secp256k1 => verify_secp256k1_signature(signature, cbor)?,
458 SignatureType::BLS => verify_bls_signature(signature, cbor)?,
459 };
460
461 Ok(result)
462}
463
464fn extract_from_pub_key_from_message(
465 cbor_message: &Vec<u8>,
466) -> Result<bls_signatures::PublicKey, SignerError> {
467 let message = transaction_parse(cbor_message, true)?;
468 let unsigned_message_api = message.get_message();
469 let pk = bls_signatures::PublicKey::from_bytes(&unsigned_message_api.from.payload_bytes())?;
470
471 Ok(pk)
472}
473
474fn extract_bls_signing_bytes_from_message(cbor_message: &Vec<u8>) -> Result<Vec<u8>, SignerError> {
475 let message = transaction_parse(cbor_message, true)?;
476 let unsigned_message_api = message.get_message();
477
478 let message_ser = to_vec(&unsigned_message_api)?;
479 let hash = cid::multihash::Code::Blake2b256.digest(&message_ser);
480 let message_cid = cid::Cid::new_v1(DAG_CBOR, hash);
481 Ok(message_cid.to_bytes())
482}
483
484pub fn verify_aggregated_signature(
485 signature: &Signature,
486 cbor_messages: &[Vec<u8>],
487) -> Result<bool, SignerError> {
488 let sig = bls_signatures::Signature::from_bytes(signature.bytes())?;
489
490 let tmp: Result<Vec<_>, SignerError> = cbor_messages
492 .iter()
493 .map(extract_from_pub_key_from_message)
494 .collect();
495
496 let pks = match tmp {
497 Ok(public_keys) => public_keys,
498 Err(_) => {
499 return Err(SignerError::GenericString(
500 "Invalid public key extracted from message".to_string(),
501 ));
502 }
503 };
504
505 let tmp: Result<Vec<_>, SignerError> = cbor_messages
507 .iter()
508 .map(extract_bls_signing_bytes_from_message)
509 .collect();
510
511 let signing_bytes = match tmp {
512 Ok(bytes) => bytes,
513 Err(_) => {
514 return Err(SignerError::GenericString(
515 "An invalid message was provided".to_string(),
516 ));
517 }
518 };
519
520 let hashes = signing_bytes
521 .par_iter()
522 .map(|signing_bytes| bls_signatures::hash(signing_bytes.as_ref()))
523 .collect::<Vec<_>>();
524
525 Ok(bls_signatures::verify(&sig, &hashes, pks.as_slice()))
526}
527
528pub fn serialize_params(params: MessageParams) -> Result<Vec<u8>, SignerError> {
535 let serialized_params = params.serialize()?;
536 let message_cbor = serialized_params.bytes().to_vec();
537 Ok(message_cbor)
538}
539
540pub fn sign_voucher(
548 voucher_string: String,
549 private_key: &PrivateKey,
550) -> Result<String, SignerError> {
551 let decoded_voucher = base64::decode(voucher_string)?;
552 let mut voucher: paych::SignedVoucher = from_slice(&decoded_voucher)?;
553
554 let secret_key = libsecp256k1::SecretKey::parse_slice(&private_key.0)?;
555
556 let svb = voucher
557 .signing_bytes()
558 .map_err(|err| SignerError::GenericString(err.to_string()))?;
559 let digest = utils::get_digest_voucher(&svb)?;
560
561 let blob_to_sign = libsecp256k1::Message::parse_slice(&digest)?;
562
563 let (signature_rs, recovery_id) = libsecp256k1::sign(&blob_to_sign, &secret_key);
564
565 let mut sig = [0; 65];
566 sig[..64].copy_from_slice(&signature_rs.serialize()[..]);
567 sig[64] = recovery_id.serialize();
568
569 voucher.signature = Some(Signature::new_secp256k1(sig.to_vec()));
570
571 let binary_voucher = to_vec(&voucher)?;
572 let cbor_voucher = base64::encode(binary_voucher);
573
574 Ok(cbor_voucher)
575}
576
577pub fn create_voucher(
589 payment_channel_address: String,
590 time_lock_min: i64,
591 time_lock_max: i64,
592 amount: String,
593 lane: u64,
594 nonce: u64,
595 min_settle_height: i64,
596) -> Result<String, SignerError> {
597 let network: Network;
598 if payment_channel_address.starts_with("f") {
599 network = Network::Mainnet;
600 } else {
601 network = Network::Testnet;
602 }
603
604 let pch = network.parse_address(&payment_channel_address)?;
605 let amount = match fvm_shared::bigint::BigInt::parse_bytes(amount.as_bytes(), 10) {
606 Some(value) => value,
607 None => {
608 return Err(SignerError::GenericString(
609 "`amount` couldn't be parsed.".to_string(),
610 ));
611 }
612 };
613
614 let voucher = paych::SignedVoucher {
615 channel_addr: pch,
616 time_lock_min,
617 time_lock_max,
618 secret_pre_image: Vec::new(),
619 extra: None,
620 lane,
621 nonce,
622 amount: TokenAmount::from_atto(amount),
623 min_settle_height,
624 merges: Vec::new(),
625 signature: None,
626 };
627
628 let cbor_voucher = base64::encode(to_vec(&voucher)?);
629
630 Ok(cbor_voucher)
631}
632
633pub fn deserialize_params(
641 params_b64_string: String,
642 actor_type: String,
643 method: u64,
644) -> Result<MessageParams, SignerError> {
645 let params_decode = base64::decode(params_b64_string)?;
646 let serialized_params = RawBytes::new(params_decode);
647
648 if actor_type.as_str() == "init" {
650 match FromPrimitive::from_u64(method) {
651 Some(MethodInit::Exec) => {
652 let params: ExecParams = RawBytes::deserialize(&serialized_params)?;
653 return Ok(MessageParams::ExecParams(params));
654 }
655 _ => {
656 return Err(SignerError::GenericString(
657 "Unknown method for init actor.".to_string(),
658 ));
659 }
660 }
661 }
662
663 if actor_type.as_str() == "multisig" {
665 match FromPrimitive::from_u64(method) {
666 Some(multisig::Method::Propose) => {
667 let params = serialized_params.deserialize::<multisig::ProposeParams>()?;
668
669 return Ok(MessageParams::ProposeParams(params));
670 }
671 Some(multisig::Method::Approve) | Some(multisig::Method::Cancel) => {
672 let params = serialized_params.deserialize::<multisig::TxnIDParams>()?;
673
674 return Ok(MessageParams::TxnIDParams(params));
675 }
676 Some(multisig::Method::AddSigner) => {
677 let params = serialized_params.deserialize::<multisig::AddSignerParams>()?;
678
679 return Ok(MessageParams::AddSignerParams(params));
680 }
681 Some(multisig::Method::RemoveSigner) => {
682 let params = serialized_params.deserialize::<multisig::RemoveSignerParams>()?;
683
684 return Ok(MessageParams::RemoveSignerParams(params));
685 }
686 Some(multisig::Method::SwapSigner) => {
687 let params = serialized_params.deserialize::<multisig::SwapSignerParams>()?;
688
689 return Ok(MessageParams::SwapSignerParams(params));
690 }
691 Some(multisig::Method::ChangeNumApprovalsThreshold) => {
692 let params = serialized_params
693 .deserialize::<multisig::ChangeNumApprovalsThresholdParams>()?;
694
695 return Ok(MessageParams::ChangeNumApprovalsThresholdParams(params));
696 }
697 Some(multisig::Method::LockBalance) => {
698 let params = serialized_params.deserialize::<multisig::LockBalanceParams>()?;
699
700 return Ok(MessageParams::LockBalanceParams(params));
701 }
702 _ => {
703 return Err(SignerError::GenericString(
704 "Unknown method for multisig actor.".to_string(),
705 ));
706 }
707 }
708 }
709
710 if actor_type.as_str() == "paymentchannel" {
712 match FromPrimitive::from_u64(method) {
713 Some(paych::Method::UpdateChannelState) => {
714 let params: fil_actor_paych::UpdateChannelStateParams =
715 RawBytes::deserialize(&serialized_params)?;
716
717 return Ok(MessageParams::UpdateChannelStateParams(params));
718 }
719 Some(paych::Method::Settle) | Some(paych::Method::Collect) => {
720 return Ok(MessageParams::MessageParamsSerialized("".to_string()));
722 }
723 _ => {
724 return Err(SignerError::GenericString(
725 "Unknown method for paymentchannel actor.".to_string(),
726 ));
727 }
728 }
729 }
730
731 Err(SignerError::GenericString(
732 "Actor type not supported.".to_string(),
733 ))
734}
735
736pub fn deserialize_constructor_params(
743 params_b64_string: String,
744 code_cid: String,
745) -> Result<MessageParams, SignerError> {
746 let params_decode = base64::decode(params_b64_string)?;
747 let serialized_params = RawBytes::new(params_decode);
748
749 if code_cid.as_str() == "multisig" {
750 let params = serialized_params.deserialize::<multisig::ConstructorParams>()?;
751 return Ok(MessageParams::MultisigConstructorParams(params));
752 }
753
754 if code_cid.as_str() == "paymentchannel" {
755 let params = serialized_params.deserialize::<paych::ConstructorParams>()?;
756 return Ok(MessageParams::PaychConstructorParams(params.into()));
757 }
758
759 if code_cid.as_str() == "fil/1/multisig" {
760 let deprecated_multisig_params = serialized_params.deserialize::<ConstructorParamsV1>()?;
761 let params = multisig::ConstructorParams {
762 signers: deprecated_multisig_params.signers,
763 num_approvals_threshold: deprecated_multisig_params.num_approvals_threshold,
764 unlock_duration: deprecated_multisig_params.unlock_duration,
765 start_epoch: 0,
766 };
767 return Ok(MessageParams::MultisigConstructorParams(params));
768 }
769
770 Err(SignerError::GenericString(
771 "Code CID not supported.".to_string(),
772 ))
773}
774
775pub fn verify_voucher_signature(
782 voucher_base64_string: String,
783 address_signer: String,
784) -> Result<bool, SignerError> {
785 let decoded_voucher = base64::decode(voucher_base64_string)?;
786 let signed_voucher: paych::SignedVoucher = from_slice(&decoded_voucher)?;
787
788 let network: Network;
789 if address_signer.starts_with("f") {
790 network = Network::Mainnet;
791 } else {
792 network = Network::Testnet;
793 }
794 let address = network.parse_address(&address_signer)?;
795
796 let sv_bytes = signed_voucher
797 .signing_bytes()
798 .map_err(|err| SignerError::GenericString(err.to_string()))?;
799 let digest = utils::get_digest_voucher(&sv_bytes)?;
800
801 match &signed_voucher.signature {
802 Some(signature) => match address.protocol() {
803 Protocol::Secp256k1 => {
804 let sig = libsecp256k1::Signature::parse_standard_slice(&signature.bytes()[..64])?;
805 let recovery_id = libsecp256k1::RecoveryId::parse(signature.bytes()[64])?;
806 let message = libsecp256k1::Message::parse(&digest);
807 let public_key = libsecp256k1::recover(&message, &sig, &recovery_id)?;
808 let signer = Address::new_secp256k1(public_key.serialize().as_ref())?;
809
810 if signer.to_string() != address.to_string() {
811 Err(SignerError::GenericString(
812 "Address recovered doesn't match address given".to_string(),
813 ))
814 } else {
815 Ok(libsecp256k1::verify(&message, &sig, &public_key))
816 }
817 }
818 Protocol::BLS => {
819 let pk = bls_signatures::PublicKey::from_bytes(&address.payload_bytes())?;
820 let sig = bls_signatures::Signature::from_bytes(signature.bytes())?;
821
822 Ok(pk.verify(sig, digest))
823 }
824 _ => Err(SignerError::GenericString(
825 "Address should BLS or Secp256k1.".to_string(),
826 )),
827 },
828 None => Err(SignerError::GenericString(
829 "Voucher not signed.".to_string(),
830 )),
831 }
832}
833
834pub fn serialize_voucher(voucher: SignedVoucherWrapper) -> Result<String, SignerError> {
840 let serialized_voucher = to_vec(&voucher)?;
841
842 Ok(base64::encode(serialized_voucher))
843}
844
845pub fn deserialize_voucher(
851 voucher_base64_string: String,
852) -> Result<SignedVoucherWrapper, SignerError> {
853 let serialized_voucher = base64::decode(&voucher_base64_string)?;
854
855 let signed_voucher: paych::SignedVoucher = from_slice(&serialized_voucher)?;
856
857 Ok(SignedVoucherWrapper(signed_voucher))
858}
859
860pub fn compute_proposal_hash(
866 proposal_hash_data: ProposalHashDataAPI,
867) -> Result<String, SignerError> {
868 let proposal_data = multisig::ProposalHashData {
869 requester: proposal_hash_data.requester.as_ref(),
870 to: &proposal_hash_data.to,
871 value: &proposal_hash_data.value,
872 method: &proposal_hash_data.method,
873 params: &proposal_hash_data.params,
874 };
875
876 let serialize_proposal_data = RawBytes::serialize(proposal_data)
877 .map_err(|err| SignerError::GenericString(err.to_string()))?;
878 let proposal_hash = utils::blake2b_256(&serialize_proposal_data);
879
880 Ok(base64::encode(proposal_hash))
881}
882
883pub fn get_cid(message_api: MessageTxAPI) -> Result<String, SignerError> {
889 match message_api {
890 MessageTxAPI::Message(message) => {
891 let message_ser = to_vec(&message)?;
892 let hash = cid::multihash::Code::Blake2b256.digest(&message_ser);
893 let message_cid = cid::Cid::new_v1(DAG_CBOR, hash);
894
895 Ok(message_cid.to_string())
896 }
897 MessageTxAPI::SignedMessage(signed_message) => {
898 let message_ser = to_vec(&signed_message)?;
899 let hash = cid::multihash::Code::Blake2b256.digest(&message_ser);
900 let message_cid = cid::Cid::new_v1(DAG_CBOR, hash);
901
902 Ok(message_cid.to_string())
903 }
904 }
905}