diff --git a/cumulus/client/network/src/tests.rs b/cumulus/client/network/src/tests.rs index d986635f96..3f5757d5ea 100644 --- a/cumulus/client/network/src/tests.rs +++ b/cumulus/client/network/src/tests.rs @@ -144,7 +144,7 @@ impl RelayChainInterface for DummyRelayChainInterface { persisted_validation_data_hash: PHash::random(), pov_hash: PHash::random(), erasure_root: PHash::random(), - signature: sp_core::sr25519::Signature([0u8; 64]).into(), + signature: sp_core::sr25519::Signature::default().into(), validation_code_hash: ValidationCodeHash::from(PHash::random()), }, commitments: CandidateCommitments { @@ -325,7 +325,7 @@ async fn make_gossip_message_and_header( persisted_validation_data_hash: PHash::random(), pov_hash: PHash::random(), erasure_root: PHash::random(), - signature: sp_core::sr25519::Signature([0u8; 64]).into(), + signature: sp_core::sr25519::Signature::default().into(), para_head: polkadot_parachain_primitives::primitives::HeadData(header.encode()).hash(), validation_code_hash: ValidationCodeHash::from(PHash::random()), }, @@ -516,7 +516,7 @@ async fn check_statement_seconded() { persisted_validation_data_hash: PHash::random(), pov_hash: PHash::random(), erasure_root: PHash::random(), - signature: sp_core::sr25519::Signature([0u8; 64]).into(), + signature: sp_core::sr25519::Signature::default().into(), validation_code_hash: ValidationCodeHash::from(PHash::random()), }, }, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs index 239bd946e7..101b8d86d5 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs @@ -190,12 +190,7 @@ fn construct_extrinsic( ); let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap(); let signature = payload.using_encoded(|e| sender.sign(e)); - UncheckedExtrinsic::new_signed( - call, - account_id.into(), - Signature::Sr25519(signature.clone()), - extra, - ) + UncheckedExtrinsic::new_signed(call, account_id.into(), Signature::Sr25519(signature), extra) } fn construct_and_apply_extrinsic( diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs index f11954cf16..fad357b095 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs @@ -67,12 +67,7 @@ fn construct_extrinsic( ); let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap(); let signature = payload.using_encoded(|e| sender.sign(e)); - UncheckedExtrinsic::new_signed( - call, - account_id.into(), - Signature::Sr25519(signature.clone()), - extra, - ) + UncheckedExtrinsic::new_signed(call, account_id.into(), Signature::Sr25519(signature), extra) } fn construct_and_apply_extrinsic( diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs index 149a3bbeb7..235b7f146c 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs @@ -81,12 +81,7 @@ fn construct_extrinsic( ); let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap(); let signature = payload.using_encoded(|e| sender.sign(e)); - UncheckedExtrinsic::new_signed( - call, - account_id.into(), - Signature::Sr25519(signature.clone()), - extra, - ) + UncheckedExtrinsic::new_signed(call, account_id.into(), Signature::Sr25519(signature), extra) } fn construct_and_apply_extrinsic( diff --git a/polkadot/node/service/src/benchmarking.rs b/polkadot/node/service/src/benchmarking.rs index 400daf1aee..a0c4d3b044 100644 --- a/polkadot/node/service/src/benchmarking.rs +++ b/polkadot/node/service/src/benchmarking.rs @@ -222,7 +222,7 @@ fn westend_sign_call( runtime::UncheckedExtrinsic::new_signed( call, sp_runtime::AccountId32::from(acc.public()).into(), - polkadot_core_primitives::Signature::Sr25519(signature.clone()), + polkadot_core_primitives::Signature::Sr25519(signature), extra, ) .into() @@ -274,7 +274,7 @@ fn rococo_sign_call( runtime::UncheckedExtrinsic::new_signed( call, sp_runtime::AccountId32::from(acc.public()).into(), - polkadot_core_primitives::Signature::Sr25519(signature.clone()), + polkadot_core_primitives::Signature::Sr25519(signature), extra, ) .into() diff --git a/polkadot/node/test/service/src/lib.rs b/polkadot/node/test/service/src/lib.rs index ca904bae28..eed11e62c2 100644 --- a/polkadot/node/test/service/src/lib.rs +++ b/polkadot/node/test/service/src/lib.rs @@ -410,7 +410,7 @@ pub fn construct_extrinsic( UncheckedExtrinsic::new_signed( function.clone(), polkadot_test_runtime::Address::Id(caller.public().into()), - polkadot_primitives::Signature::Sr25519(signature.clone()), + polkadot_primitives::Signature::Sr25519(signature), extra.clone(), ) } diff --git a/polkadot/primitives/src/v6/mod.rs b/polkadot/primitives/src/v6/mod.rs index cab34deeb5..742dbed1cd 100644 --- a/polkadot/primitives/src/v6/mod.rs +++ b/polkadot/primitives/src/v6/mod.rs @@ -1953,11 +1953,11 @@ mod tests { descriptor: CandidateDescriptor { para_id: 0.into(), relay_parent: zeros, - collator: CollatorId::from(sr25519::Public::from_raw([0; 32])), + collator: CollatorId::from(sr25519::Public::default()), persisted_validation_data_hash: zeros, pov_hash: zeros, erasure_root: zeros, - signature: CollatorSignature::from(sr25519::Signature([0u8; 64])), + signature: CollatorSignature::from(sr25519::Signature::default()), para_head: zeros, validation_code_hash: ValidationCode(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]).hash(), }, diff --git a/polkadot/primitives/test-helpers/src/lib.rs b/polkadot/primitives/test-helpers/src/lib.rs index c0118f5960..b7c5d82341 100644 --- a/polkadot/primitives/test-helpers/src/lib.rs +++ b/polkadot/primitives/test-helpers/src/lib.rs @@ -136,17 +136,17 @@ pub fn dummy_head_data() -> HeadData { /// Create a meaningless collator id. pub fn dummy_collator() -> CollatorId { - CollatorId::from(sr25519::Public::from_raw([0; 32])) + CollatorId::from(sr25519::Public::default()) } /// Create a meaningless validator id. pub fn dummy_validator() -> ValidatorId { - ValidatorId::from(sr25519::Public::from_raw([0; 32])) + ValidatorId::from(sr25519::Public::default()) } /// Create a meaningless collator signature. pub fn dummy_collator_signature() -> CollatorSignature { - CollatorSignature::from(sr25519::Signature([0u8; 64])) + CollatorSignature::from(sr25519::Signature::default()) } /// Create a meaningless persisted validation data. diff --git a/polkadot/runtime/common/src/purchase.rs b/polkadot/runtime/common/src/purchase.rs index 8de93bd68b..b90bbb3a7c 100644 --- a/polkadot/runtime/common/src/purchase.rs +++ b/polkadot/runtime/common/src/purchase.rs @@ -425,8 +425,8 @@ pub mod pallet { impl Pallet { fn verify_signature(who: &T::AccountId, signature: &[u8]) -> Result<(), DispatchError> { // sr25519 always expects a 64 byte signature. - let signature: AnySignature = sr25519::Signature::from_slice(signature) - .ok_or(Error::::InvalidSignature)? + let signature: AnySignature = sr25519::Signature::try_from(signature) + .map_err(|_| Error::::InvalidSignature)? .into(); // In Polkadot, the AccountId is always the same as the 32 byte public key. diff --git a/polkadot/runtime/parachains/src/builder.rs b/polkadot/runtime/parachains/src/builder.rs index 23ec80e66f..05f6845f3b 100644 --- a/polkadot/runtime/parachains/src/builder.rs +++ b/polkadot/runtime/parachains/src/builder.rs @@ -272,7 +272,7 @@ impl BenchBuilder { persisted_validation_data_hash: Default::default(), pov_hash: Default::default(), erasure_root: Default::default(), - signature: CollatorSignature::from(sr25519::Signature([42u8; 64])), + signature: CollatorSignature::from(sr25519::Signature::from_raw([42u8; 64])), para_head: Default::default(), validation_code_hash: mock_validation_code().hash(), } diff --git a/substrate/client/authority-discovery/src/tests.rs b/substrate/client/authority-discovery/src/tests.rs index 4fbc196c5e..edd50d073c 100644 --- a/substrate/client/authority-discovery/src/tests.rs +++ b/substrate/client/authority-discovery/src/tests.rs @@ -100,7 +100,7 @@ fn cryptos_are_compatible() { let sp_core_signature = sp_core_secret.sign(message); // no error expected... assert!(sp_core::ed25519::Pair::verify( - &sp_core::ed25519::Signature::from_slice(&libp2p_signature).unwrap(), + &sp_core::ed25519::Signature::try_from(libp2p_signature.as_slice()).unwrap(), message, &sp_core_public )); diff --git a/substrate/client/executor/runtime-test/src/lib.rs b/substrate/client/executor/runtime-test/src/lib.rs index ec9b2378d4..40683fbb66 100644 --- a/substrate/client/executor/runtime-test/src/lib.rs +++ b/substrate/client/executor/runtime-test/src/lib.rs @@ -181,7 +181,7 @@ sp_core::wasm_export_functions! { sig.copy_from_slice(&input[32..96]); let msg = b"all ok!"; - ed25519_verify(&ed25519::Signature(sig), &msg[..], &ed25519::Public(pubkey)) + ed25519_verify(&ed25519::Signature::from(sig), &msg[..], &ed25519::Public::from(pubkey)) } fn test_sr25519_verify(input: Vec) -> bool { @@ -192,7 +192,7 @@ sp_core::wasm_export_functions! { sig.copy_from_slice(&input[32..96]); let msg = b"all ok!"; - sr25519_verify(&sr25519::Signature(sig), &msg[..], &sr25519::Public(pubkey)) + sr25519_verify(&sr25519::Signature::from(sig), &msg[..], &sr25519::Public::from(pubkey)) } fn test_ordered_trie_root() -> Vec { diff --git a/substrate/client/service/test/src/client/mod.rs b/substrate/client/service/test/src/client/mod.rs index ba83bec827..51dcc4966e 100644 --- a/substrate/client/service/test/src/client/mod.rs +++ b/substrate/client/service/test/src/client/mod.rs @@ -2226,11 +2226,11 @@ fn reorg_triggers_a_notification_even_for_sources_that_should_not_trigger_notifi #[test] fn use_dalek_ext_works() { fn zero_ed_pub() -> sp_core::ed25519::Public { - sp_core::ed25519::Public([0u8; 32]) + sp_core::ed25519::Public::default() } fn zero_ed_sig() -> sp_core::ed25519::Signature { - sp_core::ed25519::Signature::from_raw([0u8; 64]) + sp_core::ed25519::Signature::default() } let mut client = TestClientBuilder::new().build(); diff --git a/substrate/frame/contracts/src/exec.rs b/substrate/frame/contracts/src/exec.rs index 7da321af54..d24657b65b 100644 --- a/substrate/frame/contracts/src/exec.rs +++ b/substrate/frame/contracts/src/exec.rs @@ -1466,14 +1466,14 @@ where fn sr25519_verify(&self, signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> bool { sp_io::crypto::sr25519_verify( - &SR25519Signature(*signature), + &SR25519Signature::from(*signature), message, - &SR25519Public(*pub_key), + &SR25519Public::from(*pub_key), ) } fn ecdsa_to_eth_address(&self, pk: &[u8; 33]) -> Result<[u8; 20], ()> { - ECDSAPublic(*pk).to_eth_address() + ECDSAPublic::from(*pk).to_eth_address() } #[cfg(test)] diff --git a/substrate/frame/sassafras/src/benchmarking.rs b/substrate/frame/sassafras/src/benchmarking.rs index 921f2f0793..1c9626ad26 100644 --- a/substrate/frame/sassafras/src/benchmarking.rs +++ b/substrate/frame/sassafras/src/benchmarking.rs @@ -139,8 +139,8 @@ mod benchmarks { TicketsIds::::insert((epoch_tag as u8, i), id); let body = TicketBody { attempt_idx: i, - erased_public: EphemeralPublic([i as u8; 32]), - revealed_public: EphemeralPublic([i as u8; 32]), + erased_public: EphemeralPublic::from([i as u8; 32]), + revealed_public: EphemeralPublic::from([i as u8; 32]), }; TicketsData::::set(id, Some(body)); }); @@ -236,8 +236,8 @@ mod benchmarks { .map(|i| { let body = TicketBody { attempt_idx: i, - erased_public: EphemeralPublic([i as u8; 32]), - revealed_public: EphemeralPublic([i as u8; 32]), + erased_public: EphemeralPublic::from([i as u8; 32]), + revealed_public: EphemeralPublic::from([i as u8; 32]), }; let id_bytes = crate::hashing::blake2_128(&i.to_le_bytes()); let id = TicketId::from_le_bytes(id_bytes); diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr index 4229d1e8a5..d269e6d272 100644 --- a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr @@ -13,8 +13,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied | = help: the following other types implement trait `WrapperTypeDecode`: Box - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc = note: required for `Bar` to implement `Decode` = note: required for `Bar` to implement `FullCodec` @@ -65,8 +65,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied bytes::bytes::Bytes Cow<'a, T> parity_scale_codec::Ref<'a, T, U> - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc Vec and $N others @@ -106,8 +106,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied | = help: the following other types implement trait `WrapperTypeDecode`: Box - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc = note: required for `Bar` to implement `Decode` = note: required for `Bar` to implement `FullCodec` @@ -148,8 +148,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied bytes::bytes::Bytes Cow<'a, T> parity_scale_codec::Ref<'a, T, U> - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc Vec and $N others @@ -168,8 +168,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied | = help: the following other types implement trait `WrapperTypeDecode`: Box - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc = note: required for `Bar` to implement `Decode` = note: required for `Bar` to implement `FullCodec` @@ -210,8 +210,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied bytes::bytes::Bytes Cow<'a, T> parity_scale_codec::Ref<'a, T, U> - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc Vec and $N others diff --git a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr index 855d289d0a..13d761d65d 100644 --- a/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr @@ -13,8 +13,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied | = help: the following other types implement trait `WrapperTypeDecode`: Box - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc = note: required for `Bar` to implement `Decode` = note: required for `Bar` to implement `FullCodec` @@ -65,8 +65,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied bytes::bytes::Bytes Cow<'a, T> parity_scale_codec::Ref<'a, T, U> - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc Vec and $N others @@ -106,8 +106,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied | = help: the following other types implement trait `WrapperTypeDecode`: Box - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc = note: required for `Bar` to implement `Decode` = note: required for `Bar` to implement `FullCodec` @@ -148,8 +148,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied bytes::bytes::Bytes Cow<'a, T> parity_scale_codec::Ref<'a, T, U> - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc Vec and $N others @@ -168,8 +168,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied | = help: the following other types implement trait `WrapperTypeDecode`: Box - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc = note: required for `Bar` to implement `Decode` = note: required for `Bar` to implement `FullCodec` @@ -210,8 +210,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeEncode` is not satisfied bytes::bytes::Bytes Cow<'a, T> parity_scale_codec::Ref<'a, T, U> - Rc frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes + Rc Arc Vec and $N others diff --git a/substrate/primitives/core/src/bandersnatch.rs b/substrate/primitives/core/src/bandersnatch.rs index 5cae6047f1..c9d5f27b47 100644 --- a/substrate/primitives/core/src/bandersnatch.rs +++ b/substrate/primitives/core/src/bandersnatch.rs @@ -26,7 +26,8 @@ use crate::crypto::Ss58Codec; use crate::crypto::VrfSecret; use crate::crypto::{ ByteArray, CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, Pair as TraitPair, - Public as TraitPublic, SecretStringError, UncheckedFrom, VrfPublic, + Public as TraitPublic, PublicBytes, SecretStringError, SignatureBytes, UncheckedFrom, + VrfPublic, }; #[cfg(feature = "serde")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; @@ -37,7 +38,6 @@ use bandersnatch_vrfs::{CanonicalSerialize, SecretKey}; use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; use scale_info::TypeInfo; -use sp_runtime_interface::pass_by::PassByInner; use sp_std::{vec, vec::Vec}; /// Identifier used to match public keys against bandersnatch-vrf keys. @@ -46,69 +46,23 @@ pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"band"); /// Context used to produce a plain signature without any VRF input/output. pub const SIGNING_CTX: &[u8] = b"BandersnatchSigningContext"; -const SEED_SERIALIZED_SIZE: usize = 32; +/// The byte length of secret key seed. +pub const SEED_SERIALIZED_SIZE: usize = 32; -const PUBLIC_SERIALIZED_SIZE: usize = 33; -const SIGNATURE_SERIALIZED_SIZE: usize = 65; -const PREOUT_SERIALIZED_SIZE: usize = 33; +/// The byte length of serialized public key. +pub const PUBLIC_SERIALIZED_SIZE: usize = 33; + +/// The byte length of serialized signature. +pub const SIGNATURE_SERIALIZED_SIZE: usize = 65; + +/// The byte length of serialized pre-output. +pub const PREOUT_SERIALIZED_SIZE: usize = 33; + +#[doc(hidden)] +pub struct BandersnatchTag; /// Bandersnatch public key. -#[derive( - Clone, - Copy, - PartialEq, - Eq, - PartialOrd, - Ord, - Encode, - Decode, - PassByInner, - MaxEncodedLen, - TypeInfo, - Hash, -)] -pub struct Public(pub [u8; PUBLIC_SERIALIZED_SIZE]); - -impl UncheckedFrom<[u8; PUBLIC_SERIALIZED_SIZE]> for Public { - fn unchecked_from(raw: [u8; PUBLIC_SERIALIZED_SIZE]) -> Self { - Public(raw) - } -} - -impl AsRef<[u8; PUBLIC_SERIALIZED_SIZE]> for Public { - fn as_ref(&self) -> &[u8; PUBLIC_SERIALIZED_SIZE] { - &self.0 - } -} - -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Public { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - -impl TryFrom<&[u8]> for Public { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != PUBLIC_SERIALIZED_SIZE { - return Err(()) - } - let mut r = [0u8; PUBLIC_SERIALIZED_SIZE]; - r.copy_from_slice(data); - Ok(Self::unchecked_from(r)) - } -} - -impl ByteArray for Public { - const LEN: usize = PUBLIC_SERIALIZED_SIZE; -} +pub type Public = PublicBytes; impl TraitPublic for Public {} @@ -150,45 +104,7 @@ impl<'de> Deserialize<'de> for Public { /// /// The signature is created via the [`VrfSecret::vrf_sign`] using [`SIGNING_CTX`] as transcript /// `label`. -#[derive( - Clone, Copy, PartialEq, Eq, Encode, Decode, PassByInner, MaxEncodedLen, TypeInfo, Hash, -)] -pub struct Signature([u8; SIGNATURE_SERIALIZED_SIZE]); - -impl UncheckedFrom<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature { - fn unchecked_from(raw: [u8; SIGNATURE_SERIALIZED_SIZE]) -> Self { - Signature(raw) - } -} - -impl AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Signature { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - -impl TryFrom<&[u8]> for Signature { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != SIGNATURE_SERIALIZED_SIZE { - return Err(()) - } - let mut r = [0u8; SIGNATURE_SERIALIZED_SIZE]; - r.copy_from_slice(data); - Ok(Self::unchecked_from(r)) - } -} - -impl ByteArray for Signature { - const LEN: usize = SIGNATURE_SERIALIZED_SIZE; -} +pub type Signature = SignatureBytes; impl CryptoType for Signature { type Pair = Pair; @@ -542,8 +458,7 @@ pub mod vrf { thin_signature.preouts.into_iter().map(VrfPreOutput).collect(); let pre_outputs = VrfIosVec::truncate_from(pre_outputs); - let mut signature = - VrfSignature { signature: Signature([0; SIGNATURE_SERIALIZED_SIZE]), pre_outputs }; + let mut signature = VrfSignature { signature: Signature::default(), pre_outputs }; thin_signature .proof @@ -582,7 +497,7 @@ pub mod vrf { // This is another hack used because backend signature type is generic over // the number of ios. let Ok(proof) = ThinVrfSignature::<0>::deserialize_compressed_unchecked( - signature.signature.as_ref(), + signature.signature.as_slice(), ) .map(|s| s.proof) else { return false diff --git a/substrate/primitives/core/src/bls.rs b/substrate/primitives/core/src/bls.rs index 2256e4cd82..9492a14ff0 100644 --- a/substrate/primitives/core/src/bls.rs +++ b/substrate/primitives/core/src/bls.rs @@ -26,28 +26,21 @@ #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; use crate::crypto::{ - ByteArray, CryptoType, Derive, DeriveError, DeriveJunction, Pair as TraitPair, - Public as TraitPublic, SecretStringError, UncheckedFrom, + CryptoType, Derive, DeriveError, DeriveJunction, Pair as TraitPair, Public as TraitPublic, + PublicBytes, SecretStringError, SignatureBytes, UncheckedFrom, }; -use sp_std::vec::Vec; - -use codec::{Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; - #[cfg(feature = "serde")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; #[cfg(all(not(feature = "std"), feature = "serde"))] use sp_std::alloc::{format, string::String}; +use sp_std::vec::Vec; use w3f_bls::{ DoublePublicKey, DoublePublicKeyScheme, DoubleSignature, EngineBLS, Keypair, Message, SecretKey, SerializableToBytes, TinyBLS381, }; -use sp_runtime_interface::pass_by::{self, PassBy, PassByInner}; -use sp_std::{convert::TryFrom, marker::PhantomData, ops::Deref}; - /// BLS-377 specialized types pub mod bls377 { pub use super::{PUBLIC_KEY_SERIALIZED_SIZE, SIGNATURE_SERIALIZED_SIZE}; @@ -57,6 +50,9 @@ pub mod bls377 { /// An identifier used to match public keys against BLS12-377 keys pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"bls7"); + #[doc(hidden)] + pub type Bls377Tag = TinyBLS377; + /// BLS12-377 key pair. pub type Pair = super::Pair; /// BLS12-377 public key. @@ -113,114 +109,11 @@ pub const SIGNATURE_SERIALIZED_SIZE: usize = /// will need it later (such as for HDKD). type Seed = [u8; SECRET_KEY_SERIALIZED_SIZE]; +#[doc(hidden)] +pub struct BlsTag; + /// A public key. -#[derive(Copy, Encode, Decode, MaxEncodedLen, TypeInfo)] -#[scale_info(skip_type_params(T))] -pub struct Public { - inner: [u8; PUBLIC_KEY_SERIALIZED_SIZE], - _phantom: PhantomData T>, -} - -impl Clone for Public { - fn clone(&self) -> Self { - Self { inner: self.inner, _phantom: PhantomData } - } -} - -impl PartialEq for Public { - fn eq(&self, other: &Self) -> bool { - self.inner == other.inner - } -} - -impl Eq for Public {} - -impl PartialOrd for Public { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for Public { - fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { - self.inner.cmp(&other.inner) - } -} - -impl sp_std::hash::Hash for Public { - fn hash(&self, state: &mut H) { - self.inner.hash(state) - } -} - -impl ByteArray for Public { - const LEN: usize = PUBLIC_KEY_SERIALIZED_SIZE; -} - -impl PassByInner for Public { - type Inner = [u8; PUBLIC_KEY_SERIALIZED_SIZE]; - - fn into_inner(self) -> Self::Inner { - self.inner - } - - fn inner(&self) -> &Self::Inner { - &self.inner - } - - fn from_inner(inner: Self::Inner) -> Self { - Self { inner, _phantom: PhantomData } - } -} - -impl PassBy for Public { - type PassBy = pass_by::Inner; -} - -impl AsRef<[u8; PUBLIC_KEY_SERIALIZED_SIZE]> for Public { - fn as_ref(&self) -> &[u8; PUBLIC_KEY_SERIALIZED_SIZE] { - &self.inner - } -} - -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.inner[..] - } -} - -impl AsMut<[u8]> for Public { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.inner[..] - } -} - -impl Deref for Public { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - &self.inner - } -} - -impl TryFrom<&[u8]> for Public { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != PUBLIC_KEY_SERIALIZED_SIZE { - return Err(()) - } - let mut r = [0u8; PUBLIC_KEY_SERIALIZED_SIZE]; - r.copy_from_slice(data); - Ok(Self::unchecked_from(r)) - } -} - -impl From> for [u8; PUBLIC_KEY_SERIALIZED_SIZE] { - fn from(x: Public) -> Self { - x.inner - } -} +pub type Public = PublicBytes; impl From> for Public { fn from(x: Pair) -> Self { @@ -228,12 +121,6 @@ impl From> for Public { } } -impl UncheckedFrom<[u8; PUBLIC_KEY_SERIALIZED_SIZE]> for Public { - fn unchecked_from(data: [u8; PUBLIC_KEY_SERIALIZED_SIZE]) -> Self { - Public { inner: data, _phantom: PhantomData } - } -} - #[cfg(feature = "std")] impl std::str::FromStr for Public { type Err = crate::crypto::PublicError; @@ -254,7 +141,7 @@ impl std::fmt::Display for Public { impl sp_std::fmt::Debug for Public { fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { let s = self.to_ss58check(); - write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.inner), &s[0..8]) + write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) } } @@ -295,49 +182,7 @@ impl CryptoType for Public { } /// A generic BLS signature. -#[derive(Copy, Encode, Decode, MaxEncodedLen, TypeInfo)] -#[scale_info(skip_type_params(T))] -pub struct Signature { - inner: [u8; SIGNATURE_SERIALIZED_SIZE], - _phantom: PhantomData T>, -} - -impl Clone for Signature { - fn clone(&self) -> Self { - Self { inner: self.inner, _phantom: PhantomData } - } -} - -impl PartialEq for Signature { - fn eq(&self, other: &Self) -> bool { - self.inner == other.inner - } -} - -impl Eq for Signature {} - -impl sp_std::hash::Hash for Signature { - fn hash(&self, state: &mut H) { - self.inner.hash(state) - } -} - -impl ByteArray for Signature { - const LEN: usize = SIGNATURE_SERIALIZED_SIZE; -} - -impl TryFrom<&[u8]> for Signature { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != SIGNATURE_SERIALIZED_SIZE { - return Err(()) - } - let mut inner = [0u8; SIGNATURE_SERIALIZED_SIZE]; - inner.copy_from_slice(data); - Ok(Signature::unchecked_from(inner)) - } -} +pub type Signature = SignatureBytes; #[cfg(feature = "serde")] impl Serialize for Signature { @@ -362,34 +207,10 @@ impl<'de, T> Deserialize<'de> for Signature { } } -impl From> for [u8; SIGNATURE_SERIALIZED_SIZE] { - fn from(signature: Signature) -> [u8; SIGNATURE_SERIALIZED_SIZE] { - signature.inner - } -} - -impl AsRef<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature { - fn as_ref(&self) -> &[u8; SIGNATURE_SERIALIZED_SIZE] { - &self.inner - } -} - -impl AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { - &self.inner[..] - } -} - -impl AsMut<[u8]> for Signature { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.inner[..] - } -} - impl sp_std::fmt::Debug for Signature { #[cfg(feature = "std")] fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.inner)) + write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) } #[cfg(not(feature = "std"))] @@ -398,12 +219,6 @@ impl sp_std::fmt::Debug for Signature { } } -impl UncheckedFrom<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature { - fn unchecked_from(data: [u8; SIGNATURE_SERIALIZED_SIZE]) -> Self { - Signature { inner: data, _phantom: PhantomData } - } -} - impl CryptoType for Signature { type Pair = Pair; } @@ -423,6 +238,7 @@ trait HardJunctionId { /// Derive a single hard junction. fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { + use codec::Encode; (T::ID, secret_seed, cc).using_encoded(sp_crypto_hashing::blake2_256) } @@ -489,7 +305,7 @@ impl TraitPair for Pair { Err(_) => return false, }; - let sig_array = match sig.inner[..].try_into() { + let sig_array = match sig.0[..].try_into() { Ok(s) => s, Err(_) => return false, }; diff --git a/substrate/primitives/core/src/crypto.rs b/substrate/primitives/core/src/crypto.rs index fab865d8c1..a2bdc6ed58 100644 --- a/substrate/primitives/core/src/crypto.rs +++ b/substrate/primitives/core/src/crypto.rs @@ -39,7 +39,10 @@ pub use ss58_registry::{from_known_address_format, Ss58AddressFormat, Ss58Addres /// Trait to zeroize a memory buffer. pub use zeroize::Zeroize; -pub use crate::address_uri::{AddressUri, Error as AddressUriError}; +pub use crate::{ + address_uri::{AddressUri, Error as AddressUriError}, + crypto_bytes::{CryptoBytes, PublicBytes, SignatureBytes}, +}; /// The root phrase for our publicly known keys. pub const DEV_PHRASE: &str = diff --git a/substrate/primitives/core/src/crypto_bytes.rs b/substrate/primitives/core/src/crypto_bytes.rs new file mode 100644 index 0000000000..069878e165 --- /dev/null +++ b/substrate/primitives/core/src/crypto_bytes.rs @@ -0,0 +1,244 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Generic byte array which can be specialized with a marker type. + +use crate::{ + crypto::{FromEntropy, UncheckedFrom}, + hash::{H256, H512}, +}; + +use codec::{Decode, Encode, MaxEncodedLen}; +use core::marker::PhantomData; +use scale_info::TypeInfo; +use sp_runtime_interface::pass_by::{self, PassBy, PassByInner}; + +/// Generic byte array holding some crypto-related raw data. +/// +/// The type is generic over a constant length `N` and a "tag" `T` which +/// can be used to specialize the byte array without requiring newtypes. +/// +/// The tag `T` is held in a `PhantomDataT>`, a trick allowing +/// `CryptoBytes` to be `Send` and `Sync` regardless of `T` properties +/// ([ref](https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns)). +#[derive(Encode, Decode, MaxEncodedLen)] +#[repr(transparent)] +pub struct CryptoBytes(pub [u8; N], PhantomData T>); + +impl Copy for CryptoBytes {} + +impl Clone for CryptoBytes { + fn clone(&self) -> Self { + Self(self.0, PhantomData) + } +} + +impl TypeInfo for CryptoBytes { + type Identity = [u8; N]; + + fn type_info() -> scale_info::Type { + Self::Identity::type_info() + } +} + +impl PartialOrd for CryptoBytes { + fn partial_cmp(&self, other: &Self) -> Option { + self.0.partial_cmp(&other.0) + } +} + +impl Ord for CryptoBytes { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.0.cmp(&other.0) + } +} + +impl PartialEq for CryptoBytes { + fn eq(&self, other: &Self) -> bool { + self.0.eq(&other.0) + } +} + +impl core::hash::Hash for CryptoBytes { + fn hash(&self, state: &mut H) { + self.0.hash(state) + } +} + +impl Eq for CryptoBytes {} + +impl Default for CryptoBytes { + fn default() -> Self { + Self([0_u8; N], PhantomData) + } +} + +impl PassByInner for CryptoBytes { + type Inner = [u8; N]; + + fn into_inner(self) -> Self::Inner { + self.0 + } + + fn inner(&self) -> &Self::Inner { + &self.0 + } + + fn from_inner(inner: Self::Inner) -> Self { + Self(inner, PhantomData) + } +} + +impl PassBy for CryptoBytes { + type PassBy = pass_by::Inner; +} + +impl AsRef<[u8]> for CryptoBytes { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + +impl AsMut<[u8]> for CryptoBytes { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} + +impl From> for [u8; N] { + fn from(v: CryptoBytes) -> [u8; N] { + v.0 + } +} + +impl AsRef<[u8; N]> for CryptoBytes { + fn as_ref(&self) -> &[u8; N] { + &self.0 + } +} + +impl AsMut<[u8; N]> for CryptoBytes { + fn as_mut(&mut self) -> &mut [u8; N] { + &mut self.0 + } +} + +impl From<[u8; N]> for CryptoBytes { + fn from(value: [u8; N]) -> Self { + Self::from_raw(value) + } +} + +impl TryFrom<&[u8]> for CryptoBytes { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() != N { + return Err(()) + } + let mut r = [0u8; N]; + r.copy_from_slice(data); + Ok(Self::from_raw(r)) + } +} + +impl UncheckedFrom<[u8; N]> for CryptoBytes { + fn unchecked_from(data: [u8; N]) -> Self { + Self::from_raw(data) + } +} + +impl core::ops::Deref for CryptoBytes { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl CryptoBytes { + /// Construct from raw array. + pub fn from_raw(inner: [u8; N]) -> Self { + Self(inner, PhantomData) + } + + /// Construct from raw array. + pub fn to_raw(self) -> [u8; N] { + self.0 + } + + /// Return a slice filled with raw data. + pub fn as_array_ref(&self) -> &[u8; N] { + &self.0 + } +} + +impl crate::ByteArray for CryptoBytes { + const LEN: usize = N; +} + +impl FromEntropy for CryptoBytes { + fn from_entropy(input: &mut impl codec::Input) -> Result { + let mut result = Self::default(); + input.read(result.as_mut())?; + Ok(result) + } +} + +impl From> for H256 { + fn from(x: CryptoBytes<32, T>) -> H256 { + H256::from(x.0) + } +} + +impl From> for H512 { + fn from(x: CryptoBytes<64, T>) -> H512 { + H512::from(x.0) + } +} + +impl UncheckedFrom for CryptoBytes<32, T> { + fn unchecked_from(x: H256) -> Self { + Self::from_h256(x) + } +} + +impl CryptoBytes<32, T> { + /// A new instance from an H256. + pub fn from_h256(x: H256) -> Self { + Self::from_raw(x.into()) + } +} + +impl CryptoBytes<64, T> { + /// A new instance from an H512. + pub fn from_h512(x: H512) -> Self { + Self::from_raw(x.into()) + } +} + +/// Tag used for generic public key bytes. +pub struct PublicTag; + +/// Generic encoded public key. +pub type PublicBytes = CryptoBytes; + +/// Tag used for generic signature bytes. +pub struct SignatureTag; + +/// Generic encoded signature. +pub type SignatureBytes = CryptoBytes; diff --git a/substrate/primitives/core/src/ecdsa.rs b/substrate/primitives/core/src/ecdsa.rs index fa071e1b03..0e6b06a34d 100644 --- a/substrate/primitives/core/src/ecdsa.rs +++ b/substrate/primitives/core/src/ecdsa.rs @@ -17,15 +17,11 @@ //! Simple ECDSA secp256k1 API. -use codec::{Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; -use sp_runtime_interface::pass_by::PassByInner; - #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; use crate::crypto::{ - ByteArray, CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, Pair as TraitPair, - Public as TraitPublic, SecretStringError, UncheckedFrom, + CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, Pair as TraitPair, + Public as TraitPublic, PublicBytes, SecretStringError, SignatureBytes, }; #[cfg(not(feature = "std"))] @@ -51,45 +47,18 @@ pub const PUBLIC_KEY_SERIALIZED_SIZE: usize = 33; /// The byte length of signature pub const SIGNATURE_SERIALIZED_SIZE: usize = 65; +#[doc(hidden)] +pub struct EcdsaTag; + /// The secret seed. /// /// The raw secret seed, which can be used to create the `Pair`. type Seed = [u8; 32]; /// The ECDSA compressed public key. -#[derive( - Clone, - Copy, - Encode, - Decode, - PassByInner, - MaxEncodedLen, - TypeInfo, - Eq, - PartialEq, - PartialOrd, - Ord, - Hash, -)] -pub struct Public(pub [u8; PUBLIC_KEY_SERIALIZED_SIZE]); - -impl crate::crypto::FromEntropy for Public { - fn from_entropy(input: &mut impl codec::Input) -> Result { - let mut result = Self([0u8; PUBLIC_KEY_SERIALIZED_SIZE]); - input.read(&mut result.0[..])?; - Ok(result) - } -} +pub type Public = PublicBytes; impl Public { - /// A new instance from the given 33-byte `data`. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - pub fn from_raw(data: [u8; PUBLIC_KEY_SERIALIZED_SIZE]) -> Self { - Self(data) - } - /// Create a new instance from the given full public key. /// /// This will convert the full public key into the compressed format. @@ -111,54 +80,22 @@ impl Public { } } -impl ByteArray for Public { - const LEN: usize = PUBLIC_KEY_SERIALIZED_SIZE; -} - impl TraitPublic for Public {} impl Derive for Public {} -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Public { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - #[cfg(feature = "std")] impl From for Public { fn from(pubkey: PublicKey) -> Self { - Self(pubkey.serialize()) + Self::from(pubkey.serialize()) } } #[cfg(not(feature = "std"))] impl From for Public { fn from(pubkey: VerifyingKey) -> Self { - Self::unchecked_from( - pubkey.to_sec1_bytes()[..] - .try_into() - .expect("valid key is serializable to [u8,33]. qed."), - ) - } -} - -impl TryFrom<&[u8]> for Public { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != Self::LEN { - return Err(()) - } - let mut r = [0u8; Self::LEN]; - r.copy_from_slice(data); - Ok(Self::unchecked_from(r)) + Self::try_from(&pubkey.to_sec1_bytes()[..]) + .expect("Valid key is serializable to [u8; 33]. qed.") } } @@ -169,12 +106,6 @@ impl From for Public { } } -impl UncheckedFrom<[u8; PUBLIC_KEY_SERIALIZED_SIZE]> for Public { - fn unchecked_from(x: [u8; PUBLIC_KEY_SERIALIZED_SIZE]) -> Self { - Public(x) - } -} - #[cfg(feature = "std")] impl std::fmt::Display for Public { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { @@ -217,26 +148,7 @@ impl<'de> Deserialize<'de> for Public { } /// A signature (a 512-bit value, plus 8 bits for recovery ID). -#[derive(Hash, Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq)] -pub struct Signature(pub [u8; SIGNATURE_SERIALIZED_SIZE]); - -impl ByteArray for Signature { - const LEN: usize = SIGNATURE_SERIALIZED_SIZE; -} - -impl TryFrom<&[u8]> for Signature { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() == SIGNATURE_SERIALIZED_SIZE { - let mut inner = [0u8; SIGNATURE_SERIALIZED_SIZE]; - inner.copy_from_slice(data); - Ok(Signature(inner)) - } else { - Err(()) - } - } -} +pub type Signature = SignatureBytes; #[cfg(feature = "serde")] impl Serialize for Signature { @@ -261,44 +173,6 @@ impl<'de> Deserialize<'de> for Signature { } } -impl Clone for Signature { - fn clone(&self) -> Self { - let mut r = [0u8; SIGNATURE_SERIALIZED_SIZE]; - r.copy_from_slice(&self.0[..]); - Signature(r) - } -} - -impl Default for Signature { - fn default() -> Self { - Signature([0u8; SIGNATURE_SERIALIZED_SIZE]) - } -} - -impl From for [u8; SIGNATURE_SERIALIZED_SIZE] { - fn from(v: Signature) -> [u8; SIGNATURE_SERIALIZED_SIZE] { - v.0 - } -} - -impl AsRef<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature { - fn as_ref(&self) -> &[u8; SIGNATURE_SERIALIZED_SIZE] { - &self.0 - } -} - -impl AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Signature { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - impl sp_std::fmt::Debug for Signature { #[cfg(feature = "std")] fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { @@ -311,34 +185,7 @@ impl sp_std::fmt::Debug for Signature { } } -impl UncheckedFrom<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature { - fn unchecked_from(data: [u8; SIGNATURE_SERIALIZED_SIZE]) -> Signature { - Signature(data) - } -} - impl Signature { - /// A new instance from the given 65-byte `data`. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use it if - /// you are certain that the array actually is a signature. GIGO! - pub fn from_raw(data: [u8; SIGNATURE_SERIALIZED_SIZE]) -> Signature { - Signature(data) - } - - /// A new instance from the given slice that should be 65 bytes long. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use it if - /// you are certain that the array actually is a signature. GIGO! - pub fn from_slice(data: &[u8]) -> Option { - if data.len() != SIGNATURE_SERIALIZED_SIZE { - return None - } - let mut r = [0u8; SIGNATURE_SERIALIZED_SIZE]; - r.copy_from_slice(data); - Some(Signature(r)) - } - /// Recover the public key from this signature and a message. pub fn recover>(&self, message: M) -> Option { self.recover_prehashed(&sp_crypto_hashing::blake2_256(message.as_ref())) @@ -350,7 +197,8 @@ impl Signature { { let rid = RecoveryId::from_i32(self.0[64] as i32).ok()?; let sig = RecoverableSignature::from_compact(&self.0[..64], rid).ok()?; - let message = Message::from_digest_slice(message).expect("Message is 32 bytes; qed"); + let message = + Message::from_digest_slice(message).expect("Message is a 32 bytes hash; qed"); SECP256K1.recover_ecdsa(&message, &sig).ok().map(Public::from) } @@ -387,6 +235,7 @@ impl From for Signature { /// Derive a single hard junction. fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { + use codec::Encode; ("Secp256k1HDKD", secret_seed, cc).using_encoded(sp_crypto_hashing::blake2_256) } @@ -490,15 +339,18 @@ impl Pair { pub fn sign_prehashed(&self, message: &[u8; 32]) -> Signature { #[cfg(feature = "std")] { - let message = Message::from_digest_slice(message).expect("Message is 32 bytes; qed"); + let message = + Message::from_digest_slice(message).expect("Message is a 32 bytes hash; qed"); SECP256K1.sign_ecdsa_recoverable(&message, &self.secret).into() } #[cfg(not(feature = "std"))] { + // Signing fails only if the `message` number of bytes is less than the field length + // (unfallible as we're using a fixed message length of 32). self.secret .sign_prehash_recoverable(message) - .expect("signing may not fail (???). qed.") + .expect("Signing can't fail when using 32 bytes message hash. qed.") .into() } } diff --git a/substrate/primitives/core/src/ed25519.rs b/substrate/primitives/core/src/ed25519.rs index 9f42b36dc8..0dda7b9597 100644 --- a/substrate/primitives/core/src/ed25519.rs +++ b/substrate/primitives/core/src/ed25519.rs @@ -15,119 +15,45 @@ // See the License for the specific language governing permissions and // limitations under the License. -// tag::description[] //! Simple Ed25519 API. -// end::description[] - -use sp_std::vec::Vec; - -use crate::{ - crypto::ByteArray, - hash::{H256, H512}, -}; -use codec::{Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; use crate::crypto::{ - CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, FromEntropy, Pair as TraitPair, - Public as TraitPublic, SecretStringError, UncheckedFrom, + ByteArray, CryptoType, CryptoTypeId, Derive, DeriveError, DeriveJunction, Pair as TraitPair, + Public as TraitPublic, PublicBytes, SecretStringError, SignatureBytes, }; -#[cfg(feature = "full_crypto")] -use core::convert::TryFrom; + use ed25519_zebra::{SigningKey, VerificationKey}; #[cfg(feature = "serde")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; -use sp_runtime_interface::pass_by::PassByInner; #[cfg(all(not(feature = "std"), feature = "serde"))] use sp_std::alloc::{format, string::String}; -use sp_std::ops::Deref; +use sp_std::vec::Vec; /// An identifier used to match public keys against ed25519 keys pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ed25"); +/// The byte length of public key +pub const PUBLIC_KEY_SERIALIZED_SIZE: usize = 32; + +/// The byte length of signature +pub const SIGNATURE_SERIALIZED_SIZE: usize = 64; + /// A secret seed. It's not called a "secret key" because ring doesn't expose the secret keys /// of the key pair (yeah, dumb); as such we're forced to remember the seed manually if we /// will need it later (such as for HDKD). type Seed = [u8; 32]; +#[doc(hidden)] +pub struct Ed25519Tag; + /// A public key. -#[derive( - PartialEq, - Eq, - PartialOrd, - Ord, - Clone, - Copy, - Encode, - Decode, - PassByInner, - MaxEncodedLen, - TypeInfo, - Hash, -)] -pub struct Public(pub [u8; 32]); +pub type Public = PublicBytes; -/// A key pair. -#[derive(Copy, Clone)] -pub struct Pair { - public: VerificationKey, - secret: SigningKey, -} +impl TraitPublic for Public {} -impl FromEntropy for Public { - fn from_entropy(input: &mut impl codec::Input) -> Result { - let mut result = Self([0u8; 32]); - input.read(&mut result.0[..])?; - Ok(result) - } -} - -impl AsRef<[u8; 32]> for Public { - fn as_ref(&self) -> &[u8; 32] { - &self.0 - } -} - -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Public { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - -impl Deref for Public { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl TryFrom<&[u8]> for Public { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != Self::LEN { - return Err(()) - } - let mut r = [0u8; Self::LEN]; - r.copy_from_slice(data); - Ok(Self::unchecked_from(r)) - } -} - -impl From for [u8; 32] { - fn from(x: Public) -> Self { - x.0 - } -} +impl Derive for Public {} #[cfg(feature = "full_crypto")] impl From for Public { @@ -136,12 +62,6 @@ impl From for Public { } } -impl From for H256 { - fn from(x: Public) -> Self { - x.0.into() - } -} - #[cfg(feature = "std")] impl std::str::FromStr for Public { type Err = crate::crypto::PublicError; @@ -151,18 +71,6 @@ impl std::str::FromStr for Public { } } -impl UncheckedFrom<[u8; 32]> for Public { - fn unchecked_from(x: [u8; 32]) -> Self { - Public::from_raw(x) - } -} - -impl UncheckedFrom for Public { - fn unchecked_from(x: H256) -> Self { - Public::from_h256(x) - } -} - #[cfg(feature = "std")] impl std::fmt::Display for Public { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { @@ -204,23 +112,8 @@ impl<'de> Deserialize<'de> for Public { } } -/// A signature (a 512-bit value). -#[derive(Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq, Hash)] -pub struct Signature(pub [u8; 64]); - -impl TryFrom<&[u8]> for Signature { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() == 64 { - let mut inner = [0u8; 64]; - inner.copy_from_slice(data); - Ok(Signature(inner)) - } else { - Err(()) - } - } -} +/// A signature. +pub type Signature = SignatureBytes; #[cfg(feature = "serde")] impl Serialize for Signature { @@ -245,44 +138,6 @@ impl<'de> Deserialize<'de> for Signature { } } -impl Clone for Signature { - fn clone(&self) -> Self { - let mut r = [0u8; 64]; - r.copy_from_slice(&self.0[..]); - Signature(r) - } -} - -impl From for H512 { - fn from(v: Signature) -> H512 { - H512::from(v.0) - } -} - -impl From for [u8; 64] { - fn from(v: Signature) -> [u8; 64] { - v.0 - } -} - -impl AsRef<[u8; 64]> for Signature { - fn as_ref(&self) -> &[u8; 64] { - &self.0 - } -} - -impl AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Signature { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - impl sp_std::fmt::Debug for Signature { #[cfg(feature = "std")] fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { @@ -295,76 +150,16 @@ impl sp_std::fmt::Debug for Signature { } } -impl UncheckedFrom<[u8; 64]> for Signature { - fn unchecked_from(data: [u8; 64]) -> Signature { - Signature(data) - } +/// A key pair. +#[derive(Copy, Clone)] +pub struct Pair { + public: VerificationKey, + secret: SigningKey, } -impl Signature { - /// A new instance from the given 64-byte `data`. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use it if - /// you are certain that the array actually is a signature. GIGO! - pub fn from_raw(data: [u8; 64]) -> Signature { - Signature(data) - } - - /// A new instance from the given slice that should be 64 bytes long. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use it if - /// you are certain that the array actually is a signature. GIGO! - pub fn from_slice(data: &[u8]) -> Option { - if data.len() != 64 { - return None - } - let mut r = [0u8; 64]; - r.copy_from_slice(data); - Some(Signature(r)) - } - - /// A new instance from an H512. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use it if - /// you are certain that the array actually is a signature. GIGO! - pub fn from_h512(v: H512) -> Signature { - Signature(v.into()) - } -} - -impl Public { - /// A new instance from the given 32-byte `data`. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - pub fn from_raw(data: [u8; 32]) -> Self { - Public(data) - } - - /// A new instance from an H256. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - pub fn from_h256(x: H256) -> Self { - Public(x.into()) - } - - /// Return a slice filled with raw data. - pub fn as_array_ref(&self) -> &[u8; 32] { - self.as_ref() - } -} - -impl ByteArray for Public { - const LEN: usize = 32; -} - -impl TraitPublic for Public {} - -impl Derive for Public {} - /// Derive a single hard junction. fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { + use codec::Encode; ("Ed25519HDKD", secret_seed, cc).using_encoded(sp_crypto_hashing::blake2_256) } @@ -402,7 +197,7 @@ impl TraitPair for Pair { /// Get the public key. fn public(&self) -> Public { - Public(self.public.into()) + Public::from_raw(self.public.into()) } /// Sign a message. diff --git a/substrate/primitives/core/src/lib.rs b/substrate/primitives/core/src/lib.rs index c0b4123446..cf803c6fb4 100644 --- a/substrate/primitives/core/src/lib.rs +++ b/substrate/primitives/core/src/lib.rs @@ -62,6 +62,7 @@ mod address_uri; pub mod bandersnatch; #[cfg(feature = "bls-experimental")] pub mod bls; +pub mod crypto_bytes; pub mod defer; pub mod ecdsa; pub mod ed25519; diff --git a/substrate/primitives/core/src/paired_crypto.rs b/substrate/primitives/core/src/paired_crypto.rs index 6d2e6ddf33..27a7ab28df 100644 --- a/substrate/primitives/core/src/paired_crypto.rs +++ b/substrate/primitives/core/src/paired_crypto.rs @@ -17,25 +17,22 @@ //! API for using a pair of crypto schemes together. +use core::marker::PhantomData; + #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; use crate::crypto::{ ByteArray, CryptoType, Derive, DeriveError, DeriveJunction, Pair as PairT, Public as PublicT, - SecretStringError, UncheckedFrom, + PublicBytes, SecretStringError, SignatureBytes, UncheckedFrom, }; use sp_std::vec::Vec; -use codec::{Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; #[cfg(feature = "serde")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; #[cfg(all(not(feature = "std"), feature = "serde"))] use sp_std::alloc::{format, string::String}; -use sp_runtime_interface::pass_by::{self, PassBy, PassByInner}; -use sp_std::convert::TryFrom; - /// ECDSA and BLS12-377 paired crypto scheme #[cfg(feature = "bls-experimental")] pub mod ecdsa_bls377 { @@ -54,12 +51,20 @@ pub mod ecdsa_bls377 { const SIGNATURE_LEN: usize = ecdsa::SIGNATURE_SERIALIZED_SIZE + bls377::SIGNATURE_SERIALIZED_SIZE; + #[doc(hidden)] + pub struct EcdsaBls377Tag(ecdsa::EcdsaTag, bls377::Bls377Tag); + + impl super::PairedCryptoSubTagBound for EcdsaBls377Tag {} + /// (ECDSA,BLS12-377) key-pair pair. - pub type Pair = super::Pair; + pub type Pair = + super::Pair; + /// (ECDSA,BLS12-377) public key pair. - pub type Public = super::Public; + pub type Public = super::Public; + /// (ECDSA,BLS12-377) signature pair. - pub type Signature = super::Signature; + pub type Signature = super::Signature; impl super::CryptoType for Public { type Pair = Pair; @@ -110,7 +115,7 @@ pub mod ecdsa_bls377 { let Ok(left_pub) = public.0[..ecdsa::PUBLIC_KEY_SERIALIZED_SIZE].try_into() else { return false }; - let Ok(left_sig) = sig.0[0..ecdsa::SIGNATURE_SERIALIZED_SIZE].try_into() else { + let Ok(left_sig) = sig.0[..ecdsa::SIGNATURE_SERIALIZED_SIZE].try_into() else { return false }; if !ecdsa::Pair::verify_prehashed(&left_sig, &msg_hash, &left_pub) { @@ -140,110 +145,49 @@ const SECURE_SEED_LEN: usize = 32; /// will need it later (such as for HDKD). type Seed = [u8; SECURE_SEED_LEN]; +#[doc(hidden)] +pub trait PairedCryptoSubTagBound {} +#[doc(hidden)] +pub struct PairedCryptoTag; + /// A public key. -#[derive(Clone, Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Eq, PartialOrd, Ord)] -pub struct Public([u8; LEFT_PLUS_RIGHT_LEN]); - -impl sp_std::hash::Hash for Public { - fn hash(&self, state: &mut H) { - self.0.hash(state); - } -} - -impl ByteArray for Public { - const LEN: usize = LEFT_PLUS_RIGHT_LEN; -} - -impl TryFrom<&[u8]> for Public { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != LEFT_PLUS_RIGHT_LEN { - return Err(()) - } - let mut inner = [0u8; LEFT_PLUS_RIGHT_LEN]; - inner.copy_from_slice(data); - Ok(Public(inner)) - } -} - -impl AsRef<[u8; LEFT_PLUS_RIGHT_LEN]> - for Public -{ - fn as_ref(&self) -> &[u8; LEFT_PLUS_RIGHT_LEN] { - &self.0 - } -} - -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Public { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - -impl PassByInner for Public { - type Inner = [u8; LEFT_PLUS_RIGHT_LEN]; - - fn into_inner(self) -> Self::Inner { - self.0 - } - - fn inner(&self) -> &Self::Inner { - &self.0 - } - - fn from_inner(inner: Self::Inner) -> Self { - Self(inner) - } -} - -impl PassBy for Public { - type PassBy = pass_by::Inner; -} +pub type Public = + PublicBytes; impl< LeftPair: PairT, RightPair: PairT, const LEFT_PLUS_RIGHT_PUBLIC_LEN: usize, const SIGNATURE_LEN: usize, - > From> - for Public + SubTag: PairedCryptoSubTagBound, + > From> + for Public where - Pair: - PairT>, + Pair: + PairT>, { - fn from(x: Pair) -> Self { + fn from( + x: Pair, + ) -> Self { x.public() } } -impl UncheckedFrom<[u8; LEFT_PLUS_RIGHT_LEN]> - for Public -{ - fn unchecked_from(data: [u8; LEFT_PLUS_RIGHT_LEN]) -> Self { - Public(data) - } -} - #[cfg(feature = "std")] -impl std::fmt::Display for Public +impl std::fmt::Display + for Public where - Public: CryptoType, + Public: CryptoType, { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.to_ss58check()) } } -impl sp_std::fmt::Debug for Public +impl sp_std::fmt::Debug + for Public where - Public: CryptoType, + Public: CryptoType, [u8; LEFT_PLUS_RIGHT_LEN]: crate::hexdisplay::AsBytesRef, { #[cfg(feature = "std")] @@ -259,9 +203,10 @@ where } #[cfg(feature = "serde")] -impl Serialize for Public +impl Serialize + for Public where - Public: CryptoType, + Public: CryptoType, { fn serialize(&self, serializer: S) -> Result where @@ -272,9 +217,10 @@ where } #[cfg(feature = "serde")] -impl<'de, const LEFT_PLUS_RIGHT_LEN: usize> Deserialize<'de> for Public +impl<'de, const LEFT_PLUS_RIGHT_LEN: usize, SubTag: PairedCryptoSubTagBound> Deserialize<'de> + for Public where - Public: CryptoType, + Public: CryptoType, { fn deserialize(deserializer: D) -> Result where @@ -285,12 +231,17 @@ where } } -impl PublicT for Public where - Public: CryptoType +impl PublicT + for Public +where + Public: CryptoType, { } -impl Derive for Public {} +impl Derive + for Public +{ +} /// Trait characterizing a signature which could be used as individual component of an /// `paired_crypto:Signature` pair. @@ -299,54 +250,13 @@ pub trait SignatureBound: ByteArray {} impl SignatureBound for T {} /// A pair of signatures of different types -#[derive(Clone, Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Eq)] -pub struct Signature([u8; LEFT_PLUS_RIGHT_LEN]); - -impl sp_std::hash::Hash for Signature { - fn hash(&self, state: &mut H) { - self.0.hash(state); - } -} - -impl ByteArray for Signature { - const LEN: usize = LEFT_PLUS_RIGHT_LEN; -} - -impl TryFrom<&[u8]> for Signature { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != LEFT_PLUS_RIGHT_LEN { - return Err(()) - } - let mut inner = [0u8; LEFT_PLUS_RIGHT_LEN]; - inner.copy_from_slice(data); - Ok(Signature(inner)) - } -} - -impl AsMut<[u8]> for Signature { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - -impl AsRef<[u8; LEFT_PLUS_RIGHT_LEN]> - for Signature -{ - fn as_ref(&self) -> &[u8; LEFT_PLUS_RIGHT_LEN] { - &self.0 - } -} - -impl AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} +pub type Signature = + SignatureBytes; #[cfg(feature = "serde")] -impl Serialize for Signature { +impl Serialize + for Signature +{ fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -356,28 +266,23 @@ impl Serialize for Signature Deserialize<'de> for Signature { +impl<'de, const LEFT_PLUS_RIGHT_LEN: usize, SubTag> Deserialize<'de> + for Signature +{ fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let bytes = array_bytes::hex2bytes(&String::deserialize(deserializer)?) .map_err(|e| de::Error::custom(format!("{:?}", e)))?; - Signature::::try_from(bytes.as_ref()).map_err(|e| { + Signature::::try_from(bytes.as_ref()).map_err(|e| { de::Error::custom(format!("Error converting deserialized data into signature: {:?}", e)) }) } } -impl From> - for [u8; LEFT_PLUS_RIGHT_LEN] -{ - fn from(signature: Signature) -> [u8; LEFT_PLUS_RIGHT_LEN] { - signature.0 - } -} - -impl sp_std::fmt::Debug for Signature +impl sp_std::fmt::Debug + for Signature where [u8; LEFT_PLUS_RIGHT_LEN]: crate::hexdisplay::AsBytesRef, { @@ -392,24 +297,30 @@ where } } -impl UncheckedFrom<[u8; LEFT_PLUS_RIGHT_LEN]> - for Signature -{ - fn unchecked_from(data: [u8; LEFT_PLUS_RIGHT_LEN]) -> Self { - Signature(data) - } -} - /// A key pair. -#[derive(Clone)] pub struct Pair< LeftPair: PairT, RightPair: PairT, const PUBLIC_KEY_LEN: usize, const SIGNATURE_LEN: usize, + SubTag, > { left: LeftPair, right: RightPair, + _phantom: PhantomData SubTag>, +} + +impl< + LeftPair: PairT + Clone, + RightPair: PairT + Clone, + const PUBLIC_KEY_LEN: usize, + const SIGNATURE_LEN: usize, + SubTag, + > Clone for Pair +{ + fn clone(&self) -> Self { + Self { left: self.left.clone(), right: self.right.clone(), _phantom: PhantomData } + } } impl< @@ -417,18 +328,19 @@ impl< RightPair: PairT, const PUBLIC_KEY_LEN: usize, const SIGNATURE_LEN: usize, - > PairT for Pair + SubTag: PairedCryptoSubTagBound, + > PairT for Pair where - Pair: CryptoType, + Pair: CryptoType, LeftPair::Signature: SignatureBound, RightPair::Signature: SignatureBound, - Public: CryptoType, + Public: CryptoType, LeftPair::Seed: From + Into, RightPair::Seed: From + Into, { type Seed = Seed; - type Public = Public; - type Signature = Signature; + type Public = Public; + type Signature = Signature; fn from_seed_slice(seed_slice: &[u8]) -> Result { if seed_slice.len() != SECURE_SEED_LEN { @@ -436,7 +348,7 @@ where } let left = LeftPair::from_seed_slice(&seed_slice)?; let right = RightPair::from_seed_slice(&seed_slice)?; - Ok(Pair { left, right }) + Ok(Pair { left, right, _phantom: PhantomData }) } /// Derive a child key from a series of given junctions. @@ -459,7 +371,7 @@ where _ => None, }; - Ok((Self { left: left.0, right: right.0 }, seed)) + Ok((Self { left: left.0, right: right.0, _phantom: PhantomData }, seed)) } fn public(&self) -> Self::Public { @@ -479,16 +391,18 @@ where Self::Signature::unchecked_from(raw) } - fn verify>(sig: &Self::Signature, message: M, public: &Self::Public) -> bool { + fn verify>( + sig: &Self::Signature, + message: Msg, + public: &Self::Public, + ) -> bool { let Ok(left_pub) = public.0[..LeftPair::Public::LEN].try_into() else { return false }; let Ok(left_sig) = sig.0[0..LeftPair::Signature::LEN].try_into() else { return false }; if !LeftPair::verify(&left_sig, message.as_ref(), &left_pub) { return false } - let Ok(right_pub) = public.0[LeftPair::Public::LEN..PUBLIC_KEY_LEN].try_into() else { - return false - }; + let Ok(right_pub) = public.0[LeftPair::Public::LEN..].try_into() else { return false }; let Ok(right_sig) = sig.0[LeftPair::Signature::LEN..].try_into() else { return false }; RightPair::verify(&right_sig, message.as_ref(), &right_pub) } @@ -506,6 +420,7 @@ where mod test { use super::*; use crate::{crypto::DEV_PHRASE, KeccakHasher}; + use codec::{Decode, Encode}; use ecdsa_bls377::{Pair, Signature}; use crate::{bls377, ecdsa}; diff --git a/substrate/primitives/core/src/sr25519.rs b/substrate/primitives/core/src/sr25519.rs index 6c04eb8def..ee0546bc53 100644 --- a/substrate/primitives/core/src/sr25519.rs +++ b/substrate/primitives/core/src/sr25519.rs @@ -19,6 +19,7 @@ //! //! Note: `CHAIN_CODE_LENGTH` must be equal to `crate::crypto::JUNCTION_ID_LEN` //! for this to work. + #[cfg(feature = "serde")] use crate::crypto::Ss58Codec; use crate::crypto::{DeriveError, DeriveJunction, Pair as TraitPair, SecretStringError}; @@ -30,20 +31,16 @@ use schnorrkel::{ }; use sp_std::vec::Vec; -use crate::{ - crypto::{ - ByteArray, CryptoType, CryptoTypeId, Derive, FromEntropy, Public as TraitPublic, - UncheckedFrom, - }, - hash::{H256, H512}, +use crate::crypto::{ + CryptoType, CryptoTypeId, Derive, Public as TraitPublic, PublicBytes, SignatureBytes, }; use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; -use sp_std::ops::Deref; use schnorrkel::keys::{MINI_SECRET_KEY_LENGTH, SECRET_KEY_LENGTH}; #[cfg(feature = "serde")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; +#[cfg(feature = "std")] use sp_runtime_interface::pass_by::PassByInner; #[cfg(all(not(feature = "std"), feature = "serde"))] use sp_std::alloc::{format, string::String}; @@ -54,22 +51,17 @@ const SIGNING_CTX: &[u8] = b"substrate"; /// An identifier used to match public keys against sr25519 keys pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"sr25"); +/// The byte length of public key +pub const PUBLIC_KEY_SERIALIZED_SIZE: usize = 32; + +/// The byte length of signature +pub const SIGNATURE_SERIALIZED_SIZE: usize = 64; + +#[doc(hidden)] +pub struct Sr25519Tag; + /// An Schnorrkel/Ristretto x25519 ("sr25519") public key. -#[derive( - PartialEq, - Eq, - PartialOrd, - Ord, - Clone, - Copy, - Encode, - Decode, - PassByInner, - MaxEncodedLen, - TypeInfo, - Hash, -)] -pub struct Public(pub [u8; 32]); +pub type Public = PublicBytes; /// An Schnorrkel/Ristretto x25519 ("sr25519") key pair. pub struct Pair(Keypair); @@ -84,52 +76,6 @@ impl Clone for Pair { } } -impl FromEntropy for Public { - fn from_entropy(input: &mut impl codec::Input) -> Result { - let mut result = Self([0u8; 32]); - input.read(&mut result.0[..])?; - Ok(result) - } -} - -impl AsRef<[u8; 32]> for Public { - fn as_ref(&self) -> &[u8; 32] { - &self.0 - } -} - -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Public { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - -impl Deref for Public { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl From for [u8; 32] { - fn from(x: Public) -> [u8; 32] { - x.0 - } -} - -impl From for H256 { - fn from(x: Public) -> H256 { - x.0.into() - } -} - #[cfg(feature = "std")] impl std::str::FromStr for Public { type Err = crate::crypto::PublicError; @@ -139,31 +85,6 @@ impl std::str::FromStr for Public { } } -impl TryFrom<&[u8]> for Public { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() != Self::LEN { - return Err(()) - } - let mut r = [0u8; 32]; - r.copy_from_slice(data); - Ok(Self::unchecked_from(r)) - } -} - -impl UncheckedFrom<[u8; 32]> for Public { - fn unchecked_from(x: [u8; 32]) -> Self { - Public::from_raw(x) - } -} - -impl UncheckedFrom for Public { - fn unchecked_from(x: H256) -> Self { - Public::from_h256(x) - } -} - #[cfg(feature = "std")] impl std::fmt::Display for Public { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { @@ -175,7 +96,7 @@ impl sp_std::fmt::Debug for Public { #[cfg(feature = "std")] fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { let s = self.to_ss58check(); - write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) + write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(self.inner()), &s[0..8]) } #[cfg(not(feature = "std"))] @@ -206,22 +127,7 @@ impl<'de> Deserialize<'de> for Public { } /// An Schnorrkel/Ristretto x25519 ("sr25519") signature. -#[derive(Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq, Hash)] -pub struct Signature(pub [u8; 64]); - -impl TryFrom<&[u8]> for Signature { - type Error = (); - - fn try_from(data: &[u8]) -> Result { - if data.len() == 64 { - let mut inner = [0u8; 64]; - inner.copy_from_slice(data); - Ok(Signature(inner)) - } else { - Err(()) - } - } -} +pub type Signature = SignatureBytes; #[cfg(feature = "serde")] impl Serialize for Signature { @@ -246,48 +152,10 @@ impl<'de> Deserialize<'de> for Signature { } } -impl Clone for Signature { - fn clone(&self) -> Self { - let mut r = [0u8; 64]; - r.copy_from_slice(&self.0[..]); - Signature(r) - } -} - -impl From for [u8; 64] { - fn from(v: Signature) -> [u8; 64] { - v.0 - } -} - -impl From for H512 { - fn from(v: Signature) -> H512 { - H512::from(v.0) - } -} - -impl AsRef<[u8; 64]> for Signature { - fn as_ref(&self) -> &[u8; 64] { - &self.0 - } -} - -impl AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl AsMut<[u8]> for Signature { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0[..] - } -} - #[cfg(feature = "full_crypto")] impl From for Signature { fn from(s: schnorrkel::Signature) -> Signature { - Signature(s.to_bytes()) + Signature::from(s.to_bytes()) } } @@ -303,45 +171,6 @@ impl sp_std::fmt::Debug for Signature { } } -impl UncheckedFrom<[u8; 64]> for Signature { - fn unchecked_from(data: [u8; 64]) -> Signature { - Signature(data) - } -} - -impl Signature { - /// A new instance from the given 64-byte `data`. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use - /// it if you are certain that the array actually is a signature, or if you - /// immediately verify the signature. All functions that verify signatures - /// will fail if the `Signature` is not actually a valid signature. - pub fn from_raw(data: [u8; 64]) -> Signature { - Signature(data) - } - - /// A new instance from the given slice that should be 64 bytes long. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use it if - /// you are certain that the array actually is a signature. GIGO! - pub fn from_slice(data: &[u8]) -> Option { - if data.len() != 64 { - return None - } - let mut r = [0u8; 64]; - r.copy_from_slice(data); - Some(Signature(r)) - } - - /// A new instance from an H512. - /// - /// NOTE: No checking goes on to ensure this is a real signature. Only use it if - /// you are certain that the array actually is a signature. GIGO! - pub fn from_h512(v: H512) -> Signature { - Signature(v.into()) - } -} - impl Derive for Public { /// Derive a child key from a series of given junctions. /// @@ -355,37 +184,10 @@ impl Derive for Public { DeriveJunction::Hard(_cc) => return None, } } - Some(Self(acc.to_bytes())) + Some(Self::from(acc.to_bytes())) } } -impl Public { - /// A new instance from the given 32-byte `data`. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - pub fn from_raw(data: [u8; 32]) -> Self { - Public(data) - } - - /// A new instance from an H256. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - pub fn from_h256(x: H256) -> Self { - Public(x.into()) - } - - /// Return a slice filled with raw data. - pub fn as_array_ref(&self) -> &[u8; 32] { - self.as_ref() - } -} - -impl ByteArray for Public { - const LEN: usize = 32; -} - impl TraitPublic for Public {} #[cfg(feature = "std")] @@ -438,9 +240,7 @@ impl TraitPair for Pair { /// Get the public key. fn public(&self) -> Public { - let mut pk = [0u8; 32]; - pk.copy_from_slice(&self.0.public.to_bytes()); - Public(pk) + Public::from(self.0.public.to_bytes()) } /// Make a new key pair from raw secret seed material. @@ -720,7 +520,7 @@ pub mod vrf { impl VrfPublic for Public { fn vrf_verify(&self, data: &Self::VrfSignData, signature: &Self::VrfSignature) -> bool { let do_verify = || { - let public = schnorrkel::PublicKey::from_bytes(self)?; + let public = schnorrkel::PublicKey::from_bytes(&self.0)?; let inout = signature.pre_output.0.attach_input_hash(&public, data.transcript.0.clone())?; @@ -820,7 +620,10 @@ pub mod vrf { #[cfg(test)] mod tests { use super::{vrf::*, *}; - use crate::crypto::{Ss58Codec, VrfPublic, VrfSecret, DEV_ADDRESS, DEV_PHRASE}; + use crate::{ + crypto::{Ss58Codec, VrfPublic, VrfSecret, DEV_ADDRESS, DEV_PHRASE}, + ByteArray as _, + }; use serde_json; #[test] @@ -984,10 +787,10 @@ mod tests { let (pair, _) = Pair::generate(); let public = pair.public(); let message = b"Signed payload"; - let Signature(mut bytes) = pair.sign(&message[..]); + let mut signature = pair.sign(&message[..]); + let bytes = &mut signature.0; bytes[0] = !bytes[0]; bytes[2] = !bytes[2]; - let signature = Signature(bytes); assert!(!Pair::verify(&signature, &message[..], &public)); } diff --git a/substrate/primitives/keystore/src/testing.rs b/substrate/primitives/keystore/src/testing.rs index e10660b126..d8610ecfa5 100644 --- a/substrate/primitives/keystore/src/testing.rs +++ b/substrate/primitives/keystore/src/testing.rs @@ -528,7 +528,7 @@ mod tests { assert!(res.is_some()); // does not verify with default out-of-the-box verification - assert!(!ecdsa_bls377::Pair::verify(&res.clone().unwrap(), &msg[..], &pair.public())); + assert!(!ecdsa_bls377::Pair::verify(&res.unwrap(), &msg[..], &pair.public())); // should verify using keccak256 as hasher assert!(ecdsa_bls377::Pair::verify_with_hasher::( diff --git a/substrate/primitives/runtime/src/traits.rs b/substrate/primitives/runtime/src/traits.rs index caede5e2b5..9ee41339d5 100644 --- a/substrate/primitives/runtime/src/traits.rs +++ b/substrate/primitives/runtime/src/traits.rs @@ -133,7 +133,7 @@ impl Verify for sp_core::ecdsa::Signature { self.as_ref(), &sp_io::hashing::blake2_256(msg.get()), ) { - Ok(pubkey) => signer.as_ref() == &pubkey[..], + Ok(pubkey) => signer.0 == pubkey, _ => false, } } diff --git a/substrate/primitives/statement-store/src/lib.rs b/substrate/primitives/statement-store/src/lib.rs index bfcd0d1a52..dbac017ff6 100644 --- a/substrate/primitives/statement-store/src/lib.rs +++ b/substrate/primitives/statement-store/src/lib.rs @@ -340,8 +340,8 @@ impl Statement { Some(Proof::OnChain { .. }) | None => SignatureVerificationResult::NoSignature, Some(Proof::Sr25519 { signature, signer }) => { let to_sign = self.signature_material(); - let signature = sp_core::sr25519::Signature(*signature); - let public = sp_core::sr25519::Public(*signer); + let signature = sp_core::sr25519::Signature::from(*signature); + let public = sp_core::sr25519::Public::from(*signer); if signature.verify(to_sign.as_slice(), &public) { SignatureVerificationResult::Valid(*signer) } else { @@ -350,8 +350,8 @@ impl Statement { }, Some(Proof::Ed25519 { signature, signer }) => { let to_sign = self.signature_material(); - let signature = sp_core::ed25519::Signature(*signature); - let public = sp_core::ed25519::Public(*signer); + let signature = sp_core::ed25519::Signature::from(*signature); + let public = sp_core::ed25519::Public::from(*signer); if signature.verify(to_sign.as_slice(), &public) { SignatureVerificationResult::Valid(*signer) } else { @@ -360,8 +360,8 @@ impl Statement { }, Some(Proof::Secp256k1Ecdsa { signature, signer }) => { let to_sign = self.signature_material(); - let signature = sp_core::ecdsa::Signature(*signature); - let public = sp_core::ecdsa::Public(*signer); + let signature = sp_core::ecdsa::Signature::from(*signature); + let public = sp_core::ecdsa::Public::from(*signer); if signature.verify(to_sign.as_slice(), &public) { let sender_hash = ::hash(signer);