1use serde::de::DeserializeOwned;
2#[cfg(feature = "stargate")]
3use serde::Serialize;
4use std::collections::HashMap;
5
6use crate::addresses::{Addr, CanonicalAddr};
7use crate::binary::Binary;
8use crate::coins::Coin;
9use crate::deps::OwnedDeps;
10use crate::errors::{RecoverPubkeyError, StdError, StdResult, SystemError, VerificationError};
11#[cfg(feature = "stargate")]
12use crate::ibc::{
13 IbcAcknowledgement, IbcChannel, IbcChannelCloseMsg, IbcChannelConnectMsg, IbcChannelOpenMsg,
14 IbcEndpoint, IbcOrder, IbcPacket, IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg,
15 IbcTimeoutBlock,
16};
17use crate::query::{
18 AllBalanceResponse, BalanceResponse, BankQuery, CustomQuery, QueryRequest, WasmQuery,
19};
20#[cfg(feature = "staking")]
21use crate::query::{
22 AllDelegationsResponse, AllValidatorsResponse, BondedDenomResponse, DelegationResponse,
23 FullDelegation, StakingQuery, Validator, ValidatorResponse,
24};
25use crate::results::{ContractResult, Empty, SystemResult};
26use crate::serde::{from_slice, to_binary};
27use crate::storage::MemoryStorage;
28use crate::timestamp::Timestamp;
29use crate::traits::{Api, Querier, QuerierResult};
30use crate::types::{BlockInfo, ContractInfo, Env, MessageInfo};
31use crate::Attribute;
32
33pub const MOCK_CONTRACT_ADDR: &str = "cosmos2contract";
34
35pub fn mock_dependencies(
38 contract_balance: &[Coin],
39) -> OwnedDeps<MockStorage, MockApi, MockQuerier> {
40 OwnedDeps {
41 storage: MockStorage::default(),
42 api: MockApi::default(),
43 querier: MockQuerier::new(&[(MOCK_CONTRACT_ADDR, contract_balance)]),
44 }
45}
46
47pub fn mock_dependencies_with_balances(
50 balances: &[(&str, &[Coin])],
51) -> OwnedDeps<MockStorage, MockApi, MockQuerier> {
52 OwnedDeps {
53 storage: MockStorage::default(),
54 api: MockApi::default(),
55 querier: MockQuerier::new(balances),
56 }
57}
58
59pub type MockStorage = MemoryStorage;
62
63const CANONICAL_LENGTH: usize = 54;
67
68const SHUFFLES_ENCODE: usize = 18;
69const SHUFFLES_DECODE: usize = 2;
70
71#[derive(Copy, Clone)]
75pub struct MockApi {
76 canonical_length: usize,
79}
80
81impl Default for MockApi {
82 fn default() -> Self {
83 MockApi {
84 canonical_length: CANONICAL_LENGTH,
85 }
86 }
87}
88
89impl Api for MockApi {
90 fn addr_validate(&self, human: &str) -> StdResult<Addr> {
91 self.addr_canonicalize(human).map(|_canonical| ())?;
92 Ok(Addr::unchecked(human))
93 }
94
95 fn addr_canonicalize(&self, human: &str) -> StdResult<CanonicalAddr> {
96 if human.len() < 3 {
98 return Err(StdError::generic_err(
99 "Invalid input: human address too short",
100 ));
101 }
102 if human.len() > self.canonical_length {
103 return Err(StdError::generic_err(
104 "Invalid input: human address too long",
105 ));
106 }
107
108 let mut out = Vec::from(human);
109
110 out.resize(self.canonical_length, 0x00);
112 let rotate_by = digit_sum(&out) % self.canonical_length;
115 out.rotate_left(rotate_by);
116 for _ in 0..SHUFFLES_ENCODE {
117 out = riffle_shuffle(&out);
118 }
119 Ok(out.into())
120 }
121
122 fn addr_humanize(&self, canonical: &CanonicalAddr) -> StdResult<Addr> {
123 if canonical.len() != self.canonical_length {
124 return Err(StdError::generic_err(
125 "Invalid input: canonical address length not correct",
126 ));
127 }
128
129 let mut tmp: Vec<u8> = canonical.clone().into();
130 for _ in 0..SHUFFLES_DECODE {
132 tmp = riffle_shuffle(&tmp);
133 }
134 let rotate_by = digit_sum(&tmp) % self.canonical_length;
136 tmp.rotate_right(rotate_by);
137 let trimmed = tmp.into_iter().filter(|&x| x != 0x00).collect();
139 let human = String::from_utf8(trimmed)?;
141 Ok(Addr::unchecked(human))
142 }
143
144 fn secp256k1_verify(
145 &self,
146 message_hash: &[u8],
147 signature: &[u8],
148 public_key: &[u8],
149 ) -> Result<bool, VerificationError> {
150 Ok(cosmwasm_crypto::secp256k1_verify(
151 message_hash,
152 signature,
153 public_key,
154 )?)
155 }
156
157 fn secp256k1_recover_pubkey(
158 &self,
159 message_hash: &[u8],
160 signature: &[u8],
161 recovery_param: u8,
162 ) -> Result<Vec<u8>, RecoverPubkeyError> {
163 let pubkey =
164 cosmwasm_crypto::secp256k1_recover_pubkey(message_hash, signature, recovery_param)?;
165 Ok(pubkey.to_vec())
166 }
167
168 fn ed25519_verify(
169 &self,
170 message: &[u8],
171 signature: &[u8],
172 public_key: &[u8],
173 ) -> Result<bool, VerificationError> {
174 Ok(cosmwasm_crypto::ed25519_verify(
175 message, signature, public_key,
176 )?)
177 }
178
179 fn ed25519_batch_verify(
180 &self,
181 messages: &[&[u8]],
182 signatures: &[&[u8]],
183 public_keys: &[&[u8]],
184 ) -> Result<bool, VerificationError> {
185 Ok(cosmwasm_crypto::ed25519_batch_verify(
186 messages,
187 signatures,
188 public_keys,
189 )?)
190 }
191
192 fn debug(&self, message: &str) {
193 println!("{}", message);
194 }
195}
196
197pub fn mock_env() -> Env {
203 Env {
204 block: BlockInfo {
205 height: 12_345,
206 time: Timestamp::from_nanos(1_571_797_419_879_305_533),
207 chain_id: "cosmos-testnet-14002".to_string(),
208 },
209 contract: ContractInfo {
210 address: Addr::unchecked(MOCK_CONTRACT_ADDR),
211 },
212 }
213}
214
215pub fn mock_info(sender: &str, funds: &[Coin]) -> MessageInfo {
218 MessageInfo {
219 sender: Addr::unchecked(sender),
220 funds: funds.to_vec(),
221 }
222}
223
224#[cfg(feature = "stargate")]
227pub fn mock_ibc_channel(my_channel_id: &str, order: IbcOrder, version: &str) -> IbcChannel {
228 IbcChannel {
229 endpoint: IbcEndpoint {
230 port_id: "my_port".to_string(),
231 channel_id: my_channel_id.to_string(),
232 },
233 counterparty_endpoint: IbcEndpoint {
234 port_id: "their_port".to_string(),
235 channel_id: "channel-7".to_string(),
236 },
237 order,
238 version: version.to_string(),
239 connection_id: "connection-2".to_string(),
240 }
241}
242
243#[cfg(feature = "stargate")]
245pub fn mock_ibc_channel_open_init(
246 my_channel_id: &str,
247 order: IbcOrder,
248 version: &str,
249) -> IbcChannelOpenMsg {
250 IbcChannelOpenMsg::new_init(mock_ibc_channel(my_channel_id, order, version))
251}
252
253#[cfg(feature = "stargate")]
255pub fn mock_ibc_channel_open_try(
256 my_channel_id: &str,
257 order: IbcOrder,
258 version: &str,
259) -> IbcChannelOpenMsg {
260 IbcChannelOpenMsg::new_try(mock_ibc_channel(my_channel_id, order, version), version)
261}
262
263#[cfg(feature = "stargate")]
265pub fn mock_ibc_channel_connect_ack(
266 my_channel_id: &str,
267 order: IbcOrder,
268 version: &str,
269) -> IbcChannelConnectMsg {
270 IbcChannelConnectMsg::new_ack(mock_ibc_channel(my_channel_id, order, version), version)
271}
272
273#[cfg(feature = "stargate")]
275pub fn mock_ibc_channel_connect_confirm(
276 my_channel_id: &str,
277 order: IbcOrder,
278 version: &str,
279) -> IbcChannelConnectMsg {
280 IbcChannelConnectMsg::new_confirm(mock_ibc_channel(my_channel_id, order, version))
281}
282
283#[cfg(feature = "stargate")]
285pub fn mock_ibc_channel_close_init(
286 my_channel_id: &str,
287 order: IbcOrder,
288 version: &str,
289) -> IbcChannelCloseMsg {
290 IbcChannelCloseMsg::new_init(mock_ibc_channel(my_channel_id, order, version))
291}
292
293#[cfg(feature = "stargate")]
295pub fn mock_ibc_channel_close_confirm(
296 my_channel_id: &str,
297 order: IbcOrder,
298 version: &str,
299) -> IbcChannelCloseMsg {
300 IbcChannelCloseMsg::new_confirm(mock_ibc_channel(my_channel_id, order, version))
301}
302
303#[cfg(feature = "stargate")]
306pub fn mock_ibc_packet_recv(
307 my_channel_id: &str,
308 data: &impl Serialize,
309) -> StdResult<IbcPacketReceiveMsg> {
310 Ok(IbcPacketReceiveMsg::new(IbcPacket {
311 data: to_binary(data)?,
312 src: IbcEndpoint {
313 port_id: "their-port".to_string(),
314 channel_id: "channel-1234".to_string(),
315 },
316 dest: IbcEndpoint {
317 port_id: "our-port".to_string(),
318 channel_id: my_channel_id.into(),
319 },
320 sequence: 27,
321 timeout: IbcTimeoutBlock {
322 revision: 1,
323 height: 12345678,
324 }
325 .into(),
326 }))
327}
328
329#[cfg(feature = "stargate")]
333fn mock_ibc_packet(my_channel_id: &str, data: &impl Serialize) -> StdResult<IbcPacket> {
334 Ok(IbcPacket {
335 data: to_binary(data)?,
336 src: IbcEndpoint {
337 port_id: "their-port".to_string(),
338 channel_id: my_channel_id.into(),
339 },
340 dest: IbcEndpoint {
341 port_id: "our-port".to_string(),
342 channel_id: "channel-1234".to_string(),
343 },
344 sequence: 29,
345 timeout: IbcTimeoutBlock {
346 revision: 1,
347 height: 432332552,
348 }
349 .into(),
350 })
351}
352
353#[cfg(feature = "stargate")]
357pub fn mock_ibc_packet_ack(
358 my_channel_id: &str,
359 data: &impl Serialize,
360 ack: IbcAcknowledgement,
361) -> StdResult<IbcPacketAckMsg> {
362 let packet = mock_ibc_packet(my_channel_id, data)?;
363
364 Ok(IbcPacketAckMsg::new(ack, packet))
365}
366
367#[cfg(feature = "stargate")]
371pub fn mock_ibc_packet_timeout(
372 my_channel_id: &str,
373 data: &impl Serialize,
374) -> StdResult<IbcPacketTimeoutMsg> {
375 mock_ibc_packet(my_channel_id, data).map(IbcPacketTimeoutMsg::new)
376}
377
378pub type MockQuerierCustomHandlerResult = SystemResult<ContractResult<Binary>>;
381
382pub struct MockQuerier<C: DeserializeOwned = Empty> {
385 bank: BankQuerier,
386 #[cfg(feature = "staking")]
387 staking: StakingQuerier,
388 wasm: NoWasmQuerier,
390 custom_handler: Box<dyn for<'a> Fn(&'a C) -> MockQuerierCustomHandlerResult>,
395}
396
397impl<C: DeserializeOwned> MockQuerier<C> {
398 pub fn new(balances: &[(&str, &[Coin])]) -> Self {
399 MockQuerier {
400 bank: BankQuerier::new(balances),
401 #[cfg(feature = "staking")]
402 staking: StakingQuerier::default(),
403 wasm: NoWasmQuerier {},
404 custom_handler: Box::from(|_: &_| -> MockQuerierCustomHandlerResult {
406 SystemResult::Err(SystemError::UnsupportedRequest {
407 kind: "custom".to_string(),
408 })
409 }),
410 }
411 }
412
413 pub fn update_balance(
415 &mut self,
416 addr: impl Into<String>,
417 balance: Vec<Coin>,
418 ) -> Option<Vec<Coin>> {
419 self.bank.balances.insert(addr.into(), balance)
420 }
421
422 #[cfg(feature = "staking")]
423 pub fn update_staking(
424 &mut self,
425 denom: &str,
426 validators: &[crate::query::Validator],
427 delegations: &[crate::query::FullDelegation],
428 ) {
429 self.staking = StakingQuerier::new(denom, validators, delegations);
430 }
431
432 pub fn with_custom_handler<CH: 'static>(mut self, handler: CH) -> Self
433 where
434 CH: Fn(&C) -> MockQuerierCustomHandlerResult,
435 {
436 self.custom_handler = Box::from(handler);
437 self
438 }
439}
440
441impl<C: CustomQuery + DeserializeOwned> Querier for MockQuerier<C> {
442 fn raw_query(&self, bin_request: &[u8]) -> QuerierResult {
443 let request: QueryRequest<C> = match from_slice(bin_request) {
444 Ok(v) => v,
445 Err(e) => {
446 return SystemResult::Err(SystemError::InvalidRequest {
447 error: format!("Parsing query request: {}", e),
448 request: bin_request.into(),
449 })
450 }
451 };
452 self.handle_query(&request)
453 }
454}
455
456impl<C: CustomQuery + DeserializeOwned> MockQuerier<C> {
457 pub fn handle_query(&self, request: &QueryRequest<C>) -> QuerierResult {
458 match &request {
459 QueryRequest::Bank(bank_query) => self.bank.query(bank_query),
460 QueryRequest::Custom(custom_query) => (*self.custom_handler)(custom_query),
461 #[cfg(feature = "staking")]
462 QueryRequest::Staking(staking_query) => self.staking.query(staking_query),
463 QueryRequest::Wasm(msg) => self.wasm.query(msg),
464 #[cfg(feature = "stargate")]
465 QueryRequest::Stargate { .. } => SystemResult::Err(SystemError::UnsupportedRequest {
466 kind: "Stargate".to_string(),
467 }),
468 #[cfg(feature = "stargate")]
469 QueryRequest::Ibc(_) => SystemResult::Err(SystemError::UnsupportedRequest {
470 kind: "Ibc".to_string(),
471 }),
472 }
473 }
474}
475
476#[derive(Clone, Default)]
477struct NoWasmQuerier {
478 }
480
481impl NoWasmQuerier {
482 fn query(&self, request: &WasmQuery) -> QuerierResult {
483 let addr = match request {
484 WasmQuery::Smart { contract_addr, .. } => contract_addr,
485 WasmQuery::Raw { contract_addr, .. } => contract_addr,
486 }
487 .clone();
488 SystemResult::Err(SystemError::NoSuchContract { addr })
489 }
490}
491
492#[derive(Clone, Default)]
493pub struct BankQuerier {
494 balances: HashMap<String, Vec<Coin>>,
495}
496
497impl BankQuerier {
498 pub fn new(balances: &[(&str, &[Coin])]) -> Self {
499 let mut map = HashMap::new();
500 for (addr, coins) in balances.iter() {
501 map.insert(addr.to_string(), coins.to_vec());
502 }
503 BankQuerier { balances: map }
504 }
505
506 pub fn query(&self, request: &BankQuery) -> QuerierResult {
507 let contract_result: ContractResult<Binary> = match request {
508 BankQuery::Balance { address, denom } => {
509 let amount = self
511 .balances
512 .get(address)
513 .and_then(|v| v.iter().find(|c| &c.denom == denom).map(|c| c.amount))
514 .unwrap_or_default();
515 let bank_res = BalanceResponse {
516 amount: Coin {
517 amount,
518 denom: denom.to_string(),
519 },
520 };
521 to_binary(&bank_res).into()
522 }
523 BankQuery::AllBalances { address } => {
524 let bank_res = AllBalanceResponse {
526 amount: self.balances.get(address).cloned().unwrap_or_default(),
527 };
528 to_binary(&bank_res).into()
529 }
530 };
531 SystemResult::Ok(contract_result)
533 }
534}
535
536#[cfg(feature = "staking")]
537#[derive(Clone, Default)]
538pub struct StakingQuerier {
539 denom: String,
540 validators: Vec<Validator>,
541 delegations: Vec<FullDelegation>,
542}
543
544#[cfg(feature = "staking")]
545impl StakingQuerier {
546 pub fn new(denom: &str, validators: &[Validator], delegations: &[FullDelegation]) -> Self {
547 StakingQuerier {
548 denom: denom.to_string(),
549 validators: validators.to_vec(),
550 delegations: delegations.to_vec(),
551 }
552 }
553
554 pub fn query(&self, request: &StakingQuery) -> QuerierResult {
555 let contract_result: ContractResult<Binary> = match request {
556 StakingQuery::BondedDenom {} => {
557 let res = BondedDenomResponse {
558 denom: self.denom.clone(),
559 };
560 to_binary(&res).into()
561 }
562 StakingQuery::AllValidators {} => {
563 let res = AllValidatorsResponse {
564 validators: self.validators.clone(),
565 };
566 to_binary(&res).into()
567 }
568 StakingQuery::Validator { address } => {
569 let validator: Option<Validator> = self
570 .validators
571 .iter()
572 .find(|validator| validator.address == *address)
573 .cloned();
574 let res = ValidatorResponse { validator };
575 to_binary(&res).into()
576 }
577 StakingQuery::AllDelegations { delegator } => {
578 let delegations: Vec<_> = self
579 .delegations
580 .iter()
581 .filter(|d| d.delegator.as_str() == delegator)
582 .cloned()
583 .map(|d| d.into())
584 .collect();
585 let res = AllDelegationsResponse { delegations };
586 to_binary(&res).into()
587 }
588 StakingQuery::Delegation {
589 delegator,
590 validator,
591 } => {
592 let delegation = self
593 .delegations
594 .iter()
595 .find(|d| d.delegator.as_str() == delegator && d.validator == *validator);
596 let res = DelegationResponse {
597 delegation: delegation.cloned(),
598 };
599 to_binary(&res).into()
600 }
601 };
602 SystemResult::Ok(contract_result)
604 }
605}
606
607pub fn riffle_shuffle<T: Clone>(input: &[T]) -> Vec<T> {
655 assert!(
656 input.len() % 2 == 0,
657 "Method only defined for even number of elements"
658 );
659 let mid = input.len() / 2;
660 let (left, right) = input.split_at(mid);
661 let mut out = Vec::<T>::with_capacity(input.len());
662 for i in 0..mid {
663 out.push(right[i].clone());
664 out.push(left[i].clone());
665 }
666 out
667}
668
669pub fn digit_sum(input: &[u8]) -> usize {
670 input.iter().fold(0, |sum, val| sum + (*val as usize))
671}
672
673pub fn mock_wasmd_attr(key: impl Into<String>, value: impl Into<String>) -> Attribute {
676 Attribute {
677 key: key.into(),
678 value: value.into(),
679 }
680}
681
682#[cfg(test)]
683mod tests {
684 use super::*;
685 use crate::{coin, coins, from_binary};
686 #[cfg(feature = "staking")]
687 use crate::{Decimal, Delegation};
688 use hex_literal::hex;
689
690 const SECP256K1_MSG_HASH_HEX: &str =
691 "5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0";
692 const SECP256K1_SIG_HEX: &str = "207082eb2c3dfa0b454e0906051270ba4074ac93760ba9e7110cd9471475111151eb0dbbc9920e72146fb564f99d039802bf6ef2561446eb126ef364d21ee9c4";
693 const SECP256K1_PUBKEY_HEX: &str = "04051c1ee2190ecfb174bfe4f90763f2b4ff7517b70a2aec1876ebcfd644c4633fb03f3cfbd94b1f376e34592d9d41ccaf640bb751b00a1fadeb0c01157769eb73";
694
695 const ED25519_MSG_HEX: &str = "72";
696 const ED25519_SIG_HEX: &str = "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00";
697 const ED25519_PUBKEY_HEX: &str =
698 "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c";
699
700 #[test]
701 fn mock_info_works() {
702 let info = mock_info("my name", &coins(100, "atom"));
703 assert_eq!(
704 info,
705 MessageInfo {
706 sender: Addr::unchecked("my name"),
707 funds: vec![Coin {
708 amount: 100u128.into(),
709 denom: "atom".into(),
710 }]
711 }
712 );
713 }
714
715 #[test]
716 fn canonicalize_and_humanize_restores_original() {
717 let api = MockApi::default();
718
719 let original = String::from("shorty");
720 let canonical = api.addr_canonicalize(&original).unwrap();
721 let recovered = api.addr_humanize(&canonical).unwrap();
722 assert_eq!(recovered, original);
723 }
724
725 #[test]
726 #[should_panic(expected = "address too short")]
727 fn addr_canonicalize_min_input_length() {
728 let api = MockApi::default();
729 let human = String::from("1");
730 let _ = api.addr_canonicalize(&human).unwrap();
731 }
732
733 #[test]
734 #[should_panic(expected = "address too long")]
735 fn addr_canonicalize_max_input_length() {
736 let api = MockApi::default();
737 let human =
738 String::from("some-extremely-long-address-not-supported-by-this-api-longer-than-54");
739 let _ = api.addr_canonicalize(&human).unwrap();
740 }
741
742 #[test]
743 fn addr_canonicalize_works_with_string_inputs() {
744 let api = MockApi::default();
745
746 let input = String::from("foobar123");
747 api.addr_canonicalize(&input).unwrap();
748
749 let input = "foobar456";
750 api.addr_canonicalize(input).unwrap();
751 }
752
753 #[test]
754 #[should_panic(expected = "length not correct")]
755 fn addr_humanize_input_length() {
756 let api = MockApi::default();
757 let input = CanonicalAddr(Binary(vec![61; 11]));
758 api.addr_humanize(&input).unwrap();
759 }
760
761 #[test]
763 fn secp256k1_verify_works() {
764 let api = MockApi::default();
765
766 let hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
767 let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
768 let public_key = hex::decode(SECP256K1_PUBKEY_HEX).unwrap();
769
770 assert!(api
771 .secp256k1_verify(&hash, &signature, &public_key)
772 .unwrap());
773 }
774
775 #[test]
777 fn secp256k1_verify_fails() {
778 let api = MockApi::default();
779
780 let mut hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
781 hash[0] ^= 0x01;
783 let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
784 let public_key = hex::decode(SECP256K1_PUBKEY_HEX).unwrap();
785
786 assert!(!api
787 .secp256k1_verify(&hash, &signature, &public_key)
788 .unwrap());
789 }
790
791 #[test]
793 fn secp256k1_verify_errs() {
794 let api = MockApi::default();
795
796 let hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
797 let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
798 let public_key = vec![];
799
800 let res = api.secp256k1_verify(&hash, &signature, &public_key);
801 assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
802 }
803
804 #[test]
805 fn secp256k1_recover_pubkey_works() {
806 let api = MockApi::default();
807
808 let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
810 let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
811 let recovery_param = 1;
812 let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
813
814 let pubkey = api
815 .secp256k1_recover_pubkey(&hash, &signature, recovery_param)
816 .unwrap();
817 assert_eq!(pubkey, expected);
818 }
819
820 #[test]
821 fn secp256k1_recover_pubkey_fails_for_wrong_recovery_param() {
822 let api = MockApi::default();
823
824 let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
826 let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
827 let _recovery_param = 1;
828 let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
829
830 let pubkey = api.secp256k1_recover_pubkey(&hash, &signature, 0).unwrap();
832 assert_eq!(pubkey.len(), 65);
833 assert_ne!(pubkey, expected);
834
835 let result = api.secp256k1_recover_pubkey(&hash, &signature, 42);
837 match result.unwrap_err() {
838 RecoverPubkeyError::InvalidRecoveryParam => {}
839 err => panic!("Unexpected error: {:?}", err),
840 }
841 }
842
843 #[test]
844 fn secp256k1_recover_pubkey_fails_for_wrong_hash() {
845 let api = MockApi::default();
846
847 let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
849 let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
850 let recovery_param = 1;
851 let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
852
853 let mut corrupted_hash = hash;
855 corrupted_hash[0] ^= 0x01;
856 let pubkey = api
857 .secp256k1_recover_pubkey(&corrupted_hash, &signature, recovery_param)
858 .unwrap();
859 assert_eq!(pubkey.len(), 65);
860 assert_ne!(pubkey, expected);
861
862 let mut malformed_hash = hash.to_vec();
864 malformed_hash.push(0x8a);
865 let result = api.secp256k1_recover_pubkey(&malformed_hash, &signature, recovery_param);
866 match result.unwrap_err() {
867 RecoverPubkeyError::InvalidHashFormat => {}
868 err => panic!("Unexpected error: {:?}", err),
869 }
870 }
871
872 #[test]
874 fn ed25519_verify_works() {
875 let api = MockApi::default();
876
877 let msg = hex::decode(ED25519_MSG_HEX).unwrap();
878 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
879 let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
880
881 assert!(api.ed25519_verify(&msg, &signature, &public_key).unwrap());
882 }
883
884 #[test]
886 fn ed25519_verify_fails() {
887 let api = MockApi::default();
888
889 let mut msg = hex::decode(ED25519_MSG_HEX).unwrap();
890 msg[0] ^= 0x01;
892 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
893 let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
894
895 assert!(!api.ed25519_verify(&msg, &signature, &public_key).unwrap());
896 }
897
898 #[test]
900 fn ed25519_verify_errs() {
901 let api = MockApi::default();
902
903 let msg = hex::decode(ED25519_MSG_HEX).unwrap();
904 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
905 let public_key = vec![];
906
907 let res = api.ed25519_verify(&msg, &signature, &public_key);
908 assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
909 }
910
911 #[test]
913 fn ed25519_batch_verify_works() {
914 let api = MockApi::default();
915
916 let msg = hex::decode(ED25519_MSG_HEX).unwrap();
917 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
918 let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
919
920 let msgs: Vec<&[u8]> = vec![&msg];
921 let signatures: Vec<&[u8]> = vec![&signature];
922 let public_keys: Vec<&[u8]> = vec![&public_key];
923
924 assert!(api
925 .ed25519_batch_verify(&msgs, &signatures, &public_keys)
926 .unwrap());
927 }
928
929 #[test]
931 fn ed25519_batch_verify_fails() {
932 let api = MockApi::default();
933
934 let mut msg = hex::decode(ED25519_MSG_HEX).unwrap();
935 msg[0] ^= 0x01;
937 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
938 let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
939
940 let msgs: Vec<&[u8]> = vec![&msg];
941 let signatures: Vec<&[u8]> = vec![&signature];
942 let public_keys: Vec<&[u8]> = vec![&public_key];
943
944 assert!(!api
945 .ed25519_batch_verify(&msgs, &signatures, &public_keys)
946 .unwrap());
947 }
948
949 #[test]
951 fn ed25519_batch_verify_errs() {
952 let api = MockApi::default();
953
954 let msg = hex::decode(ED25519_MSG_HEX).unwrap();
955 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
956 let public_key: Vec<u8> = vec![0u8; 0];
957
958 let msgs: Vec<&[u8]> = vec![msg.as_slice()];
959 let signatures: Vec<&[u8]> = vec![signature.as_slice()];
960 let public_keys: Vec<&[u8]> = vec![&public_key];
961
962 let res = api.ed25519_batch_verify(&msgs, &signatures, &public_keys);
963 assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
964 }
965
966 #[test]
967 fn bank_querier_all_balances() {
968 let addr = String::from("foobar");
969 let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
970 let bank = BankQuerier::new(&[(&addr, &balance)]);
971
972 let all = bank
973 .query(&BankQuery::AllBalances { address: addr })
974 .unwrap()
975 .unwrap();
976 let res: AllBalanceResponse = from_binary(&all).unwrap();
977 assert_eq!(&res.amount, &balance);
978 }
979
980 #[test]
981 fn bank_querier_one_balance() {
982 let addr = String::from("foobar");
983 let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
984 let bank = BankQuerier::new(&[(&addr, &balance)]);
985
986 let fly = bank
988 .query(&BankQuery::Balance {
989 address: addr.clone(),
990 denom: "FLY".to_string(),
991 })
992 .unwrap()
993 .unwrap();
994 let res: BalanceResponse = from_binary(&fly).unwrap();
995 assert_eq!(res.amount, coin(777, "FLY"));
996
997 let miss = bank
999 .query(&BankQuery::Balance {
1000 address: addr,
1001 denom: "MISS".to_string(),
1002 })
1003 .unwrap()
1004 .unwrap();
1005 let res: BalanceResponse = from_binary(&miss).unwrap();
1006 assert_eq!(res.amount, coin(0, "MISS"));
1007 }
1008
1009 #[test]
1010 fn bank_querier_missing_account() {
1011 let addr = String::from("foobar");
1012 let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
1013 let bank = BankQuerier::new(&[(&addr, &balance)]);
1014
1015 let all = bank
1017 .query(&BankQuery::AllBalances {
1018 address: String::from("elsewhere"),
1019 })
1020 .unwrap()
1021 .unwrap();
1022 let res: AllBalanceResponse = from_binary(&all).unwrap();
1023 assert_eq!(res.amount, vec![]);
1024
1025 let miss = bank
1027 .query(&BankQuery::Balance {
1028 address: String::from("elsewhere"),
1029 denom: "ELF".to_string(),
1030 })
1031 .unwrap()
1032 .unwrap();
1033 let res: BalanceResponse = from_binary(&miss).unwrap();
1034 assert_eq!(res.amount, coin(0, "ELF"));
1035 }
1036
1037 #[cfg(feature = "staking")]
1038 #[test]
1039 fn staking_querier_all_validators() {
1040 let val1 = Validator {
1041 address: String::from("validator-one"),
1042 commission: Decimal::percent(1),
1043 max_commission: Decimal::percent(3),
1044 max_change_rate: Decimal::percent(1),
1045 };
1046 let val2 = Validator {
1047 address: String::from("validator-two"),
1048 commission: Decimal::permille(15),
1049 max_commission: Decimal::permille(40),
1050 max_change_rate: Decimal::permille(5),
1051 };
1052
1053 let staking = StakingQuerier::new("ustake", &[val1.clone(), val2.clone()], &[]);
1054
1055 let raw = staking
1057 .query(&StakingQuery::AllValidators {})
1058 .unwrap()
1059 .unwrap();
1060 let vals: AllValidatorsResponse = from_binary(&raw).unwrap();
1061 assert_eq!(vals.validators, vec![val1, val2]);
1062 }
1063
1064 #[cfg(feature = "staking")]
1065 #[test]
1066 fn staking_querier_validator() {
1067 let address1 = String::from("validator-one");
1068 let address2 = String::from("validator-two");
1069 let address_non_existent = String::from("wannabe-validator");
1070
1071 let val1 = Validator {
1072 address: address1.clone(),
1073 commission: Decimal::percent(1),
1074 max_commission: Decimal::percent(3),
1075 max_change_rate: Decimal::percent(1),
1076 };
1077 let val2 = Validator {
1078 address: address2.clone(),
1079 commission: Decimal::permille(15),
1080 max_commission: Decimal::permille(40),
1081 max_change_rate: Decimal::permille(5),
1082 };
1083
1084 let staking = StakingQuerier::new("ustake", &[val1.clone(), val2.clone()], &[]);
1085
1086 let raw = staking
1088 .query(&StakingQuery::Validator { address: address1 })
1089 .unwrap()
1090 .unwrap();
1091 let res: ValidatorResponse = from_binary(&raw).unwrap();
1092 assert_eq!(res.validator, Some(val1));
1093
1094 let raw = staking
1096 .query(&StakingQuery::Validator { address: address2 })
1097 .unwrap()
1098 .unwrap();
1099 let res: ValidatorResponse = from_binary(&raw).unwrap();
1100 assert_eq!(res.validator, Some(val2));
1101
1102 let raw = staking
1104 .query(&StakingQuery::Validator {
1105 address: address_non_existent,
1106 })
1107 .unwrap()
1108 .unwrap();
1109 let res: ValidatorResponse = from_binary(&raw).unwrap();
1110 assert_eq!(res.validator, None);
1111 }
1112
1113 #[cfg(feature = "staking")]
1114 fn get_all_delegators(
1116 staking: &StakingQuerier,
1117 delegator: impl Into<String>,
1118 ) -> Vec<Delegation> {
1119 let raw = staking
1120 .query(&StakingQuery::AllDelegations {
1121 delegator: delegator.into(),
1122 })
1123 .unwrap()
1124 .unwrap();
1125 let dels: AllDelegationsResponse = from_binary(&raw).unwrap();
1126 dels.delegations
1127 }
1128
1129 #[cfg(feature = "staking")]
1130 fn get_delegator(
1132 staking: &StakingQuerier,
1133 delegator: impl Into<String>,
1134 validator: impl Into<String>,
1135 ) -> Option<FullDelegation> {
1136 let raw = staking
1137 .query(&StakingQuery::Delegation {
1138 delegator: delegator.into(),
1139 validator: validator.into(),
1140 })
1141 .unwrap()
1142 .unwrap();
1143 let dels: DelegationResponse = from_binary(&raw).unwrap();
1144 dels.delegation
1145 }
1146
1147 #[cfg(feature = "staking")]
1148 #[test]
1149 fn staking_querier_delegations() {
1150 let val1 = String::from("validator-one");
1151 let val2 = String::from("validator-two");
1152
1153 let user_a = Addr::unchecked("investor");
1154 let user_b = Addr::unchecked("speculator");
1155 let user_c = Addr::unchecked("hodler");
1156
1157 let del1a = FullDelegation {
1159 delegator: user_a.clone(),
1160 validator: val1.clone(),
1161 amount: coin(100, "ustake"),
1162 can_redelegate: coin(100, "ustake"),
1163 accumulated_rewards: coins(5, "ustake"),
1164 };
1165 let del2a = FullDelegation {
1166 delegator: user_a.clone(),
1167 validator: val2.clone(),
1168 amount: coin(500, "ustake"),
1169 can_redelegate: coin(500, "ustake"),
1170 accumulated_rewards: coins(20, "ustake"),
1171 };
1172
1173 let del1b = FullDelegation {
1175 delegator: user_b.clone(),
1176 validator: val1.clone(),
1177 amount: coin(500, "ustake"),
1178 can_redelegate: coin(0, "ustake"),
1179 accumulated_rewards: coins(0, "ustake"),
1180 };
1181
1182 let del2c = FullDelegation {
1184 delegator: user_c.clone(),
1185 validator: val2.clone(),
1186 amount: coin(8888, "ustake"),
1187 can_redelegate: coin(4567, "ustake"),
1188 accumulated_rewards: coins(900, "ustake"),
1189 };
1190
1191 let staking = StakingQuerier::new(
1192 "ustake",
1193 &[],
1194 &[del1a.clone(), del1b.clone(), del2a.clone(), del2c.clone()],
1195 );
1196
1197 let dels = get_all_delegators(&staking, user_a.clone());
1199 assert_eq!(dels, vec![del1a.clone().into(), del2a.clone().into()]);
1200
1201 let dels = get_all_delegators(&staking, user_b.clone());
1203 assert_eq!(dels, vec![del1b.clone().into()]);
1204
1205 let dels = get_all_delegators(&staking, user_c.clone());
1207 assert_eq!(dels, vec![del2c.clone().into()]);
1208
1209 let dels = get_all_delegators(&staking, String::from("no one"));
1211 assert_eq!(dels, vec![]);
1212
1213 let dels = get_delegator(&staking, user_a.clone(), val1.clone());
1215 assert_eq!(dels, Some(del1a));
1216 let dels = get_delegator(&staking, user_a, val2.clone());
1217 assert_eq!(dels, Some(del2a));
1218
1219 let dels = get_delegator(&staking, user_b.clone(), val1.clone());
1221 assert_eq!(dels, Some(del1b));
1222 let dels = get_delegator(&staking, user_b, val2.clone());
1223 assert_eq!(dels, None);
1224
1225 let dels = get_delegator(&staking, user_c.clone(), val1);
1227 assert_eq!(dels, None);
1228 let dels = get_delegator(&staking, user_c, val2);
1229 assert_eq!(dels, Some(del2c));
1230 }
1231
1232 #[test]
1233 fn riffle_shuffle_works() {
1234 let start = [0xA, 0x2, 0x3, 0x4, 0x5, 0x6];
1236 let round1 = riffle_shuffle(&start);
1237 assert_eq!(round1, [0x4, 0xA, 0x5, 0x2, 0x6, 0x3]);
1238 let round2 = riffle_shuffle(&round1);
1239 assert_eq!(round2, [0x2, 0x4, 0x6, 0xA, 0x3, 0x5]);
1240 let round3 = riffle_shuffle(&round2);
1241 assert_eq!(round3, start);
1242
1243 let original = [12, 33, 76, 576, 0, 44, 1, 14, 78, 99, 871212, -7, 2, -1];
1246 let mut result = Vec::from(original);
1247 for _ in 0..4 {
1248 result = riffle_shuffle(&result);
1249 }
1250 assert_eq!(result, original);
1251
1252 let original = [
1254 7, 4, 2, 4656, 23, 45, 23, 1, 12, 76, 576, 0, 12, 1, 14, 78, 99, 12, 1212, 444, 31,
1255 111, 424, 34,
1256 ];
1257 let mut result = Vec::from(original);
1258 for _ in 0..20 {
1259 result = riffle_shuffle(&result);
1260 }
1261 assert_eq!(result, original);
1262 }
1263
1264 #[test]
1265 fn digit_sum_works() {
1266 assert_eq!(digit_sum(&[]), 0);
1267 assert_eq!(digit_sum(&[0]), 0);
1268 assert_eq!(digit_sum(&[0, 0]), 0);
1269 assert_eq!(digit_sum(&[0, 0, 0]), 0);
1270
1271 assert_eq!(digit_sum(&[1, 0, 0]), 1);
1272 assert_eq!(digit_sum(&[0, 1, 0]), 1);
1273 assert_eq!(digit_sum(&[0, 0, 1]), 1);
1274
1275 assert_eq!(digit_sum(&[1, 2, 3]), 6);
1276
1277 assert_eq!(digit_sum(&[255, 1]), 256);
1278 }
1279}