mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 10:01:17 +00:00
Implement crypto byte array newtypes in term of a shared type (#3684)
Introduces `CryptoBytes` type defined as: ```rust pub struct CryptoBytes<const N: usize, Tag = ()>(pub [u8; N], PhantomData<fn() -> Tag>); ``` The type implements a bunch of methods and traits which are typically expected from a byte array newtype (NOTE: some of the methods and trait implementations IMO are a bit redundant, but I decided to maintain them all to not change too much stuff in this PR) It also introduces two (generic) typical consumers of `CryptoBytes`: `PublicBytes` and `SignatureBytes`. ```rust pub struct PublicTag; pub PublicBytes<const N: usize, CryptoTag> = CryptoBytes<N, (PublicTag, CryptoTag)>; pub struct SignatureTag; pub SignatureBytes<const N: usize, CryptoTag> = CryptoBytes<N, (SignatureTag, CryptoTag)>; ``` Both of them use a tag to differentiate the two types at a higher level. Downstream specializations will further specialize using a dedicated crypto tag. For example in ECDSA: ```rust pub struct EcdsaTag; pub type Public = PublicBytes<PUBLIC_KEY_SERIALIZED_SIZE, EcdsaTag>; pub type Signature = PublicBytes<PUBLIC_KEY_SERIALIZED_SIZE, EcdsaTag>; ``` Overall we have a cleaner and most importantly **consistent** code for all the types involved All these details are opaque to the end user which can use `Public` and `Signature` for the cryptos as before
This commit is contained in:
@@ -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()),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
},
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -425,8 +425,8 @@ pub mod pallet {
|
||||
impl<T: Config> Pallet<T> {
|
||||
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::<T>::InvalidSignature)?
|
||||
let signature: AnySignature = sr25519::Signature::try_from(signature)
|
||||
.map_err(|_| Error::<T>::InvalidSignature)?
|
||||
.into();
|
||||
|
||||
// In Polkadot, the AccountId is always the same as the 32 byte public key.
|
||||
|
||||
@@ -272,7 +272,7 @@ impl<T: paras_inherent::Config> BenchBuilder<T> {
|
||||
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(),
|
||||
}
|
||||
|
||||
@@ -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
|
||||
));
|
||||
|
||||
@@ -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<u8>) -> 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<u8> {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -139,8 +139,8 @@ mod benchmarks {
|
||||
TicketsIds::<T>::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::<T>::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);
|
||||
|
||||
+6
-6
@@ -13,8 +13,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied
|
||||
|
|
||||
= help: the following other types implement trait `WrapperTypeDecode`:
|
||||
Box<T>
|
||||
Rc<T>
|
||||
frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes
|
||||
Rc<T>
|
||||
Arc<T>
|
||||
= 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<T>
|
||||
frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes
|
||||
Rc<T>
|
||||
Arc<T>
|
||||
Vec<T>
|
||||
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<T>
|
||||
Rc<T>
|
||||
frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes
|
||||
Rc<T>
|
||||
Arc<T>
|
||||
= 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<T>
|
||||
frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes
|
||||
Rc<T>
|
||||
Arc<T>
|
||||
Vec<T>
|
||||
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<T>
|
||||
Rc<T>
|
||||
frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes
|
||||
Rc<T>
|
||||
Arc<T>
|
||||
= 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<T>
|
||||
frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes
|
||||
Rc<T>
|
||||
Arc<T>
|
||||
Vec<T>
|
||||
and $N others
|
||||
|
||||
+6
-6
@@ -13,8 +13,8 @@ error[E0277]: the trait bound `Bar: WrapperTypeDecode` is not satisfied
|
||||
|
|
||||
= help: the following other types implement trait `WrapperTypeDecode`:
|
||||
Box<T>
|
||||
Rc<T>
|
||||
frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes
|
||||
Rc<T>
|
||||
Arc<T>
|
||||
= 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<T>
|
||||
frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes
|
||||
Rc<T>
|
||||
Arc<T>
|
||||
Vec<T>
|
||||
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<T>
|
||||
Rc<T>
|
||||
frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes
|
||||
Rc<T>
|
||||
Arc<T>
|
||||
= 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<T>
|
||||
frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes
|
||||
Rc<T>
|
||||
Arc<T>
|
||||
Vec<T>
|
||||
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<T>
|
||||
Rc<T>
|
||||
frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes
|
||||
Rc<T>
|
||||
Arc<T>
|
||||
= 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<T>
|
||||
frame_support::sp_runtime::sp_application_crypto::sp_core::Bytes
|
||||
Rc<T>
|
||||
Arc<T>
|
||||
Vec<T>
|
||||
and $N others
|
||||
|
||||
@@ -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<Self, Self::Error> {
|
||||
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<PUBLIC_SERIALIZED_SIZE, BandersnatchTag>;
|
||||
|
||||
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<Self, Self::Error> {
|
||||
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<SIGNATURE_SERIALIZED_SIZE, BandersnatchTag>;
|
||||
|
||||
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
|
||||
|
||||
@@ -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<TinyBLS377>;
|
||||
/// 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<T> {
|
||||
inner: [u8; PUBLIC_KEY_SERIALIZED_SIZE],
|
||||
_phantom: PhantomData<fn() -> T>,
|
||||
}
|
||||
|
||||
impl<T> Clone for Public<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self { inner: self.inner, _phantom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PartialEq for Public<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner == other.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Eq for Public<T> {}
|
||||
|
||||
impl<T> PartialOrd for Public<T> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<sp_std::cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Ord for Public<T> {
|
||||
fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering {
|
||||
self.inner.cmp(&other.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> sp_std::hash::Hash for Public<T> {
|
||||
fn hash<H: sp_std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.inner.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByteArray for Public<T> {
|
||||
const LEN: usize = PUBLIC_KEY_SERIALIZED_SIZE;
|
||||
}
|
||||
|
||||
impl<T> PassByInner for Public<T> {
|
||||
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<T> PassBy for Public<T> {
|
||||
type PassBy = pass_by::Inner<Self, [u8; PUBLIC_KEY_SERIALIZED_SIZE]>;
|
||||
}
|
||||
|
||||
impl<T> AsRef<[u8; PUBLIC_KEY_SERIALIZED_SIZE]> for Public<T> {
|
||||
fn as_ref(&self) -> &[u8; PUBLIC_KEY_SERIALIZED_SIZE] {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsRef<[u8]> for Public<T> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.inner[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsMut<[u8]> for Public<T> {
|
||||
fn as_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.inner[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for Public<T> {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> TryFrom<&[u8]> for Public<T> {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
|
||||
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<T> From<Public<T>> for [u8; PUBLIC_KEY_SERIALIZED_SIZE] {
|
||||
fn from(x: Public<T>) -> Self {
|
||||
x.inner
|
||||
}
|
||||
}
|
||||
pub type Public<SubTag> = PublicBytes<PUBLIC_KEY_SERIALIZED_SIZE, (BlsTag, SubTag)>;
|
||||
|
||||
impl<T: BlsBound> From<Pair<T>> for Public<T> {
|
||||
fn from(x: Pair<T>) -> Self {
|
||||
@@ -228,12 +121,6 @@ impl<T: BlsBound> From<Pair<T>> for Public<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> UncheckedFrom<[u8; PUBLIC_KEY_SERIALIZED_SIZE]> for Public<T> {
|
||||
fn unchecked_from(data: [u8; PUBLIC_KEY_SERIALIZED_SIZE]) -> Self {
|
||||
Public { inner: data, _phantom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: BlsBound> std::str::FromStr for Public<T> {
|
||||
type Err = crate::crypto::PublicError;
|
||||
@@ -254,7 +141,7 @@ impl<T: BlsBound> std::fmt::Display for Public<T> {
|
||||
impl<T: BlsBound> sp_std::fmt::Debug for Public<T> {
|
||||
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<T: BlsBound> CryptoType for Public<T> {
|
||||
}
|
||||
|
||||
/// A generic BLS signature.
|
||||
#[derive(Copy, Encode, Decode, MaxEncodedLen, TypeInfo)]
|
||||
#[scale_info(skip_type_params(T))]
|
||||
pub struct Signature<T> {
|
||||
inner: [u8; SIGNATURE_SERIALIZED_SIZE],
|
||||
_phantom: PhantomData<fn() -> T>,
|
||||
}
|
||||
|
||||
impl<T> Clone for Signature<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self { inner: self.inner, _phantom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PartialEq for Signature<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner == other.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Eq for Signature<T> {}
|
||||
|
||||
impl<T> sp_std::hash::Hash for Signature<T> {
|
||||
fn hash<H: sp_std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.inner.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByteArray for Signature<T> {
|
||||
const LEN: usize = SIGNATURE_SERIALIZED_SIZE;
|
||||
}
|
||||
|
||||
impl<T> TryFrom<&[u8]> for Signature<T> {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
|
||||
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<SubTag> = SignatureBytes<SIGNATURE_SERIALIZED_SIZE, (BlsTag, SubTag)>;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<T> Serialize for Signature<T> {
|
||||
@@ -362,34 +207,10 @@ impl<'de, T> Deserialize<'de> for Signature<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Signature<T>> for [u8; SIGNATURE_SERIALIZED_SIZE] {
|
||||
fn from(signature: Signature<T>) -> [u8; SIGNATURE_SERIALIZED_SIZE] {
|
||||
signature.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsRef<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature<T> {
|
||||
fn as_ref(&self) -> &[u8; SIGNATURE_SERIALIZED_SIZE] {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsRef<[u8]> for Signature<T> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.inner[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsMut<[u8]> for Signature<T> {
|
||||
fn as_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.inner[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> sp_std::fmt::Debug for Signature<T> {
|
||||
#[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<T> sp_std::fmt::Debug for Signature<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> UncheckedFrom<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature<T> {
|
||||
fn unchecked_from(data: [u8; SIGNATURE_SERIALIZED_SIZE]) -> Self {
|
||||
Signature { inner: data, _phantom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BlsBound> CryptoType for Signature<T> {
|
||||
type Pair = Pair<T>;
|
||||
}
|
||||
@@ -423,6 +238,7 @@ trait HardJunctionId {
|
||||
|
||||
/// Derive a single hard junction.
|
||||
fn derive_hard_junction<T: HardJunctionId>(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<T: BlsBound> TraitPair for Pair<T> {
|
||||
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,
|
||||
};
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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 `PhantomData<fn() ->T>`, 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<const N: usize, T = ()>(pub [u8; N], PhantomData<fn() -> T>);
|
||||
|
||||
impl<const N: usize, T> Copy for CryptoBytes<N, T> {}
|
||||
|
||||
impl<const N: usize, T> Clone for CryptoBytes<N, T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> TypeInfo for CryptoBytes<N, T> {
|
||||
type Identity = [u8; N];
|
||||
|
||||
fn type_info() -> scale_info::Type {
|
||||
Self::Identity::type_info()
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> PartialOrd for CryptoBytes<N, T> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
|
||||
self.0.partial_cmp(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> Ord for CryptoBytes<N, T> {
|
||||
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
|
||||
self.0.cmp(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> PartialEq for CryptoBytes<N, T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.0.eq(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> core::hash::Hash for CryptoBytes<N, T> {
|
||||
fn hash<H: scale_info::prelude::hash::Hasher>(&self, state: &mut H) {
|
||||
self.0.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> Eq for CryptoBytes<N, T> {}
|
||||
|
||||
impl<const N: usize, T> Default for CryptoBytes<N, T> {
|
||||
fn default() -> Self {
|
||||
Self([0_u8; N], PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> PassByInner for CryptoBytes<N, T> {
|
||||
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<const N: usize, T> PassBy for CryptoBytes<N, T> {
|
||||
type PassBy = pass_by::Inner<Self, [u8; N]>;
|
||||
}
|
||||
|
||||
impl<const N: usize, T> AsRef<[u8]> for CryptoBytes<N, T> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> AsMut<[u8]> for CryptoBytes<N, T> {
|
||||
fn as_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> From<CryptoBytes<N, T>> for [u8; N] {
|
||||
fn from(v: CryptoBytes<N, T>) -> [u8; N] {
|
||||
v.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> AsRef<[u8; N]> for CryptoBytes<N, T> {
|
||||
fn as_ref(&self) -> &[u8; N] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> AsMut<[u8; N]> for CryptoBytes<N, T> {
|
||||
fn as_mut(&mut self) -> &mut [u8; N] {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> From<[u8; N]> for CryptoBytes<N, T> {
|
||||
fn from(value: [u8; N]) -> Self {
|
||||
Self::from_raw(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> TryFrom<&[u8]> for CryptoBytes<N, T> {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
|
||||
if data.len() != N {
|
||||
return Err(())
|
||||
}
|
||||
let mut r = [0u8; N];
|
||||
r.copy_from_slice(data);
|
||||
Ok(Self::from_raw(r))
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> UncheckedFrom<[u8; N]> for CryptoBytes<N, T> {
|
||||
fn unchecked_from(data: [u8; N]) -> Self {
|
||||
Self::from_raw(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> core::ops::Deref for CryptoBytes<N, T> {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, T> CryptoBytes<N, T> {
|
||||
/// 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<const N: usize, T> crate::ByteArray for CryptoBytes<N, T> {
|
||||
const LEN: usize = N;
|
||||
}
|
||||
|
||||
impl<const N: usize, T> FromEntropy for CryptoBytes<N, T> {
|
||||
fn from_entropy(input: &mut impl codec::Input) -> Result<Self, codec::Error> {
|
||||
let mut result = Self::default();
|
||||
input.read(result.as_mut())?;
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<CryptoBytes<32, T>> for H256 {
|
||||
fn from(x: CryptoBytes<32, T>) -> H256 {
|
||||
H256::from(x.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<CryptoBytes<64, T>> for H512 {
|
||||
fn from(x: CryptoBytes<64, T>) -> H512 {
|
||||
H512::from(x.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> UncheckedFrom<H256> for CryptoBytes<32, T> {
|
||||
fn unchecked_from(x: H256) -> Self {
|
||||
Self::from_h256(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CryptoBytes<32, T> {
|
||||
/// A new instance from an H256.
|
||||
pub fn from_h256(x: H256) -> Self {
|
||||
Self::from_raw(x.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> 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<const N: usize, SubTag> = CryptoBytes<N, (PublicTag, SubTag)>;
|
||||
|
||||
/// Tag used for generic signature bytes.
|
||||
pub struct SignatureTag;
|
||||
|
||||
/// Generic encoded signature.
|
||||
pub type SignatureBytes<const N: usize, SubTag> = CryptoBytes<N, (SignatureTag, SubTag)>;
|
||||
@@ -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<Self, codec::Error> {
|
||||
let mut result = Self([0u8; PUBLIC_KEY_SERIALIZED_SIZE]);
|
||||
input.read(&mut result.0[..])?;
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
pub type Public = PublicBytes<PUBLIC_KEY_SERIALIZED_SIZE, EcdsaTag>;
|
||||
|
||||
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<PublicKey> for Public {
|
||||
fn from(pubkey: PublicKey) -> Self {
|
||||
Self(pubkey.serialize())
|
||||
Self::from(pubkey.serialize())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl From<VerifyingKey> 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<Self, Self::Error> {
|
||||
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<Pair> 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<Self, Self::Error> {
|
||||
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<SIGNATURE_SERIALIZED_SIZE, EcdsaTag>;
|
||||
|
||||
#[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<Signature> 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<Self> {
|
||||
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<M: AsRef<[u8]>>(&self, message: M) -> Option<Public> {
|
||||
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<RecoverableSignature> 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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<PUBLIC_KEY_SERIALIZED_SIZE, Ed25519Tag>;
|
||||
|
||||
/// 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<Self, codec::Error> {
|
||||
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<Self, Self::Error> {
|
||||
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<Public> for [u8; 32] {
|
||||
fn from(x: Public) -> Self {
|
||||
x.0
|
||||
}
|
||||
}
|
||||
impl Derive for Public {}
|
||||
|
||||
#[cfg(feature = "full_crypto")]
|
||||
impl From<Pair> for Public {
|
||||
@@ -136,12 +62,6 @@ impl From<Pair> for Public {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Public> 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<H256> 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<Self, Self::Error> {
|
||||
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<SIGNATURE_SERIALIZED_SIZE, Ed25519Tag>;
|
||||
|
||||
#[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<Signature> for H512 {
|
||||
fn from(v: Signature) -> H512 {
|
||||
H512::from(v.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Signature> 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<Self> {
|
||||
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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<ecdsa::Pair, bls377::Pair, PUBLIC_KEY_LEN, SIGNATURE_LEN>;
|
||||
pub type Pair =
|
||||
super::Pair<ecdsa::Pair, bls377::Pair, PUBLIC_KEY_LEN, SIGNATURE_LEN, EcdsaBls377Tag>;
|
||||
|
||||
/// (ECDSA,BLS12-377) public key pair.
|
||||
pub type Public = super::Public<PUBLIC_KEY_LEN>;
|
||||
pub type Public = super::Public<PUBLIC_KEY_LEN, EcdsaBls377Tag>;
|
||||
|
||||
/// (ECDSA,BLS12-377) signature pair.
|
||||
pub type Signature = super::Signature<SIGNATURE_LEN>;
|
||||
pub type Signature = super::Signature<SIGNATURE_LEN, EcdsaBls377Tag>;
|
||||
|
||||
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<const LEFT_PLUS_RIGHT_LEN: usize>([u8; LEFT_PLUS_RIGHT_LEN]);
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> sp_std::hash::Hash for Public<LEFT_PLUS_RIGHT_LEN> {
|
||||
fn hash<H: sp_std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.0.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> ByteArray for Public<LEFT_PLUS_RIGHT_LEN> {
|
||||
const LEN: usize = LEFT_PLUS_RIGHT_LEN;
|
||||
}
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> TryFrom<&[u8]> for Public<LEFT_PLUS_RIGHT_LEN> {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
|
||||
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<const LEFT_PLUS_RIGHT_LEN: usize> AsRef<[u8; LEFT_PLUS_RIGHT_LEN]>
|
||||
for Public<LEFT_PLUS_RIGHT_LEN>
|
||||
{
|
||||
fn as_ref(&self) -> &[u8; LEFT_PLUS_RIGHT_LEN] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> AsRef<[u8]> for Public<LEFT_PLUS_RIGHT_LEN> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> AsMut<[u8]> for Public<LEFT_PLUS_RIGHT_LEN> {
|
||||
fn as_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> PassByInner for Public<LEFT_PLUS_RIGHT_LEN> {
|
||||
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<const LEFT_PLUS_RIGHT_LEN: usize> PassBy for Public<LEFT_PLUS_RIGHT_LEN> {
|
||||
type PassBy = pass_by::Inner<Self, [u8; LEFT_PLUS_RIGHT_LEN]>;
|
||||
}
|
||||
pub type Public<const LEFT_PLUS_RIGHT_LEN: usize, SubTag> =
|
||||
PublicBytes<LEFT_PLUS_RIGHT_LEN, (PairedCryptoTag, SubTag)>;
|
||||
|
||||
impl<
|
||||
LeftPair: PairT,
|
||||
RightPair: PairT,
|
||||
const LEFT_PLUS_RIGHT_PUBLIC_LEN: usize,
|
||||
const SIGNATURE_LEN: usize,
|
||||
> From<Pair<LeftPair, RightPair, LEFT_PLUS_RIGHT_PUBLIC_LEN, SIGNATURE_LEN>>
|
||||
for Public<LEFT_PLUS_RIGHT_PUBLIC_LEN>
|
||||
SubTag: PairedCryptoSubTagBound,
|
||||
> From<Pair<LeftPair, RightPair, LEFT_PLUS_RIGHT_PUBLIC_LEN, SIGNATURE_LEN, SubTag>>
|
||||
for Public<LEFT_PLUS_RIGHT_PUBLIC_LEN, SubTag>
|
||||
where
|
||||
Pair<LeftPair, RightPair, LEFT_PLUS_RIGHT_PUBLIC_LEN, SIGNATURE_LEN>:
|
||||
PairT<Public = Public<LEFT_PLUS_RIGHT_PUBLIC_LEN>>,
|
||||
Pair<LeftPair, RightPair, LEFT_PLUS_RIGHT_PUBLIC_LEN, SIGNATURE_LEN, SubTag>:
|
||||
PairT<Public = Public<LEFT_PLUS_RIGHT_PUBLIC_LEN, SubTag>>,
|
||||
{
|
||||
fn from(x: Pair<LeftPair, RightPair, LEFT_PLUS_RIGHT_PUBLIC_LEN, SIGNATURE_LEN>) -> Self {
|
||||
fn from(
|
||||
x: Pair<LeftPair, RightPair, LEFT_PLUS_RIGHT_PUBLIC_LEN, SIGNATURE_LEN, SubTag>,
|
||||
) -> Self {
|
||||
x.public()
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> UncheckedFrom<[u8; LEFT_PLUS_RIGHT_LEN]>
|
||||
for Public<LEFT_PLUS_RIGHT_LEN>
|
||||
{
|
||||
fn unchecked_from(data: [u8; LEFT_PLUS_RIGHT_LEN]) -> Self {
|
||||
Public(data)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> std::fmt::Display for Public<LEFT_PLUS_RIGHT_LEN>
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize, SubTag: PairedCryptoSubTagBound> std::fmt::Display
|
||||
for Public<LEFT_PLUS_RIGHT_LEN, SubTag>
|
||||
where
|
||||
Public<LEFT_PLUS_RIGHT_LEN>: CryptoType,
|
||||
Public<LEFT_PLUS_RIGHT_LEN, SubTag>: CryptoType,
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{}", self.to_ss58check())
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> sp_std::fmt::Debug for Public<LEFT_PLUS_RIGHT_LEN>
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize, SubTag: PairedCryptoSubTagBound> sp_std::fmt::Debug
|
||||
for Public<LEFT_PLUS_RIGHT_LEN, SubTag>
|
||||
where
|
||||
Public<LEFT_PLUS_RIGHT_LEN>: CryptoType,
|
||||
Public<LEFT_PLUS_RIGHT_LEN, SubTag>: CryptoType,
|
||||
[u8; LEFT_PLUS_RIGHT_LEN]: crate::hexdisplay::AsBytesRef,
|
||||
{
|
||||
#[cfg(feature = "std")]
|
||||
@@ -259,9 +203,10 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> Serialize for Public<LEFT_PLUS_RIGHT_LEN>
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize, SubTag: PairedCryptoSubTagBound> Serialize
|
||||
for Public<LEFT_PLUS_RIGHT_LEN, SubTag>
|
||||
where
|
||||
Public<LEFT_PLUS_RIGHT_LEN>: CryptoType,
|
||||
Public<LEFT_PLUS_RIGHT_LEN, SubTag>: CryptoType,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -272,9 +217,10 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de, const LEFT_PLUS_RIGHT_LEN: usize> Deserialize<'de> for Public<LEFT_PLUS_RIGHT_LEN>
|
||||
impl<'de, const LEFT_PLUS_RIGHT_LEN: usize, SubTag: PairedCryptoSubTagBound> Deserialize<'de>
|
||||
for Public<LEFT_PLUS_RIGHT_LEN, SubTag>
|
||||
where
|
||||
Public<LEFT_PLUS_RIGHT_LEN>: CryptoType,
|
||||
Public<LEFT_PLUS_RIGHT_LEN, SubTag>: CryptoType,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
@@ -285,12 +231,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> PublicT for Public<LEFT_PLUS_RIGHT_LEN> where
|
||||
Public<LEFT_PLUS_RIGHT_LEN>: CryptoType
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize, SubTag: PairedCryptoSubTagBound> PublicT
|
||||
for Public<LEFT_PLUS_RIGHT_LEN, SubTag>
|
||||
where
|
||||
Public<LEFT_PLUS_RIGHT_LEN, SubTag>: CryptoType,
|
||||
{
|
||||
}
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> Derive for Public<LEFT_PLUS_RIGHT_LEN> {}
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize, SubTag: PairedCryptoSubTagBound> Derive
|
||||
for Public<LEFT_PLUS_RIGHT_LEN, SubTag>
|
||||
{
|
||||
}
|
||||
|
||||
/// 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<T: ByteArray> SignatureBound for T {}
|
||||
|
||||
/// A pair of signatures of different types
|
||||
#[derive(Clone, Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Eq)]
|
||||
pub struct Signature<const LEFT_PLUS_RIGHT_LEN: usize>([u8; LEFT_PLUS_RIGHT_LEN]);
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> sp_std::hash::Hash for Signature<LEFT_PLUS_RIGHT_LEN> {
|
||||
fn hash<H: sp_std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.0.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> ByteArray for Signature<LEFT_PLUS_RIGHT_LEN> {
|
||||
const LEN: usize = LEFT_PLUS_RIGHT_LEN;
|
||||
}
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> TryFrom<&[u8]> for Signature<LEFT_PLUS_RIGHT_LEN> {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
|
||||
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<const LEFT_PLUS_RIGHT_LEN: usize> AsMut<[u8]> for Signature<LEFT_PLUS_RIGHT_LEN> {
|
||||
fn as_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> AsRef<[u8; LEFT_PLUS_RIGHT_LEN]>
|
||||
for Signature<LEFT_PLUS_RIGHT_LEN>
|
||||
{
|
||||
fn as_ref(&self) -> &[u8; LEFT_PLUS_RIGHT_LEN] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> AsRef<[u8]> for Signature<LEFT_PLUS_RIGHT_LEN> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0[..]
|
||||
}
|
||||
}
|
||||
pub type Signature<const LEFT_PLUS_RIGHT_LEN: usize, SubTag> =
|
||||
SignatureBytes<LEFT_PLUS_RIGHT_LEN, (PairedCryptoTag, SubTag)>;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> Serialize for Signature<LEFT_PLUS_RIGHT_LEN> {
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize, SubTag> Serialize
|
||||
for Signature<LEFT_PLUS_RIGHT_LEN, SubTag>
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -356,28 +266,23 @@ impl<const LEFT_PLUS_RIGHT_LEN: usize> Serialize for Signature<LEFT_PLUS_RIGHT_L
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de, const LEFT_PLUS_RIGHT_LEN: usize> Deserialize<'de> for Signature<LEFT_PLUS_RIGHT_LEN> {
|
||||
impl<'de, const LEFT_PLUS_RIGHT_LEN: usize, SubTag> Deserialize<'de>
|
||||
for Signature<LEFT_PLUS_RIGHT_LEN, SubTag>
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let bytes = array_bytes::hex2bytes(&String::deserialize(deserializer)?)
|
||||
.map_err(|e| de::Error::custom(format!("{:?}", e)))?;
|
||||
Signature::<LEFT_PLUS_RIGHT_LEN>::try_from(bytes.as_ref()).map_err(|e| {
|
||||
Signature::<LEFT_PLUS_RIGHT_LEN, SubTag>::try_from(bytes.as_ref()).map_err(|e| {
|
||||
de::Error::custom(format!("Error converting deserialized data into signature: {:?}", e))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> From<Signature<LEFT_PLUS_RIGHT_LEN>>
|
||||
for [u8; LEFT_PLUS_RIGHT_LEN]
|
||||
{
|
||||
fn from(signature: Signature<LEFT_PLUS_RIGHT_LEN>) -> [u8; LEFT_PLUS_RIGHT_LEN] {
|
||||
signature.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> sp_std::fmt::Debug for Signature<LEFT_PLUS_RIGHT_LEN>
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize, SubTag> sp_std::fmt::Debug
|
||||
for Signature<LEFT_PLUS_RIGHT_LEN, SubTag>
|
||||
where
|
||||
[u8; LEFT_PLUS_RIGHT_LEN]: crate::hexdisplay::AsBytesRef,
|
||||
{
|
||||
@@ -392,24 +297,30 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<const LEFT_PLUS_RIGHT_LEN: usize> UncheckedFrom<[u8; LEFT_PLUS_RIGHT_LEN]>
|
||||
for Signature<LEFT_PLUS_RIGHT_LEN>
|
||||
{
|
||||
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<fn() -> SubTag>,
|
||||
}
|
||||
|
||||
impl<
|
||||
LeftPair: PairT + Clone,
|
||||
RightPair: PairT + Clone,
|
||||
const PUBLIC_KEY_LEN: usize,
|
||||
const SIGNATURE_LEN: usize,
|
||||
SubTag,
|
||||
> Clone for Pair<LeftPair, RightPair, PUBLIC_KEY_LEN, SIGNATURE_LEN, SubTag>
|
||||
{
|
||||
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<LeftPair, RightPair, PUBLIC_KEY_LEN, SIGNATURE_LEN>
|
||||
SubTag: PairedCryptoSubTagBound,
|
||||
> PairT for Pair<LeftPair, RightPair, PUBLIC_KEY_LEN, SIGNATURE_LEN, SubTag>
|
||||
where
|
||||
Pair<LeftPair, RightPair, PUBLIC_KEY_LEN, SIGNATURE_LEN>: CryptoType,
|
||||
Pair<LeftPair, RightPair, PUBLIC_KEY_LEN, SIGNATURE_LEN, SubTag>: CryptoType,
|
||||
LeftPair::Signature: SignatureBound,
|
||||
RightPair::Signature: SignatureBound,
|
||||
Public<PUBLIC_KEY_LEN>: CryptoType,
|
||||
Public<PUBLIC_KEY_LEN, SubTag>: CryptoType,
|
||||
LeftPair::Seed: From<Seed> + Into<Seed>,
|
||||
RightPair::Seed: From<Seed> + Into<Seed>,
|
||||
{
|
||||
type Seed = Seed;
|
||||
type Public = Public<PUBLIC_KEY_LEN>;
|
||||
type Signature = Signature<SIGNATURE_LEN>;
|
||||
type Public = Public<PUBLIC_KEY_LEN, SubTag>;
|
||||
type Signature = Signature<SIGNATURE_LEN, SubTag>;
|
||||
|
||||
fn from_seed_slice(seed_slice: &[u8]) -> Result<Self, SecretStringError> {
|
||||
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<M: AsRef<[u8]>>(sig: &Self::Signature, message: M, public: &Self::Public) -> bool {
|
||||
fn verify<Msg: AsRef<[u8]>>(
|
||||
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};
|
||||
|
||||
@@ -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<PUBLIC_KEY_SERIALIZED_SIZE, Sr25519Tag>;
|
||||
|
||||
/// 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<Self, codec::Error> {
|
||||
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<Public> for [u8; 32] {
|
||||
fn from(x: Public) -> [u8; 32] {
|
||||
x.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Public> 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<Self, Self::Error> {
|
||||
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<H256> 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<Self, Self::Error> {
|
||||
if data.len() == 64 {
|
||||
let mut inner = [0u8; 64];
|
||||
inner.copy_from_slice(data);
|
||||
Ok(Signature(inner))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
pub type Signature = SignatureBytes<SIGNATURE_SERIALIZED_SIZE, Sr25519Tag>;
|
||||
|
||||
#[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<Signature> for [u8; 64] {
|
||||
fn from(v: Signature) -> [u8; 64] {
|
||||
v.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Signature> 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<schnorrkel::Signature> 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<Self> {
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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::<KeccakHasher>(
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 =
|
||||
<sp_runtime::traits::BlakeTwo256 as sp_core::Hasher>::hash(signer);
|
||||
|
||||
Reference in New Issue
Block a user