tet_core/
crypto.rs

1// This file is part of Tetcore.
2
3// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18// tag::description[]
19//! Cryptographic utilities.
20// end::description[]
21
22use crate::{sr25519, ed25519};
23use tetcore_std::hash::Hash;
24use tetcore_std::vec::Vec;
25use tetcore_std::str;
26#[cfg(feature = "std")]
27use tetcore_std::convert::TryInto;
28use tetcore_std::convert::TryFrom;
29#[cfg(feature = "std")]
30use parking_lot::Mutex;
31#[cfg(feature = "std")]
32use rand::{RngCore, rngs::OsRng};
33use codec::{Encode, Decode};
34#[cfg(feature = "std")]
35use regex::Regex;
36#[cfg(feature = "std")]
37use base58::{FromBase58, ToBase58};
38#[cfg(feature = "std")]
39use crate::hexdisplay::HexDisplay;
40#[doc(hidden)]
41pub use tetcore_std::ops::Deref;
42use tp_runtime_interface::pass_by::PassByInner;
43/// Trait to zeroize a memory buffer.
44pub use zeroize::Zeroize;
45/// Trait for accessing reference to `SecretString`.
46pub use secrecy::ExposeSecret;
47/// A store for sensitive data.
48#[cfg(feature = "std")]
49pub use secrecy::SecretString;
50
51/// The root phrase for our publicly known keys.
52pub const DEV_PHRASE: &str = "bottom drive obey lake curtain smoke basket hold race lonely fit walk";
53
54/// The address of the associated root phrase for our publicly known keys.
55pub const DEV_ADDRESS: &str = "5DfhGyQdFobKM8NsWvEeAKk5EQQgYe9AydgJ7rMB6E1EqRzV";
56
57/// The infallible type.
58#[derive(crate::RuntimeDebug)]
59pub enum Infallible {}
60
61/// The length of the junction identifier. Note that this is also referred to as the
62/// `CHAIN_CODE_LENGTH` in the context of Schnorrkel.
63#[cfg(feature = "full_crypto")]
64pub const JUNCTION_ID_LEN: usize = 32;
65
66/// Similar to `From`, except that the onus is on the part of the caller to ensure
67/// that data passed in makes sense. Basically, you're not guaranteed to get anything
68/// sensible out.
69pub trait UncheckedFrom<T> {
70	/// Convert from an instance of `T` to Self. This is not guaranteed to be
71	/// whatever counts as a valid instance of `T` and it's up to the caller to
72	/// ensure that it makes sense.
73	fn unchecked_from(t: T) -> Self;
74}
75
76/// The counterpart to `UncheckedFrom`.
77pub trait UncheckedInto<T> {
78	/// The counterpart to `unchecked_from`.
79	fn unchecked_into(self) -> T;
80}
81
82impl<S, T: UncheckedFrom<S>> UncheckedInto<T> for S {
83	fn unchecked_into(self) -> T {
84		T::unchecked_from(self)
85	}
86}
87
88/// An error with the interpretation of a secret.
89#[derive(Debug, Clone, PartialEq, Eq)]
90#[cfg(feature = "full_crypto")]
91pub enum SecretStringError {
92	/// The overall format was invalid (e.g. the seed phrase contained symbols).
93	InvalidFormat,
94	/// The seed phrase provided is not a valid BIP39 phrase.
95	InvalidPhrase,
96	/// The supplied password was invalid.
97	InvalidPassword,
98	/// The seed is invalid (bad content).
99	InvalidSeed,
100	/// The seed has an invalid length.
101	InvalidSeedLength,
102	/// The derivation path was invalid (e.g. contains soft junctions when they are not supported).
103	InvalidPath,
104}
105
106/// A since derivation junction description. It is the single parameter used when creating
107/// a new secret key from an existing secret key and, in the case of `SoftRaw` and `SoftIndex`
108/// a new public key from an existing public key.
109#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Encode, Decode)]
110#[cfg(feature = "full_crypto")]
111pub enum DeriveJunction {
112	/// Soft (vanilla) derivation. Public keys have a correspondent derivation.
113	Soft([u8; JUNCTION_ID_LEN]),
114	/// Hard ("hardened") derivation. Public keys do not have a correspondent derivation.
115	Hard([u8; JUNCTION_ID_LEN]),
116}
117
118#[cfg(feature = "full_crypto")]
119impl DeriveJunction {
120	/// Consume self to return a soft derive junction with the same chain code.
121	pub fn soften(self) -> Self { DeriveJunction::Soft(self.unwrap_inner()) }
122
123	/// Consume self to return a hard derive junction with the same chain code.
124	pub fn harden(self) -> Self { DeriveJunction::Hard(self.unwrap_inner()) }
125
126	/// Create a new soft (vanilla) DeriveJunction from a given, encodable, value.
127	///
128	/// If you need a hard junction, use `hard()`.
129	pub fn soft<T: Encode>(index: T) -> Self {
130		let mut cc: [u8; JUNCTION_ID_LEN] = Default::default();
131		index.using_encoded(|data| if data.len() > JUNCTION_ID_LEN {
132			let hash_result = blake2_rfc::blake2b::blake2b(JUNCTION_ID_LEN, &[], data);
133			let hash = hash_result.as_bytes();
134			cc.copy_from_slice(hash);
135		} else {
136			cc[0..data.len()].copy_from_slice(data);
137		});
138		DeriveJunction::Soft(cc)
139	}
140
141	/// Create a new hard (hardened) DeriveJunction from a given, encodable, value.
142	///
143	/// If you need a soft junction, use `soft()`.
144	pub fn hard<T: Encode>(index: T) -> Self {
145		Self::soft(index).harden()
146	}
147
148	/// Consume self to return the chain code.
149	pub fn unwrap_inner(self) -> [u8; JUNCTION_ID_LEN] {
150		match self {
151			DeriveJunction::Hard(c) | DeriveJunction::Soft(c) => c,
152		}
153	}
154
155	/// Get a reference to the inner junction id.
156	pub fn inner(&self) -> &[u8; JUNCTION_ID_LEN] {
157		match self {
158			DeriveJunction::Hard(ref c) | DeriveJunction::Soft(ref c) => c,
159		}
160	}
161
162	/// Return `true` if the junction is soft.
163	pub fn is_soft(&self) -> bool {
164		match *self {
165			DeriveJunction::Soft(_) => true,
166			_ => false,
167		}
168	}
169
170	/// Return `true` if the junction is hard.
171	pub fn is_hard(&self) -> bool {
172		match *self {
173			DeriveJunction::Hard(_) => true,
174			_ => false,
175		}
176	}
177}
178
179#[cfg(feature = "full_crypto")]
180impl<T: AsRef<str>> From<T> for DeriveJunction {
181	fn from(j: T) -> DeriveJunction {
182		let j = j.as_ref();
183		let (code, hard) = if j.starts_with('/') {
184			(&j[1..], true)
185		} else {
186			(j, false)
187		};
188
189		let res = if let Ok(n) = str::parse::<u64>(code) {
190			// number
191			DeriveJunction::soft(n)
192		} else {
193			// something else
194			DeriveJunction::soft(code)
195		};
196
197		if hard {
198			res.harden()
199		} else {
200			res
201		}
202	}
203}
204
205/// An error type for SS58 decoding.
206#[cfg(feature = "full_crypto")]
207#[derive(Clone, Copy, Eq, PartialEq, Debug)]
208pub enum PublicError {
209	/// Bad alphabet.
210	BadBase58,
211	/// Bad length.
212	BadLength,
213	/// Unknown version.
214	UnknownVersion,
215	/// Invalid checksum.
216	InvalidChecksum,
217	/// Invalid format.
218	InvalidFormat,
219	/// Invalid derivation path.
220	InvalidPath,
221}
222
223/// Key that can be encoded to/from SS58.
224#[cfg(feature = "full_crypto")]
225pub trait Ss58Codec: Sized + AsMut<[u8]> + AsRef<[u8]> + Default {
226	/// Some if the string is a properly encoded SS58Check address.
227	#[cfg(feature = "std")]
228	fn from_ss58check(s: &str) -> Result<Self, PublicError> {
229		Self::from_ss58check_with_version(s)
230			.and_then(|(r, v)| match v {
231				v if !v.is_custom() => Ok(r),
232				v if v == *DEFAULT_VERSION.lock() => Ok(r),
233				_ => Err(PublicError::UnknownVersion),
234			})
235	}
236	/// Some if the string is a properly encoded SS58Check address.
237	#[cfg(feature = "std")]
238	fn from_ss58check_with_version(s: &str) -> Result<(Self, Ss58AddressFormat), PublicError> {
239		let mut res = Self::default();
240		let len = res.as_mut().len();
241		let d = s.from_base58().map_err(|_| PublicError::BadBase58)?; // failure here would be invalid encoding.
242		if d.len() != len + 3 {
243			// Invalid length.
244			return Err(PublicError::BadLength);
245		}
246		let ver = d[0].try_into().map_err(|_: ()| PublicError::UnknownVersion)?;
247
248		if d[len + 1..len + 3] != ss58hash(&d[0..len + 1]).as_bytes()[0..2] {
249			// Invalid checksum.
250			return Err(PublicError::InvalidChecksum);
251		}
252		res.as_mut().copy_from_slice(&d[1..len + 1]);
253		Ok((res, ver))
254	}
255	/// Some if the string is a properly encoded SS58Check address, optionally with
256	/// a derivation path following.
257	#[cfg(feature = "std")]
258	fn from_string(s: &str) -> Result<Self, PublicError> {
259		Self::from_string_with_version(s)
260			.and_then(|(r, v)| match v {
261				v if !v.is_custom() => Ok(r),
262				v if v == *DEFAULT_VERSION.lock() => Ok(r),
263				_ => Err(PublicError::UnknownVersion),
264			})
265	}
266
267	/// Return the ss58-check string for this key.
268	#[cfg(feature = "std")]
269	fn to_ss58check_with_version(&self, version: Ss58AddressFormat) -> String {
270		let mut v = vec![version.into()];
271		v.extend(self.as_ref());
272		let r = ss58hash(&v);
273		v.extend(&r.as_bytes()[0..2]);
274		v.to_base58()
275	}
276
277	/// Return the ss58-check string for this key.
278	#[cfg(feature = "std")]
279	fn to_ss58check(&self) -> String { self.to_ss58check_with_version(*DEFAULT_VERSION.lock()) }
280
281	/// Some if the string is a properly encoded SS58Check address, optionally with
282	/// a derivation path following.
283	#[cfg(feature = "std")]
284	fn from_string_with_version(s: &str) -> Result<(Self, Ss58AddressFormat), PublicError> {
285		Self::from_ss58check_with_version(s)
286	}
287}
288
289/// Derivable key trait.
290pub trait Derive: Sized {
291	/// Derive a child key from a series of given junctions.
292	///
293	/// Will be `None` for public keys if there are any hard junctions in there.
294	#[cfg(feature = "std")]
295	fn derive<Iter: Iterator<Item=DeriveJunction>>(&self, _path: Iter) -> Option<Self> {
296		None
297	}
298}
299
300#[cfg(feature = "std")]
301const PREFIX: &[u8] = b"SS58PRE";
302
303#[cfg(feature = "std")]
304fn ss58hash(data: &[u8]) -> blake2_rfc::blake2b::Blake2bResult {
305	let mut context = blake2_rfc::blake2b::Blake2b::new(64);
306	context.update(PREFIX);
307	context.update(data);
308	context.finalize()
309}
310
311#[cfg(feature = "std")]
312lazy_static::lazy_static! {
313	static ref DEFAULT_VERSION: Mutex<Ss58AddressFormat>
314		= Mutex::new(Ss58AddressFormat::TetcoreAccount);
315}
316
317#[cfg(feature = "full_crypto")]
318macro_rules! ss58_address_format {
319	( $( $identifier:tt => ($number:expr, $name:expr, $desc:tt) )* ) => (
320		/// A known address (sub)format/network ID for SS58.
321		#[derive(Copy, Clone, PartialEq, Eq, crate::RuntimeDebug)]
322		pub enum Ss58AddressFormat {
323			$(#[doc = $desc] $identifier),*,
324			/// Use a manually provided numeric value.
325			Custom(u8),
326		}
327
328		#[cfg(feature = "std")]
329		impl std::fmt::Display for Ss58AddressFormat {
330			fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
331				match self {
332					$(
333						Ss58AddressFormat::$identifier => write!(f, "{}", $name),
334					)*
335					Ss58AddressFormat::Custom(x) => write!(f, "{}", x),
336				}
337
338			}
339		}
340
341		static ALL_SS58_ADDRESS_FORMATS: [Ss58AddressFormat; 0 $(+ { let _ = $number; 1})*] = [
342			$(Ss58AddressFormat::$identifier),*,
343		];
344
345		impl Ss58AddressFormat {
346			/// names of all address formats
347			pub fn all_names() -> &'static [&'static str] {
348				&[
349					$($name),*,
350				]
351			}
352			/// All known address formats.
353			pub fn all() -> &'static [Ss58AddressFormat] {
354				&ALL_SS58_ADDRESS_FORMATS
355			}
356
357			/// Whether the address is custom.
358			pub fn is_custom(&self) -> bool {
359				match self {
360					Self::Custom(_) => true,
361					_ => false,
362				}
363			}
364		}
365
366		impl From<Ss58AddressFormat> for u8 {
367			fn from(x: Ss58AddressFormat) -> u8 {
368				match x {
369					$(Ss58AddressFormat::$identifier => $number),*,
370					Ss58AddressFormat::Custom(n) => n,
371				}
372			}
373		}
374
375		impl TryFrom<u8> for Ss58AddressFormat {
376			type Error = ();
377
378			fn try_from(x: u8) -> Result<Ss58AddressFormat, ()> {
379				match x {
380					$($number => Ok(Ss58AddressFormat::$identifier)),*,
381					_ => {
382						#[cfg(feature = "std")]
383						match Ss58AddressFormat::default() {
384							Ss58AddressFormat::Custom(n) if n == x => Ok(Ss58AddressFormat::Custom(x)),
385							_ => Err(()),
386						}
387
388						#[cfg(not(feature = "std"))]
389						Err(())
390					},
391				}
392			}
393		}
394
395		/// Error encountered while parsing `Ss58AddressFormat` from &'_ str
396		/// unit struct for now.
397		#[derive(Copy, Clone, PartialEq, Eq, crate::RuntimeDebug)]
398		pub struct ParseError;
399
400		impl<'a> TryFrom<&'a str> for Ss58AddressFormat {
401			type Error = ParseError;
402
403			fn try_from(x: &'a str) -> Result<Ss58AddressFormat, Self::Error> {
404				match x {
405					$($name => Ok(Ss58AddressFormat::$identifier)),*,
406					a => a.parse::<u8>().map(Ss58AddressFormat::Custom).map_err(|_| ParseError),
407				}
408			}
409		}
410
411		#[cfg(feature = "std")]
412		impl std::str::FromStr for Ss58AddressFormat {
413			type Err = ParseError;
414
415			fn from_str(data: &str) -> Result<Self, Self::Err> {
416				Self::try_from(data)
417			}
418		}
419
420		#[cfg(feature = "std")]
421		impl std::fmt::Display for ParseError {
422			fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
423				write!(f, "failed to parse network value as u8")
424			}
425		}
426
427		#[cfg(feature = "std")]
428		impl Default for Ss58AddressFormat {
429			fn default() -> Self {
430				*DEFAULT_VERSION.lock()
431			}
432		}
433
434		#[cfg(feature = "std")]
435		impl From<Ss58AddressFormat> for String {
436			fn from(x: Ss58AddressFormat) -> String {
437				x.to_string()
438			}
439		}
440	)
441}
442
443#[cfg(feature = "full_crypto")]
444ss58_address_format!(
445	TetcoinAccount =>
446		(0, "tetcoin", "Tetcoin Relay-chain, standard account (*25519).")
447	Reserved1 =>
448		(1, "reserved1", "Reserved for future use (1).")
449	MetrocoinAccount =>
450		(2, "Metrocoin", "Metrocoin Relay-chain, standard account (*25519).")
451	Reserved3 =>
452		(3, "reserved3", "Reserved for future use (3).")
453	KatalChainAccount =>
454		(4, "katalchain", "Katal Chain, standard account (*25519).")
455	PlasmAccount =>
456		(5, "plasm", "Plasm Network, standard account (*25519).")
457	BifrostAccount =>
458		(6, "bifrost", "Bifrost mainnet, direct checksum, standard account (*25519).")
459	EdgewareAccount =>
460		(7, "edgeware", "Edgeware mainnet, standard account (*25519).")
461	KaruraAccount =>
462		(8, "karura", "Acala Karura canary network, standard account (*25519).")
463	ReynoldsAccount =>
464		(9, "reynolds", "Laminar Reynolds canary network, standard account (*25519).")
465	AcalaAccount =>
466		(10, "acala", "Acala mainnet, standard account (*25519).")
467	LaminarAccount =>
468		(11, "laminar", "Laminar mainnet, standard account (*25519).")
469	PolymathAccount =>
470		(12, "polymath", "Polymath network, standard account (*25519).")
471	TetcoReeAccount =>
472		(13, "tetcoree", "Any TetcoREE off-chain network private account (*25519).")
473	TotemAccount =>
474		(14, "totem", "Any Totem Live Accounting network standard account (*25519).")
475	SynesthesiaAccount =>
476		(15, "synesthesia", "Synesthesia mainnet, standard account (*25519).")
477	KulupuAccount =>
478		(16, "kulupu", "Kulupu mainnet, standard account (*25519).")
479	DarkAccount =>
480		(17, "dark", "Dark mainnet, standard account (*25519).")
481	DarwiniaAccount =>
482		(18, "darwinia", "Darwinia Chain mainnet, standard account (*25519).")
483	GeekAccount =>
484		(19, "geek", "GeekCash mainnet, standard account (*25519).")
485	StafiAccount =>
486		(20, "stafi", "Stafi mainnet, standard account (*25519).")
487	DockTestAccount =>
488		(21, "dock-testnet", "Dock testnet, standard account (*25519).")
489	DockMainAccount =>
490		(22, "dock-mainnet", "Dock mainnet, standard account (*25519).")
491	ShiftNrg =>
492		(23, "shift", "ShiftNrg mainnet, standard account (*25519).")
493	ZeroAccount =>
494		(24, "zero", "ZERO mainnet, standard account (*25519).")
495	AlphavilleAccount =>
496		(25, "alphaville", "ZERO testnet, standard account (*25519).")
497	JupiterAccount =>
498		(26, "jupiter", "Jupiter testnet, standard account (*25519).")
499	PatractAccount =>
500		(27, "patract", "Patract mainnet, standard account (*25519).")
501	SubsocialAccount =>
502		(28, "subsocial", "Subsocial network, standard account (*25519).")
503	DhiwayAccount =>
504		(29, "cord", "Dhiway CORD network, standard account (*25519).")
505	PhalaAccount =>
506		(30, "phala", "Phala Network, standard account (*25519).")
507	LitentryAccount =>
508		(31, "litentry", "Litentry Network, standard account (*25519).")
509	RobonomicsAccount =>
510		(32, "robonomics", "Any Robonomics network standard account (*25519).")
511	DataHighwayAccount =>
512		(33, "datahighway", "DataHighway mainnet, standard account (*25519).")
513	ValiuAccount =>
514		(35, "vln", "Valiu Liquidity Network mainnet, standard account (*25519).")
515	CentrifugeAccount =>
516		(36, "centrifuge", "Centrifuge Chain mainnet, standard account (*25519).")
517	NodleAccount =>
518		(37, "nodle", "Nodle Chain mainnet, standard account (*25519).")
519	KiltAccount =>
520		(38, "kilt", "KILT Chain mainnet, standard account (*25519).")
521	PolimecAccount =>
522		(41, "poli", "Polimec Chain mainnet, standard account (*25519).")
523	TetcoreAccount =>
524		(42, "tetcore", "Any Tetcore network, standard account (*25519).")
525	Reserved43 =>
526		(43, "reserved43", "Reserved for future use (43).")
527	ChainXAccount =>
528		(44, "chainx", "ChainX mainnet, standard account (*25519).")
529	UniartsAccount =>
530		(45, "uniarts", "UniArts Chain mainnet, standard account (*25519).")
531	Reserved46 =>
532		(46, "reserved46", "Reserved for future use (46).")
533	Reserved47 =>
534		(47, "reserved47", "Reserved for future use (47).")
535	// Note: 48 and above are reserved.
536);
537
538/// Set the default "version" (actually, this is a bit of a misnomer and the version byte is
539/// typically used not just to encode format/version but also network identity) that is used for
540/// encoding and decoding SS58 addresses. If an unknown version is provided then it fails.
541///
542/// See `ss58_address_format!` for all current known "versions".
543#[cfg(feature = "std")]
544pub fn set_default_ss58_version(version: Ss58AddressFormat) {
545	*DEFAULT_VERSION.lock() = version
546}
547
548#[cfg(feature = "std")]
549impl<T: Sized + AsMut<[u8]> + AsRef<[u8]> + Default + Derive> Ss58Codec for T {
550	fn from_string(s: &str) -> Result<Self, PublicError> {
551		let re = Regex::new(r"^(?P<ss58>[\w\d ]+)?(?P<path>(//?[^/]+)*)$")
552			.expect("constructed from known-good static value; qed");
553		let cap = re.captures(s).ok_or(PublicError::InvalidFormat)?;
554		let re_junction = Regex::new(r"/(/?[^/]+)")
555			.expect("constructed from known-good static value; qed");
556		let s = cap.name("ss58")
557			.map(|r| r.as_str())
558			.unwrap_or(DEV_ADDRESS);
559		let addr = if s.starts_with("0x") {
560			let d = hex::decode(&s[2..]).map_err(|_| PublicError::InvalidFormat)?;
561			let mut r = Self::default();
562			if d.len() == r.as_ref().len() {
563				r.as_mut().copy_from_slice(&d);
564				r
565			} else {
566				Err(PublicError::BadLength)?
567			}
568		} else {
569			Self::from_ss58check(s)?
570		};
571		if cap["path"].is_empty() {
572			Ok(addr)
573		} else {
574			let path = re_junction.captures_iter(&cap["path"])
575				.map(|f| DeriveJunction::from(&f[1]));
576			addr.derive(path)
577				.ok_or(PublicError::InvalidPath)
578		}
579	}
580
581	fn from_string_with_version(s: &str) -> Result<(Self, Ss58AddressFormat), PublicError> {
582		let re = Regex::new(r"^(?P<ss58>[\w\d ]+)?(?P<path>(//?[^/]+)*)$")
583			.expect("constructed from known-good static value; qed");
584		let cap = re.captures(s).ok_or(PublicError::InvalidFormat)?;
585		let re_junction = Regex::new(r"/(/?[^/]+)")
586			.expect("constructed from known-good static value; qed");
587		let (addr, v) = Self::from_ss58check_with_version(
588			cap.name("ss58")
589				.map(|r| r.as_str())
590				.unwrap_or(DEV_ADDRESS)
591		)?;
592		if cap["path"].is_empty() {
593			Ok((addr, v))
594		} else {
595			let path = re_junction.captures_iter(&cap["path"])
596				.map(|f| DeriveJunction::from(&f[1]));
597			addr.derive(path)
598				.ok_or(PublicError::InvalidPath)
599				.map(|a| (a, v))
600		}
601	}
602}
603
604/// Trait suitable for typical cryptographic PKI key public type.
605pub trait Public:
606	AsRef<[u8]>
607	+ AsMut<[u8]>
608	+ Default
609	+ Derive
610	+ CryptoType
611	+ PartialEq
612	+ Eq
613	+ Clone
614	+ Send
615	+ Sync
616	+ for<'a> TryFrom<&'a [u8]>
617{
618	/// A new instance from the given slice.
619	///
620	/// NOTE: No checking goes on to ensure this is a real public key. Only use it if
621	/// you are certain that the array actually is a pubkey. GIGO!
622	fn from_slice(data: &[u8]) -> Self;
623
624	/// Return a `Vec<u8>` filled with raw data.
625	fn to_raw_vec(&self) -> Vec<u8> { self.as_slice().to_vec() }
626
627	/// Return a slice filled with raw data.
628	fn as_slice(&self) -> &[u8] { self.as_ref() }
629	/// Return `CryptoTypePublicPair` from public key.
630	fn to_public_crypto_pair(&self) -> CryptoTypePublicPair;
631}
632
633/// An opaque 32-byte cryptographic identifier.
634#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Default, Encode, Decode)]
635#[cfg_attr(feature = "std", derive(Hash))]
636pub struct AccountId32([u8; 32]);
637
638impl AccountId32 {
639	/// Create a new instance from its raw inner byte value.
640	///
641	/// Equivalent to this types `From<[u8; 32]>` implementation. For the lack of const
642	/// support in traits we have this constructor.
643	pub const fn new(inner: [u8; 32]) -> Self {
644		Self(inner)
645	}
646}
647
648impl UncheckedFrom<crate::hash::H256> for AccountId32 {
649	fn unchecked_from(h: crate::hash::H256) -> Self {
650		AccountId32(h.into())
651	}
652}
653
654#[cfg(feature = "std")]
655impl Ss58Codec for AccountId32 {}
656
657impl AsRef<[u8]> for AccountId32 {
658	fn as_ref(&self) -> &[u8] {
659		&self.0[..]
660	}
661}
662
663impl AsMut<[u8]> for AccountId32 {
664	fn as_mut(&mut self) -> &mut [u8] {
665		&mut self.0[..]
666	}
667}
668
669impl AsRef<[u8; 32]> for AccountId32 {
670	fn as_ref(&self) -> &[u8; 32] {
671		&self.0
672	}
673}
674
675impl AsMut<[u8; 32]> for AccountId32 {
676	fn as_mut(&mut self) -> &mut [u8; 32] {
677		&mut self.0
678	}
679}
680
681impl From<[u8; 32]> for AccountId32 {
682	fn from(x: [u8; 32]) -> Self {
683		Self::new(x)
684	}
685}
686
687impl<'a> tetcore_std::convert::TryFrom<&'a [u8]> for AccountId32 {
688	type Error = ();
689	fn try_from(x: &'a [u8]) -> Result<AccountId32, ()> {
690		if x.len() == 32 {
691			let mut r = AccountId32::default();
692			r.0.copy_from_slice(x);
693			Ok(r)
694		} else {
695			Err(())
696		}
697	}
698}
699
700impl From<AccountId32> for [u8; 32] {
701	fn from(x: AccountId32) -> [u8; 32] {
702		x.0
703	}
704}
705
706impl From<sr25519::Public> for AccountId32 {
707	fn from(k: sr25519::Public) -> Self {
708		k.0.into()
709	}
710}
711
712impl From<ed25519::Public> for AccountId32 {
713	fn from(k: ed25519::Public) -> Self {
714		k.0.into()
715	}
716}
717
718#[cfg(feature = "std")]
719impl std::fmt::Display for AccountId32 {
720	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
721		write!(f, "{}", self.to_ss58check())
722	}
723}
724
725impl tetcore_std::fmt::Debug for AccountId32 {
726	#[cfg(feature = "std")]
727	fn fmt(&self, f: &mut tetcore_std::fmt::Formatter) -> tetcore_std::fmt::Result {
728		let s = self.to_ss58check();
729		write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8])
730	}
731
732	#[cfg(not(feature = "std"))]
733	fn fmt(&self, _: &mut tetcore_std::fmt::Formatter) -> tetcore_std::fmt::Result {
734		Ok(())
735	}
736}
737
738#[cfg(feature = "std")]
739impl serde::Serialize for AccountId32 {
740	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
741		serializer.serialize_str(&self.to_ss58check())
742	}
743}
744
745#[cfg(feature = "std")]
746impl<'de> serde::Deserialize<'de> for AccountId32 {
747	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de> {
748		Ss58Codec::from_ss58check(&String::deserialize(deserializer)?)
749			.map_err(|e| serde::de::Error::custom(format!("{:?}", e)))
750	}
751}
752
753#[cfg(feature = "std")]
754impl tetcore_std::str::FromStr for AccountId32 {
755	type Err = &'static str;
756
757	fn from_str(s: &str) -> Result<Self, Self::Err> {
758		let hex_or_ss58_without_prefix = s.trim_start_matches("0x");
759		if hex_or_ss58_without_prefix.len() == 64 {
760			let mut bytes = [0u8; 32];
761			hex::decode_to_slice(hex_or_ss58_without_prefix, &mut bytes)
762				.map_err(|_| "invalid hex address.")
763				.map(|_| Self::from(bytes))
764		} else {
765			Self::from_ss58check(s).map_err(|_| "invalid ss58 address.")
766		}
767	}
768}
769
770#[cfg(feature = "std")]
771pub use self::dummy::*;
772
773#[cfg(feature = "std")]
774mod dummy {
775	use super::*;
776
777	/// Dummy cryptography. Doesn't do anything.
778	#[derive(Clone, Hash, Default, Eq, PartialEq)]
779	pub struct Dummy;
780
781	impl AsRef<[u8]> for Dummy {
782		fn as_ref(&self) -> &[u8] { &b""[..] }
783	}
784
785	impl AsMut<[u8]> for Dummy {
786		fn as_mut(&mut self) -> &mut[u8] {
787			unsafe {
788				#[allow(mutable_transmutes)]
789				tetcore_std::mem::transmute::<_, &'static mut [u8]>(&b""[..])
790			}
791		}
792	}
793
794	impl<'a> TryFrom<&'a [u8]> for Dummy {
795		type Error = ();
796
797		fn try_from(_: &'a [u8]) -> Result<Self, ()> {
798			Ok(Self)
799		}
800	}
801
802	impl CryptoType for Dummy {
803		type Pair = Dummy;
804	}
805
806	impl Derive for Dummy {}
807
808	impl Public for Dummy {
809		fn from_slice(_: &[u8]) -> Self { Self }
810		#[cfg(feature = "std")]
811		fn to_raw_vec(&self) -> Vec<u8> { vec![] }
812		fn as_slice(&self) -> &[u8] { b"" }
813		fn to_public_crypto_pair(&self) -> CryptoTypePublicPair {
814			CryptoTypePublicPair(
815				CryptoTypeId(*b"dumm"), Public::to_raw_vec(self)
816			)
817		}
818	}
819
820	impl Pair for Dummy {
821		type Public = Dummy;
822		type Seed = Dummy;
823		type Signature = Dummy;
824		type DeriveError = ();
825		#[cfg(feature = "std")]
826		fn generate_with_phrase(_: Option<&str>) -> (Self, String, Self::Seed) { Default::default() }
827		#[cfg(feature = "std")]
828		fn from_phrase(_: &str, _: Option<&str>)
829			-> Result<(Self, Self::Seed), SecretStringError>
830		{
831			Ok(Default::default())
832		}
833		fn derive<
834			Iter: Iterator<Item=DeriveJunction>,
835		>(&self, _: Iter, _: Option<Dummy>) -> Result<(Self, Option<Dummy>), Self::DeriveError> { Ok((Self, None)) }
836		fn from_seed(_: &Self::Seed) -> Self { Self }
837		fn from_seed_slice(_: &[u8]) -> Result<Self, SecretStringError> { Ok(Self) }
838		fn sign(&self, _: &[u8]) -> Self::Signature { Self }
839		fn verify<M: AsRef<[u8]>>(_: &Self::Signature, _: M, _: &Self::Public) -> bool { true }
840		fn verify_weak<P: AsRef<[u8]>, M: AsRef<[u8]>>(_: &[u8], _: M, _: P) -> bool { true }
841		fn public(&self) -> Self::Public { Self }
842		fn to_raw_vec(&self) -> Vec<u8> { vec![] }
843	}
844}
845
846/// Trait suitable for typical cryptographic PKI key pair type.
847///
848/// For now it just specifies how to create a key from a phrase and derivation path.
849#[cfg(feature = "full_crypto")]
850pub trait Pair: CryptoType + Sized + Clone + Send + Sync + 'static {
851	/// The type which is used to encode a public key.
852	type Public: Public + Hash;
853
854	/// The type used to (minimally) encode the data required to securely create
855	/// a new key pair.
856	type Seed: Default + AsRef<[u8]> + AsMut<[u8]> + Clone;
857
858	/// The type used to represent a signature. Can be created from a key pair and a message
859	/// and verified with the message and a public key.
860	type Signature: AsRef<[u8]>;
861
862	/// Error returned from the `derive` function.
863	type DeriveError;
864
865	/// Generate new secure (random) key pair.
866	///
867	/// This is only for ephemeral keys really, since you won't have access to the secret key
868	/// for storage. If you want a persistent key pair, use `generate_with_phrase` instead.
869	#[cfg(feature = "std")]
870	fn generate() -> (Self, Self::Seed) {
871		let mut seed = Self::Seed::default();
872		OsRng.fill_bytes(seed.as_mut());
873		(Self::from_seed(&seed), seed)
874	}
875
876	/// Generate new secure (random) key pair and provide the recovery phrase.
877	///
878	/// You can recover the same key later with `from_phrase`.
879	///
880	/// This is generally slower than `generate()`, so prefer that unless you need to persist
881	/// the key from the current session.
882	#[cfg(feature = "std")]
883	fn generate_with_phrase(password: Option<&str>) -> (Self, String, Self::Seed);
884
885	/// Returns the KeyPair from the English BIP39 seed `phrase`, or `None` if it's invalid.
886	#[cfg(feature = "std")]
887	fn from_phrase(phrase: &str, password: Option<&str>) -> Result<(Self, Self::Seed), SecretStringError>;
888
889	/// Derive a child key from a series of given junctions.
890	fn derive<Iter: Iterator<Item=DeriveJunction>>(&self,
891		path: Iter,
892		seed: Option<Self::Seed>,
893	) -> Result<(Self, Option<Self::Seed>), Self::DeriveError>;
894
895	/// Generate new key pair from the provided `seed`.
896	///
897	/// @WARNING: THIS WILL ONLY BE SECURE IF THE `seed` IS SECURE. If it can be guessed
898	/// by an attacker then they can also derive your key.
899	fn from_seed(seed: &Self::Seed) -> Self;
900
901	/// Make a new key pair from secret seed material. The slice must be the correct size or
902	/// it will return `None`.
903	///
904	/// @WARNING: THIS WILL ONLY BE SECURE IF THE `seed` IS SECURE. If it can be guessed
905	/// by an attacker then they can also derive your key.
906	fn from_seed_slice(seed: &[u8]) -> Result<Self, SecretStringError>;
907
908	/// Sign a message.
909	fn sign(&self, message: &[u8]) -> Self::Signature;
910
911	/// Verify a signature on a message. Returns true if the signature is good.
912	fn verify<M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: &Self::Public) -> bool;
913
914	/// Verify a signature on a message. Returns true if the signature is good.
915	fn verify_weak<P: AsRef<[u8]>, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool;
916
917	/// Get the public key.
918	fn public(&self) -> Self::Public;
919
920	/// Interprets the string `s` in order to generate a key Pair. Returns both the pair and an optional seed, in the
921	/// case that the pair can be expressed as a direct derivation from a seed (some cases, such as Sr25519 derivations
922	/// with path components, cannot).
923	///
924	/// This takes a helper function to do the key generation from a phrase, password and
925	/// junction iterator.
926	///
927	/// - If `s` is a possibly `0x` prefixed 64-digit hex string, then it will be interpreted
928	/// directly as a `MiniSecretKey` (aka "seed" in `tetkey`).
929	/// - If `s` is a valid BIP-39 key phrase of 12, 15, 18, 21 or 24 words, then the key will
930	/// be derived from it. In this case:
931	///   - the phrase may be followed by one or more items delimited by `/` characters.
932	///   - the path may be followed by `///`, in which case everything after the `///` is treated
933	/// as a password.
934	/// - If `s` begins with a `/` character it is prefixed with the Tetcore public `DEV_PHRASE` and
935	/// interpreted as above.
936	///
937	/// In this case they are interpreted as HDKD junctions; purely numeric items are interpreted as
938	/// integers, non-numeric items as strings. Junctions prefixed with `/` are interpreted as soft
939	/// junctions, and with `//` as hard junctions.
940	///
941	/// There is no correspondence mapping between SURI strings and the keys they represent.
942	/// Two different non-identical strings can actually lead to the same secret being derived.
943	/// Notably, integer junction indices may be legally prefixed with arbitrary number of zeros.
944	/// Similarly an empty password (ending the SURI with `///`) is perfectly valid and will generally
945	/// be equivalent to no password at all.
946	///
947	/// `None` is returned if no matches are found.
948	#[cfg(feature = "std")]
949	fn from_string_with_seed(s: &str, password_override: Option<&str>)
950		-> Result<(Self, Option<Self::Seed>), SecretStringError>
951	{
952		let re = Regex::new(r"^(?P<phrase>[\d\w ]+)?(?P<path>(//?[^/]+)*)(///(?P<password>.*))?$")
953			.expect("constructed from known-good static value; qed");
954		let cap = re.captures(s).ok_or(SecretStringError::InvalidFormat)?;
955
956		let re_junction = Regex::new(r"/(/?[^/]+)")
957			.expect("constructed from known-good static value; qed");
958		let path = re_junction.captures_iter(&cap["path"])
959			.map(|f| DeriveJunction::from(&f[1]));
960
961		let phrase = cap.name("phrase").map(|r| r.as_str()).unwrap_or(DEV_PHRASE);
962		let password = password_override.or_else(|| cap.name("password").map(|m| m.as_str()));
963
964		let (root, seed) = if phrase.starts_with("0x") {
965			hex::decode(&phrase[2..]).ok()
966				.and_then(|seed_vec| {
967					let mut seed = Self::Seed::default();
968					if seed.as_ref().len() == seed_vec.len() {
969						seed.as_mut().copy_from_slice(&seed_vec);
970						Some((Self::from_seed(&seed), seed))
971					} else {
972						None
973					}
974				})
975				.ok_or(SecretStringError::InvalidSeed)?
976		} else {
977			Self::from_phrase(phrase, password)
978				.map_err(|_| SecretStringError::InvalidPhrase)?
979		};
980		root.derive(path, Some(seed)).map_err(|_| SecretStringError::InvalidPath)
981	}
982
983	/// Interprets the string `s` in order to generate a key pair.
984	///
985	/// See [`from_string_with_seed`](Pair::from_string_with_seed) for more extensive documentation.
986	#[cfg(feature = "std")]
987	fn from_string(s: &str, password_override: Option<&str>) -> Result<Self, SecretStringError> {
988		Self::from_string_with_seed(s, password_override).map(|x| x.0)
989	}
990
991	/// Return a vec filled with raw data.
992	fn to_raw_vec(&self) -> Vec<u8>;
993}
994
995/// One type is wrapped by another.
996pub trait IsWrappedBy<Outer>: From<Outer> + Into<Outer> {
997	/// Get a reference to the inner from the outer.
998	fn from_ref(outer: &Outer) -> &Self;
999	/// Get a mutable reference to the inner from the outer.
1000	fn from_mut(outer: &mut Outer) -> &mut Self;
1001}
1002
1003/// Opposite of `IsWrappedBy` - denotes a type which is a simple wrapper around another type.
1004pub trait Wraps: Sized {
1005	/// The inner type it is wrapping.
1006	type Inner: IsWrappedBy<Self>;
1007}
1008
1009impl<T, Outer> IsWrappedBy<Outer> for T where
1010	Outer: AsRef<Self> + AsMut<Self> + From<Self>,
1011	T: From<Outer>,
1012{
1013	/// Get a reference to the inner from the outer.
1014	fn from_ref(outer: &Outer) -> &Self { outer.as_ref() }
1015
1016	/// Get a mutable reference to the inner from the outer.
1017	fn from_mut(outer: &mut Outer) -> &mut Self { outer.as_mut() }
1018}
1019
1020impl<Inner, Outer, T> UncheckedFrom<T> for Outer where
1021	Outer: Wraps<Inner=Inner>,
1022	Inner: IsWrappedBy<Outer> + UncheckedFrom<T>,
1023{
1024	fn unchecked_from(t: T) -> Self {
1025		let inner: Inner = t.unchecked_into();
1026		inner.into()
1027	}
1028}
1029
1030/// Type which has a particular kind of crypto associated with it.
1031pub trait CryptoType {
1032	/// The pair key type of this crypto.
1033	#[cfg(feature = "full_crypto")]
1034	type Pair: Pair;
1035}
1036
1037/// An identifier for a type of cryptographic key.
1038///
1039/// To avoid clashes with other modules when distributing your module publicly, register your
1040/// `KeyTypeId` on the list here by making a PR.
1041///
1042/// Values whose first character is `_` are reserved for private use and won't conflict with any
1043/// public modules.
1044#[derive(
1045	Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, Decode, PassByInner,
1046	crate::RuntimeDebug
1047)]
1048#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
1049pub struct KeyTypeId(pub [u8; 4]);
1050
1051impl From<u32> for KeyTypeId {
1052	fn from(x: u32) -> Self {
1053		Self(x.to_le_bytes())
1054	}
1055}
1056
1057impl From<KeyTypeId> for u32 {
1058	fn from(x: KeyTypeId) -> Self {
1059		u32::from_le_bytes(x.0)
1060	}
1061}
1062
1063impl<'a> TryFrom<&'a str> for KeyTypeId {
1064	type Error = ();
1065
1066	fn try_from(x: &'a str) -> Result<Self, ()> {
1067		let b = x.as_bytes();
1068		if b.len() != 4 {
1069			return Err(());
1070		}
1071		let mut res = KeyTypeId::default();
1072		res.0.copy_from_slice(&b[0..4]);
1073		Ok(res)
1074	}
1075}
1076
1077/// An identifier for a specific cryptographic algorithm used by a key pair
1078#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, Decode)]
1079#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
1080pub struct CryptoTypeId(pub [u8; 4]);
1081
1082/// A type alias of CryptoTypeId & a public key
1083#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, Decode)]
1084#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
1085pub struct CryptoTypePublicPair(pub CryptoTypeId, pub Vec<u8>);
1086
1087#[cfg(feature = "std")]
1088impl tetcore_std::fmt::Display for CryptoTypePublicPair {
1089	fn fmt(&self, f: &mut tetcore_std::fmt::Formatter) -> tetcore_std::fmt::Result {
1090		let id = match str::from_utf8(&(self.0).0[..]) {
1091			Ok(id) => id.to_string(),
1092			Err(_) => {
1093				format!("{:#?}", self.0)
1094			}
1095		};
1096		write!(f, "{}-{}", id, HexDisplay::from(&self.1))
1097	}
1098}
1099
1100/// Known key types; this also functions as a global registry of key types for projects wishing to
1101/// avoid collisions with each other.
1102///
1103/// It's not universal in the sense that *all* key types need to be mentioned here, it's just a
1104/// handy place to put common key types.
1105pub mod key_types {
1106	use super::KeyTypeId;
1107
1108	/// Key type for Babe module, built-in. Identified as `babe`.
1109	pub const BABE: KeyTypeId = KeyTypeId(*b"babe");
1110	/// Key type for Grandpa module, built-in. Identified as `gran`.
1111	pub const GRANDPA: KeyTypeId = KeyTypeId(*b"gran");
1112	/// Key type for controlling an account in a Tetcore runtime, built-in. Identified as `acco`.
1113	pub const ACCOUNT: KeyTypeId = KeyTypeId(*b"acco");
1114	/// Key type for Aura module, built-in. Identified as `aura`.
1115	pub const AURA: KeyTypeId = KeyTypeId(*b"aura");
1116	/// Key type for ImOnline module, built-in. Identified as `imon`.
1117	pub const IM_ONLINE: KeyTypeId = KeyTypeId(*b"imon");
1118	/// Key type for AuthorityDiscovery module, built-in. Identified as `audi`.
1119	pub const AUTHORITY_DISCOVERY: KeyTypeId = KeyTypeId(*b"audi");
1120	/// Key type for staking, built-in. Identified as `stak`.
1121	pub const STAKING: KeyTypeId = KeyTypeId(*b"stak");
1122	/// Key type for equivocation reporting, built-in. Identified as `fish`.
1123	pub const REPORTING: KeyTypeId = KeyTypeId(*b"fish");
1124	/// A key type ID useful for tests.
1125	pub const DUMMY: KeyTypeId = KeyTypeId(*b"dumy");
1126}
1127
1128#[cfg(test)]
1129mod tests {
1130	use crate::DeriveJunction;
1131	use hex_literal::hex;
1132	use super::*;
1133
1134	#[derive(Clone, Eq, PartialEq, Debug)]
1135	enum TestPair {
1136		Generated,
1137		GeneratedWithPhrase,
1138		GeneratedFromPhrase{phrase: String, password: Option<String>},
1139		Standard{phrase: String, password: Option<String>, path: Vec<DeriveJunction>},
1140		Seed(Vec<u8>),
1141	}
1142	impl Default for TestPair {
1143		fn default() -> Self {
1144			TestPair::Generated
1145		}
1146	}
1147	impl CryptoType for TestPair {
1148		type Pair = Self;
1149	}
1150
1151	#[derive(Clone, PartialEq, Eq, Hash, Default)]
1152	struct TestPublic;
1153	impl AsRef<[u8]> for TestPublic {
1154		fn as_ref(&self) -> &[u8] {
1155			&[]
1156		}
1157	}
1158	impl AsMut<[u8]> for TestPublic {
1159		fn as_mut(&mut self) -> &mut [u8] {
1160			&mut []
1161		}
1162	}
1163	impl<'a> TryFrom<&'a [u8]> for TestPublic {
1164		type Error = ();
1165
1166		fn try_from(_: &'a [u8]) -> Result<Self, ()> {
1167			Ok(Self)
1168		}
1169	}
1170	impl CryptoType for TestPublic {
1171		type Pair = TestPair;
1172	}
1173	impl Derive for TestPublic {}
1174	impl Public for TestPublic {
1175		fn from_slice(_bytes: &[u8]) -> Self {
1176			Self
1177		}
1178		fn as_slice(&self) -> &[u8] {
1179			&[]
1180		}
1181		fn to_raw_vec(&self) -> Vec<u8> {
1182			vec![]
1183		}
1184		fn to_public_crypto_pair(&self) -> CryptoTypePublicPair {
1185			CryptoTypePublicPair(
1186				CryptoTypeId(*b"dumm"), self.to_raw_vec(),
1187			)
1188		}
1189	}
1190	impl Pair for TestPair {
1191		type Public = TestPublic;
1192		type Seed = [u8; 8];
1193		type Signature = [u8; 0];
1194		type DeriveError = ();
1195
1196		fn generate() -> (Self, <Self as Pair>::Seed) { (TestPair::Generated, [0u8; 8]) }
1197		fn generate_with_phrase(_password: Option<&str>) -> (Self, String, <Self as Pair>::Seed) {
1198			(TestPair::GeneratedWithPhrase, "".into(), [0u8; 8])
1199		}
1200		fn from_phrase(phrase: &str, password: Option<&str>)
1201			-> Result<(Self, <Self as Pair>::Seed), SecretStringError>
1202		{
1203			Ok((TestPair::GeneratedFromPhrase {
1204				phrase: phrase.to_owned(),
1205				password: password.map(Into::into)
1206			}, [0u8; 8]))
1207		}
1208		fn derive<Iter: Iterator<Item=DeriveJunction>>(&self, path_iter: Iter, _: Option<[u8; 8]>)
1209			-> Result<(Self, Option<[u8; 8]>), Self::DeriveError>
1210		{
1211			Ok((match self.clone() {
1212				TestPair::Standard {phrase, password, path} =>
1213					TestPair::Standard { phrase, password, path: path.into_iter().chain(path_iter).collect() },
1214				TestPair::GeneratedFromPhrase {phrase, password} =>
1215					TestPair::Standard { phrase, password, path: path_iter.collect() },
1216				x => if path_iter.count() == 0 { x } else { return Err(()) },
1217			}, None))
1218		}
1219		fn from_seed(_seed: &<TestPair as Pair>::Seed) -> Self { TestPair::Seed(_seed.as_ref().to_owned()) }
1220		fn sign(&self, _message: &[u8]) -> Self::Signature { [] }
1221		fn verify<M: AsRef<[u8]>>(_: &Self::Signature, _: M, _: &Self::Public) -> bool { true }
1222		fn verify_weak<P: AsRef<[u8]>, M: AsRef<[u8]>>(
1223			_sig: &[u8],
1224			_message: M,
1225			_pubkey: P
1226		) -> bool { true }
1227		fn public(&self) -> Self::Public { TestPublic }
1228		fn from_seed_slice(seed: &[u8])
1229			-> Result<Self, SecretStringError>
1230		{
1231			Ok(TestPair::Seed(seed.to_owned()))
1232		}
1233		fn to_raw_vec(&self) -> Vec<u8> {
1234			vec![]
1235		}
1236	}
1237
1238	#[test]
1239	fn interpret_std_seed_should_work() {
1240		assert_eq!(
1241			TestPair::from_string("0x0123456789abcdef", None),
1242			Ok(TestPair::Seed(hex!["0123456789abcdef"][..].to_owned()))
1243		);
1244	}
1245
1246	#[test]
1247	fn password_override_should_work() {
1248		assert_eq!(
1249			TestPair::from_string("hello world///password", None),
1250			TestPair::from_string("hello world", Some("password")),
1251		);
1252		assert_eq!(
1253			TestPair::from_string("hello world///password", None),
1254			TestPair::from_string("hello world///other password", Some("password")),
1255		);
1256	}
1257
1258	#[test]
1259	fn interpret_std_secret_string_should_work() {
1260		assert_eq!(
1261			TestPair::from_string("hello world", None),
1262			Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![]})
1263		);
1264		assert_eq!(
1265			TestPair::from_string("hello world/1", None),
1266			Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::soft(1)]})
1267		);
1268		assert_eq!(
1269			TestPair::from_string("hello world/TET", None),
1270			Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::soft("TET")]})
1271		);
1272		assert_eq!(
1273			TestPair::from_string("hello world//1", None),
1274			Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::hard(1)]})
1275		);
1276		assert_eq!(
1277			TestPair::from_string("hello world//TET", None),
1278			Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::hard("TET")]})
1279		);
1280		assert_eq!(
1281			TestPair::from_string("hello world//1/TET", None),
1282			Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::hard(1), DeriveJunction::soft("TET")]})
1283		);
1284		assert_eq!(
1285			TestPair::from_string("hello world//TET/1", None),
1286			Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::hard("TET"), DeriveJunction::soft(1)]})
1287		);
1288		assert_eq!(
1289			TestPair::from_string("hello world///password", None),
1290			Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: Some("password".to_owned()), path: vec![]})
1291		);
1292		assert_eq!(
1293			TestPair::from_string("hello world//1/TET///password", None),
1294			Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: Some("password".to_owned()), path: vec![DeriveJunction::hard(1), DeriveJunction::soft("TET")]})
1295		);
1296		assert_eq!(
1297			TestPair::from_string("hello world/1//TET///password", None),
1298			Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: Some("password".to_owned()), path: vec![DeriveJunction::soft(1), DeriveJunction::hard("TET")]})
1299		);
1300	}
1301
1302	#[test]
1303	fn accountid_32_from_str_works() {
1304		use std::str::FromStr;
1305		assert!(AccountId32::from_str("5G9VdMwXvzza9pS8qE8ZHJk3CheHW9uucBn9ngW4C1gmmzpv").is_ok());
1306		assert!(AccountId32::from_str("5c55177d67b064bb5d189a3e1ddad9bc6646e02e64d6e308f5acbb1533ac430d").is_ok());
1307		assert!(AccountId32::from_str("0x5c55177d67b064bb5d189a3e1ddad9bc6646e02e64d6e308f5acbb1533ac430d").is_ok());
1308
1309		assert_eq!(
1310			AccountId32::from_str("99G9VdMwXvzza9pS8qE8ZHJk3CheHW9uucBn9ngW4C1gmmzpv").unwrap_err(),
1311			"invalid ss58 address.",
1312		);
1313		assert_eq!(
1314			AccountId32::from_str("gc55177d67b064bb5d189a3e1ddad9bc6646e02e64d6e308f5acbb1533ac430d").unwrap_err(),
1315			"invalid hex address.",
1316		);
1317		assert_eq!(
1318			AccountId32::from_str("0xgc55177d67b064bb5d189a3e1ddad9bc6646e02e64d6e308f5acbb1533ac430d").unwrap_err(),
1319			"invalid hex address.",
1320		);
1321
1322		// valid hex but invalid length will be treated as ss58.
1323		assert_eq!(
1324			AccountId32::from_str("55c55177d67b064bb5d189a3e1ddad9bc6646e02e64d6e308f5acbb1533ac430d").unwrap_err(),
1325			"invalid ss58 address.",
1326		);
1327	}
1328}